> ## Documentation Index
> Fetch the complete documentation index at: https://trigger.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Anatomy of an agent

> The three parts of a chat agent — the agent task that runs the turn loop, the durable session that carries messages, and the frontend transport — what each does and where it's documented.

**A chat agent is three parts: an agent task that runs the turn loop, a durable session that carries messages in and streams the response out, and a frontend transport that connects the session to `useChat`.** This page is your map of the Building agents section — what each part does, how a single message flows through them, and which page to open next.

```mermaid theme={"theme":"css-variables"}
flowchart LR
  FE["Frontend<br/>useChat + transport"] -- "user messages" --> IN([Session .in])
  IN --> AGENT["Agent task<br/>turn loop + hooks"]
  AGENT --> OUT([Session .out])
  OUT -- "streamed response" --> FE
```

## Follow one message

A single turn moves through all three parts in order:

1. The **frontend transport** sends the user's message to the session's inbound stream (`.in`).
2. The **agent task** wakes on the new message, runs your turn loop, and streams the model's response into the session's outbound stream (`.out`).
3. The **frontend transport** reads `.out` and renders tokens into `useChat` as they arrive.

The session sits in the middle so both sides never have to be online at the same moment — the task keeps writing to `.out` even if the browser reloads mid-stream.

## The three parts

### The agent task

`chat.agent()` is the code you write: a long-lived agent whose `run` function is the turn loop. Messages arrive accumulated, you call `streamText`, and the returned stream is piped back to the frontend for you. [Tools](https://trigger.dev/docs/ai-chat/tools.md) the model can call and [lifecycle hooks](https://trigger.dev/docs/ai-chat/lifecycle-hooks.md) that fire around each turn both hang off the same config. See [Backend](https://trigger.dev/docs/ai-chat/backend.md) for the full `chat.agent()` surface.

### The session

The conversation lives in a [session](https://trigger.dev/docs/ai-chat/sessions.md), not in the task's memory: a pair of durable streams — `.in` and `.out` — keyed on your `chatId`. Because the session is durable, a conversation survives page refreshes, deploys, and the run boundaries between turns. The task can restart and pick up the same session. [How it works](https://trigger.dev/docs/ai-chat/how-it-works.md) covers the mechanics of what survives and why.

### The frontend transport

One hook — `useTriggerChatTransport` — connects the Vercel AI SDK's `useChat` to the agent's session. There are no API routes to write: the transport talks to the session directly using a scoped token. See [Frontend](https://trigger.dev/docs/ai-chat/frontend.md) for wiring, tokens, and starting sessions.

## An annotated agent

Everything above maps onto one task:

```ts trigger/my-agent.ts theme={"theme":"css-variables"}
import { chat } from "@trigger.dev/sdk/ai";
import { stepCountIs } from "ai";
import { anthropic } from "@ai-sdk/anthropic";

export const myAgent = chat.agent({
  id: "my-agent",

  // Tools the model can call, declared on the config so they
  // survive history re-conversion across turns — see Tools.
  tools: { searchDocs },

  // A lifecycle hook: fires after each turn, here to persist
  // the response — see Lifecycle hooks.
  onTurnComplete: async ({ responseMessage }) => {
    await db.messages.save(responseMessage);
  },

  // The turn loop. Messages arrive accumulated; the returned
  // stream is piped back to the frontend — see Backend.
  run: async ({ messages, tools, signal, streamText }) =>
    streamText({
      tools,
      model: anthropic("claude-sonnet-4-5"),
      messages,
      abortSignal: signal,
      stopWhen: stepCountIs(15),
    }),
});
```

## Related pages

Beyond the three core parts:

| Page | What it covers |
| - | - |
| [Server-side chat](https://trigger.dev/docs/ai-chat/server-chat.md) | Driving a chat from your backend instead of a browser |
| [chat.local](https://trigger.dev/docs/ai-chat/chat-local.md) | Per-run typed state inside the turn loop |
| [Types](https://trigger.dev/docs/ai-chat/types.md) | Type-safe payloads, client data, and messages |
| [Custom agents](https://trigger.dev/docs/ai-chat/custom-agents.md) | Building without the managed lifecycle |

[Features](https://trigger.dev/docs/ai-chat/fast-starts.md) covers opt-in capabilities (Head Start, compaction, steering, actions), and [Patterns](https://trigger.dev/docs/ai-chat/patterns/sub-agents.md) covers production recipes (sub-agents, HITL approvals, persistence, recovery).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.