11# Architecture And Design Decisions
22
3- Chat SDK Go's design is documented in two places, and this page is the index
4- over both. It also states the [ design goals] ( #design-goals ) , maps the
5- project against [ Vercel Chat SDK] ( #vercel-chat-sdk-alignment ) , and lists the
6- [ non-goals] ( #non-goals ) and [ intentional gaps] ( #intentional-gaps ) .
7-
8- - [ ` CONTEXT.md ` ] ( ../CONTEXT.md ) — the ubiquitous language and architecture
9- document. It defines every domain term precisely (with the synonyms to
10- avoid), states the architectural invariants as explicit relationships, and
11- records resolved ambiguities against upstream Vercel Chat SDK behavior.
12- - [ ` docs/adr/ ` ] ( adr/ ) — Architecture Decision Records. Every significant
13- decision has one, including the decisions * not* to build something.
14-
15- ## Reading CONTEXT.md
16-
17- If you want to understand the system, read ` CONTEXT.md ` top to bottom; it is
18- the single most information-dense document in the repository. Its ` Language `
19- section groups the vocabulary by area — runtime lifecycle, the platform
20- adapter boundary, Linear session lifecycle, threads and routing, the
21- event/message model, dispatch and concurrency, observability, state and
22- history, content and formatting, and tenancy and identity. The
23- ` Relationships ` section is the closest thing to a formal specification of the
24- runtime's invariants, and ` Flagged ambiguities ` explains where and why the
25- design deliberately diverges from Vercel Chat SDK.
26-
27- ## Decision Records
28-
29- | ADR | Decision | Status |
30- | --- | --- | --- |
31- | [ 0001] ( adr/0001-linear-app-actor-slice.md ) | Linear app-actor slice before a full Linear adapter | Accepted |
32- | [ 0002] ( adr/0002-async-dispatch.md ) | Deferred runtime dispatch (ack-then-work) | Accepted |
33- | [ 0003] ( adr/0003-slash-commands.md ) | Command Events and slash command routing | Accepted |
34- | [ 0004] ( adr/0004-interactive-components.md ) | Interaction Events and native content instead of a card DSL | Accepted |
35- | [ 0005] ( adr/0005-rate-limit-handling.md ) | Rate-limit retry lives in adapters, with typed ` RateLimited ` errors | Accepted |
36- | [ 0006] ( adr/0006-multi-tenant-install.md ) | Multi-tenant installs via app-implemented ` InstallStore ` ; OAuth flows stay app-owned | Accepted |
37- | [ 0007] ( adr/0007-teams-adapter.md ) | Microsoft Teams adapter approach (Bot Framework, direct HTTP) | Proposed — gated on a spike |
38- | [ 0008] ( adr/0008-linear-full-adapter.md ) | Full Linear agent activity surface (thought/response/action/elicitation/error) plus session updates (plans, external URLs) | Accepted |
39- | [ 0009] ( adr/0009-message-history.md ) | Message history stays application-owned; optional storage-free ` HistoryReader ` | Accepted |
40- | [ 0010] ( adr/0010-observability.md ) | Optional ` Observer ` seam; no OpenTelemetry in core | Accepted |
41- | [ 0011] ( adr/0011-resumable-streaming.md ) | Resumable streaming deferred from core, not foreclosed | Proposed |
42- | [ 0012] ( adr/0012-concurrency-strategy.md ) | Concurrency strategy expansion (` drop ` /` queue ` /` debounce ` /` concurrent ` /` burst ` + lock scope implemented; force/steerability names reserved) | Accepted |
43- | [ 0013] ( adr/0013-linear-generic-comments.md ) | Linear generic issue/comment participation | Accepted |
44- | [ 0014] ( adr/0014-nats-state-adapter.md ) | NATS JetStream state adapter | Accepted |
45- | [ 0015] ( adr/0015-runtime-coordination.md ) | Deferred-dispatch admission bound; cross-instance coalescing rejected for now | Accepted |
3+ This page explains why Chat SDK Go is shaped the way it is: the model in
4+ brief, the design goals, how it maps to
5+ [ Vercel Chat SDK] ( #vercel-chat-sdk-alignment ) , and what it leaves out on
6+ purpose ([ non-goals] ( #non-goals ) and [ intentional gaps] ( #intentional-gaps ) ).
7+ The full record is in [ ` CONTEXT.md ` ] ( ../CONTEXT.md ) and the
8+ [ ADRs] ( #where-the-design-is-recorded ) .
469
4710## The Short Version
4811
49- For readers who want the model in five paragraphs:
50-
5112** The runtime coordinates conversations; it does not own your product.**
5213` chat.Chat ` verifies webhooks through adapters, normalizes platform payloads
5314into events, dedupes them, serializes work per thread with token-owned lock
@@ -92,8 +53,8 @@ diverges and documents the divergence.
9253
9354Chat SDK Go follows Vercel Chat SDK's conversation semantics where they fit
9455Go, built outward from a production-shaped Slack slice. It is
95- not a TypeScript API port and does not promise full feature parity. For
96- readers who know Vercel Chat SDK, this is the concept-by-concept status map :
56+ not a TypeScript API port and does not promise full feature parity. If you
57+ know Vercel Chat SDK, this table maps each concept to its status here :
9758
9859| Vercel Chat SDK concept | Chat SDK Go status |
9960| --- | --- |
@@ -127,9 +88,9 @@ history — are documented on the affected symbols' GoDoc and in the
12788
12889## Non-Goals
12990
130- These are deliberate design boundaries, each recorded in an ADR. Most are
131- permanent ownership boundaries; streaming is the one explicitly * deferred *
132- boundary — out of the core runtime today, not foreclosed forever .
91+ These are deliberate boundaries, each recorded in an ADR. Most are
92+ permanent: they mark what belongs to your application. Streaming is the
93+ exception; it is * deferred * , out of the core today but not ruled out .
13394
13495- ** Streaming token transport in the core runtime** —
13596 [ ADR 0011] ( adr/0011-resumable-streaming.md ) defers token streaming and
@@ -159,29 +120,25 @@ boundary — out of the core runtime today, not foreclosed forever.
159120
160121## Intentional Gaps
161122
162- These are not bugs; they are things the current scope deliberately does not
163- include:
123+ These are smaller things the current scope leaves out on purpose. They are
124+ not bugs.
125+
126+ API shape:
164127
165128- no TypeScript API compatibility
166129- no full Vercel Chat SDK feature parity
167130- no multiple handlers per routing hook
168131- no lazy runtime initialization
169- - no Linear personal API key mode, and no single-install static access token
170- (pre-exchanged access tokens are supported through the multi-tenant
171- ` InstallStore ` )
172- - no Linear streaming, reactions, or Markdown conversion
173- - no built-in OAuth web flow: authorize/callback/token-exchange routes and
174- install storage are application-owned
175- ([ ADR 0006] ( adr/0006-multi-tenant-install.md ) )
176- - no live Slack end-to-end test in CI
177132- no dedicated ` OnDirectMessage ` hook
178133- no public proactive ` OpenDM ` , except adapter behavior needed for explicit
179134 ephemeral fallback
180135- no pattern handlers
181136- no middleware
182- - no history persistence APIs: ` HistoryReader ` is a storage-free live
183- read-through, implemented by the Slack and Linear adapters
184- - no thread application state APIs
137+
138+ Messages and content:
139+
140+ - no edit, delete, reaction, or other outbound mutation APIs beyond what a
141+ native interaction response needs
185142- no JSX cards, files, or typed Block Kit / Adaptive Card payload builders
186143 (native Block Kit content ships as an opaque payload via
187144 ` NativeContentPoster ` )
@@ -190,10 +147,58 @@ include:
190147- no synchronous modal ` view_submission ` response (modal open via
191148 ` views.open ` ships; the synchronous ` response_action ` is incompatible with
192149 ack-then-work and is deferred)
193- - no edit, delete, reaction, or other outbound mutation APIs beyond what a
194- native interaction response needs
150+
151+ State and history:
152+
153+ - no history persistence APIs: ` HistoryReader ` is a storage-free live
154+ read-through, implemented by the Slack and Linear adapters
155+ - no thread application state APIs
156+
157+ Linear:
158+
159+ - no Linear personal API key mode, and no single-install static access token
160+ (pre-exchanged access tokens are supported through the multi-tenant
161+ ` InstallStore ` )
162+ - no Linear streaming, reactions, or Markdown conversion
163+
164+ Operations:
165+
166+ - no built-in OAuth web flow: authorize/callback/token-exchange routes and
167+ install storage are application-owned
168+ ([ ADR 0006] ( adr/0006-multi-tenant-install.md ) )
169+ - no built-in HTTP server or router integrations
195170- no bundled metrics framework, exporters, or scrape endpoint (an optional
196171 no-op ` Observer ` seam is provided; OpenTelemetry stays out of the core
197172 import graph)
198- - no built-in HTTP server or router integrations
173+ - no live Slack end-to-end test in CI
199174- no adapter marketplace/package conventions
175+
176+ ## Where The Design Is Recorded
177+
178+ - [ ` CONTEXT.md ` ] ( ../CONTEXT.md ) is the project's vocabulary and architecture
179+ document. Read it top to bottom to understand the system. Its ` Language `
180+ section defines every domain term (with the synonyms to avoid), grouped by
181+ area. Its ` Relationships ` section is the closest thing to a formal
182+ specification of the runtime's invariants. Its ` Flagged ambiguities `
183+ section explains where and why the design diverges from Vercel Chat SDK.
184+ - [ ` docs/adr/ ` ] ( adr/ ) holds the Architecture Decision Records. Every
185+ significant decision has one, including decisions * not* to build
186+ something:
187+
188+ | ADR | Decision | Status |
189+ | --- | --- | --- |
190+ | [ 0001] ( adr/0001-linear-app-actor-slice.md ) | Linear app-actor slice before a full Linear adapter | Accepted |
191+ | [ 0002] ( adr/0002-async-dispatch.md ) | Deferred runtime dispatch (ack-then-work) | Accepted |
192+ | [ 0003] ( adr/0003-slash-commands.md ) | Command Events and slash command routing | Accepted |
193+ | [ 0004] ( adr/0004-interactive-components.md ) | Interaction Events and native content instead of a card DSL | Accepted |
194+ | [ 0005] ( adr/0005-rate-limit-handling.md ) | Rate-limit retry lives in adapters, with typed ` RateLimited ` errors | Accepted |
195+ | [ 0006] ( adr/0006-multi-tenant-install.md ) | Multi-tenant installs via app-implemented ` InstallStore ` ; OAuth flows stay app-owned | Accepted |
196+ | [ 0007] ( adr/0007-teams-adapter.md ) | Microsoft Teams adapter approach (Bot Framework, direct HTTP) | Proposed — gated on a spike |
197+ | [ 0008] ( adr/0008-linear-full-adapter.md ) | Full Linear agent activity surface (thought/response/action/elicitation/error) plus session updates (plans, external URLs) | Accepted |
198+ | [ 0009] ( adr/0009-message-history.md ) | Message history stays application-owned; optional storage-free ` HistoryReader ` | Accepted |
199+ | [ 0010] ( adr/0010-observability.md ) | Optional ` Observer ` seam; no OpenTelemetry in core | Accepted |
200+ | [ 0011] ( adr/0011-resumable-streaming.md ) | Resumable streaming deferred from core, not foreclosed | Proposed |
201+ | [ 0012] ( adr/0012-concurrency-strategy.md ) | Concurrency strategy expansion (` drop ` /` queue ` /` debounce ` /` concurrent ` /` burst ` + lock scope implemented; force/steerability names reserved) | Accepted |
202+ | [ 0013] ( adr/0013-linear-generic-comments.md ) | Linear generic issue/comment participation | Accepted |
203+ | [ 0014] ( adr/0014-nats-state-adapter.md ) | NATS JetStream state adapter | Accepted |
204+ | [ 0015] ( adr/0015-runtime-coordination.md ) | Deferred-dispatch admission bound; cross-instance coalescing rejected for now | Accepted |
0 commit comments