Skip to main content
These steps assume you already have a Trigger.dev project with the SDK installed and the CLI authenticated — if you don’t, follow Manual setup (or npx trigger.dev@latest init in an existing project) first. You should be able to run pnpm exec trigger dev from your project root before continuing. The chat surface works with Vercel AI SDK v5, v6, or v7; install whichever major you want. On v7, also install @ai-sdk/otel so your model calls are traced (the SDK registers it for you). See compatibility for the full matrix.
1

Define a chat agent

Use chat.agent from @trigger.dev/sdk/ai to define an agent that handles chat messages. The run function receives ModelMessage[] (already converted from the frontend’s UIMessage[]) — pass them directly to streamText.If you return a StreamTextResult, it’s automatically piped to the frontend.
trigger/chat.ts
The streamText passed to run connects compaction, steering, background injection, and telemetry. If you use an imported streamText from ai, spread chat.toStreamTextOptions() into its options to connect those features.
For a custom UIMessage subtype (typed data-* parts, tool map, etc.), define the agent with chat.withUIMessage<...>().agent({...}) instead of chat.agent.
2

Add two server actions

On your server (e.g. as Next.js server actions), expose two helpers the transport will call: one that creates the chat session, and one that mints a fresh session-scoped access token for refresh.
app/actions.ts
requireChatOwner is your application helper: authenticate the request, load the chat by ID and owner, and throw if it doesn’t belong to that user. Create the chat record on your server before rendering the frontend, and pass its ID into Chat. Check ownership in both actions, including token refresh.Set TRIGGER_SECRET_KEY and your model provider key in the server and worker environments. Keep both keys out of the browser.
3

Use in the frontend

Use the useTriggerChatTransport hook from @trigger.dev/sdk/chat/react to create a memoized transport instance, then pass it to useChat. Wire both server actions into the transport’s accessToken and startSession callbacks.The example below uses the Next.js @/* path alias for imports from @/trigger/chat and @/app/actions. If you’re not using Next.js (or haven’t configured the alias), swap them for relative imports.
app/components/chat.tsx

Try it

Run your frontend and pnpm exec trigger dev, then send a message. You should see an assistant response stream into the page and a run in your project’s dashboard. If session creation fails, check ownership and the server’s TRIGGER_SECRET_KEY. If the run starts but the model fails, check the worker’s provider key and run logs.

Next steps

  • Backend — Lifecycle hooks, persistence, session iterator, raw task primitives
  • Tools: Declare tools so toModelOutput survives across turns, typed in run()
  • Frontend — Session management, client data, reconnection
  • Types — chat.withUIMessage, InferChatUIMessage, and related typing
  • chat.local — Per-run typed state across hooks, run, tools, subtasks
  • Sub-agents pattern — Subtask-as-tool, target: "root" streaming, ai.toolExecute helpers
  • Background injection — chat.inject() and chat.defer() for between-turn work