Skip to content

Commit 607f8c5

Browse files
committed
docs: Sessions primitive + chat.agent on Sessions
Net-new Sessions section (4 pages under docs/sessions/) plus updates to 10 ai-chat pages and cross-reference callouts on two realtime backend pages — covers the chat.agent migration to the Session primitive and the X-Session-Settled fast-close work. Phase 1 — Sessions primitive (net-new) docs/sessions/overview.mdx — what a Session is, identity (sessionId + externalId, idempotent create on externalId), the .in / .out asymmetry, durability across runs, when to use Sessions vs run-scoped streams, relationship to chat.agent. docs/sessions/quick-start.mdx — four-step walkthrough (create → open from a task → subscribe from a client → close), plus a brief .in example. docs/sessions/channels.mdx — deep dive. .out producer methods (append / pipe / writer) and consumer method (read). .in consumer methods (on / once / peek / wait / waitWithIdleTimeout) and producer method (send). Suspend-while-idle via session-stream waitpoints. Uniform serialization. Buffering and attachment semantics. docs/sessions/reference.mdx — full API reference tables. `sessions.*` methods with signatures. CreateSessionRequestBody / SessionItem / UpdateSessionRequestBody / CloseSessionRequestBody / ListSessionsOptions shapes. SessionHandle / SessionOutputChannel / SessionInputChannel method tables. Option types (WriterStreamOptions, SessionSubscribeOptions, InputStreamOnceOptions / InputStreamWaitOptions / InputStreamWaitWithIdleTimeoutOptions). Token scopes. Wire endpoints including X-Session-Settled. docs/docs.json — added Sessions subgroup under the AI dropdown, placed right after Agents. Phase 2 — chat.agent updates docs/ai-chat/client-protocol.mdx — full rewrite. Old run-scoped endpoints (`/realtime/v1/streams/{runId}/chat`, `/realtime/v1/streams/{runId}/input/chat-messages`) replaced with session endpoints (`POST /api/v1/sessions`, `POST /realtime/v1/sessions/{sessionId}/in/append`, `GET /realtime/v1/sessions/{sessionId}/out`). Documents ChatInputChunk tagged union, Last-Event-ID resume, X-Session-Settled header. Keeps sequence diagrams, upgrade-required flow, tool approvals, actions, pending / steering messages, and continuations — all re-framed around sessions. docs/ai-chat/frontend.mdx — new "What the transport persists per chat" table under Session management: sessionId durable, publicAccessToken refreshed, lastEventId for resume, runId optional, isStreaming optional (server decides via X-Session-Settled now). Short paragraph under Restoring on page load explaining cross-run resume. docs/ai-chat/server-chat.mdx — stateless handler example rewritten around sessionId as the durable key (runId + lastEventId are live-run hints). Info callout on cross-run durability. New inbox example via sessions.list({type: "chat.agent"}). Updated session option row in the AgentChat options table to reflect the new ChatSession shape. docs/ai-chat/backend.mdx — Info callout at the top of chat.agent() section: every conversation is a Session, externalId = chatId, type = "chat.agent". Rarely need to touch directly, but `payload.sessionId` + `sessions.open()` is available. docs/ai-chat/reference.mdx — ChatTaskRunPayload gained sessionId row. TriggerChatTransport options updated for ChatSession shape. RenewRunAccessTokenParams documented with sessionId; renew callback example mints both run + session scopes. New ChatSession type section. New ChatInputChunk type section. Session scopes table with links to /sessions/reference. docs/ai-chat/overview.mdx — recast "How multi-turn works": one conversation, many runs (sessionId is durable). New "Resume and inbox" section covering cross-run resume on page load and sessions.list for inbox views. Link to /sessions/overview in Related. docs/ai-chat/quick-start.mdx — Sessions link added to Next steps. docs/ai-chat/changelog.mdx — new dated entry covering the session migration: externalId = chatId, public surface unchanged, cross-run resume is free, inbox via sessions.list, X-Session-Settled fast-close improvement, migration notes for custom-transport authors. docs/ai-chat/testing.mdx — note that mockChatAgent drives the agent's backing Session channels under the hood (API unchanged). "close" wording updated from "input stream" to ".in channel". docs/ai-chat/patterns/version-upgrades.mdx — clarified that chat.requestUpgrade() re-triggers on the same session; only runId + publicAccessToken refresh. Subsequent-messages terminology updated from "input stream" to "session's .in channel" for consistency. Phase 3 — Cross-references docs/realtime/backend/streams.mdx — Tip callout pointing to Sessions for durable long-lived channels. Run-scoped streams explicitly not deprecated. docs/realtime/backend/input-streams.mdx — same callout, framed around runId vs sessionId addressing. All 16 affected pages verified serving 200 on the local Mintlify dev server. Plan lives at .claude/docs-plans/sessions-chat-agent.md for anyone picking up the work later.
1 parent ccd9216 commit 607f8c5

