The four identifiers
| ID | Endpoint | Direction | What it identifies |
|---|---|---|---|
chat_id | Research Agent | request and response | A persistent conversation thread. Auto-created if absent on the first request; pass the same value on subsequent requests to continue the same thread. |
execution_id | Workflows | request and response | A specific workflow execution. Pass a previous execution_id to resume the conversation produced by that execution. |
from_checkpoint_id | Research Agent | request only | The point in an existing conversation to resume from. Lets you rewrite or branch a conversation by going back to an earlier state. |
checkpoint_id | Research Agent | response only | A cursor in the COMPLETE event marking the conversation state after this turn. Store it and pass as from_checkpoint_id on the next request to continue from this exact point. |
- A vanilla follow-up turn uses
chat_id(orexecution_id) alone to identify the conversation. - A branching turn additionally uses
from_checkpoint_idto specify where in the conversation to resume. - The
checkpoint_idyou store today is what becomes afrom_checkpoint_idtomorrow.
persistence_mode
The Research Agent request accepts persistence_mode with two values. Both
allow multi-turn follow-ups; they differ in how long the conversation
survives.
disabled(default) — creates an ephemeral conversation thread. Follow-up turns against the samechat_idwork for approximately one hour. After that, the underlying checkpoint is evicted and a resume attempt returns HTTP 404 with the detail"Cannot follow up: chat expired".enabled— creates a persistent conversation thread. Thechat_idandcheckpoint_idreturned inCOMPLETEcan be used to continue or branch the conversation indefinitely.
"persistence_mode mismatch") and HTTP 409 on Workflows.
Choosing a mode: leave the default disabled for one-off questions
and short sessions that wrap up within an hour. Set enabled on turn 1
when the conversation needs to survive longer — branching workflows,
research threads spanning a working session, anything you want a user to
resume the next day.
Workflows expose persistence_mode on the synchronous execute endpoint
with the same semantics (default disabled, immutable, mismatch returns
409). Asynchronous workflows always persist because the events blob is the
client’s only way to read execution state after the SSE connection closes;
they do not expose persistence_mode.
The "INITIAL" sentinel
Passing from_checkpoint_id: "INITIAL" is a special instruction that truncates
the entire conversation and starts over with the new message. Use it when the
user explicitly says “let’s start over” or when you detect a context-poisoning
mistake (a typo in a name, a wrong company id, a stale assumption) that you want
to clear cleanly while keeping the same chat_id.
"INITIAL" deletes all prior interactions for that chat_id. There is no undo.
Worked example: multi-turn conversation
The pattern below persistschat_id and checkpoint_id between turns, letting the
user ask follow-up questions on top of the agent’s previous answers.
chat_id returned by each event identifies the conversation thread; the
checkpoint_id returned in COMPLETE is your cursor for the next turn. Persist
both server-side or in client storage if you need conversations to survive across
sessions.
Branching a conversation
To “rewind” a conversation — for example, when the user edits an earlier message or wants to explore a different follow-up question from a known good state — pass thecheckpoint_id from the turn you want to resume from, with the same
chat_id. Any interactions after that checkpoint are discarded, and the new
message takes their place.
ckpt_after_turn_1 no longer exist on the server.
Workflows: resuming by execution_id
Workflows do not expose checkpoints. Instead, each execution has an execution_id
that the streaming response carries on every event. Pass that id back in a later
request to continue the same conversation.
execution_id continues the conversation but does not
re-run the original template’s research plan from scratch; the agent treats the
new input (or follow-up message) as a continuation, with prior interactions in
context.
Common pitfalls
- Treating the default
disabledmode as suitable for long sessions. Ephemeral threads expire after about an hour; a follow-up that arrives later returns HTTP 404 with detail"Cannot follow up: chat expired". Setpersistence_mode: "enabled"on turn 1 if the conversation needs to survive longer than that. - Switching modes mid-conversation. The mode is immutable once a conversation is created. Resume requests must pass the same value used on turn 1 or the server returns HTTP 400 (Research Agent) / 409 (Workflows).
- Storing
chat_idbut notcheckpoint_id. Achat_idalone is enough for the simple “continue the latest turn” case, but if you want stable replay or branching, you also need thecheckpoint_idreturned inCOMPLETE. - Mixing
chat_idbetween users. Thechat_idis a server-side conversation identifier; do not share it across users or sessions you want isolated. - Treating
checkpoint_idas introspectable. It is an opaque string; do not parse, compare, or derive meaning from its contents. - Calling
from_checkpoint_id: "INITIAL"accidentally. It deletes the entire thread. Guard this code path behind an explicit user action.
Next steps
Streaming responses
Reference for every message type, including how
checkpoint_id arrives in COMPLETE.Error handling
Handle 404s from invalid checkpoint IDs and other continuity failures.