Skip to content

Commit 82aebe4

Browse files
committed
document x-peek-settled header
1 parent 5ca423a commit 82aebe4

2 files changed

Lines changed: 28 additions & 8 deletions

File tree

docs/ai-chat/client-protocol.mdx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,19 +258,34 @@ Last-Event-ID: 42
258258
259259
`SSEStreamSubscription` tracks this automatically via its `lastEventId` option.
260260
261-
### `X-Session-Settled` — fast close on idle reconnects
261+
### `X-Peek-Settled` / `X-Session-Settled` — opt-in fast close on idle reconnects
262262
263-
When you reconnect to `.out` and the last record on the session is a `trigger:turn-complete` marker (the agent has finished a turn and is either idle-waiting or exited), the server responds with:
263+
On **reconnect-on-reload** paths (resuming a chat where nothing may be streaming), send `X-Peek-Settled: 1` as a request header when opening the SSE. When present, the server peeks the tail record of `.out`; if it's `trigger:turn-complete` (agent finished a turn and is idle-waiting or exited), the SSE:
264264
265-
- `X-Session-Settled: true` response header
266-
- A fast SSE close (milliseconds instead of the usual 60s long-poll)
265+
- Uses `wait=0` internally — drains any residual records and closes in ~1s instead of long-polling for 60s.
266+
- Sets the `X-Session-Settled: true` response header so the client can tell the close is terminal rather than a mid-stream drop.
267267
268-
This lets the client distinguish a close that means "nothing is streaming right now" from a normal mid-stream disconnect. Your transport can use this to settle into a "ready" state on page reload without maintaining its own `isStreaming` flag.
268+
**Do not send `X-Peek-Settled` on the active-send response-stream path.** The peek would race the newly-triggered turn's first chunk — if the agent hasn't written the new turn's first record yet, the peek sees the prior turn's `trigger:turn-complete` and closes the SSE before the response lands on S2. The built-in `TriggerChatTransport.reconnectToStream` sets the header; `sendMessages → subscribeToStream` does not.
269269
270270
```ts
271-
const response = await fetch(sseUrl, { headers });
271+
// Reconnect path (page reload)
272+
const response = await fetch(sseUrl, {
273+
headers: {
274+
Authorization: `Bearer ${publicAccessToken}`,
275+
"X-Peek-Settled": "1",
276+
"Last-Event-ID": lastEventId,
277+
},
278+
});
272279
const settled = response.headers.get("X-Session-Settled") === "true";
273280
// ...subscribe as normal; if settled and nothing arrives, you're done.
281+
282+
// Active send path — no X-Peek-Settled, keep long-poll semantics
283+
const liveResponse = await fetch(sseUrl, {
284+
headers: {
285+
Authorization: `Bearer ${publicAccessToken}`,
286+
"Last-Event-ID": lastEventId,
287+
},
288+
});
274289
```
275290
276291
## Step 4: Send messages, stops, and actions

docs/sessions/reference.mdx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,14 @@ For custom transports or direct HTTP use. See [AI Chat — Client Protocol](/ai-
210210
| `POST` | `/realtime/v1/sessions/:session/:io/append` | Append a record. `:io` is `"in"` for clients or `"out"` for direct server writes. |
211211
| `PUT` | `/realtime/v1/sessions/:session/:io` | Initialize an S2 direct-write channel. Returns S2 credentials in response headers. |
212212

213-
### `X-Session-Settled` response header
213+
### `X-Peek-Settled` request header (opt-in) / `X-Session-Settled` response header
214214

215-
Set on `GET /realtime/v1/sessions/:session/out` when the tail record is a terminal chunk (for chat agents: `trigger:turn-complete`). The server uses a short-wait drain instead of long-polling, so the SSE closes in milliseconds rather than up to 60 seconds. Clients can use this to tell a "nothing is streaming right now" close apart from a normal long-poll close.
215+
On `GET /realtime/v1/sessions/:session/out`, the client can send `X-Peek-Settled: 1` to ask the server to peek the tail record before proxying. If the last chunk on `.out` is a terminal marker (for chat agents: `trigger:turn-complete`), the server:
216+
217+
- Uses `wait=0` on the downstream read — drains any residual records and closes in ~1s instead of long-polling for 60s.
218+
- Sets `X-Session-Settled: true` on the response so the client can tell the close is terminal rather than a normal long-poll cycle.
219+
220+
Without `X-Peek-Settled`, the SSE always long-polls (unconditional `wait` from the caller). Clients should only opt in on **reconnect-on-reload** paths — sending the header while a turn is about to be triggered races the new turn's first chunk and would close the SSE before records land.
216221

217222
## Related
218223

0 commit comments

Comments
 (0)