18 files changed

Lines changed: 1319 additions & 206 deletions
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Docs plan — Sessions primitive + chat.agent migration
2+
3+
Plan for updating Mintlify docs to cover:
4+
5+
1. **Sessions** — net-new public primitive (`sessions.create/open/list/close`, `SessionHandle`, `.in`/`.out`) that doesn't exist in docs yet.
6+
2. **chat.agent on Sessions** — 14 ai-chat pages reference the old run-scoped wire protocol. Public `chat.agent()` surface is unchanged, but the underlying transport, persistence shape, and wire endpoints all moved.
7+
3. **Session-settled signal** — recent improvement (`X-Session-Settled` response header, `wait=0` drain on settled reconnects). Needs mention on frontend/server-chat pages.
8+
9+
Architecture reference (what the system actually does, for doc writers):
10+
`.claude/architecture/chat-agent-sessions.md`.
11+
12+
## Relationship to other doc plans
13+
14+
Coordinate with the hydration/history/actions plan saved in
15+
`project_docs_update_plan.md` (memory). Sessions should land **first**
16+
it's the foundational primitive the other features reference.
17+
18+
---
19+
20+
## Phase 1 — Sessions primitive docs (net-new)
21+
22+
New top-level section `docs/sessions/`, added as a dropdown group in
23+
`docs.json`. Should ship as its own PR and merge before Phase 2 so
24+
chat.agent docs can link into it.
25+
26+
| File | Covers |
27+
|---|---|
28+
| `sessions/overview.mdx` | What a Session is. Identity (`sessionId` + `externalId`, `session_*` friendly format, externalId idempotency on create). `.in` / `.out` channels as a durable typed I/O pair. Durability across runs. When to use Sessions vs. run-scoped streams. That `chat.agent` is built on Sessions. |
29+
| `sessions/quick-start.mdx` | Minimal end-to-end: `sessions.create``sessions.open``.out.append` + `.in.on``sessions.close`. Model on `ai-chat/quick-start.mdx` shape. |
30+
| `sessions/channels.mdx` | Deep dive. `.out` producer API (`append`, `pipe`, `writer({execute})` matching `streams.define`) and external consumer API (`read`). `.in` consumer API (`on`, `once`, `peek`, `wait`, `waitWithIdleTimeout` matching `streams.input`) and external producer API (`send`). Suspend-while-idle via session-stream waitpoints. Uniform serialization on `.out` (subscribers always get parsed objects). |
31+
| `sessions/reference.mdx` | API reference. `sessions.create / retrieve / update / close / list / open`. `SessionHandle`, `SessionInputChannel`, `SessionOutputChannel`. Token scopes: `read:sessions`, `write:sessions`, `admin:sessions`, super-scopes. |
32+
| `sessions/patterns.mdx` *(optional — can defer)* | Cross-run resume. Inbox via `sessions.list({type, tags})`. Multi-agent shared channels (two agents coordinating on one session). Custom transports keyed on `externalId`. |
33+
34+
Navigation: add `Sessions` dropdown to `docs.json`, placed adjacent to
35+
`AI Chat` so readers see the relationship.
36+
37+
---
38+
39+
## Phase 2 — Update chat.agent docs
40+
41+
Ships after Phase 1 merges. One PR.
42+
43+
| File | Change |
44+
|---|---|
45+
| `ai-chat/client-protocol.mdx` | **Full rewrite.** Old run-scoped endpoints (`POST /api/v1/tasks/:id/trigger`, `GET /realtime/v1/streams/:runId/chat`, `POST /realtime/v1/streams/:runId/input/chat-messages`) are gone. New surface: `POST /api/v1/sessions` (create, idempotent on externalId), `POST /realtime/v1/sessions/:session/:io/append` (input chunks — note `io="in"` for chat), `GET /realtime/v1/sessions/:session/:io` (SSE subscribe, `io="out"`). Document `ChatInputChunk` tagged union (`{kind: "message", payload}` / `{kind: "stop", message?}`). Document `Last-Event-ID` resume. Document `X-Session-Settled: true` response header and when it fires (server peeks `.out` tail; if last record is `trigger:turn-complete`, SSE uses `wait=0` and closes fast with this header). |
46+
| `ai-chat/frontend.mdx` | Update `TriggerChatTransport`. Persistence shape grew: `{sessionId, publicAccessToken, lastEventId, runId?, isStreaming?}``sessionId` is the durable identity now, `runId` is a live-run hint. `isStreaming` is **optional** after the settled-signal work; callers that drop it get server-decided settled behavior with no 60s hang. `onSessionChange` now carries `sessionId`. Note: cross-run resume is free — same chat persists across page reloads, across day boundaries, across process exits. |
47+
| `ai-chat/server-chat.mdx` | Same persistence shape update for `AgentChat`. `ChatSession` type gained `sessionId`. Same cross-run resume story. |
48+
| `ai-chat/backend.mdx` | `ChatTaskWirePayload` / `ChatTaskPayload` / `ChatTaskRunPayload` grew optional `sessionId`. Agent code rarely needs to touch it — `chat.stream`, `chat.messages`, `chat.stopSignal` still work identically. Show `sessions.open(payload.sessionId)` as an escape hatch for advanced cases (e.g., writing to the session from a sub-agent or from outside the turn loop). |
49+
| `ai-chat/reference.mdx` | Add `ChatInputChunk<TMessage, TMetadata>` type. Update `ChatSession` shape. Document `TriggerChatTaskResult.sessionId`. Session scopes list. Link to `sessions/reference`. |
50+
| `ai-chat/overview.mdx` | Conceptual: chats now outlive individual runs. Inbox pattern via `sessions.list({type: "chat.agent"})`. Link to `/sessions/overview`. |
51+
| `ai-chat/quick-start.mdx` | Minimal edit. One sentence: sessions power the chat primitive; link out to `/sessions/overview` for the underlying model. |
52+
| `ai-chat/changelog.mdx` | New entry covering (a) the session migration, (b) the settled-signal improvement (optional `isStreaming`). |
53+
| `ai-chat/testing.mdx` | `mockChatAgent` now drives `.in` via `drivers.sessions.in.send(sessionId, {kind, payload})` instead of the old input-stream manager. `TestSessionStreamManager` + `TestSessionOutputChannel` replace the stream-based harness. Update any code examples. |
54+
| `ai-chat/patterns/version-upgrades.mdx` | `trigger:upgrade-required` flow now reuses `sessionId` across runs — a single line clarifying that only `runId` + PAT refresh, `sessionId` stays. |
55+
| `ai-chat/patterns/human-in-the-loop.mdx` | Audit for stale stream-ID references; likely only a small update if any. |
56+
57+
---
58+
59+
## Phase 3 — Cross-references in realtime docs
60+
61+
Tacked onto the Phase 2 PR. Trivial edits.
62+
63+
| File | Change |
64+
|---|---|
65+
| `realtime/backend/streams.mdx` | Callout: "For durable, long-lived channels that outlive a single run (e.g. chat agents), see [Sessions](/sessions/overview)." Run-scoped streams are not deprecated — they're still correct for ephemeral run I/O. |
66+
| `realtime/backend/input-streams.mdx` | Same callout. |
67+
68+
---
69+
70+
## Out of scope
71+
72+
- **Deprecation of run-scoped streams.** They remain the right primitive for ephemeral per-run I/O. Sessions is additive, not a replacement.
73+
- **Rewriting pattern pages that happen to work unchanged.** `code-sandbox`, `skills`, `sub-agents`, `branching-conversations`, `database-persistence`, `compaction`, `pending-messages`, `background-injection`, `error-handling`, `mcp` — only touch if there's a concrete stale reference. Audit quickly; don't rewrite prophylactically.
74+
- **Wire-protocol examples for non-chat session uses.** If `sessions/patterns.mdx` gets written, covers this lightly. Otherwise defer — Sessions is general-purpose but chat is the primary motivating use case for v1 docs.
75+
- **Migration guide for external callers of the old wire protocol.** The `chat-constants.ts` commit already documented the mapping in its commit message (`streams.writer(CHAT_STREAM_KEY)``sessions.open(sessionId).out.writer(...)`, etc.). If we hear from users building custom non-`TriggerChatTransport` clients, we can write a dedicated migration page then.
76+
77+
---
78+
79+
## Sizing
80+
81+
Rough effort estimates, in full dedicated doc passes:
82+
83+
- Phase 1 — ~1 pass. 4 net-new pages, `sessions/overview` and `sessions/channels` are the meaty ones; `sessions/patterns` is optional and can be Phase 1.5.
84+
- Phase 2 — ~1 pass. `client-protocol.mdx` is the single biggest rewrite (~half a pass); the other 10 edits are paragraph-level.
85+
- Phase 3 — rounds to zero; fold into Phase 2 PR.
86+
87+
Total: ~2 dedicated doc passes, ideally across two PRs.
88+
89+
---
90+
91+
## Sequencing decision
92+
93+
Phase 1 **before** Phase 2. Two reasons:
94+
95+
1. Phase 2 pages will link into `/sessions/*`; merging Phase 2 first creates broken links in published docs.
96+
2. Readers encountering `sessionId` in updated chat docs need somewhere to go to learn what a Session is. That page has to exist first.
97+
98+
Phase 1.5 (the optional `sessions/patterns.mdx` page) can ship either with Phase 1 or as a follow-up — it's not on the critical path for Phase 2.

