Releases: triggerdotdev/trigger.dev
Release list
trigger.dev v4.5.0
Upgrade
npx trigger.dev@latest update # npm
pnpm dlx trigger.dev@latest update # pnpm
yarn dlx trigger.dev@latest update # yarn
bunx trigger.dev@latest update # bunSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.5.0
Release notes
Read the full release notes: https://trigger.dev/changelog/v4-5-0
What's changed
AI Agents (chat.agent)
Run Vercel AI SDK chat completions as durable Trigger.dev tasks instead of fragile API routes. A conversation runs as one long-lived task keyed on chatId, so it survives page refreshes, network blips, redeploys, and crashes, and every turn is a span in the dashboard.
import { chat } from "@trigger.dev/sdk/ai";
import { streamText, stepCountIs } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
export const myChat = chat.agent({
id: "my-chat",
run: async ({ messages, signal }) => {
return streamText({
...chat.toStreamTextOptions(), // system prompt, compaction, steering, telemetry
model: anthropic("claude-sonnet-4-5"),
messages,
abortSignal: signal,
stopWhen: stepCountIs(15),
});
},
});Sessions
The durable primitive underneath chat.agent, usable on its own: a run-aware, bidirectional stream channel keyed on a stable externalId whose .in / .out streams survive run boundaries (suspend, crash, idle-timeout, redeploy). One Session spans many runs, which makes it a good fit for agent inboxes and approval flows.
import { sessions } from "@trigger.dev/sdk";
// Create the session and trigger its first run (idempotent on externalId)
await sessions.start({
type: "inbox",
externalId: userId,
taskIdentifier: "inbox-agent",
});
const session = sessions.open(userId);
await session.in.send({ text: "hello" });
const stream = await session.out.read({ signal: AbortSignal.timeout(30_000) });
for await (const chunk of stream) console.log(chunk); // durable across run swapsAI Prompts
Define prompt templates as code, versioned on every deploy, and override the text or model from the dashboard without redeploying (environment-scoped). Each generation links back to its prompt version for usage, cost, and latency.
import { prompts } from "@trigger.dev/sdk";
import { z } from "zod";
export const supportPrompt = prompts.define({
id: "customer-support",
model: "gpt-4o",
variables: z.object({ customerName: z.string(), issue: z.string() }),
content: `You are a support agent for Acme.
Customer: {{customerName}}
Issue: {{issue}}`,
});
// Honors any active dashboard override, else the current deployed version
const resolved = await supportPrompt.resolve({ customerName: "Alice", issue: "Can't log in" });
// resolved.text, resolved.model, resolved.versionuseChat integration
useTriggerChatTransport is a Vercel AI SDK ChatTransport that runs useChat over Trigger.dev realtime with no API routes. Text, tool calls, reasoning, and data-* parts stream natively, and it works with AI SDK v5, v6, and now v7.
First-turn fast path (chat.headStart)
Runs the first turn in your warm server process while the agent boots in parallel, cutting cold-start time-to-first-chunk roughly in half (measured ~2.8s to ~1.2s). Available via the new @trigger.dev/sdk/chat-server subpath.
Human-in-the-loop, stop, and steering
The agent control surface: tool approvals (needsApproval + addToolApprovalResponse), client-driven stop-generation, mid-execution steering (pendingMessages), and between-turn context injection (chat.inject / chat.defer), all durable across the conversation.
Agent Skills
skills.define({ id, path }) bundles a SKILL.md folder into your deploy image. The agent gets a one-line summary up front and loads the full instructions plus scoped bash / readFile tools on demand (progressive disclosure), so a capability is something the model reaches for rather than a pre-declared typed tool.
trigger skills for coding assistants
trigger skills installs version-pinned Trigger.dev skills plus a bundled docs snapshot into Claude Code, Cursor, GitHub Copilot, and Codex, so your assistant's Trigger.dev knowledge stays current with your installed SDK version. trigger init now offers to set up the MCP server and skills too.
Model library
A new Models page in the dashboard: a catalog of models grouped by provider with context window, capabilities, and input / output pricing per 1M tokens, plus a "Your models" tab showing per-model usage, cost, and cache-hit sparklines from your actual traffic.
Dev branches
Run multiple local trigger dev sessions in parallel (separate git worktrees or coding agents) without runs colliding, each isolated with its own dashboard, via trigger dev --branch <name>.
TriggerClient
An instantiable client so one process can trigger and read across projects, environments, and preview branches, each with its own auth and baseURL, with no shared global state.
import { TriggerClient } from "@trigger.dev/sdk";
const prod = new TriggerClient({ accessToken: process.env.TRIGGER_PROD_KEY });
const preview = new TriggerClient({
accessToken: process.env.TRIGGER_PREVIEW_KEY,
previewBranch: "signup-flow",
});
await prod.tasks.trigger("send-email", { to: "user@example.com" });
await preview.runs.list({ status: ["COMPLETED"] });SDK and runtime
- AI SDK 7 support (v5 and v6 still supported), with OpenTelemetry telemetry auto-wired
- Large trigger-payload offload: trigger payloads at or above 128KB upload to object storage automatically, using the same auth and baseURL as the trigger call
- Region support on the runs API: filter runs by region and read each run's executing region (also on MCP
list_runs) - Duplicate task-id detection:
devanddeployfail with a clear error instead of silently overwriting envvars.uploadgains anisSecretflag to import redacted secret variables- Retry hardening:
TASK_MIDDLEWARE_ERRORnow retries under the task's retry policy
All packages: v4.5.0
@trigger.dev/build, @trigger.dev/core, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Full changelog: v4.4.0...v4.5.0
trigger.dev v4.5.0-rc.7
Upgrade
npx trigger.dev@4.5.0-rc.7 update
pnpm dlx trigger.dev@4.5.0-rc.7 update
yarn dlx trigger.dev@4.5.0-rc.7 update
bunx trigger.dev@4.5.0-rc.7 updateSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.5.0-rc.7
Improvements
-
@trigger.dev/sdknow bundles the Trigger.dev agent skills and a curated snapshot of the docs those skills reference. The skills thattrigger skillsinstalls into your coding agent read this content from node_modules, so the guidance your AI assistant follows is pinned to the SDK version installed in your project and stays current across upgrades instead of going stale until the next reinstall. (#3937) -
Running a CLI command like
dev,deploy,preview, orupdatebefore initializing a project no longer crashes with a rawCannot find matching package.jsonstack trace. The CLI now detects the missing project and points you tonpx trigger.dev@latest initinstead. (#3929) -
The agent skills installed by
trigger skillsare now namespaced with atrigger-prefix (e.g.trigger-authoring-tasks,trigger-getting-started) so they don't collide with unrelated skills in your coding agent's skills directory. Adds atrigger-cost-savingsskill for auditing and reducing compute spend (right-sizing machines,maxDuration, batching, debounce), and@trigger.dev/sdknow bundles the full Trigger.dev documentation so your agent can read the complete, version-pinned reference directly from node_modules. (#3970) -
The run span API response now includes
cachedCostandcacheCreationCoston theaiobject, alongside the existinginputCost/outputCost/totalCost.inputCostreflects only the non-cached input, so these fields let you reconstruct the full cost breakdown for prompt-cached calls. (#3958) -
chat.headStartnow works with thechat.customAgentandchat.createSessionbackends, not onlychat.agent. The warm step-1 response hands over to your loop the same way it does for a managed agent. (#3963)In a
chat.customAgentloop, consume the handover on turn 0:const conversation = new chat.MessageAccumulator(); const { isFinal, skipped } = await conversation.consumeHandover({ payload }); if (skipped) return; // warm handler aborted, so exit without a turn if (isFinal) { await chat.writeTurnComplete(); // step 1 is the response, no streamText } else { const result = streamText({ model, messages: conversation.modelMessages, tools }); // Pass originalMessages so the handed-over tool round merges into the // step-1 assistant instead of starting a new message. const response = await chat.pipeAndCapture(result, { originalMessages: conversation.uiMessages, }); if (response) await conversation.addResponse(response); }
With
chat.createSession, the iterator surfaces it asturn.handover; callturn.complete()with no argument on a final handover. The lower-levelchat.waitForHandover()andaccumulator.applyHandover()are also exported for hand-rolled loops. -
Cache your chat agent's system prompt with Anthropic prompt caching.
chat.toStreamTextOptions()now emits the system prompt as a cacheable message when you opt in, so a large, stable system block is billed at cache-read rates on every turn instead of full price. (#3952)// at the streamText call site (Anthropic sugar) streamText({ ...chat.toStreamTextOptions({ cacheControl: { type: "ephemeral" } }), messages, }); // provider-agnostic equivalent chat.toStreamTextOptions({ systemProviderOptions: { anthropic: { cacheControl: { type: "ephemeral" } } }, }); // or where the prompt is defined chat.prompt.set(SYSTEM_PROMPT, { providerOptions: { anthropic: { cacheControl: { type: "ephemeral" } } }, });
Without an option,
systemstays a plain string. Pairs with aprepareMessagescache breakpoint to cache the conversation prefix across turns too. -
Three fixes for custom agent loops (
chat.customAgent,chat.createSession, and hand-rolledMessageAccumulatorloops): (#3936)- Continuation runs no longer replay already-answered user messages into the first turn. The
.inresume cursor is now seeded before any listener attaches (the same boot logicchat.agentuses), so a chat that continues after a cancel, crash, or upgrade only sees genuinely new messages. - Steering a hand-rolled loop mid-stream no longer wipes the in-flight assistant response.
chat.pipeAndCapturenow stamps a server-generated message id on the stream, so aprepareStepinjection keeps the partial text instead of replacing the message. - Task-backed tools (
ai.toolExecute) now work from custom agent loops: the parent's session is threaded to the child run, so child tasks can stream progress into the chat withchat.stream.writer({ target: "root" })instead of failing with "session handle is not initialized".
- Continuation runs no longer replay already-answered user messages into the first turn. The
All packages: v4.5.0-rc.7
@trigger.dev/build, @trigger.dev/core, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Full changelog: v4.4.0.7...v4.5.0-rc.7
trigger.dev v4.5.0-rc.6
Upgrade
npx trigger.dev@4.5.0-rc.6 update
pnpm dlx trigger.dev@4.5.0-rc.6 update
yarn dlx trigger.dev@4.5.0-rc.6 update
bunx trigger.dev@4.5.0-rc.6 updateSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.5.0-rc.6
chat.agent Improvements
- Reliability fixes for
chat.agent. A user message sent while the agent is streaming is no longer delivered twice (which could run a duplicate turn), input appends now carry an idempotency key so a retried send can't duplicate a message, stopping a generation clears the streaming state so a page reload doesn't replay the stopped turn, and runs can now carry the full set of dashboard tags instead of being silently truncated.onTurnCompletenow fires on errored turns (with the thrown error attached) and the failed turn's user message is persisted so it isn't lost on the next run. Custom agents and manualchat.writeTurnCompletecallers now trim the output stream, sending a custom action no longer leaves a second stream reader running, and a long-livedwatchsubscription no longer grows its dedupe set without bound. (#3891) - Continuation chat boots no longer stall for around 10 seconds before the first turn. The
session.inresume cursor is now found with a non-blocking records read instead of draining an SSE long-poll (which always waited out its full 5 second inactivity window, twice per boot), the boot reads run concurrently, and chat snapshots carry the cursor so subsequent boots skip the scan entirely. (#3907) - Fix two
chat.createSession()bugs: stopping a generation no longer wedges the run (the turn loop raced atotalUsagepromise that never settles after a stop-abort), and continuation runs now wait for the next message instead of invoking the model with an empty prompt. (#3920)
Other improvements and fixes
trigger initnow sets up your AI coding assistant as part of project setup: pick the MCP server, the agent skills, or both, then scaffold with the CLI or hand off to your assistant. Adds a newgetting-startedagent skill that teaches assistants how to bootstrap Trigger.dev (install the SDK, writetrigger.config.ts, create a first task, runtrigger dev), so the AI-driven setup path works end to end. It ships in the CLI alongside the existing skills, version-matched to your SDK. (#3872)devanddeploynow fail with a clear error when two tasks are defined with the same id, including across different task types (e.g. a scheduled task and a regular task sharing an id). Previously the second definition silently overwrote the first, so one of the tasks would vanish with no warning. Task ids are detected as duplicates during indexing (naming each offending id and the files it was found in), and the same rule is enforced server-side when the background worker is registered. (#3865)trigger skillsinstalls Trigger.dev agent skills into your coding agent so it knows how to write tasks, schedules, realtime, and chat.agent code. The skills ship with the CLI and are copied into each tool's native skills directory (Claude Code, Cursor, GitHub Copilot, and Codex / AGENTS.md), andtrigger devoffers to install them on first run. (#3868)
All packages: v4.5.0-rc.6
@trigger.dev/build, @trigger.dev/core, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Full changelog: v4.4.0.6...v4.5.0-rc.6
trigger.dev v4.5.0-rc.5
Upgrade
npx trigger.dev@4.5.0-rc.5 update
pnpm dlx trigger.dev@4.5.0-rc.5 update
yarn dlx trigger.dev@4.5.0-rc.5 update
bunx trigger.dev@4.5.0-rc.5 updateSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.5.0-rc.5
Highlights
- Adds AI SDK 7 support. The
aipeer range now includes v7, and thechat.agent/ chat surfaces work against v7's ESM-only build. On v7, install@ai-sdk/otelalongsideaiand the SDK registers it for you soexperimental_telemetryspans keep flowing into your run traces (v7 stopped emitting them fromaicore). v5 and v6 keep working unchanged. (#3833) useTriggerChatTransportnow recovers when restored session state points at a session that no longer exists in the current environment (#3816)
Improvements
- The MCP server no longer tells the AI agent to wait for a run to complete after every
trigger_taskcall. Waiting is now opt-in: the agent only waits when you ask it to (for example "trigger and then wait for it to finish"). This avoids burning tokens polling runs you didn't need to block on and keeps responses clearer. (#3838) - Update the bundled OpenTelemetry packages to their latest releases (
@opentelemetry/sdk-node0.218.0,@opentelemetry/core2.7.1,@opentelemetry/host-metrics0.38.3). (#3810) envvars.uploadnow accepts an optionalisSecretflag, letting you create the imported variables as secret (redacted) environment variables. When omitted, variables default to non-secret. (#3809)- Offload large trigger payloads to object storage before sending the trigger API request. The SDK uploads packets at or above the existing 128KB limit and sends an
application/storepointer instead of embedding large JSON in the request body.TriggerTaskRequestBodynow validates thatapplication/storepayloads are non-empty storage paths. (#3785)
Bug fixes
- Fix
@trigger.dev/corebuild: cast the underlying log record exporter when callingforceFlushso it typechecks against the updated OpenTelemetryLogRecordExportertype (which no longer declaresforceFlush). (#3829)
All packages: v4.5.0-rc.5
@trigger.dev/build, @trigger.dev/core, @trigger.dev/plugins, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Full changelog: v4.4.0.5...v4.5.0-rc.5
trigger.dev v4.5.0-rc.4
Upgrade
npx trigger.dev@4.5.0-rc.1 update
pnpm dlx trigger.dev@4.5.0-rc.1 update
yarn dlx trigger.dev@4.5.0-rc.1 update
bunx trigger.dev@4.5.0-rc.1 updateSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.5.0-rc.4
Highlights
- Add a
toolsoption tochat.agent. Declaring your tools here threads them into the SDK's internalconvertToModelMessages, so each tool'stoModelOutputis re-applied when prior-turn history is re-converted. (#3790)
Improvements
- Bump
@s2-dev/streamstoreto0.22.10to fix aTASK_RUN_UNCAUGHT_EXCEPTION("Invalid state: Unable to enqueue") when achat.agentturn is aborted mid-stream. (#3792) - Coerce numeric
concurrencyKeyvalues to string at the API boundary acrosstasks.trigger,tasks.batchTrigger, and the Phase-2 streaming batch endpoint. (#3789)
All packages: v4.5.0-rc.4
@trigger.dev/build, @trigger.dev/core, @trigger.dev/plugins, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Full changelog: v4.5.0-rc.3...v4.5.0-rc.4
trigger.dev v4.5.0-rc.3
trigger.dev v4.5.0-rc.3
Upgrade
npx trigger.dev@latest update # npm
pnpm dlx trigger.dev@latest update # pnpm
yarn dlx trigger.dev@latest update # yarn
bunx trigger.dev@latest update # bunSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.5.0-rc.3
Release notes
Read the full release notes: https://trigger.dev/changelog/v4-5-0-rc-3
What's changed
Improvements
- Retry
TASK_MIDDLEWARE_ERRORunder the task's retry policy instead of failing the run on the first attempt. The error was already classified as retryable byshouldRetryError, butshouldLookupRetrySettingsdid not include it, so the retry flow fell through tofail_run. Fixes #3231. (#3676)
Bug fixes
- Fix
TypeErrorinunflattenAttributeswhen the input attribute map contains conflicting dotted key paths (e.g. botha.bset to a scalar anda.b.cset to a value). The path-walk loop now applies last-write-wins when a prior key wrote a primitive, null, or array at an intermediate slot, matching the existing precedent inAttributeFlattener.addAttribute. Callers no longer crash when handed malformed external attribute inputs. (#3762) - Fix external trace context leaking across runs on warm-started workers with
processKeepAliveenabled. Every subsequent run's attempt span was being exported with the first run'straceIdandparentSpanId, breaking causal-chain navigation in external APM tools. Runs without an external trace context are unaffected. (#3768)
All packages: v4.5.0-rc.3
@trigger.dev/build, @trigger.dev/core, @trigger.dev/plugins, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Full changelog: v4.4.0.3...v4.5.0-rc.3
trigger.dev v4.5.0-rc.2
trigger.dev v4.5.0-rc.2
Upgrade
npx trigger.dev@latest update # npm
pnpm dlx trigger.dev@latest update # pnpm
yarn dlx trigger.dev@latest update # yarn
bunx trigger.dev@latest update # bunSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.5.0-rc.2
Release notes
Read the full release notes: https://trigger.dev/changelog/v4-5-0-rc-2
What's changed
Improvements
- The per-turn merge now overlays the wire copy's tool-part state advancement onto the agent's existing chain —
state+ the matching resolution field (output/errorText/approval) come from the wire, everything else (text, reasoning, toolinput, provider metadata) stays whatever the snapshot orhydrateMessagesreturned. Previously a full-message replace overwrote those fields with whatever the client shipped, so a slimmed wire copy landed a tool call with noargumentson the next LLM call. Coversoutput-available/output-error(HITLaddToolOutput) andapproval-responded/output-denied(approval flow). TriggerChatTransport.sendMessagesandAgentChat.sendRawnow slim assistant messages that carry advanced tool parts. The wire payload is just{ id, role, parts: [<state + resolution field>] }forsubmit-messagecontinuations; everything else passes through. Reasoning blobs and full tool inputs no longer ride the wire on everyaddToolOutput/addToolApproveResponse, so continuation payloads stay well under the.in/appendcap on long agent loops.- Add
TriggerClientfor running multiple SDK clients side-by-side, each with its own auth, preview branch, and baseURL. Useful when a single process needs to trigger tasks or read runs across multiple projects, environments, or preview branches without mutating shared global state. (#3683)
Bug fixes
- Fix
chat.agentHITL continuations on reasoning-heavy turns. Two changes that work together: (#3719)
All packages: v4.5.0-rc.2
@trigger.dev/build, @trigger.dev/core, @trigger.dev/plugins, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Full changelog: v4.4.0.2...v4.5.0-rc.2
trigger.dev v4.5.0-rc.1
Upgrade
npx trigger.dev@4.5.0-rc.1 update
pnpm dlx trigger.dev@4.5.0-rc.1 update
yarn dlx trigger.dev@4.5.0-rc.1 update
bunx trigger.dev@4.5.0-rc.1 updateSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.5.0-rc.1
Release notes
Read the full release notes: https://trigger.dev/changelog/v4-5-0-rc-1
What's changed
Bug fixes
- Fix
chat.agentskills silently missing intrigger devfor projects whose task files readprocess.envat module top level (e.g. a third-party SDK client initialized at import). Skill folders now bundle into.trigger/skills/reliably regardless of which env vars are set when the CLI launches. (#3690) - Fix
COULD_NOT_FIND_EXECUTORwhen a task's definition is loaded viaawait import(...)from inside another task'srun(). The runtime workers now register such tasks with a sentinel file context, and the catalog logs a one-time warning per task id. (#3688)
All packages: v4.5.0-rc.1
@trigger.dev/build, @trigger.dev/core, @trigger.dev/plugins, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Full changelog: v4.4.0.1...v4.5.0-rc.1
trigger.dev v4.5.0-rc.0
Upgrade
npx trigger.dev@4.5.0-rc.0 update
pnpm dlx trigger.dev@4.5.0-rc.0 update
yarn dlx trigger.dev@4.5.0-rc.0 update
bunx trigger.dev@4.5.0-rc.0 updateSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.5.0-rc.0
What's changed
Improvements
- AI Prompts — define prompt templates as code alongside your tasks, version them on deploy, and override the text or model from the dashboard without redeploying. Prompts integrate with the Vercel AI SDK via
toAISDKTelemetry()(links every generation span back to the prompt) and withchat.agentviachat.prompt.set()+chat.toStreamTextOptions(). (#3629) - Code-defined, deploy-versioned templates — define with
prompts.define({ id, model, config, variables, content }). Every deploy creates a new version visible in the dashboard. Mustache-style placeholders ({{var}},{{#cond}}...{{/cond}}) with Zod / ArkType / Valibot-typed variables. - Dashboard overrides — change a prompt's text or model from the dashboard without redeploying. Overrides take priority over the deployed "current" version and are environment-scoped (dev / staging / production independent).
- Resolve API —
prompt.resolve(vars, { version?, label? })returns the compiledtext, resolvedmodel,version, and labels. Standaloneprompts.resolve<typeof handle>(slug, vars)for cross-file resolution with full type inference on slug and variable shape. - AI SDK integration — spread
resolved.toAISDKTelemetry({ ...extra })into anygenerateText/streamTextcall and every generation span links to the prompt in the dashboard alongside its input variables, model, tokens, and cost. chat.agentintegration —chat.prompt.set(resolved)stores the resolved prompt run-scoped;chat.toStreamTextOptions({ registry })pullssystem,model(resolved via the AI SDK provider registry),temperature/maxTokens/ etc., and telemetry into a single spread forstreamText.- Management SDK —
prompts.list(),prompts.versions(slug),prompts.promote(slug, version),prompts.createOverride(slug, body),prompts.updateOverride(slug, body),prompts.removeOverride(slug),prompts.reactivateOverride(slug, version). - Dashboard — prompts list with per-prompt usage sparklines; per-prompt detail with Template / Details / Versions / Generations / Metrics tabs. AI generation spans get a custom inspector showing the linked prompt's metadata, input variables, and template content alongside model, tokens, cost, and the message thread.
- Adds
onBoottochat.agent— a lifecycle hook that fires once per worker process picking up the chat. Runs for the initial run, preloaded runs, AND reactive continuation runs (post-cancel, crash,endRun,requestUpgrade, OOM retry), before any other hook. Use it to initializechat.local, open per-process resources, or re-hydrate state from your DB on continuation — anywhere the SAME run picking up after suspend/resume isn't enough. (#3543) - AI SDK
useChatintegration — a customChatTransport(useTriggerChatTransport) plugs straight into Vercel AI SDK'suseChathook. Text streaming, tool calls, reasoning, anddata-*parts all work natively over Trigger.dev's realtime streams. No custom API routes needed. - First-turn fast path (
chat.headStart) — opt-in handler that runs the first turn'sstreamTextstep in your warm server process while the agent run boots in parallel, cutting cold-start TTFC by roughly half (measured 2801ms → 1218ms onclaude-sonnet-4-6). The agent owns step 2+ (tool execution, persistence, hooks) so heavy deps stay where they belong. Web Fetch handler works natively in Next.js, Hono, SvelteKit, Remix, Workers, etc.; bridge to Express/Fastify/Koa viachat.toNodeListener. New@trigger.dev/sdk/chat-serversubpath. - Multi-turn durability via Sessions — every chat is backed by a durable Session that outlives any individual run. Conversations resume across page refreshes, idle timeout, crashes, and deploys;
resume: truereconnects vialastEventIdso clients only see new chunks.sessions.listenumerates chats for inbox-style UIs. - Auto-accumulated history, delta-only wire — the backend accumulates the full conversation across turns; clients only ship the new message each turn. Long chats never hit the 512 KiB body cap. Register
hydrateMessagesto be the source of truth yourself. - Lifecycle hooks —
onPreload,onChatStart,onValidateMessages,hydrateMessages,onTurnStart,onBeforeTurnComplete,onTurnComplete,onChatSuspend,onChatResume— for persistence, validation, and post-turn work. - Stop generation — client-driven
transport.stopGeneration(chatId)aborts mid-stream; the run stays alive for the next message, partial response is captured, and aborted parts (stuckpartial-calltools, in-progress reasoning) are auto-cleaned. - Tool approvals (HITL) — tools with
needsApproval: truepause until the user approves or denies viaaddToolApprovalResponse. The runtime reconciles the updated assistant message by ID and continuesstreamText. - Steering and background injection —
pendingMessagesinjects user messages between tool-call steps so users can steer the agent mid-execution;chat.inject()+chat.defer()adds context from background work (self-review, RAG, safety checks) between turns. - Actions — non-turn frontend commands (undo, rollback, regenerate, edit) sent via
transport.sendAction. FirehydrateMessages+onActiononly — no turn hooks, norun().onActioncan return aStreamTextResultfor a model response, orvoidfor side-effect-only. - Typed state primitives —
chat.local<T>for per-run state accessible from hooks,run(), tools, and subtasks (auto-serialized throughai.toolExecute);chat.storefor typed shared data between agent and client;chat.historyfor reading and mutating the message chain;clientDataSchemafor typedclientDatain every hook. chat.toStreamTextOptions()— one spread intostreamTextwires up versioned system Prompts, model resolution, telemetry metadata, compaction, steering, and background injection.- Multi-tab coordination —
multiTab: true+useMultiTabChatprevents duplicate sends and syncs state across browser tabs viaBroadcastChannel. Non-active tabs go read-only with live updates. - Network resilience — built-in indefinite retry with bounded backoff, reconnect on
online/ tab refocus / bfcache restore,Last-Event-IDmid-stream resume. No app code needed. - Sessions — a durable, run-aware stream channel keyed on a stable
externalId. A Session is the unit of state that owns a multi-run conversation: messages flow through.in, responses through.out, both survive run boundaries. Sessions back the newchat.agentruntime, and you can build on them directly for any pattern that needs durable bi-directional streaming across runs. (#3542) - Add
ai.toolExecute(task)so you can wire a Trigger subtask in as theexecutehandler of an AI SDKtool()while definingdescriptionandinputSchemayourself — useful when you want full control over the tool surface and just need Trigger's subtask machinery for the body. (#3546) - Type
chat.createStartSessionActionagainst your chat agent soclientDatais typed end-to-end on the first turn: (#3684) - Add
regionto the runs list / retrieve API: filter runs by region (runs.list({ region: "..." })/filter[region]=<masterQueue>) and read each run's executing region from the newregionfield on the response. (#3612) - Add
TRIGGER_BUILD_SKIP_REWRITE_TIMESTAMP=1escape hatch for local self-hosted builds whose buildx driver doesn't supportrewrite-timestampalongside push (e.g. orbstack's defaultdockerdriver). (#3618) - Reject overlong
idempotencyKeyvalues at the API boundary so they no longer trip an internal size limit on the underlying unique index and surface as a generic 500. Inputs are capped at 2048 characters — well above whatidempotencyKeys.create()produces (a 64-character hash) and above any realistic raw key. Applies totasks.trigger,tasks.batchTrigger,batch.create(Phase 1 streaming batches),wait.createToken,wait.forDuration, and the input/session stream waitpoint endpoints. Over-limit requests now return a structured 400 instead. (#3560) - AI SDK
useChatintegration — a customChatTransport(useTriggerChatTransport) plugs straight into Vercel AI SDK'suseChathook. Text streaming, tool calls, reasoning, anddata-*parts all work natively over Trigger.dev's realtime streams. No custom API routes needed. - First-turn fast path (
chat.headStart) — opt-in handler that runs the first turn'sstreamTextstep in your warm server process while the agent run boots in parallel, cutting cold-start TTFC by roughly half (measured 2801ms → 1218ms onclaude-sonnet-4-6). The agent owns step 2+ (tool execution, persistence, hooks) so heavy deps stay where they belong. Web Fetch handler works natively in Next.js, Hono, SvelteKit, Remix, Workers, etc.; bridge to Express/Fastify/Koa viachat.toNodeListener. New@trigger.dev/sdk/chat-serversubpath. - **Mul...
trigger.dev v4.4.6
trigger.dev v4.4.6
Upgrade
npx trigger.dev@latest update # npm
pnpm dlx trigger.dev@latest update # pnpm
yarn dlx trigger.dev@latest update # yarn
bunx trigger.dev@latest update # bunSelf-hosted Docker image: ghcr.io/triggerdotdev/trigger.dev:v4.4.6
Release notes
Read the full release notes: https://trigger.dev/changelog/v4-4-6
What's changed
Improvements
- Fail attempts on uncaught exceptions instead of hanging to
MAX_DURATION_EXCEEDED. A NodeEventEmitter(e.g.node-redis) emitting"error"with no.on("error", ...)listener escalates touncaughtException, which the worker previously reported but did not act on — runs drifted to maxDuration with empty attempts. They now fail fast with the original error and statusFAILED, and respect the task's normal retry policy. You should still attach.on("error", ...)listeners to long-lived clients to handle errors gracefully. (#3529)
Bug fixes
- Fix dev workers spinning at 100% CPU after the parent CLI disconnects. Orphaned
trigger-dev-run-worker(and indexer) processes were caught in anuncaughtExceptionfeedback loop: a periodic IPC send viaprocess.sendwould throwERR_IPC_CHANNEL_CLOSEDonce the parent closed the channel, which re-entered the same handler that itself calledprocess.send, scheduled viasetImmediateand amplified by source-map-support'sprepareStackTrace. Fixed by (1) silently dropping packets inZodIpcConnectionwhen the channel is disconnected, (2) adding aprocess.on("disconnect", ...)handler in dev workers so they exit cleanly when the CLI closes the IPC channel, and (3) wrapping alluncaughtException-pathprocess.sendcalls in asafeSendguard that checksprocess.connectedand swallows synchronous throws. (#3491)
All packages: v4.4.6
@trigger.dev/build, @trigger.dev/core, @trigger.dev/python, @trigger.dev/react-hooks, @trigger.dev/redis-worker, @trigger.dev/rsc, @trigger.dev/schema-to-json, @trigger.dev/sdk, trigger.dev
Contributors
Eric Allam, @nicktrn, James Ritchie, @isshaddad, @d-cs, github-actions[bot], Matt Aitken, Saadi Myftija, Oskar Otwinowski
Full changelog: v4.4.5...v4.4.6