Use a hosted code sandbox (for example E2B) when the model should run short scripts to analyze tool output (PostHog queries, CSV-like data, math) without executing arbitrary code on the Trigger worker host. This page describes a durable chat pattern that fitsDocumentation Index
Fetch the complete documentation index at: https://trigger-docs-tri-7532-ai-sdk-chat-transport-and-chat-task-s.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
chat.agent():
- Warm the sandbox at the start of each turn (non-blocking).
- Reuse it for every
executeCodetool call during that turn (and across turns in the same run if you keep the handle). - Dispose it right before the run suspends waiting for the next user message — using the
onChatSuspendhook, notonTurnComplete.
Why not tear down in onTurnComplete?
After a turn finishes, the chat runtime still goes through an idle window and only then suspends. During that window the run is still executing — useful for chat.defer() work — and the run hasn’t suspended yet.
The boundary you want for “turn done, about to sleep” is onChatSuspend, which fires right before the run transitions from idle to suspended. It provides the phase (”preload” or ”turn”) and full chat context. See onChatSuspend / onChatResume.
Recommended provider: E2B
- API key auth — works from any Trigger.dev worker; no Vercel-only OIDC.
- Code Interpreter SDK (
@e2b/code-interpreter): long-lived sandbox,runCode(),kill().
Implementation sketch
1. Run-scoped sandbox map
Keep aMap<runId, Promise<Sandbox>> (or similar) in a task-only module so your Next.js app never imports it.
2. onTurnStart — warm without blocking
3. chat.local — run id for tools
Tool execute functions do not receive hook payloads. Use chat.local() to store the current run id for the sandbox key, initialized from onTurnStart (same runId as the map):
executeCode tool reads codeSandboxRun.runId and awaits the sandbox promise before runCode.
4. onChatSuspend / onComplete — teardown
Use onChatSuspend to dispose the sandbox right before the run suspends, and onComplete as a safety net when the run ends entirely.
onWait (which fires for all wait types), onChatSuspend only fires at chat suspension points — no need to filter on wait.type. The phase discriminator tells you if this is a preload or post-turn suspension.
Optional onChatResume: log or reset flags; a fresh sandbox can be warmed again on the next onTurnStart.
5. AI SDK tool
Wrap the provider in a normal AI SDKtool({ inputSchema, execute }) (same pattern as webFetch). Keep tool definitions in task code, not in the Next.js server bundle.
6. Environment
SetE2B_API_KEY (or your provider’s secret) on the Trigger environment for the worker — not in public client env.
Typing ctx
Every chat.agent lifecycle event and the run payload include ctx: the same TaskRunContext shape as task({ run: (payload, { ctx }) => ... }).
Context is also exported from @trigger.dev/sdk and is the same type.
See also
- Database persistence for chat — conversation + session rows, hooks, token renewal
- Backend — Lifecycle hooks
- API Reference —
ctxon events - Per-run data with
chat.local

