Coming soon.
Overview
This page covers running an agent that is already saved in the Agent Registry. To create or configure an agent, see Agent. The Agent Harness ships with a Python and TypeScript SDK for interacting with agents and consuming the event stream. We also provide a React component for building a chat interface for an agent.How interaction works
Interaction is organized as a hierarchy: Session → Turn → Events, with threads running underneath.- Session — a long-running agent process. The session holds the agent configuration and persists across many Turns.
- Thread — an execution context inside the session. The main thread is the root agent, which interacts with the user and acts as a coordinator for other agents. It can spin up additional threads, each running a sub-agent. Threads are long-lived - they can live across Turns.
- Turn — a single user interaction with the session, and the request boundary. Turns within a session are chained, so each Turn builds on the history of the ones before it. Only one Turn can be running in a session at any point in time. A Turn runs until the agent finishes, or until it hits the iteration limit or timeout configured for the agent. A Turn can be cancelled while it is running.
- Events — a Turn streams events as the agent works. Each event identifies the thread it came from.
- Event Delta — some events are streamed as a base event followed by a series of deltas that you merge into it, rather than a single payload. The clearest example is model output: a base
model.messagefollowed bymodel.message.deltachunks - all sharing the base event’sid- that you merge into the base as they arrive.

Creating a Session
A Session is the conversation context for a saved agent. Create one by name withcreate_session().
Listing sessions for an agent
List the existing Sessions for a saved agent withlist_sessions(). It iterates newest-first, transparently paginating. Use it to resume an earlier conversation - each Session exposes its id (persist or reuse it to continue).
Interacting with a Session by creating a Turn
Create a Turn in the session withcreate_turn(), then call stream() to start the Turn and stream its events as they arrive. The first event is always turn.created (carrying the turn_id); the stream closes with turn.done.
Once the stream closes, the Turn is terminal. Call state() to read its final state.
To continue the conversation, create another Turn on the same session. Turns within a session are chained automatically, so each Turn sees the history of the ones before it.
Creating a new Turn in a session automatically cancels any other Turn that is still running in that session.
Listing Turns
List the Turns in a session withlist_turns(). Each Turn exposes its input, and state() returns the current state of the run.
list_turns() always returns Turns in descending order (newest-first).Handling Event Delta while streaming
Most events in a Turn are complete on their own - a single payload you can use directly. Some updates are streamed instead: the base event arrives first, followed by a series of Event Deltas - incremental fragments that you merge into the base. All deltas for one update share the base event’sid, while sequence_number increases across the base and all its deltas.
id, keep an id-keyed index of assembled events: store each non-delta event under its id, and merge each delta into the base with the same id. The id is unique per message, so deltas from concurrently streaming threads (the main agent and any sub-agents) always merge into the right base.
Event Deltas appear only while streaming. When you list events via the events API, the deltas are already merged into a single assembled event.
ModelMessageEvent followed by ModelMessageEventDelta deltas that carry incremental text and tool-call chunks. Merge the deltas into the base as they arrive - read the base’s growing content for a live typing effect.
Resume streaming
When you lose the originalcreate_turn() stream (for example, after a page reload), fetch the Turn again with get_turn() using its turn_id and check its state. If it is still running, reconnect to its live event stream with stream() and keep merging; if it has already finished, rebuild the index from its stored event log with list_events() instead.
When resuming a running Turn, pass after_sequence_number to continue after a known point (defaults to 0, replaying from the first event); the SDK also resumes transparently from the last delivered event on any mid-stream connection drop, and closes when the Turn reaches a terminal state. Either way, merge into the same id-keyed index of assembled events, so base events and their deltas keep merging seamlessly across the reconnect.
Handling Threads
A single Turn stream interleaves events from the root agent and any sub-agents that run in parallel. Every event carries athread_id:
"main"— the root agent.- A unique ID — a sub-agent thread.
thread.createdandthread.donemark sub-agent thread lifecycle; they are not emitted for the main thread. null— a turn-level event, not tied to any thread:turn.createdandturn.done(first and last on the stream),sandbox.created, andmcp.auth_required.
Non-streaming Turn
If you don’t need live events, skipstream() and call wait_for_completion() instead. It blocks until the Turn finishes.
Attaching images or files to a Turn
AUserMessage’s content can be a plain string or a list of content parts. Use content parts to send text alongside one or more file uploads (images, PDFs, and other documents). Each file is passed as a data URI of the form data:<mime>;base64,<payload>.
Whether an attached file is understood depends on the agent’s model. Send images only to a vision-capable model; document handling (for example, PDFs) likewise depends on model and agent configuration.
Non-image files such as PDFs require the sandbox to be enabled on the agent - the harness uses it to process the document.
Cancelling a Turn
To stop the currently running Turn, callcancel() on its session. Cancelling aborts any in-flight model request, waits for running MCP tool calls to finish, and force-stops any sandbox the Turn provisioned. Cancellation is idempotent. You can continue by creating a new Turn, which chains on the cancelled Turn’s history.
Listing Events
Fetch the full event log of a finished Turn withlist_events(). It yields the Turn’s events in order, auto-paginating. Pass order="asc" (default, oldest-first) or order="desc" to control the direction.
Unlike stream(), list_events() returns already-merged events: each model message arrives as a single assembled ModelMessageEvent, never as a base plus deltas. There is nothing to merge - you can use each event directly.
For example, a model message that stream() delivers as a base event followed by deltas:
list_events() as one fully-merged event:
list_events() is only available for Turns that have completed. A running Turn has no stored event log yet - use stream() for live delivery instead.Handling MCP Outbound Auth
When the agent needs to call a tool on an MCP server that requires a separate outbound authentication, it emits anmcp.auth_required event and the Turn ends. The event lists each server that needs authentication along with an auth_url. Depending on how the server is configured, this may be an OAuth flow or an API-key entry - see MCP authentication scenarios for details. Send the user to that URL to complete authentication, then resume by creating a new Turn.
When the previous Turn ended with
mcp.auth_required, passing a UserMessage in the resuming Turn is not allowed.Handling tool approvals
When a tool call is configured to require human approval, the agent emits atool.approval_required event and the Turn ends. Each event carries a thread_id and the tool_calls awaiting a decision - a single Turn can emit more than one (for example, when parallel threads each call a gated tool), so collect all of them. Resume by creating a new Turn with one UserToolApproval per pending tool call - allow it, or deny it with an optional reason.
Each pending ToolCallRef carries the event_id of the model.message that emitted the tool call. Keep the same id-keyed event index you build while streaming, then look up events[event_id] to read the tool’s name and arguments - no separate bookkeeping required.
Answering agent’s questions
When the agent needs input it cannot safely assume, it can ask the user a structured question via the built-in client-sideask_user_question tool. Since the tool runs on your side, the agent emits a tool.response_required event and the Turn ends. The pending tool call’s arguments carry the question and its options. Collect the user’s answer and resume by creating a new Turn with one UserToolResponse per pending tool call.
Each pending ToolCallRef carries the event_id of the model.message that emitted the tool call. Keep the same id-keyed event index you build while streaming, then look up events[event_id] to read the tool’s name and arguments - no separate bookkeeping required.
Turn input
Each Turn’sinput is a list of one of these types. Resuming a Turn paused by mcp.auth_required needs no input - omit input or pass [].
User messages (
UserMessage) cannot be mixed with tool approvals or client-side tool responses in the same input list. UserToolApproval and UserToolResponse may be mixed together.UserMessage
Start a new conversation or send the next user message.content is either a plain string or a list of content parts, letting you attach files alongside text.
| Field | Type | Required | Description |
|---|---|---|---|
type | "user.message" | Yes | |
content | string | UserContent[] | Yes | The message text, or a list of content parts (text and file uploads). |
UserContent
A content part is one of: Text| Field | Type | Required | Description |
|---|---|---|---|
type | "text" | Yes | |
text | string | Yes | The message text. |
| Field | Type | Required | Description |
|---|---|---|---|
type | "file_upload" | Yes | |
file.filename | string | Yes | Name of the uploaded file. |
file.file_data | string | Yes | Data URI: data:<mime>;base64,<payload>. |
UserToolApproval
Sent to resume a Turn paused bytool.approval_required. One item per pending tool call.
| Field | Type | Required | Description |
|---|---|---|---|
type | "user.tool_approval" | Yes | |
thread_id | string | Yes | thread_id from the tool.approval_required event. |
tool_call_id | string | Yes | ID of the tool call being approved or denied. |
approval | ApprovalAllow | ApprovalDeny | Yes | Use {"status": "allow"} to permit the call, or {"status": "deny", "reason": "..."} to block it. reason is optional. |
UserToolResponse
Sent to resume a Turn paused bytool.response_required. One item per pending tool call.
| Field | Type | Required | Description |
|---|---|---|---|
type | "user.tool_response" | Yes | |
thread_id | string | Yes | thread_id from the tool.response_required event. |
tool_call_id | string | Yes | ID of the tool call whose result is being supplied. |
content | string | Yes | The result to return to the agent. |
Turn Events
create_turn() streams Server-Sent Events (SSE). Each event is a JSON object with a type field.
- The stream always opens with
turn.createdand closes withturn.done. - All events carry a
thread_id. Thread-scoped events use"main"(root agent) or a unique sub-agent ID; turn-level events useNone. thread.createdandthread.donetrack sub-agent threads only - they are not emitted for the main thread, which is created automatically on the first Turn and lives for the session’s lifetime.- All events carry an
id. It identifies the logical event and is present in bothstream()andlist_events(). - Events delivered via
stream()also carry asequence_number, monotonically increasing within a Turn. - All events carry a
created_atISO-8601 timestamp marking when the event was emitted. turn.createdandturn.doneare stream-only; they appear on the stream (stream()) but are not returned bylist_events().
- turn.*
- model.*
- tool.*
- thread.*
- mcp.*
- sandbox.*
type | Description |
|---|---|
turn.created | First event on the stream. Carries turn_id. |
turn.done | Last event on every stream. Carries the final state. |
TurnCreatedEvent
First event on every Turn stream, carrying the Turn’sturn_id and metadata. Stream-only.
| Field | Type | Required | Description |
|---|---|---|---|
type | "turn.created" | Yes | |
id | string | Yes | Unique event identifier. |
thread_id | null | Yes | Always null — turn-level event, not tied to a thread. |
turn_id | string | Yes | Unique ID for this Turn. |
previous_turn_id | string | None | No | Turn ID this Turn chains from, or None for the first Turn in a session. |
created_by | string | Yes | Subject (user / service account) that created this Turn. |
created_at | string | Yes | ISO-8601 timestamp when the Turn was created. |
ModelMessageEventDelta
The most frequent SSE event. Carries an incremental LLM delta for one message - assistant text and/or tool call chunks. Every delta shares theid of the base ModelMessageEvent it belongs to; merge each delta into that base event in your id-keyed event index. A delta with a non-null finish_reason signals the message is complete.
Use merge_event_delta from truefoundry_gateway_sdk to fold a delta into its base event in place. Alternatively, ModelMessageBuilder accumulates deltas on their own (without a base event) into a complete ModelMessage: add() returns the accumulated message so far, and build_and_reset() returns the complete message once finish_reason is set.
| Field | Type | Required | Description |
|---|---|---|---|
type | "model.message.delta" | Yes | |
id | string | Yes | Shared by all deltas of one message; equal to the assembled ModelMessageEvent id. Use sequence_number to distinguish individual deltas. |
thread_id | string | Yes | Thread this message belongs to. "main" for the root agent; a unique ID for sub-agents. |
content | string | No | Incremental text content for this delta. |
reasoning_content | string | No | Incremental reasoning/thinking text for this delta; concatenate across deltas. |
tool_calls | ToolCallDelta[] | No | Tool call chunks to accumulate by index; fully assembled when finish_reason is set. |
finish_reason | string | No | Set on the final delta. Signals the accumulated message is complete. |
ToolCallDelta is shaped like an OpenAI streaming tool-call chunk. id, type, and tool_info appear only on the first chunk for a given index; function.arguments is a partial JSON string concatenated across chunks.
| Field | Type | Required | Description |
|---|---|---|---|
index | int | Yes | Position in the tool_calls array; used to merge chunks. |
id | string | No | Tool call ID. First chunk only. |
type | "function" | No | First chunk only. |
function | ToolCallFunctionDelta | Yes | The function name and partial arguments for this chunk. |
tool_info | ToolCallInfo | No | Tool metadata. First chunk only. |
ToolCallFunctionDelta:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Tool name. Present only in the first chunk for this index. |
arguments | string | No | Partial JSON string; concatenate across chunks. |
ToolCallInfo carries metadata about the tool, discriminated on type. Read the tool name from name.
For MCP-backed tools (type: "mcp"):
| Field | Type | Required | Description |
|---|---|---|---|
type | "mcp" | Yes | |
mcp_server_id | string | Yes | ID of the MCP server backing this tool. |
mcp_server_name | string | Yes | Name of the MCP server backing this tool. |
name | string | Yes | The tool’s original name on the MCP server. |
is_deferred | bool | No | Whether the tool call is deferred. |
type: "truefoundry-system"), for example ask_user_question:
| Field | Type | Required | Description |
|---|---|---|---|
type | "truefoundry-system" | Yes | |
name | string | Yes | The system tool’s name. |
ModelMessage
The complete, assembled form of a model message: fully concatenatedcontent and fully reconstructed tool_calls, with finish_reason set. This is the shape you get after merging all of a message’s deltas into its base event, or from ModelMessageBuilder.build_and_reset().
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Shared across all deltas of one message; equal to the assembled ModelMessageEvent id. |
thread_id | string | Yes | Thread this message belongs to. "main" for the root agent; a unique ID for sub-agents. |
content | string | No | The complete assistant text. |
reasoning_content | string | No | The complete reasoning/thinking text. |
tool_calls | ToolCall[] | No | Fully assembled tool calls. |
finish_reason | string | Yes | Why the message ended (for example, "stop" or "tool_calls"). |
ModelMessageEvent
The event form ofModelMessage (adds type and id). Returned by list_events(); on the stream, the assistant output arrives as ModelMessageEventDelta deltas instead.
| Field | Type | Required | Description |
|---|---|---|---|
type | "model.message" | Yes | |
id | string | Yes | Unique event identifier. Equal to the id carried by this message’s model.message.delta events. |
thread_id | string | Yes | Thread this message belongs to. "main" for the root agent; a unique ID for sub-agents. |
content | string | No | The complete assistant text. |
reasoning_content | string | No | The complete reasoning/thinking text. |
tool_calls | ToolCall[] | No | Fully assembled tool calls. |
finish_reason | string | Yes | Why the message ended (for example, "stop" or "tool_calls"). |
ToolCall is shaped like OpenAI’s ChatCompletionMessageToolCall. Read the tool name from tool_info.name.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Tool call ID. |
type | "function" | Yes | Always "function". |
function | ToolCallFunction | Yes | The tool name and complete arguments. |
tool_info | ToolCallInfo | No | Tool metadata (same shape as above). |
ToolCallFunction:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Tool name. |
arguments | string | Yes | Complete JSON string of the tool’s input arguments. |
ToolResponseEvent
A complete server-side tool result returned to the LLM. Not a streaming delta - one event carries the full result.| Field | Type | Required | Description |
|---|---|---|---|
type | "tool.response" | Yes | |
thread_id | string | Yes | Thread this result belongs to. |
tool_call_id | string | Yes | Links this result back to the originating tool call. |
content | string | Yes | The tool result. |
ThreadCreatedEvent
Emitted when a sub-agent thread starts.Not emitted for the main thread. The main thread (
thread_id: "main") is the root agent; it is created automatically on the session’s first Turn and is never the subject of a thread.created or thread.done event. thread.created/thread.done track only sub-agent threads.| Field | Type | Required | Description |
|---|---|---|---|
type | "thread.created" | Yes | |
thread_id | string | Yes | Unique ID for the sub-agent thread. |
title | string | No | Human-readable label for the sub-agent thread. |
parent | AgentParent | Yes | Parent thread and tool call that spawned this sub-agent. |
agent_info | AgentInfo | Yes | Type, name, and input of the thread’s agent. |
AgentInfo:
| Field | Type | Required | Description |
|---|---|---|---|
type | "dynamic" | Yes | How the sub-agent was defined. |
name | string | Yes | The sub-agent’s name. |
input | string | No | The input the parent thread handed to the sub-agent. |
ThreadDoneEvent
Emitted when a sub-agent thread reaches a terminal state. Does not terminate the overall Turn stream.Not emitted for the main thread. The main thread is never “done” - it lives across Turns for the lifetime of the session. The overall Turn’s completion is signalled by
turn.done, and the session ends only when it is cancelled.| Field | Type | Required | Description |
|---|---|---|---|
type | "thread.done" | Yes | |
thread_id | string | Yes | Unique ID for the sub-agent thread. |
title | string | No | Human-readable label for the sub-agent thread. |
status | "done" | "error" | Yes | done - completed normally, output is present. error - failed, message is present. |
output | ModelMessage | No | Final accumulated message. Present when status is "done". |
parent | AgentParent | Yes | Parent thread and tool call that spawned this sub-agent. |
message | string | No | Present when status is "error". |
McpInitializedEvent
Emitted when one or more MCP server sessions are initialized for a thread.| Field | Type | Required | Description |
|---|---|---|---|
type | "mcp.initialize" | Yes | |
thread_id | string | Yes | |
content | McpInitializationInfo[] | Yes | List of initialized MCP servers, each with mcp_server_name and session_id. |
SandboxCreatedEvent
Emitted once when a sandbox is provisioned for the Turn. The sandbox is reused across Turns within the session.| Field | Type | Required | Description |
|---|---|---|---|
type | "sandbox.created" | Yes | |
thread_id | null | Yes | Always null — turn-level event, not tied to a thread. |
sandbox_id | string | Yes | Unique identifier for the provisioned sandbox. |
McpAuthRequiredEvent
Emitted when one or more MCP servers require OAuth authorization before the agent can proceed. The stream ends after this event. Resume by creating a new Turn on the same session and starting it (for example withstream()) after the user completes the OAuth flow - no input is required (omit input or pass []).
| Field | Type | Required | Description |
|---|---|---|---|
type | "mcp.auth_required" | Yes | |
thread_id | null | Yes | Always null — turn-level event. Blocked threads are listed per server in servers[].thread_ids. |
servers | McpServerAuthInfo[] | Yes | List of servers needing authorization, each with mcp_server_name, auth_url, and thread_ids. |
ToolApprovalRequiredEvent
Emitted when one or more tool calls require explicit human approval before they can run. The stream ends after this event. Resume by creating a new Turn withUserToolApproval items - one per pending tool_call_id - and starting it (for example with stream()).
| Field | Type | Required | Description |
|---|---|---|---|
type | "tool.approval_required" | Yes | |
thread_id | string | Yes | |
tool_calls | ToolCallRef[] | Yes | The tool calls awaiting approval, each with a tool_call_id (id) and the event_id of the model.message that emitted it - look it up in your event index for the tool name and arguments. |
ToolResponseRequiredEvent
Emitted when the agent has called a client-side tool and is waiting for the result. The stream ends after this event. Resume by creating a new Turn withUserToolResponse items - one per pending tool_call_id - and starting it (for example with stream()).
| Field | Type | Required | Description |
|---|---|---|---|
type | "tool.response_required" | Yes | |
thread_id | string | Yes | |
tool_calls | ToolCallRef[] | Yes | The tool calls awaiting a client-supplied result, each with a tool_call_id (id) and the event_id of the model.message that emitted it - look it up in your event index for the tool name and arguments. |
TurnDoneEvent
Final event on every Turn stream. Stream-only. Itsstate is the terminal state object - the same value returned by wait_for_completion() - so callers don’t need a separate Turn fetch to know what happened.
| Field | Type | Required | Description |
|---|---|---|---|
type | "turn.done" | Yes | |
thread_id | null | Yes | Always null — turn-level event, not tied to a thread. |
state | TurnTerminalState | Yes | The Turn’s terminal state; never running. See TurnTerminalState. |
TurnTerminalState
The terminal lifecycle state of a Turn, returned bywait_for_completion() and carried by TurnDoneEvent’s state. It is one of three objects, discriminated on status: TurnDoneState, TurnCancelledState, or TurnErrorState. (The non-terminal TurnRunningState, returned by state() while a Turn is still running, has only status: "running".)
TurnDoneState
The Turn completed normally.| Field | Type | Required | Description |
|---|---|---|---|
status | "done" | Yes | |
output | ModelMessageEvent | null | No | The final assistant message, or null if the Turn paused (then required_actions is populated). |
required_actions | (ToolApprovalRequiredEvent | ToolResponseRequiredEvent | McpAuthRequiredEvent)[] | No | Pause events to act on. Empty if none. |
completed_at | string | Yes | ISO-8601 timestamp when the Turn completed. |
TurnCancelledState
The Turn was cancelled.| Field | Type | Required | Description |
|---|---|---|---|
status | "cancelled" | Yes | |
reason | string | null | No | Why the Turn was cancelled. |
completed_at | string | Yes | ISO-8601 timestamp when the Turn was cancelled. |
TurnErrorState
The Turn failed.| Field | Type | Required | Description |
|---|---|---|---|
status | "error" | Yes | |
message | string | Yes | Human-readable error description. |
completed_at | string | Yes | ISO-8601 timestamp when the Turn failed. |
Complete usage example
This is a complete, runnable terminal chat client built on the SDK. It handles every event the harness can emit:- streams assistant tokens in real time,
- shows tool calls and tool results inline,
- prompts the user to answer
ask_user_questioncalls, - prompts the user to allow or deny tool approvals,
- shows in-chat MCP OAuth prompts,
- handles parallel sub-agents,
- continues the conversation across Turns.
Sample run
Adapting the flow
A few common variations on top of the same skeleton:- Persisted history. Save
session.idafter the first Turn. On the next process start, callclient.agents.get_session(session_id)and uselist_turns()withturn.list_events()to rebuild UI state, orturn.stream()if the latest Turn is still running. - JSON output for piping. Replace the
printcalls inside_handle_eventwithjson.dumps(event.model_dump())to emit one event per line for downstream tools. - Generative UI. When you detect a fenced
```openuiblock in assembledmodel.messagecontent, hand the block to the OpenUI React renderer instead of printing it. Everything else stays the same. - Browser / web UI. The same event shape is delivered over Server-Sent Events on
POST /sessions/{session_id}/turns. Replacesession.create_turnwith an SSE consumer; the handlers above are unchanged.
Reference
create_session
| Param | Type | Required | Description |
|---|---|---|---|
agent_name | string | Yes | Name of the saved agent to invoke. |
title | string | No | Optional human-readable title for the session. |
list_sessions
| Param | Type | Required | Description |
|---|---|---|---|
agent_name | string | Yes | Filter to sessions for a specific named agent. |
created_by_subject_slug | string | No | Filter to sessions created by a specific user / service account. |
start_timestamp | string | No | ISO-8601 lower bound on session creation time. |
end_timestamp | string | No | ISO-8601 upper bound on session creation time. |
limit | int | No | Number of sessions fetched per page (not a total cap). Defaults to 100. |
Session
The conversation context for a saved agent. Turns created within a Session are chained automatically, so each Turn sees the history of earlier ones. Key members:| Member | Type | Description |
|---|---|---|
id | string | Unique session identifier. Persist it to resume the conversation later via client.agents.get_session(session_id). |
create_turn(...) | method | Prepare a Turn and return a LazyTurn without any network call. Start it with stream() (to stream events) or wait_for_completion() / state() (without streaming). See create_turn. |
list_turns() | method | Iterate over the Turns in this session, always in descending order (newest-first). |
get_turn(turn_id) | method | Fetch a single Turn by ID. |
cancel() | method | Cancel the session and any currently running Turn. Idempotent; after this, create_turn() raises. |
create_turn
LazyTurn with no id yet. The Turn is created server-side on the first method call, and the SDK branches on which one you call first: stream() opens an SSE stream, while wait_for_completion() and state() create the Turn without streaming. Calling cancel() or list_events() before the Turn is started raises.
| Param | Type | Required | Description |
|---|---|---|---|
input | TurnInput | No | Input items for this Turn. See Turn input. Omit or pass [] to resume after mcp.auth_required. |
previous_turn_id | string | "auto" | No | Turn chaining point. Defaults to "auto", letting the server chain to the latest Turn. |
Turn
A single request/response cycle within a Session. Transitions:running → done | cancelled | error.
list_turns() and get_turn() return a fully-qualified Turn whose id and metadata are always populated. create_turn() instead returns a LazyTurn - the same type with the same methods, but its id, previous_turn_id, created_by, and created_at are None until the Turn is started. Starting it via stream(), wait_for_completion(), or state() creates the Turn server-side and populates these (for stream(), from the first turn.created event). Calling list_events() or cancel() on a LazyTurn before it is started raises.
| Member | Type | Description |
|---|---|---|
id | string | None | Unique turn identifier (UUIDv7). None on a LazyTurn until it is started. |
session | Session | The Session this Turn belongs to. |
previous_turn_id | string | None | Turn ID this Turn chains from, or None for the first Turn (also None on a LazyTurn until started). |
created_by | string | None | Subject (user / service account) that created this Turn. None on a LazyTurn until started. |
created_at | string | None | ISO-8601 timestamp of Turn creation. None on a LazyTurn until started. |
input | TurnInput | None | The Turn input that triggered this Turn, if any. |
state() | method | Fetch the current lifecycle state from the server. Returns one of TurnRunningState, TurnDoneState, TurnCancelledState, or TurnErrorState. On an unstarted LazyTurn, creates the Turn first. |
stream(after_sequence_number=0) | method | Start an unstarted LazyTurn and stream its events, or reconnect to a running Turn’s live SSE stream. On reconnect, resumes after after_sequence_number (default 0, from the first event); also auto-resumes on any mid-stream drop. Closes when the Turn reaches a terminal state. On a started Turn, raises if it is not running — use list_events() for completed Turns. |
list_events(...) | method | Return a point-in-time snapshot of events accumulated so far, paginating automatically. Only available for completed Turns. order="asc" is natural for replaying history forward. Raises on an unstarted LazyTurn. |
wait_for_completion() | method | Block until the Turn reaches a terminal state and return it. Returns immediately if already terminal. On an unstarted LazyTurn, creates the Turn first. |
cancel() | method | Request cancellation. Idempotent; safe to call on already-terminal Turns. Cancellation is asynchronous — a few more events may arrive before the stream closes. Raises on an unstarted LazyTurn. |
To define or configure the agent itself, see Agent.