Skip to main content
Conversation state lives on the server. You send one new user message per call and identify the thread with metadata.conversation_id; the agent resumes its full prior context — including files it wrote and what it learned — without you replaying any history.
Examples use DataGen Cloud (https://api.datagen.dev). Self-hosted installs swap in their own host, e.g. http://10.0.0.42:3001 — see Base URL.

Resuming

1

Start a conversation

Call /v1/messages with no conversation_id. Read the X-Conversation-Id response header — or supply your own id up front and skip this step entirely.
2

Send the next turn with that id

Bring your own id. An id that doesn’t exist yet is created with exactly the string you sent — it doesn’t have to be a UUID. Derive it from your ticket number, Slack thread, or user id and you never have to store a mapping table.
Don’t send the next turn the instant the stream ends. A turn’s stream closes a few seconds before the server finishes recording which session the conversation now points at. A message sent inside that window resumes a conversation with no session recorded yet, and the agent answers with no memory of the turn that just happened — no error, just amnesia.A person typing the next message never notices. An automated client does, every time. Before resuming a conversation you just ran a turn on, poll GET /conversations/{id} until claude_session_id is non-null:
Bound the wait and proceed anyway if it expires — a turn that produced no output legitimately has no session id.

How an id resolves

Durability

Transcripts are stored durably, so a conversation resumes days or weeks later. The agent’s sandbox is kept warm for a while after each turn and then reclaimed; resuming after that costs a slower first turn but loses no context.
If a turn ends without producing any output while resuming, the resume pointer is cleared so the next turn starts a clean session instead of silently returning nothing forever. Retrying a “silent” conversation is the right move.

Forking

Branch a conversation to explore an alternative without disturbing the original.
The child is owned by you and private by default. Its first turn answers from the parent’s context, then continues on its own branch — the parent is untouched.

Managing conversations

All routes are under /api/agents/{agent}/conversations and use the same authentication. You can see conversations that are yours, shared with the workspace, or channel-owned (Slack, email). List query parameters: channel (INTERACTIVE, NOTEBOOK, SLACK, EMAIL), channel_id, notebook_path, automation=<name>, since=<iso8601>, and limit (1–200, default 50).
title is derived from the first prompt when the conversation is created and never re-stamped, so it always names the original question.

Transcript

GET /conversations/{id}/messages returns the conversation metadata, an Anthropic-shaped messages[] array, and a raw events[] array for callers that want the underlying agent event stream.
Long conversations are compacted automatically by the agent runtime. A compaction appears as a user message flagged is_compact_summary: true — render it as a “context compacted” notice rather than a user turn. GET /conversations/{id}/last-compaction returns {compacted, summary} so a client can tell an empty turn apart from a compaction step.

Sharing and ownership

Conversations are private to their creator until shared. Sharing grants read access to the workspace — never write: a member who opens a shared conversation can read it and fork it, but sending a turn into it returns 403. Only the owner can toggle sharing or delete, with no admin override.