Skip to main content
Already running? Jump to the SDK Quickstart to install and stream your first turn. This page is the mental model behind that code: how an agent, a session, a turn, an event, and a delta fit together. Once it clicks, Use an agent is the runnable cookbook, and the API Reference tab has the raw HTTP schemas.

Core concepts

Talking to an agent follows one hierarchy: one Agent → many Sessions → many Turns → many Events → some Deltas. The sections below walk through each layer with one running example: a customer support agent named support-bot.
Hierarchy diagram. A single agent (support-bot), defined once, is reused across many sessions. Two example sessions are shown, Jane's refund issue and Bob's shipping question, each containing turns. Turn 1 in each session expands to show the events emitted on the stream (turn.created, user.message, mcp.initialize, model.message, tool.response, tool.approval_required, turn.done) and the deltas that events like model.message produce as streaming chunks. A legend lists each event type and a pyramid summarizes Agent to Sessions to Turns to Events to Deltas.

One agent serves many sessions; each session has many turns; each turn emits events; some events stream as deltas

Agent

An agent is a definition, not a running process. You define it once (the model, instructions, tools, and config), and any number of conversations can use it. support-bot is a support assistant that looks up orders and processes refunds through an MCP server. Its AgentSpec looks like this:
support-bot AgentSpec
Save this spec as a named agent and reference it by name in every session, or pass it inline when you create a session. The agent spec reference lists every field.

Session

A session is one issue worked through with the agent. It holds the conversation context: every turn on that issue chains together, and the agent remembers what happened earlier in the same session. Each new issue gets its own session, whether it comes from the same customer or a different one. Jane’s follow-ups about the refund stay in sess-7f2a9c1b. Bob’s question runs in a separate session, so the two conversations never share context.
Session for Jane's refund issue
Persist the session id so Jane can come back tomorrow and pick up where she left off. Only one turn runs in a session at a time.

Turn

A turn is one request in the conversation: a single back-and-forth between your app and the agent. Each time Jane sends a message (or your app sends an approval), you create a new turn. Turns in a session chain automatically (previous_turn_id defaults to "auto"), so the agent sees every earlier turn without you resending history.
A turn can also pause when the agent asks a clarifying question (tool.response_required) or needs MCP OAuth (mcp.auth_required). You resume with a new turn, just like Turn 3 above.

Event

While a turn runs, the agent emits events on the SDK stream, one JSON object at a time. Each event tells your app what the agent is doing: calling a tool, getting a result, writing a reply, or finishing. Events during Turn 1 (Jane asks for order status): Sample payload:
turn.done
Every event carries an id and a thread_id ("main" for the root agent, a generated id for subagents, or null for run-level events), plus a sequence number used for resuming after a disconnect. The stream always opens with turn.created and closes with turn.done. Field-level schemas for every event type are in the turn events reference.

Delta

Most events arrive as a complete payload. Model output is the exception: the LLM streams token by token, so the harness sends a base model.message event first, then a series of model.message.delta fragments that you merge into it. All deltas share the base event’s id. The agent’s full reply in Turn 1 is “Your order ORD-2031 shipped on June 12. Total: $1,240.00.” Your client receives:
Base event (empty shell)
Deltas (merge into msg-a1 as they arrive)
Append each delta’s content to the event with the matching id and re-render on every chunk. That’s how the chat UI shows the reply word by word:
Deltas only exist on the live stream. When you list a turn’s events afterwards (GET .../events), each model.message is already merged, so you use it directly.
A thread is a related idea: an execution context inside a turn. The root agent runs on thread_id: "main", and subagents get their own thread ids, announced by thread.created / thread.done events. Events carry thread_id so you can separate a single turn stream when subagents run in parallel.

The three turns, end to end

Here is Jane’s whole refund session: your app opens a session, runs turns, and reads the streamed events.
Sequence diagram of the support-bot session across three turns. Turn 1 streams tool calls and a reply; Turn 2 pauses for approval; Turn 3 resumes with the approval and streams the confirmation.

Three chained turns in one session: your app creates the session and turns; TrueForge streams events back

A separate issue (Bob’s shipping question, or Jane’s next problem) runs in its own session, where Turn 1 starts fresh with no refund history.

Next steps

  • SDK Quickstart installs the SDK, connects with a token, and streams your first turn.
  • Use an agent is the full cookbook: streaming, approvals, questions, threads, and reconnects.
  • The API Reference tab has the raw HTTP endpoints and OpenAPI schemas.