AgentChat lets you chat with agents from server-side code. It works inside tasks (agent-to-agent), request handlers, webhook processors, and scripts.
Type-safe client data
Pass typeof yourAgent as a type parameter and clientData is automatically typed from the agent’s withClientData schema:
Conversation lifecycle
Each AgentChat instance represents one conversation. The conversation ID is auto-generated or can be set explicitly:
Sending messages
sendMessage() triggers a new run on the first call, then reuses the same run for subsequent messages via input streams:
Preloading (optional)
If you want the agent to initialize before the first message (e.g., load data, authenticate), call preload(). This is optional — sendMessage() triggers the run automatically if needed.
Closing
Signal the agent to exit its loop gracefully:
Without close(), the agent exits on its own when its idle/suspend timeout expires.
Reading responses
sendMessage() returns a ChatStream — a typed wrapper around the response.
Get the full text
Get structured results
Stream chunks in real-time
Stateless request handlers
In a stateless environment (HTTP handler, serverless function), you need to persist and restore the session across requests.
Each chat is backed by a durable Session row that outlives any single run. AgentChat exposes the persistable state via chat.session (the SSE resume cursor) and surfaces the current run id via the onTriggered callback for telemetry / dashboard linking.
The Session row is the run manager — a chat that was active yesterday
resumes against the same chatId today, even if the original run has
long since exited. AgentChat (server-side) and TriggerChatTransport
(browser) both rely on this: send a new message and the server
triggers a fresh continuation run on the same session, carrying the
conversation forward without losing history or identity.
AgentChat can be used inside an AI SDK tool to delegate work to a durable sub-agent. The sub-agent’s response streams as preliminary tool results:
This supports single-turn delegation, multi-turn LLM-driven conversations with persistent sub-agents, and cross-turn state that survives snapshot/restore.
See the Sub-Agents guide for the full pattern including multi-turn conversations, cleanup, and what the frontend sees.
Additional methods
Steering
Send a message during an active stream without interrupting it:
Stop generation
Abort the current streamText call without ending the run:
Raw messages
For full control over the UIMessage shape:
Reconnect
Resume a stream subscription after a disconnect:
AgentChat options
| Option | Type | Default | Description |
|---|
agent | string | required | The agent task ID to trigger |
id | string | crypto.randomUUID() | Conversation ID for tagging and correlation |
clientData | typed from agent | undefined | Client data included in every request |
session | ChatSession ({ lastEventId?: string }) | undefined | Restore a previous session’s SSE resume cursor. The Session row itself is keyed on chatId (durable) — no other state to thread. |
onTriggered | (event) => void | undefined | Called when a new run is created |
onTurnComplete | (event) => void | undefined | Called when a turn’s stream ends |
streamTimeoutSeconds | number | 120 | SSE timeout in seconds |
triggerConfig | SessionTriggerConfig | undefined | Tags, queue, machine, maxAttempts, idleTimeoutInSeconds, basePayload — folded into sessions.start({...}) |
baseURL | string | (ctx: { endpoint: "in" | "out"; chatId: string }) => string | apiClientManager.baseURL | API base URL. String form applies to every endpoint; function form picks per endpoint — useful for routing .in/append through an edge proxy while keeping .out SSE direct. Defaults to whatever @trigger.dev/sdk was configured with (typically TRIGGER_API_URL). |
fetch | (url: string, init: RequestInit, ctx: { endpoint: "in" | "out"; chatId: string }) => Promise<Response> | undefined | Per-request fetch override. Invoked for both .in/append POSTs and the .out SSE GET. Use for header injection, custom retries, or proxy rewrites. |
ChatStream methods
| Method | Returns | Description |
|---|
text() | Promise<string> | Consume stream, return accumulated text |
result() | Promise<ChatStreamResult> | Consume stream, return { text, toolCalls, toolResults } |
messages() | AsyncGenerator<UIMessage> | Yield accumulated UIMessage snapshots (sub-agent pattern) |
[Symbol.asyncIterator] | UIMessageChunk | Iterate over typed stream chunks |
.stream | ReadableStream<UIMessageChunk> | Raw stream for AI SDK utilities |