Skip to main content
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.

Sub-agent tool pattern

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

OptionTypeDefaultDescription
agentstringrequiredThe agent task ID to trigger
idstringcrypto.randomUUID()Conversation ID for tagging and correlation
clientDatatyped from agentundefinedClient data included in every request
sessionChatSession ({ lastEventId?: string })undefinedRestore a previous session’s SSE resume cursor. The Session row itself is keyed on chatId (durable) — no other state to thread.
onTriggered(event) => voidundefinedCalled when a new run is created
onTurnComplete(event) => voidundefinedCalled when a turn’s stream ends
streamTimeoutSecondsnumber120SSE timeout in seconds
triggerConfigSessionTriggerConfigundefinedTags, queue, machine, maxAttempts, idleTimeoutInSeconds, basePayload — folded into sessions.start({...})
baseURLstring | (ctx: { endpoint: "in" | "out"; chatId: string }) => stringapiClientManager.baseURLAPI 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>undefinedPer-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

MethodReturnsDescription
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]UIMessageChunkIterate over typed stream chunks
.streamReadableStream<UIMessageChunk>Raw stream for AI SDK utilities