docs/ai-chat/backend.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ The highest-level approach. Handles message accumulation, stop signals, turn lif
1212
To fix a **custom** `UIMessage` subtype or typed client data schema, use the [ChatBuilder](/ai-chat/types#chatbuilder) via `chat.withUIMessage<...>()` and/or `chat.withClientData({ schema })`. Builder-level hooks can also be chained before `.agent()`. See [Types](/ai-chat/types).
1313
</Tip>
1414

15+
<Info>
16+
Every `chat.agent` conversation is backed by a [Session](/sessions/overview)`externalId` is your `chatId`, `type` is `"chat.agent"`. The session outlives any single run, which is why chats can resume across days or deploys without losing identity. You rarely need to touch the session directly (`chat.stream`, `chat.messages`, `chat.stopSignal` wrap everything), but `payload.sessionId` is available if you want to reach in — e.g. `sessions.open(payload.sessionId)` to write from a sub-agent or from outside the turn loop.
17+
</Info>
18+
1519
### Simple: return a StreamTextResult
1620

1721
Return the `streamText` result from `run` and it's automatically piped to the frontend:

docs/ai-chat/changelog.mdx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,39 @@ sidebarTitle: "Changelog"
44
description: "Pre-release updates for AI chat agents."
55
---
66

7+
<Update label="April 24, 2026" description="chat.agent on Sessions" tags={["SDK", "Platform"]}>
8+
9+
## `chat.agent` now runs on Sessions
10+
11+
Every chat is backed by a [Session](/sessions/overview) — a new public, durable, bidirectional I/O primitive that outlives any single run. `externalId` = your chat ID, `type` = `"chat.agent"`. Under the hood:
12+
13+
- Output chunks stream on `session.out` (was a run-scoped `streams.writer("chat")`).
14+
- Client messages and stops land on `session.in` as a [`ChatInputChunk`](/ai-chat/reference#chatinputchunk) tagged union (was two run-scoped `streams.input` definitions).
15+
- Wire endpoints moved from `/realtime/v1/streams/{runId}/...` to `/realtime/v1/sessions/{sessionId}/...`. See the rewritten [Client Protocol](/ai-chat/client-protocol).
16+
17+
Public surface (`chat.agent()`, `TriggerChatTransport`, `AgentChat`, `chat.stream` / `chat.messages` / `chat.stopSignal`) is unchanged — existing apps keep working. What's new is:
18+
19+
- **Cross-run resume is free.** A chat you were in yesterday resumes against the same `sessionId` today, even if the original run long since exited. No more lost conversations when a run idle-times-out.
20+
- **Inbox views via `sessions.list({type: "chat.agent"})`.** Enumerate every chat in your environment, filter by tag or status.
21+
- **`TriggerChatTaskResult.sessionId`** + **`ChatTaskRunPayload.sessionId`** — you can reach into the raw session via `sessions.open(payload.sessionId)` for advanced cases (writing from a sub-agent, custom transport).
22+
- **Dashboard Agent tab** resolves via `sessionId` and stays in sync with the live stream across runs.
23+
24+
See the new [Sessions docs](/sessions/overview) for the underlying primitive.
25+
26+
## `X-Session-Settled` — fast reconnect on idle chats
27+
28+
When a client reconnects to `session.out` and the tail record is a `trigger:turn-complete` marker (agent finished a turn, idle-waiting or exited), the server sets `X-Session-Settled: true` and uses `wait=0` on the underlying S2 read. The SSE drains any remaining records then closes in ~1s instead of long-polling for 60s.
29+
30+
Practical impact: `TriggerChatTransport.reconnectToStream` no longer needs a client-side `isStreaming` flag. You can drop the field from your persisted `ChatSession` state entirely — the server decides. Existing callers that still persist `isStreaming` are unaffected; `reconnectToStream` keeps the fast-path short-circuit when it's `false`.
31+
32+
## Migration
33+
34+
Nothing to do for users of `chat.agent()` + `TriggerChatTransport` + `AgentChat`. Your existing code keeps working; you pick up the new durability guarantees for free.
35+
36+
If you built a custom transport against the old `/realtime/v1/streams/{runId}/...` endpoints, see the rewritten [Client Protocol](/ai-chat/client-protocol) for the new session-based wire format. The old constants (`CHAT_STREAM_KEY`, `CHAT_MESSAGES_STREAM_ID`, `CHAT_STOP_STREAM_ID`) are removed from `@trigger.dev/core/v3/chat-client` — migrate to `sessions.open(sessionId).out` / `.in`.
37+
38+
</Update>
39+
740
<Update label="April 19, 2026" description="0.0.0-chat-prerelease-20260419173457" tags={["SDK", "CLI"]}>
841

942
## Agent Skills (Phase 1)

0 commit comments

Comments
 (0)