Trigger.dev Release Notes

58 release notes curated from 27 sources by the Releasebot Team. Last updated: May 29, 2026

Get this feed:
  • May 29, 2026
    • Date parsed from source:
      May 29, 2026
    • First seen by Releasebot:
      May 29, 2026
    Trigger.dev logo

    Trigger.dev

    build-supervisor-wide-events.rc4

    Trigger.dev adds start_time emission on wide events for supervisor.

    feat(supervisor): emit start_time on wide events

    Original source
  • May 23, 2026
    • Date parsed from source:
      May 23, 2026
    • First seen by Releasebot:
      May 23, 2026
    Trigger.dev logo

    Trigger.dev

    trigger.dev v4.5.0-rc.2

    Trigger.dev releases v4.5.0-rc.2 with smarter agent message handling, slimmer continuation payloads, and a new TriggerClient for running multiple SDK clients side by side. It also fixes chat agent HITL continuations on reasoning-heavy turns.

    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 # bun
    

    Self-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, tool input, provider metadata) stays whatever the snapshot or hydrateMessages returned. Previously a full-message replace overwrote those fields with whatever the client shipped, so a slimmed wire copy landed a tool call with no arguments on the next LLM call. Covers output-available / output-error (HITL addToolOutput) and approval-responded / output-denied (approval flow).

    TriggerChatTransport.sendMessages and AgentChat.sendRaw now slim assistant messages that carry advanced tool parts. The wire payload is just { id, role, parts: [<state + resolution field>] } for submit-message continuations; everything else passes through. Reasoning blobs and full tool inputs no longer ride the wire on every addToolOutput / addToolApproveResponse, so continuation payloads stay well under the .in/append cap on long agent loops.

    Add TriggerClient for 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.agent HITL 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

    Original source
  • All of your release notes in one feed

    Join Releasebot and get updates from Trigger.dev and hundreds of other software products.

    Create account
  • May 23, 2026
    • Date parsed from source:
      May 23, 2026
    • First seen by Releasebot:
      May 23, 2026
    Trigger.dev logo

    Trigger.dev

    v.docker.4.5.0-rc.2: chore: release v4.5.0-rc.2 (#3702)

    Trigger.dev improves chat agent HITL continuations by preserving tool-state changes while slimming wire payloads to avoid oversized loops, and adds TriggerClient for running multiple SDK clients with separate auth, preview branch, and baseURL.

    Summary

    3 improvements, 1 bug fix.

    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, tool input, provider metadata)
    stays whatever the snapshot or hydrateMessages returned. Previously a
    full-message replace overwrote those fields with whatever the client
    shipped, so a slimmed wire copy landed a tool call with no arguments
    on the next LLM call. Covers output-available / output-error (HITL
    addToolOutput) and approval-responded / output-denied (approval
    flow).

    TriggerChatTransport.sendMessages and AgentChat.sendRaw now slim
    assistant messages that carry advanced tool parts. The wire payload is
    just { id, role, parts: [<state + resolution field>] } for
    submit-message continuations; everything else passes through.
    Reasoning blobs and full tool inputs no longer ride the wire on every
    addToolOutput / addToolApproveResponse, so continuation payloads
    stay well under the .in/append cap on long agent loops.

    Add TriggerClient for 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.agent HITL continuations on reasoning-heavy turns. Two
    changes that work together:
    (#3719)

    Raw changeset output

    ⚠️⚠️⚠️⚠️⚠️⚠️

    main is currently in pre mode so this branch has prereleases
    rather than normal releases. If you want to exit prereleases, run
    changeset pre exit on main.

    ⚠️️⚠️⚠️⚠️⚠️⚠️

    Releases

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    [email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Fix chat.agent HITL continuations on reasoning-heavy turns. Two
    changes that work together:
    (#3719)

    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, tool input, provider metadata)
    stays whatever the snapshot or hydrateMessages returned. Previously a
    full-message replace overwrote those fields with whatever the client
    shipped, so a slimmed wire copy landed a tool call with no arguments
    on the next LLM call. Covers output-available / output-error (HITL
    addToolOutput) and approval-responded / output-denied (approval
    flow).

    TriggerChatTransport.sendMessages and AgentChat.sendRaw now slim
    assistant messages that carry advanced tool parts. The wire payload is
    just { id, role, parts: [<state + resolution field>] } for
    submit-message continuations; everything else passes through.
    Reasoning blobs and full tool inputs no longer ride the wire on every
    addToolOutput / addToolApproveResponse, so continuation payloads
    stay well under the .in/append cap on long agent loops.

    Note: onValidateMessages receives the slim wire on HITL turns. If you
    call validateUIMessages from ai against the full messages array it
    will reject the slim assistant; filter to user messages (or skip on HITL
    turns) — see the updated docstring on onValidateMessages for the
    recommended pattern.

    For hydrateMessages hooks that persist the chain, this release also
    adds a small helper to the @trigger.dev/sdk/ai surface:

    import { chat, upsertIncomingMessage } from "@trigger.dev/sdk/ai";
    chat.agent({
    hydrateMessages: async ({ chatId, trigger, incomingMessages }) =&gt; {
    const record = await db.chat.findUnique({ where: { id: chatId } });
    const stored = record?.messages ?? [];
    if (upsertIncomingMessage(stored, { trigger, incomingMessages })) {
    await db.chat.update({ where: { id: chatId }, data: { messages: stored }
    });
    }
    return stored;
    },
    });
    

    It pushes fresh user messages by id, no-ops on HITL continuations (the
    incoming shares an id with the existing assistant — the runtime overlays
    the new tool-state advance), and skips on non-submit-message triggers.
    Returns true if it mutated stored so the caller knows whether to
    persist.

    Net effect: chat.addToolOutput(...) /
    chat.addToolApproveResponse(...) on multi-step reasoning agents
    (OpenAI Responses with store: false, Anthropic extended thinking,
    etc.) no longer blows the cap and no longer corrupts the LLM input.

    Add TriggerClient for 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)

    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", payload);
    await preview.runs.list({ status: ["COMPLETED"] });
    

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

    Original source
  • May 21, 2026
    • Date parsed from source:
      May 21, 2026
    • First seen by Releasebot:
      May 22, 2026
    Trigger.dev logo

    Trigger.dev

    trigger.dev v4.5.0-rc.1

    Trigger.dev ships v4.5.0-rc.1 with bug fixes for missing chat.agent skills, more reliable skill folder bundling, and a fix for COULD_NOT_FIND_EXECUTOR when tasks are loaded with await import() inside another task.

    Upgrade

    npx [email protected] update
    pnpm dlx [email protected] update
    yarn dlx [email protected] update
    bunx [email protected] update
    Self-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.agent skills silently missing in trigger dev for projects whose task files read process.env at 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_EXECUTOR when a task's definition is loaded via await import(...) from inside another task's run(). 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

    Original source
  • May 21, 2026
    • Date parsed from source:
      May 21, 2026
    • First seen by Releasebot:
      May 22, 2026
    Trigger.dev logo

    Trigger.dev

    trigger.dev v4.5.0-rc.0

    Trigger.dev ships a major release focused on AI chat and prompt tooling, with code-defined versioned prompts, dashboard overrides, durable sessions, multi-turn chat resilience, and tighter Vercel AI SDK integration. It also adds region filtering, improved retries, and bug fixes.

    Upgrade

    npx [email protected] update
    pnpm dlx [email protected] update
    yarn dlx [email protected] update
    bunx [email protected] update
    

    Self-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 with chat.agent via chat.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 compiled text, resolved model, version, and labels. Standalone prompts.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 any generateText / streamText call and every generation span links to the prompt in the dashboard alongside its input variables, model, tokens, and cost.

    chat.agent integration — chat.prompt.set(resolved) stores the resolved prompt run-scoped; chat.toStreamTextOptions({ registry }) pulls system, model (resolved via the AI SDK provider registry), temperature / maxTokens / etc., and telemetry into a single spread for streamText.

    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 onBoot to chat.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 initialize chat.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 useChat integration — a custom ChatTransport (useTriggerChatTransport) plugs straight into Vercel AI SDK's useChat hook. Text streaming, tool calls, reasoning, and data-* 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's streamText step in your warm server process while the agent run boots in parallel, cutting cold-start TTFC by roughly half (measured 2801ms → 1218ms on claude-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 via chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.

    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: true reconnects via lastEventId so clients only see new chunks. sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools, in-progress reasoning) are auto-cleaned.

    Tool approvals (HITL) — tools with needsApproval: true pause until the user approves or denies via addToolApprovalResponse. The runtime reconciles the updated assistant message by ID and continues streamText.

    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages + onAction only — no turn hooks, no run(). onAction can return a StreamTextResult for a model response, or void for side-effect-only.

    Typed state primitives — chat.local<T> for per-run state accessible from hooks, run(), tools, and subtasks (auto-serialized through ai.toolExecute); chat.store for typed shared data between agent and client; chat.history for reading and mutating the message chain; clientDataSchema for typed clientData in every hook.

    chat.toStreamTextOptions() — one spread into streamText wires up versioned system Prompts, model resolution, telemetry metadata, compaction, steering, and background injection.

    Multi-tab coordination — multiTab: true + useMultiTabChat prevents duplicate sends and syncs state across browser tabs via BroadcastChannel. 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-ID mid-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 new chat.agent runtime, 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 the execute handler of an AI SDK tool() while defining description and inputSchema yourself — useful when you want full control over the tool surface and just need Trigger's subtask machinery for the body. (#3546)

    Type chat.createStartSessionAction against your chat agent so clientData is typed end-to-end on the first turn: (#3684)

    Add region to the runs list / retrieve API: filter runs by region (runs.list({ region: "..." }) / filter[region]=<masterQueue>) and read each run's executing region from the new region field on the response. (#3612)

    Add TRIGGER_BUILD_SKIP_REWRITE_TIMESTAMP=1 escape hatch for local self-hosted builds whose buildx driver doesn't support rewrite-timestamp alongside push (e.g. orbstack's default docker driver). (#3618)

    Reject overlong idempotencyKey values 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 what idempotencyKeys.create() produces (a 64-character hash) and above any realistic raw key. Applies to tasks.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 useChat integration — a custom ChatTransport (useTriggerChatTransport) plugs straight into Vercel AI SDK's useChat hook. Text streaming, tool calls, reasoning, and data-* 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's streamText step in your warm server process while the agent run boots in parallel, cutting cold-start TTFC by roughly half (measured 2801ms → 1218ms on claude-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 via chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.

    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: true reconnects via lastEventId so clients only see new chunks. sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools, in-progress reasoning) are auto-cleaned.

    Tool approvals (HITL) — tools with needsApproval: true pause until the user approves or denies via addToolApprovalResponse. The runtime reconciles the updated assistant message by ID and continues streamText.

    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages + onAction only — no turn hooks, no run(). onAction can return a StreamTextResult for a model response, or void for side-effect-only.

    Typed state primitives — chat.local<T> for per-run state accessible from hooks, run(), tools, and subtasks (auto-serialized through ai.toolExecute); chat.store for typed shared data between agent and client; chat.history for reading and mutating the message chain; clientDataSchema for typed clientData in every hook.

    chat.toStreamTextOptions() — one spread into streamText wires up versioned system Prompts, model resolution, telemetry metadata, compaction, steering, and background injection.

    Multi-tab coordination — multiTab: true + useMultiTabChat prevents duplicate sends and syncs state across browser tabs via BroadcastChannel. 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-ID mid-stream resume. No app code needed.

    Retry TASK_PROCESS_SIGSEGV task crashes under the user's retry policy instead of failing the run on the first segfault. SIGSEGV in Node tasks is frequently non-deterministic (native addon races, JIT/GC interaction, near-OOM in native code, host issues), so retrying on a fresh process often succeeds. The retry is gated by the task's existing retry config + maxAttempts — same path TASK_PROCESS_SIGTERM and uncaught exceptions already use — so tasks without a retry policy still fail fast. (#3552)

    The public interfaces for a plugin system. Initially consolidated authentication and authorization interfaces. (#3499)

    Add MollifierBuffer and MollifierDrainer primitives for trigger burst smoothing. (#3614)

    Bug fixes

    Fix LocalsKey<T> type incompatibility across dual-package builds. The phantom value-type brand no longer uses a module-level unique symbol, so a single TypeScript compilation that resolves the type from both the ESM and CJS outputs (which can happen under certain pnpm hoisting layouts) no longer sees two structurally-incompatible variants of the same type. (#3626)

    All packages: v4.5.0-rc.0

    @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.0...v4.5.0-rc.0

    Original source
  • May 21, 2026
    • Date parsed from source:
      May 21, 2026
    • First seen by Releasebot:
      May 22, 2026
    Trigger.dev logo

    Trigger.dev

    v.docker.4.5.0-rc.1: chore: release v4.5.0-rc.1 (#3691)

    Trigger.dev fixes two runtime and CLI bugs, making chat.agent skills bundle reliably in trigger dev and resolving COULD_NOT_FIND_EXECUTOR when tasks are loaded with await import() from inside another task. This prerelease also updates related packages.

    Summary

    2 bug fixes.

    Bug fixes

    Fix chat.agent skills silently missing in trigger dev for projects whose task files read process.env at 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_EXECUTOR when a task's definition is loaded via await import(...) from inside another task's run(). The runtime workers now register such tasks with a sentinel file context, and the catalog logs a one-time warning per task id.

    (#3688)

    Raw changeset output

    ⚠️⚠️⚠️⚠️⚠️⚠️

    main is currently in pre mode so this branch has prereleases rather than normal releases. If you want to exit prereleases, run changeset pre exit on main.

    ⚠️⚠️⚠️⚠️⚠️⚠️

    Releases

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    [email protected]

    Patch Changes

    Fix chat.agent skills silently missing in trigger dev for projects whose task files read process.env at 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_EXECUTOR when a task's definition is loaded via await import(...) from inside another task's run(). The runtime workers now register such tasks with a sentinel file context, and the catalog logs a one-time warning per task id.

    (#3688)

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Fix COULD_NOT_FIND_EXECUTOR when a task's definition is loaded via await import(...) from inside another task's run(). The runtime workers now register such tasks with a sentinel file context, and the catalog logs a one-time warning per task id.

    (#3688)

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

    Original source
  • May 21, 2026
    • Date parsed from source:
      May 21, 2026
    • First seen by Releasebot:
      May 22, 2026
    Trigger.dev logo

    Trigger.dev

    v.docker.4.5.0-rc.0: chore: release v4.5.0-rc.0 (#3563)

    Trigger.dev releases major AI chat and prompt tooling, adding code-defined versioned prompts, durable Sessions for multi-turn chats, Vercel AI SDK useChat integration, agent lifecycle hooks, tool approvals, skills, and broader reliability and API improvements.

    Summary

    44 improvements, 1 bug fix.

    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 with chat.agent via chat.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 compiled text, resolved model, version, and labels. Standalone
    prompts.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 any generateText / streamText call and every generation
    span links to the prompt in the dashboard alongside its input variables,
    model, tokens, and cost.

    chat.agent integration — chat.prompt.set(resolved) stores the
    resolved prompt run-scoped; chat.toStreamTextOptions({ registry })
    pulls system, model (resolved via the AI SDK provider registry),
    temperature / maxTokens / etc., and telemetry into a single spread
    for streamText.

    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 onBoot to chat.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
    initialize chat.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 useChat integration — a custom
    ChatTransport
    (useTriggerChatTransport) plugs straight into Vercel AI SDK's
    useChat hook. Text streaming, tool calls, reasoning, and data-*
    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's streamText step in your warm server process while the
    agent run boots in parallel, cutting cold-start TTFC by roughly half
    (measured 2801ms → 1218ms on claude-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 via
    chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.

    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: true reconnects via lastEventId so clients only see new chunks.
    sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools,
    in-progress reasoning) are auto-cleaned.

    Tool approvals (HITL) — tools with needsApproval: true pause
    until the user approves or denies via addToolApprovalResponse. The
    runtime reconciles the updated assistant message by ID and continues
    streamText.

    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages +
    onAction only — no turn hooks, no run(). onAction can return a
    StreamTextResult for a model response, or void for side-effect-only.

    Typed state primitives — chat.local<T> for per-run state
    accessible from hooks, run(), tools, and subtasks (auto-serialized
    through ai.toolExecute); chat.store for typed shared data between
    agent and client; chat.history for reading and mutating the message
    chain; clientDataSchema for typed clientData in every hook.

    chat.toStreamTextOptions() — one spread into streamText wires
    up versioned system Prompts,
    model resolution, telemetry metadata, compaction, steering, and
    background injection.

    Multi-tab coordination — multiTab: true + useMultiTabChat
    prevents duplicate sends and syncs state across browser tabs via
    BroadcastChannel. 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-ID mid-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 new chat.agent runtime,
    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 the
    execute handler of an AI SDK tool() while defining description and
    inputSchema yourself — useful when you want full control over the tool
    surface and just need Trigger's subtask machinery for the body.
    (#3546)

    Type chat.createStartSessionAction against your chat agent so
    clientData is typed end-to-end on the first turn:
    (#3684)

    Add region to the runs list / retrieve API: filter runs by region
    (runs.list({ region: "..." }) / filter[region]=<masterQueue>) and
    read each run's executing region from the new region field on the
    response.
    (#3612)

    Add TRIGGER_BUILD_SKIP_REWRITE_TIMESTAMP=1 escape hatch for local
    self-hosted builds whose buildx driver doesn't support
    rewrite-timestamp alongside push (e.g. orbstack's default docker
    driver).
    (#3618)

    Reject overlong idempotencyKey values 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 what idempotencyKeys.create() produces (a 64-character hash) and
    above any realistic raw key. Applies to tasks.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 useChat integration — a custom
    ChatTransport
    (useTriggerChatTransport) plugs straight into Vercel AI SDK's
    useChat hook. Text streaming, tool calls, reasoning, and data-*
    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's streamText step in your warm server process while the
    agent run boots in parallel, cutting cold-start TTFC by roughly half
    (measured 2801ms → 1218ms on claude-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 via
    chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.

    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: true reconnects via lastEventId so clients only see new chunks.
    sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools,
    in-progress reasoning) are auto-cleaned.

    Tool approvals (HITL) — tools with needsApproval: true pause
    until the user approves or denies via addToolApprovalResponse. The
    runtime reconciles the updated assistant message by ID and continues
    streamText.

    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages +
    onAction only — no turn hooks, no run(). onAction can return a
    StreamTextResult for a model response, or void for side-effect-only.

    Typed state primitives — chat.local<T> for per-run state
    accessible from hooks, run(), tools, and subtasks (auto-serialized
    through ai.toolExecute); chat.store for typed shared data between
    agent and client; chat.history for reading and mutating the message
    chain; clientDataSchema for typed clientData in every hook.

    chat.toStreamTextOptions() — one spread into streamText wires
    up versioned system Prompts,
    model resolution, telemetry metadata, compaction, steering, and
    background injection.

    Multi-tab coordination — multiTab: true + useMultiTabChat
    prevents duplicate sends and syncs state across browser tabs via
    BroadcastChannel. 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-ID mid-stream resume. No app code needed.

    Retry TASK_PROCESS_SIGSEGV task crashes under the user's retry
    policy instead of failing the run on the first segfault. SIGSEGV in Node
    tasks is frequently non-deterministic (native addon races, JIT/GC
    interaction, near-OOM in native code, host issues), so retrying on a
    fresh process often succeeds. The retry is gated by the task's existing
    retry config + maxAttempts — same path TASK_PROCESS_SIGTERM and
    uncaught exceptions already use — so tasks without a retry policy still
    fail fast.
    (#3552)

    The public interfaces for a plugin system. Initially consolidated
    authentication and authorization interfaces.
    (#3499)

    Add MollifierBuffer and MollifierDrainer primitives for trigger burst
    smoothing.
    (#3614)

    Bug fixes

    Fix LocalsKey<T> type incompatibility across dual-package builds.
    The phantom value-type brand no longer uses a module-level unique symbol, so a single TypeScript compilation that resolves the type from
    both the ESM and CJS outputs (which can happen under certain pnpm
    hoisting layouts) no longer sees two structurally-incompatible variants
    of the same type.
    (#3626)

    Raw changeset output

    ⚠️⚠️⚠️⚠️⚠️⚠️
    main is currently in pre mode so this branch has prereleases
    rather than normal releases. If you want to exit prereleases, run
    changeset pre exit on main.
    ⚠️⚠️⚠️⚠️⚠️⚠️

    Releases

    @trigger.dev/[email protected]

    Minor Changes

    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 with chat.agent via chat.prompt.set() +
    chat.toStreamTextOptions().
    (#3629)

    import { prompts } from "@trigger.dev/sdk";
    import { generateText } from "ai";
    import { openai } from "@ai-sdk/openai";
    import { z } from "zod";
    
    export const supportPrompt = prompts.define({
      id: "customer-support",
      model: "gpt-4o",
      config: { temperature: 0.7 },
      variables: z.object({
        customerName: z.string(),
        plan: z.string(),
        issue: z.string(),
      }),
      content: `You are a support agent for Acme.
    Customer: {{customerName}} ({{plan}} plan)
    Issue: {{issue}}`,
    });
    
    const resolved = await supportPrompt.resolve({
      customerName: "Alice",
      plan: "Pro",
      issue: "Can't access billing",
    });
    
    const result = await generateText({
      model: openai(resolved.model ?? "gpt-4o"),
      system: resolved.text,
      prompt: "Can't access billing",
      ...resolved.toAISDKTelemetry(),
    });
    

    What you get:

    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 compiled text, resolved model, version, and labels. Standalone
    prompts.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 any generateText / streamText call and every generation
    span links to the prompt in the dashboard alongside its input variables,
    model, tokens, and cost.

    chat.agent integration — chat.prompt.set(resolved) stores the
    resolved prompt run-scoped; chat.toStreamTextOptions({ registry })
    pulls system, model (resolved via the AI SDK provider registry),
    temperature / maxTokens / etc., and telemetry into a single spread
    for streamText.

    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.

    See /docs/ai/prompts for the full
    reference — template syntax, version resolution order, override
    workflow, and type utilities (PromptHandle, PromptIdentifier,
    PromptVariables).

    Adds onBoot to chat.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
    initialize chat.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)

    const userContext = chat.local<{ name: string; plan: string }>({ id:
    "userContext" });
    
    export const myChat = chat.agent({
      id: "my-chat",
      onBoot: async ({ clientData, continuation }) => {
        const user = await db.user.findUnique({ where: { id: clientData.userId }
        });
        userContext.init({ name: user.name, plan: user.plan });
      },
      run: async ({ messages, signal }) =>
        streamText({ model: openai("gpt-4o"), messages, abortSignal: signal }),
    });
    

    Use onBoot (not onChatStart) for state setup that must run every
    time a worker picks up the chat — onChatStart fires once per chat and
    won't run on continuation, leaving chat.local uninitialized when
    run() tries to use it.

    AI Agents — run AI SDK chat completions as durable Trigger.dev
    agents instead of fragile API routes. Define an agent in one function,
    point useChat at it from React, and the conversation survives page
    refreshes, network blips, and process restarts.
    (#3543)

    import { chat } from "@trigger.dev/sdk/ai";
    import { streamText } from "ai";
    import { openai } from "@ai-sdk/openai";
    
    export const myChat = chat.agent({
      id: "my-chat",
      run: async ({ messages, signal }) =>
        streamText({ model: openai("gpt-4o"), messages, abortSignal: signal }),
    });
    
    import { useChat } from "@ai-sdk/react";
    import { useTriggerChatTransport } from "@trigger.dev/sdk/chat/react";
    
    const transport = useTriggerChatTransport({ task: "my-chat",
    accessToken, startSession });
    const { messages, sendMessage } = useChat({ transport });
    

    What you get:

    AI SDK useChat integration — a custom
    ChatTransport
    (useTriggerChatTransport) plugs straight into Vercel AI SDK's
    useChat hook. Text streaming, tool calls, reasoning, and data-*
    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's streamText step in your warm server process while the
    agent run boots in parallel, cutting cold-start TTFC by roughly half
    (measured 2801ms → 1218ms on claude-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 via
    chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.

    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: true reconnects via lastEventId so clients only see new chunks.
    sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools,
    in-progress reasoning) are auto-cleaned.

    Tool approvals (HITL) — tools with needsApproval: true pause
    until the user approves or denies via addToolApprovalResponse. The
    runtime reconciles the updated assistant message by ID and continues
    streamText.

    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages +
    onAction only — no turn hooks, no run(). onAction can return a
    StreamTextResult for a model response, or void for side-effect-only.

    Typed state primitives — chat.local<T> for per-run state
    accessible from hooks, run(), tools, and subtasks (auto-serialized
    through ai.toolExecute); chat.store for typed shared data between
    agent and client; chat.history for reading and mutating the message
    chain; clientDataSchema for typed clientData in every hook.

    chat.toStreamTextOptions() — one spread into streamText wires
    up versioned system Prompts,
    model resolution, telemetry metadata, compaction, steering, and
    background injection.

    Multi-tab coordination — multiTab: true + useMultiTabChat
    prevents duplicate sends and syncs state across browser tabs via
    BroadcastChannel. 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-ID mid-stream resume. No app code needed.

    See /docs/ai-chat for the
    full surface — quick start, three backend approaches (chat.agent,
    chat.createSession, raw task), persistence and code-sandbox patterns,
    type-level guides, and API reference.

    Add read primitives to chat.history for HITL flows:
    getPendingToolCalls(), getResolvedToolCalls(),
    extractNewToolResults(message), getChain(), and
    findMessage(messageId). These lift the accumulator-walking logic that
    customers building human-in-the-loop tools were re-implementing into the
    SDK. (#3543)

    Use getPendingToolCalls() to gate fresh user turns while a tool call
    is awaiting an answer. Use extractNewToolResults(message) to dedup
    tool results when persisting to your own store — the helper returns only
    the parts whose toolCallId is not already resolved on the chain.

    const pending = chat.history.getPendingToolCalls();
    if (pending.length &gt; 0) {
      // an addToolOutput is expected before a new user message
    }
    onTurnComplete: async ({ responseMessage }) =&gt; {
      const newResults = chat.history.extractNewToolResults(responseMessage);
      for (const r of newResults) {
        await db.toolResults.upsert({ id: r.toolCallId, output: r.output,
    errorText: r.errorText });
      }
    };
    

    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 new chat.agent runtime,
    and you can build on them directly for any pattern that needs durable
    bi-directional streaming across runs.
    (#3542)

    import { sessions, tasks } from "@trigger.dev/sdk";
    // Trigger a task and subscribe to its session output in one call
    const { runId, stream } = await tasks.triggerAndSubscribe("my-task",
    payload, {
    externalId: "user-456",
    });
    for await (const chunk of stream) {
    // ...
    }
    // Enumerate existing sessions (powers inbox-style UIs without a
    // separate index)
    for await (const s of sessions.list({ type: "chat.agent", tag:
    "user:user-456" })) {
      console.log(s.id, s.externalId, s.createdAt, s.closedAt);
    }
    

    See /docs/ai-chat/overview
    for the full surface — Sessions powers the durable, resumable chat
    runtime described there.

    Patch Changes

    Add Agent Skills for chat.agent. Drop a folder with a SKILL.md and
    any helper scripts/references next to your task code, register it with
    skills.define({ id, path }), and the CLI bundles it into the deploy
    image automatically — no trigger.config.ts changes. The agent gets a
    one-line summary in its system prompt and discovers full instructions on
    demand via loadSkill, with bash and readFile tools scoped
    per-skill (path-traversal guards, output caps, abort-signal
    propagation).
    (#3543)

    const pdfSkill = skills.define({ id: "pdf-extract", path:
    "./skills/pdf-extract" });
    chat.skills.set([await pdfSkill.local()]);
    

    Built on the AI SDK cookbook
    pattern — portable
    across providers. SDK + CLI only for now; dashboard-editable SKILL.md
    text is on the roadmap.

    Add ai.toolExecute(task) so you can wire a Trigger subtask in as the
    execute handler of an AI SDK tool() while defining description and
    inputSchema yourself — useful when you want full control over the tool
    surface and just need Trigger's subtask machinery for the body.
    (#3546)

    const myTool = tool({
      description: "...",
      inputSchema: z.object({ ... }),
      execute: ai.toolExecute(mySubtask),
    });
    

    ai.tool(task) (toolFromTask) keeps doing the all-in-one wrap and now
    aligns its return type with AI SDK's ToolSet. Minimum ai peer raised
    to ^6.0.116 to avoid cross-version ToolSet mismatches in monorepos.

    Stamp gen_ai.conversation.id (the chat id) on every span and metric
    emitted from inside a chat.task or chat.agent run. Lets you filter
    dashboard spans, runs, and metrics by the chat conversation that
    produced them — independent of the run boundary, so multi-run chats
    correlate cleanly. No code changes required on the user side.
    (#3543)

    Type chat.createStartSessionAction against your chat agent so
    clientData is typed end-to-end on the first turn:
    (#3684)

    import { chat } from "@trigger.dev/sdk/ai";
    import type { myChat } from "@/trigger/chat";
    
    export const startChatSession = chat.createStartSessionAction("my-chat");
    // In the browser, threaded from the transport's typed startSession
    callback:
    const transport = useTriggerChatTransport({
      task: "my-chat",
      startSession: ({ chatId, clientData }) =&gt; startChatSession({ chatId,
    clientData }),
      // ...
    });
    

    ChatStartSessionParams gains a typed clientData field — folded into
    the first run's payload.metadata so onPreload / onChatStart see
    the same shape per-turn metadata carries via the transport. The opaque
    session-level metadata field is unchanged.

    Unit-test chat.agent definitions offline with mockChatAgent from
    @trigger.dev/sdk/ai/test. Drives a real agent's turn loop in-process —
    no network, no task runtime — so you can send messages, actions, and
    stop signals via driver methods, inspect captured output chunks, and
    verify hooks fire. Pairs with MockLanguageModelV3 from ai/test for
    model mocking. setupLocals lets you pre-seed locals (DB clients,
    service stubs) before run() starts.
    (#3543)

    The broader runInMockTaskContext harness it's built on lives at
    @trigger.dev/core/v3/test — useful for unit-testing any task code, not
    just chat.

    Add region to the runs list / retrieve API: filter runs by region
    (runs.list({ region: "..." }) / filter[region]=<masterQueue>) and
    read each run's executing region from the new region field on the
    response.
    (#3612)

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Add Agent Skills for chat.agent. Drop a folder with a SKILL.md and
    any helper scripts/references next to your task code, register it with
    skills.define({ id, path }), and the CLI bundles it into the deploy
    image automatically — no trigger.config.ts changes. The agent gets a
    one-line summary in its system prompt and discovers full instructions on
    demand via loadSkill, with bash and readFile tools scoped
    per-skill (path-traversal guards, output caps, abort-signal
    propagation).
    (#3543)

    const pdfSkill = skills.define({ id: "pdf-extract", path:
    "./skills/pdf-extract" });
    chat.skills.set([await pdfSkill.local()]);
    

    Built on the AI SDK cookbook
    pattern — portable
    across providers. SDK + CLI only for now; dashboard-editable SKILL.md
    text is on the roadmap.

    Updated dependencies:
    @trigger.dev/[email protected]
    [email protected]

    Patch Changes

    Add Agent Skills for chat.agent. Drop a folder with a SKILL.md and
    any helper scripts/references next to your task code, register it with
    skills.define({ id, path }), and the CLI bundles it into the deploy
    image automatically — no trigger.config.ts changes. The agent gets a
    one-line summary in its system prompt and discovers full instructions on
    demand via loadSkill, with bash and readFile tools scoped
    per-skill (path-traversal guards, output caps, abort-signal
    propagation).
    (#3543)

    const pdfSkill = skills.define({ id: "pdf-extract", path:
    "./skills/pdf-extract" });
    chat.skills.set([await pdfSkill.local()]);
    

    Built on the AI SDK cookbook
    pattern — portable
    across providers. SDK + CLI only for now; dashboard-editable SKILL.md
    text is on the roadmap.

    Add TRIGGER_BUILD_SKIP_REWRITE_TIMESTAMP=1 escape hatch for local
    self-hosted builds whose buildx driver doesn't support
    rewrite-timestamp alongside push (e.g. orbstack's default docker
    driver).
    (#3618)

    The CLI MCP server's agent-chat tools (start_agent_chat,
    send_agent_message, close_agent_chat) now run on the new Sessions
    primitive, so AI assistants driving a chat.agent get the same
    idempotent-by-chatId, durable-across-runs behavior the browser
    transport gets. Required PAT scopes go from write:inputStreams to
    read:sessions + write:sessions.
    (#3546)

    MCP list_runs tool: add a region filter input and surface each
    run's executing region in the formatted summary.
    (#3612)

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Add Agent Skills for chat.agent. Drop a folder with a SKILL.md and
    any helper scripts/references next to your task code, register it with
    skills.define({ id, path }), and the CLI bundles it into the deploy
    image automatically — no trigger.config.ts changes. The agent gets a
    one-line summary in its system prompt and discovers full instructions on
    demand via loadSkill, with bash and readFile tools scoped
    per-skill (path-traversal guards, output caps, abort-signal
    propagation).
    (#3543)

    const pdfSkill = skills.define({ id: "pdf-extract", path:
    "./skills/pdf-extract" });
    chat.skills.set([await pdfSkill.local()]);
    

    Built on the AI SDK cookbook
    pattern — portable
    across providers. SDK + CLI only for now; dashboard-editable SKILL.md
    text is on the roadmap.

    Reject overlong idempotencyKey values 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 what idempotencyKeys.create() produces (a 64-character hash) and
    above any realistic raw key. Applies to tasks.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 Agents — run AI SDK chat completions as durable Trigger.dev
    agents instead of fragile API routes. Define an agent in one function,
    point useChat at it from React, and the conversation survives page
    refreshes, network blips, and process restarts.
    (#3543)

    import { chat } from "@trigger.dev/sdk/ai";
    import { streamText } from "ai";
    import { openai } from "@ai-sdk/openai";
    
    export const myChat = chat.agent({
      id: "my-chat",
      run: async ({ messages, signal }) =>
        streamText({ model: openai("gpt-4o"), messages, abortSignal: signal }),
    });
    
    import { useChat } from "@ai-sdk/react";
    import { useTriggerChatTransport } from "@trigger.dev/sdk/chat/react";
    
    const transport = useTriggerChatTransport({ task: "my-chat",
    accessToken, startSession });
    const { messages, sendMessage } = useChat({ transport });
    

    What you get:

    AI SDK useChat integration — a custom
    ChatTransport
    (useTriggerChatTransport) plugs straight into Vercel AI SDK's
    useChat hook. Text streaming, tool calls, reasoning, and data-*
    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's streamText step in your warm server process while the
    agent run boots in parallel, cutting cold-start TTFC by roughly half
    (measured 2801ms → 1218ms on claude-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 via
    chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.

    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: true reconnects via lastEventId so clients only see new chunks.
    sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools,
    in-progress reasoning) are auto-cleaned.

    Tool approvals (HITL) — tools with needsApproval: true pause
    until the user approves or denies via addToolApprovalResponse. The
    runtime reconciles the updated assistant message by ID and continues
    streamText.

    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages +
    onAction only — no turn hooks, no run(). onAction can return a
    StreamTextResult for a model response, or void for side-effect-only.

    Typed state primitives — chat.local<T> for per-run state
    accessible from hooks, run(), tools, and subtasks (auto-serialized
    through ai.toolExecute); chat.store for typed shared data between
    agent and client; chat.history for reading and mutating the message
    chain; clientDataSchema for typed clientData in every hook.

    chat.toStreamTextOptions() — one spread into streamText wires
    up versioned system Prompts,
    model resolution, telemetry metadata, compaction, steering, and
    background injection.

    Multi-tab coordination — multiTab: true + useMultiTabChat
    prevents duplicate sends and syncs state across browser tabs via
    BroadcastChannel. 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-ID mid-stream resume. No app code needed.

    See /docs/ai-chat for the
    full surface — quick start, three backend approaches (chat.agent,
    chat.createSession, raw task), persistence and code-sandbox patterns,
    type-level guides, and API reference.

    Stamp gen_ai.conversation.id (the chat id) on every span and metric
    emitted from inside a chat.task or chat.agent run. Lets you filter
    dashboard spans, runs, and metrics by the chat conversation that
    produced them — independent of the run boundary, so multi-run chats
    correlate cleanly. No code changes required on the user side.
    (#3543)

    Fix LocalsKey<T> type incompatibility across dual-package builds.
    The phantom value-type brand no longer uses a module-level unique symbol, so a single TypeScript compilation that resolves the type from
    both the ESM and CJS outputs (which can happen under certain pnpm
    hoisting layouts) no longer sees two structurally-incompatible variants
    of the same type.
    (#3626)

    Unit-test chat.agent definitions offline with mockChatAgent from
    @trigger.dev/sdk/ai/test. Drives a real agent's turn loop in-process —
    no network, no task runtime — so you can send messages, actions, and
    stop signals via driver methods, inspect captured output chunks, and
    verify hooks fire. Pairs with MockLanguageModelV3 from ai/test for
    model mocking. setupLocals lets you pre-seed locals (DB clients,
    service stubs) before run() starts.
    (#3543)

    The broader runInMockTaskContext harness it's built on lives at
    @trigger.dev/core/v3/test — useful for unit-testing any task code, not
    just chat.

    Retry TASK_PROCESS_SIGSEGV task crashes under the user's retry
    policy instead of failing the run on the first segfault. SIGSEGV in Node
    tasks is frequently non-deterministic (native addon races, JIT/GC
    interaction, near-OOM in native code, host issues), so retrying on a
    fresh process often succeeds. The retry is gated by the task's existing
    retry config + maxAttempts — same path TASK_PROCESS_SIGTERM and
    uncaught exceptions already use — so tasks without a retry policy still
    fail fast.
    (#3552)

    Add region to the runs list / retrieve API: filter runs by region
    (runs.list({ region: "..." }) / filter[region]=<masterQueue>) and
    read each run's executing region from the new region field on the
    response.
    (#3612)

    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 new chat.agent runtime,
    and you can build on them directly for any pattern that needs durable
    bi-directional streaming across runs.
    (#3542)

    import { sessions, tasks } from "@trigger.dev/sdk";
    // Trigger a task and subscribe to its session output in one call
    const { runId, stream } = await tasks.triggerAndSubscribe("my-task",
    payload, {
    externalId: "user-456",
    });
    for await (const chunk of stream) {
    // ...
    }
    // Enumerate existing sessions (powers inbox-style UIs without a
    // separate index)
    for await (const s of sessions.list({ type: "chat.agent", tag:
    "user:user-456" })) {
      console.log(s.id, s.externalId, s.createdAt, s.closedAt);
    }
    

    See /docs/ai-chat/overview
    for the full surface — Sessions powers the durable, resumable chat
    runtime described there.

    @trigger.dev/[email protected]

    Patch Changes

    The public interfaces for a plugin system. Initially consolidated
    authentication and authorization interfaces.
    (#3499)

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Add MollifierBuffer and MollifierDrainer primitives for trigger burst
    smoothing.
    (#3614)

    MollifierBuffer (accept, pop, ack, requeue, fail,
    evaluateTrip) is a per-env FIFO over Redis with atomic Lua transitions
    for status tracking. evaluateTrip is a sliding-window trip evaluator
    the webapp gate uses to detect per-env trigger bursts.

    MollifierDrainer pops entries through a polling loop with a
    user-supplied handler. The loop survives transient Redis errors via
    capped exponential backoff (up to 5s), and per-env pop failures don't
    poison the rest of the batch — one env's blip is logged and counted as
    failed for that tick. Rotation is two-level: orgs at the top, envs
    within each org. The buffer maintains mollifier:orgs and
    mollifier:org-envs:${orgId} atomically with per-env queues, so the
    drainer walks orgs → envs directly without an in-memory cache. The
    maxOrgsPerTick option (default 500) caps how many orgs are scheduled
    per tick; for each picked org, one env is popped (rotating round-robin
    within the org). An org with N envs gets the same per-tick scheduling
    slot as an org with 1 env, so tenant-level drainage throughput is
    determined by org count rather than env count.

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:
    @trigger.dev/[email protected]

    Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

    Original source
  • May 21, 2026
    • Date parsed from source:
      May 21, 2026
    • First seen by Releasebot:
      May 22, 2026
    Trigger.dev logo

    Trigger.dev

    helm-v4.5.0-rc.1: chore: release v4.5.0-rc.1 (#3691)

    Trigger.dev fixes two runtime issues in prerelease updates, restoring chat.agent skill bundling in trigger dev and resolving COULD_NOT_FIND_EXECUTOR for tasks loaded with await import() inside another task run.

    Summary

    2 bug fixes.

    Bug fixes

    Fix chat.agent skills silently missing in trigger dev for projects whose task files read process.env at 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_EXECUTOR when a task's definition is loaded via await import(...) from inside another task's run(). The runtime workers now register such tasks with a sentinel file context, and the catalog logs a one-time warning per task id.

    (#3688)

    Raw changeset output

    ⚠️⚠️⚠️⚠️⚠️⚠️

    main is currently in pre mode so this branch has prereleases rather than normal releases. If you want to exit prereleases, run changeset pre exit on main.

    ⚠️⚠️⚠️⚠️⚠️⚠️

    Releases

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    [email protected]

    Patch Changes

    Fix chat.agent skills silently missing in trigger dev for projects whose task files read process.env at 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_EXECUTOR when a task's definition is loaded via await import(...) from inside another task's run(). The runtime workers now register such tasks with a sentinel file context, and the catalog logs a one-time warning per task id.

    (#3688)

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Fix COULD_NOT_FIND_EXECUTOR when a task's definition is loaded via await import(...) from inside another task's run(). The runtime workers now register such tasks with a sentinel file context, and the catalog logs a one-time warning per task id.

    (#3688)

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    @trigger.dev/[email protected]

    Patch Changes

    Updated dependencies:

    @trigger.dev/[email protected]

    Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

    Original source
  • May 21, 2026
    • Date parsed from source:
      May 21, 2026
    • First seen by Releasebot:
      May 22, 2026
    Trigger.dev logo

    Trigger.dev

    helm-v4.5.0-rc.0: chore: release v4.5.0-rc.0 (#3563)

    Trigger.dev adds AI Prompts, durable chat.agent sessions, and a richer AI SDK integration with useChat transport, headStart, tool approvals, and multi-turn resilience. It also brings new workflow hooks, session APIs, region filtering, and a few reliability fixes.

    Summary
    44 improvements, 1 bug fix.
    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 with chat.agent via chat.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 compiled text, resolved model, version, and labels. Standalone
    prompts.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 any generateText / streamText call and every generation
    span links to the prompt in the dashboard alongside its input variables,
    model, tokens, and cost.
    chat.agent integration — chat.prompt.set(resolved) stores the
    resolved prompt run-scoped; chat.toStreamTextOptions({ registry })
    pulls system, model (resolved via the AI SDK provider registry),
    temperature / maxTokens / etc., and telemetry into a single spread
    for streamText.
    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 onBoot to chat.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
    initialize chat.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 useChat integration — a custom
    ChatTransport
    (useTriggerChatTransport) plugs straight into Vercel AI SDK's
    useChat hook. Text streaming, tool calls, reasoning, and data-*
    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's streamText step in your warm server process while the
    agent run boots in parallel, cutting cold-start TTFC by roughly half
    (measured 2801ms → 1218ms on claude-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 via
    chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.
    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: true reconnects via lastEventId so clients only see new chunks.
    sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools,
    in-progress reasoning) are auto-cleaned.
    Tool approvals (HITL) — tools with needsApproval: true pause
    until the user approves or denies via addToolApprovalResponse. The
    runtime reconciles the updated assistant message by ID and continues
    streamText.
    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages +
    onAction only — no turn hooks, no run(). onAction can return a
    StreamTextResult for a model response, or void for side-effect-only.
    Typed state primitives — chat.local<T> for per-run state
    accessible from hooks, run(), tools, and subtasks (auto-serialized
    through ai.toolExecute); chat.store for typed shared data between
    agent and client; chat.history for reading and mutating the message
    chain; clientDataSchema for typed clientData in every hook.
    chat.toStreamTextOptions() — one spread into streamText wires
    up versioned system Prompts,
    model resolution, telemetry metadata, compaction, steering, and
    background injection.
    Multi-tab coordination — multiTab: true + useMultiTabChat
    prevents duplicate sends and syncs state across browser tabs via
    BroadcastChannel. 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-ID mid-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 new chat.agent runtime,
    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 the
    execute handler of an AI SDK tool() while defining description and
    inputSchema yourself — useful when you want full control over the tool
    surface and just need Trigger's subtask machinery for the body.
    (#3546)
    Type chat.createStartSessionAction against your chat agent so
    clientData is typed end-to-end on the first turn:
    (#3684)
    Add region to the runs list / retrieve API: filter runs by region
    (runs.list({ region: "..." }) / filter[region]=<masterQueue>) and
    read each run's executing region from the new region field on the
    response.
    (#3612)
    Add TRIGGER_BUILD_SKIP_REWRITE_TIMESTAMP=1 escape hatch for local
    self-hosted builds whose buildx driver doesn't support
    rewrite-timestamp alongside push (e.g. orbstack's default docker
    driver).
    (#3618)
    Reject overlong idempotencyKey values 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 what idempotencyKeys.create() produces (a 64-character hash) and
    above any realistic raw key. Applies to tasks.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 useChat integration — a custom
    ChatTransport
    (useTriggerChatTransport) plugs straight into Vercel AI SDK's
    useChat hook. Text streaming, tool calls, reasoning, and data-*
    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's streamText step in your warm server process while the
    agent run boots in parallel, cutting cold-start TTFC by roughly half
    (measured 2801ms → 1218ms on claude-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 via
    chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.
    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: true reconnects via lastEventId so clients only see new chunks.
    sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools,
    in-progress reasoning) are auto-cleaned.
    Tool approvals (HITL) — tools with needsApproval: true pause
    until the user approves or denies via addToolApprovalResponse. The
    runtime reconciles the updated assistant message by ID and continues
    streamText.
    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages +
    onAction only — no turn hooks, no run(). onAction can return a
    StreamTextResult for a model response, or void for side-effect-only.
    Typed state primitives — chat.local<T> for per-run state
    accessible from hooks, run(), tools, and subtasks (auto-serialized
    through ai.toolExecute); chat.store for typed shared data between
    agent and client; chat.history for reading and mutating the message
    chain; clientDataSchema for typed clientData in every hook.
    chat.toStreamTextOptions() — one spread into streamText wires
    up versioned system Prompts,
    model resolution, telemetry metadata, compaction, steering, and
    background injection.
    Multi-tab coordination — multiTab: true + useMultiTabChat
    prevents duplicate sends and syncs state across browser tabs via
    BroadcastChannel. 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-ID mid-stream resume. No app code needed.
    Retry TASK_PROCESS_SIGSEGV task crashes under the user's retry
    policy instead of failing the run on the first segfault. SIGSEGV in Node
    tasks is frequently non-deterministic (native addon races, JIT/GC
    interaction, near-OOM in native code, host issues), so retrying on a
    fresh process often succeeds. The retry is gated by the task's existing
    retry config + maxAttempts — same path TASK_PROCESS_SIGTERM and
    uncaught exceptions already use — so tasks without a retry policy still
    fail fast.
    (#3552)
    The public interfaces for a plugin system. Initially consolidated
    authentication and authorization interfaces.
    (#3499)
    Add MollifierBuffer and MollifierDrainer primitives for trigger burst
    smoothing.
    (#3614)
    Bug fixes
    Fix LocalsKey<T> type incompatibility across dual-package builds.
    The phantom value-type brand no longer uses a module-level unique symbol, so a single TypeScript compilation that resolves the type from
    both the ESM and CJS outputs (which can happen under certain pnpm
    hoisting layouts) no longer sees two structurally-incompatible variants
    of the same type.
    (#3626)
    Raw changeset output
    ⚠️⚠️⚠️⚠️⚠️⚠️
    main is currently in pre mode so this branch has prereleases
    rather than normal releases. If you want to exit prereleases, run
    changeset pre exit on main.
    ⚠️⚠️⚠️⚠️⚠️⚠️
    Releases
    @trigger.dev/[email protected]
    Minor Changes
    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 with chat.agent via chat.prompt.set() +
    chat.toStreamTextOptions().
    (#3629)
    import { prompts } from "@trigger.dev/sdk";
    import { generateText } from "ai";
    import { openai } from "@ai-sdk/openai";
    import { z } from "zod";
    export const supportPrompt = prompts.define({
    id: "customer-support",
    model: "gpt-4o",
    config: { temperature: 0.7 },
    variables: z.object({
    customerName: z.string(),
    plan: z.string(),
    issue: z.string(),
    }),
    content: You are a support agent for Acme. Customer: {{customerName}} ({{plan}} plan) Issue: {{issue}},
    });
    const resolved = await supportPrompt.resolve({
    customerName: "Alice",
    plan: "Pro",
    issue: "Can't access billing",
    });
    const result = await generateText({
    model: openai(resolved.model ?? "gpt-4o"),
    system: resolved.text,
    prompt: "Can't access billing",
    ...resolved.toAISDKTelemetry(),
    });
    What you get:
    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 compiled text, resolved model, version, and labels. Standalone
    prompts.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 any generateText / streamText call and every generation
    span links to the prompt in the dashboard alongside its input variables,
    model, tokens, and cost.
    chat.agent integration — chat.prompt.set(resolved) stores the
    resolved prompt run-scoped; chat.toStreamTextOptions({ registry })
    pulls system, model (resolved via the AI SDK provider registry),
    temperature / maxTokens / etc., and telemetry into a single spread
    for streamText.
    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.
    See /docs/ai/prompts for the full
    reference — template syntax, version resolution order, override
    workflow, and type utilities (PromptHandle, PromptIdentifier,
    PromptVariables).
    Adds onBoot to chat.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
    initialize chat.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)
    const userContext = chat.local<{ name: string; plan: string }>({ id:
    "userContext" });
    export const myChat = chat.agent({
    id: "my-chat",
    onBoot: async ({ clientData, continuation }) => {
    const user = await db.user.findUnique({ where: { id: clientData.userId }
    });
    userContext.init({ name: user.name, plan: user.plan });
    },
    run: async ({ messages, signal }) =>
    streamText({ model: openai("gpt-4o"), messages, abortSignal: signal }),
    });

    Use onBoot (not onChatStart) for state setup that must run every
    time a worker picks up the chat — onChatStart fires once per chat and
    won't run on continuation, leaving chat.local uninitialized when
    run() tries to use it.
    AI Agents — run AI SDK chat completions as durable Trigger.dev
    agents instead of fragile API routes. Define an agent in one function,
    point useChat at it from React, and the conversation survives page
    refreshes, network blips, and process restarts.
    (#3543)
    import { chat } from "@trigger.dev/sdk/ai";
    import { streamText } from "ai";
    import { openai } from "@ai-sdk/openai";
    export const myChat = chat.agent({
    id: "my-chat",
    run: async ({ messages, signal }) =&gt;
    streamText({ model: openai("gpt-4o"), messages, abortSignal: signal }),
    });
    
    import { useChat } from "@ai-sdk/react";
    import { useTriggerChatTransport } from "@trigger.dev/sdk/chat/react";
    const transport = useTriggerChatTransport({ task: "my-chat",
    accessToken, startSession });
    const { messages, sendMessage } = useChat({ transport });
    

    What you get:
    AI SDK useChat integration — a custom
    ChatTransport
    (useTriggerChatTransport) plugs straight into Vercel AI SDK's
    useChat hook. Text streaming, tool calls, reasoning, and data-*
    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's streamText step in your warm server process while the
    agent run boots in parallel, cutting cold-start TTFC by roughly half
    (measured 2801ms → 1218ms on claude-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 via
    chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.
    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: true reconnects via lastEventId so clients only see new chunks.
    sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools,
    in-progress reasoning) are auto-cleaned.
    Tool approvals (HITL) — tools with needsApproval: true pause
    until the user approves or denies via addToolApprovalResponse. The
    runtime reconciles the updated assistant message by ID and continues
    streamText.
    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages +
    onAction only — no turn hooks, no run(). onAction can return a
    StreamTextResult for a model response, or void for side-effect-only.
    Typed state primitives — chat.local<T> for per-run state
    accessible from hooks, run(), tools, and subtasks (auto-serialized
    through ai.toolExecute); chat.store for typed shared data between
    agent and client; chat.history for reading and mutating the message
    chain; clientDataSchema for typed clientData in every hook.
    chat.toStreamTextOptions() — one spread into streamText wires
    up versioned system Prompts,
    model resolution, telemetry metadata, compaction, steering, and
    background injection.
    Multi-tab coordination — multiTab: true + useMultiTabChat
    prevents duplicate sends and syncs state across browser tabs via
    BroadcastChannel. 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-ID mid-stream resume. No app code needed.
    See /docs/ai-chat for the
    full surface — quick start, three backend approaches (chat.agent,
    chat.createSession, raw task), persistence and code-sandbox patterns,
    type-level guides, and API reference.
    Add read primitives to chat.history for HITL flows:
    getPendingToolCalls(), getResolvedToolCalls(),
    extractNewToolResults(message), getChain(), and
    findMessage(messageId). These lift the accumulator-walking logic that
    customers building human-in-the-loop tools were re-implementing into the
    SDK. (#3543)
    Use getPendingToolCalls() to gate fresh user turns while a tool call
    is awaiting an answer. Use extractNewToolResults(message) to dedup
    tool results when persisting to your own store — the helper returns only
    the parts whose toolCallId is not already resolved on the chain.

    const pending = chat.history.getPendingToolCalls();
    if (pending.length &gt; 0) {
    // an addToolOutput is expected before a new user message
    }
    onTurnComplete: async ({ responseMessage }) =&gt; {
    const newResults = chat.history.extractNewToolResults(responseMessage);
    for (const r of newResults) {
    await db.toolResults.upsert({ id: r.toolCallId, output: r.output,
    errorText: r.errorText });
    }
    };
    

    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 new chat.agent runtime,
    and you can build on them directly for any pattern that needs durable
    bi-directional streaming across runs.
    (#3542)
    import { sessions, tasks } from "@trigger.dev/sdk";
    // Trigger a task and subscribe to its session output in one call
    const { runId, stream } = await tasks.triggerAndSubscribe("my-task",
    payload, {
    externalId: "user-456",
    });
    for await (const chunk of stream) {
    // ...
    }
    // Enumerate existing sessions (powers inbox-style UIs without a
    separate index)
    for await (const s of sessions.list({ type: "chat.agent", tag:
    "user:user-456" })) {
    console.log(s.id, s.externalId, s.createdAt, s.closedAt);
    }

    See /docs/ai-chat/overview
    for the full surface — Sessions powers the durable, resumable chat
    runtime described there.
    Patch Changes
    Add Agent Skills for chat.agent. Drop a folder with a SKILL.md and
    any helper scripts/references next to your task code, register it with
    skills.define({ id, path }), and the CLI bundles it into the deploy
    image automatically — no trigger.config.ts changes. The agent gets a
    one-line summary in its system prompt and discovers full instructions on
    demand via loadSkill, with bash and readFile tools scoped
    per-skill (path-traversal guards, output caps, abort-signal
    propagation).
    (#3543)
    const pdfSkill = skills.define({ id: "pdf-extract", path:
    "./skills/pdf-extract" });
    chat.skills.set([await pdfSkill.local()]);
    

    Built on the AI SDK cookbook
    pattern — portable
    across providers. SDK + CLI only for now; dashboard-editable SKILL.md
    text is on the roadmap.
    Add ai.toolExecute(task) so you can wire a Trigger subtask in as the
    execute handler of an AI SDK tool() while defining description and
    inputSchema yourself — useful when you want full control over the tool
    surface and just need Trigger's subtask machinery for the body.
    (#3546)
    const myTool = tool({
    description: "...",
    inputSchema: z.object({ ... }),
    execute: ai.toolExecute(mySubtask),
    });
    ai.tool(task) (toolFromTask) keeps doing the all-in-one wrap and now
    aligns its return type with AI SDK's ToolSet. Minimum ai peer raised
    to ^6.0.116 to avoid cross-version ToolSet mismatches in monorepos.
    Stamp gen_ai.conversation.id (the chat id) on every span and metric
    emitted from inside a chat.task or chat.agent run. Lets you filter
    dashboard spans, runs, and metrics by the chat conversation that
    produced them — independent of the run boundary, so multi-run chats
    correlate cleanly. No code changes required on the user side.
    (#3543)
    Type chat.createStartSessionAction against your chat agent so
    clientData is typed end-to-end on the first turn:
    (#3684)
    import { chat } from "@trigger.dev/sdk/ai";
    import type { myChat } from "@/trigger/chat";
    export const startChatSession = chat.createStartSessionAction("my-chat");
    // In the browser, threaded from the transport's typed startSession
    callback:
    const transport = useTriggerChatTransport({
    task: "my-chat",
    startSession: ({ chatId, clientData }) => startChatSession({ chatId,
    clientData }),
    // ...
    });

    ChatStartSessionParams gains a typed clientData field — folded into
    the first run's payload.metadata so onPreload / onChatStart see
    the same shape per-turn metadata carries via the transport. The opaque
    session-level metadata field is unchanged.
    Unit-test chat.agent definitions offline with mockChatAgent from
    @trigger.dev/sdk/ai/test. Drives a real agent's turn loop in-process —
    no network, no task runtime — so you can send messages, actions, and
    stop signals via driver methods, inspect captured output chunks, and
    verify hooks fire. Pairs with MockLanguageModelV3 from ai/test for
    model mocking. setupLocals lets you pre-seed locals (DB clients,
    service stubs) before run() starts.
    (#3543)
    The broader runInMockTaskContext harness it's built on lives at
    @trigger.dev/core/v3/test — useful for unit-testing any task code, not
    just chat.
    Add region to the runs list / retrieve API: filter runs by region
    (runs.list({ region: "..." }) / filter[region]=&lt;masterQueue&gt;) and
    read each run's executing region from the new region field on the
    response.
    (#3612)
    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    Patch Changes
    Add Agent Skills for chat.agent. Drop a folder with a SKILL.md and
    any helper scripts/references next to your task code, register it with
    skills.define({ id, path }), and the CLI bundles it into the deploy
    image automatically — no trigger.config.ts changes. The agent gets a
    one-line summary in its system prompt and discovers full instructions on
    demand via loadSkill, with bash and readFile tools scoped
    per-skill (path-traversal guards, output caps, abort-signal
    propagation).
    (#3543)
    const pdfSkill = skills.define({ id: "pdf-extract", path:
    "./skills/pdf-extract" });
    chat.skills.set([await pdfSkill.local()]);
    

    Built on the AI SDK cookbook
    pattern — portable
    across providers. SDK + CLI only for now; dashboard-editable SKILL.md
    text is on the roadmap.
    Updated dependencies:
    @trigger.dev/[email protected]
    [email protected]
    Patch Changes
    Add Agent Skills for chat.agent. Drop a folder with a SKILL.md and
    any helper scripts/references next to your task code, register it with
    skills.define({ id, path }), and the CLI bundles it into the deploy
    image automatically — no trigger.config.ts changes. The agent gets a
    one-line summary in its system prompt and discovers full instructions on
    demand via loadSkill, with bash and readFile tools scoped
    per-skill (path-traversal guards, output caps, abort-signal
    propagation).
    (#3543)
    const pdfSkill = skills.define({ id: "pdf-extract", path:
    "./skills/pdf-extract" });
    chat.skills.set([await pdfSkill.local()]);

    Built on the AI SDK cookbook
    pattern — portable
    across providers. SDK + CLI only for now; dashboard-editable SKILL.md
    text is on the roadmap.
    Add TRIGGER_BUILD_SKIP_REWRITE_TIMESTAMP=1 escape hatch for local
    self-hosted builds whose buildx driver doesn't support
    rewrite-timestamp alongside push (e.g. orbstack's default docker
    driver).
    (#3618)
    The CLI MCP server's agent-chat tools (start_agent_chat,
    send_agent_message, close_agent_chat) now run on the new Sessions
    primitive, so AI assistants driving a chat.agent get the same
    idempotent-by-chatId, durable-across-runs behavior the browser
    transport gets. Required PAT scopes go from write:inputStreams to
    read:sessions + write:sessions.
    (#3546)
    MCP list_runs tool: add a region filter input and surface each
    run's executing region in the formatted summary.
    (#3612)
    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    Patch Changes
    Add Agent Skills for chat.agent. Drop a folder with a SKILL.md and
    any helper scripts/references next to your task code, register it with
    skills.define({ id, path }), and the CLI bundles it into the deploy
    image automatically — no trigger.config.ts changes. The agent gets a
    one-line summary in its system prompt and discovers full instructions on
    demand via loadSkill, with bash and readFile tools scoped
    per-skill (path-traversal guards, output caps, abort-signal
    propagation).
    (#3543)
    const pdfSkill = skills.define({ id: "pdf-extract", path:
    "./skills/pdf-extract" });
    chat.skills.set([await pdfSkill.local()]);
    

    Built on the AI SDK cookbook
    pattern — portable
    across providers. SDK + CLI only for now; dashboard-editable SKILL.md
    text is on the roadmap.
    Reject overlong idempotencyKey values 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 what idempotencyKeys.create() produces (a 64-character hash) and
    above any realistic raw key. Applies to tasks.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 Agents — run AI SDK chat completions as durable Trigger.dev
    agents instead of fragile API routes. Define an agent in one function,
    point useChat at it from React, and the conversation survives page
    refreshes, network blips, and process restarts.
    (#3543)
    import { chat } from "@trigger.dev/sdk/ai";
    import { streamText } from "ai";
    import { openai } from "@ai-sdk/openai";
    export const myChat = chat.agent({
    id: "my-chat",
    run: async ({ messages, signal }) =>
    streamText({ model: openai("gpt-4o"), messages, abortSignal: signal }),
    });

    ```tsx
    import { useChat } from "@ai-sdk/react";
    import { useTriggerChatTransport } from "@trigger.dev/sdk/chat/react";
    const transport = useTriggerChatTransport({ task: "my-chat",
    accessToken, startSession });
    const { messages, sendMessage } = useChat({ transport });
    

    What you get:
    AI SDK useChat integration — a custom
    ChatTransport
    (useTriggerChatTransport) plugs straight into Vercel AI SDK's
    useChat hook. Text streaming, tool calls, reasoning, and data-*
    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's streamText step in your warm server process while the
    agent run boots in parallel, cutting cold-start TTFC by roughly half
    (measured 2801ms → 1218ms on claude-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 via
    chat.toNodeListener. New @trigger.dev/sdk/chat-server subpath.
    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: true reconnects via lastEventId so clients only see new chunks.
    sessions.list enumerates 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 hydrateMessages to 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 (stuck partial-call tools,
    in-progress reasoning) are auto-cleaned.
    Tool approvals (HITL) — tools with needsApproval: true pause
    until the user approves or denies via addToolApprovalResponse. The
    runtime reconciles the updated assistant message by ID and continues
    streamText.
    Steering and background injection — pendingMessages injects 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. Fire hydrateMessages +
    onAction only — no turn hooks, no run(). onAction can return a
    StreamTextResult for a model response, or void for side-effect-only.
    Typed state primitives — chat.local<T> for per-run state
    accessible from hooks, run(), tools, and subtasks (auto-serialized
    through ai.toolExecute); chat.store for typed shared data between
    agent and client; chat.history for reading and mutating the message
    chain; clientDataSchema for typed clientData in every hook.
    chat.toStreamTextOptions() — one spread into streamText wires
    up versioned system Prompts,
    model resolution, telemetry metadata, compaction, steering, and
    background injection.
    Multi-tab coordination — multiTab: true + useMultiTabChat
    prevents duplicate sends and syncs state across browser tabs via
    BroadcastChannel. 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-ID mid-stream resume. No app code needed.
    See /docs/ai-chat for the
    full surface — quick start, three backend approaches (chat.agent,
    chat.createSession, raw task), persistence and code-sandbox patterns,
    type-level guides, and API reference.
    Stamp gen_ai.conversation.id (the chat id) on every span and metric
    emitted from inside a chat.task or chat.agent run. Lets you filter
    dashboard spans, runs, and metrics by the chat conversation that
    produced them — independent of the run boundary, so multi-run chats
    correlate cleanly. No code changes required on the user side.
    (#3543)
    Fix LocalsKey<T> type incompatibility across dual-package builds.
    The phantom value-type brand no longer uses a module-level unique symbol, so a single TypeScript compilation that resolves the type from
    both the ESM and CJS outputs (which can happen under certain pnpm
    hoisting layouts) no longer sees two structurally-incompatible variants
    of the same type.
    (#3626)
    Unit-test chat.agent definitions offline with mockChatAgent from
    @trigger.dev/sdk/ai/test. Drives a real agent's turn loop in-process —
    no network, no task runtime — so you can send messages, actions, and
    stop signals via driver methods, inspect captured output chunks, and
    verify hooks fire. Pairs with MockLanguageModelV3 from ai/test for
    model mocking. setupLocals lets you pre-seed locals (DB clients,
    service stubs) before run() starts.
    (#3543)
    The broader runInMockTaskContext harness it's built on lives at
    @trigger.dev/core/v3/test — useful for unit-testing any task code, not
    just chat.
    Retry TASK_PROCESS_SIGSEGV task crashes under the user's retry
    policy instead of failing the run on the first segfault. SIGSEGV in Node
    tasks is frequently non-deterministic (native addon races, JIT/GC
    interaction, near-OOM in native code, host issues), so retrying on a
    fresh process often succeeds. The retry is gated by the task's existing
    retry config + maxAttempts — same path TASK_PROCESS_SIGTERM and
    uncaught exceptions already use — so tasks without a retry policy still
    fail fast.
    (#3552)
    Add region to the runs list / retrieve API: filter runs by region
    (runs.list({ region: "..." }) / filter[region]=<masterQueue>) and
    read each run's executing region from the new region field on the
    response.
    (#3612)
    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 new chat.agent runtime,
    and you can build on them directly for any pattern that needs durable
    bi-directional streaming across runs.
    (#3542)
    import { sessions, tasks } from "@trigger.dev/sdk";
    // Trigger a task and subscribe to its session output in one call
    const { runId, stream } = await tasks.triggerAndSubscribe("my-task",
    payload, {
    externalId: "user-456",
    });
    for await (const chunk of stream) {
    // ...
    }
    // Enumerate existing sessions (powers inbox-style UIs without a
    separate index)
    for await (const s of sessions.list({ type: "chat.agent", tag:
    "user:user-456" })) {
    console.log(s.id, s.externalId, s.createdAt, s.closedAt);
    }

    See /docs/ai-chat/overview
    for the full surface — Sessions powers the durable, resumable chat
    runtime described there.
    @trigger.dev/[email protected]
    Patch Changes
    The public interfaces for a plugin system. Initially consolidated
    authentication and authorization interfaces.
    (#3499)
    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    Patch Changes
    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    Patch Changes
    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    Patch Changes
    Add MollifierBuffer and MollifierDrainer primitives for trigger burst
    smoothing.
    (#3614)
    MollifierBuffer (accept, pop, ack, requeue, fail,
    evaluateTrip) is a per-env FIFO over Redis with atomic Lua transitions
    for status tracking. evaluateTrip is a sliding-window trip evaluator
    the webapp gate uses to detect per-env trigger bursts.
    MollifierDrainer pops entries through a polling loop with a
    user-supplied handler. The loop survives transient Redis errors via
    capped exponential backoff (up to 5s), and per-env pop failures don't
    poison the rest of the batch — one env's blip is logged and counted as
    failed for that tick. Rotation is two-level: orgs at the top, envs
    within each org. The buffer maintains mollifier:orgs and
    mollifier:org-envs:${orgId} atomically with per-env queues, so the
    drainer walks orgs → envs directly without an in-memory cache. The
    maxOrgsPerTick option (default 500) caps how many orgs are scheduled
    per tick; for each picked org, one env is popped (rotating round-robin
    within the org). An org with N envs gets the same per-tick scheduling
    slot as an org with 1 env, so tenant-level drainage throughput is
    determined by org count rather than env count.
    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    Patch Changes
    Updated dependencies:
    @trigger.dev/[email protected]
    @trigger.dev/[email protected]
    Patch Changes
    Updated dependencies:
    @trigger.dev/[email protected]
    Co-authored-by: github-actions[bot] &lt;41898282+github-actions[bot]@users.noreply.github.com&gt;
    
    Original source
  • May 21, 2026
    • Date parsed from source:
      May 21, 2026
    • First seen by Releasebot:
      May 22, 2026
    Trigger.dev logo

    Trigger.dev

    build-supervisor-wide-events.rc3

    Trigger.dev forwards Baggage outbound on compute calls.

    feat(supervisor): forward Baggage outbound on compute calls

    Original source
  • May 21, 2026
    • Date parsed from source:
      May 21, 2026
    • First seen by Releasebot:
      May 22, 2026
    Trigger.dev logo

    Trigger.dev

    build-supervisor-wide-events.rc2

    Trigger.dev refactors Supervisor State with first-class op and kind support.

    refactor(supervisor): op + kind first-class on State

    Original source
  • May 20, 2026
    • Date parsed from source:
      May 20, 2026
    • First seen by Releasebot:
      May 22, 2026
    Trigger.dev logo

    Trigger.dev

    build-supervisor-wide-events.rc1

    Trigger.dev adds wide events on snapshot lifecycle.

    feat(supervisor): wide events on snapshot lifecycle

    Original source
  • May 19, 2026
    • Date parsed from source:
      May 19, 2026
    • First seen by Releasebot:
      May 19, 2026
    Trigger.dev logo

    Trigger.dev

    build-supervisor-wide-events.rc0

    Trigger.dev fixes supervisor event review issues and adds a noisy-routes flag.

    fix(supervisor): wide-event review fixes + noisy-routes flag + socket…

    Original source
  • May 17, 2026
    • Date parsed from source:
      May 17, 2026
    • First seen by Releasebot:
      May 17, 2026
    Trigger.dev logo

    Trigger.dev

    build-realtimestreams-dedupe: fix(webapp): dedupe realtimeStreams array push on stream create

    Trigger.dev fixes a task run stream update bug to prevent duplicate realtime stream entries and hot-looped writes.

    The PUT handler unconditionally appended streamId to TaskRun.realtimeStreams on every call, so repeat inits for the same (run, streamId) hot-looped a row UPDATE and bloated the array. Read first and only push when the streamId isn't already present, matching the existing append handler.

    Original source
  • May 12, 2026
    • Date parsed from source:
      May 12, 2026
    • First seen by Releasebot:
      May 12, 2026
    Trigger.dev logo

    Trigger.dev

    trigger.dev v4.4.6

    Trigger.dev ships v4.4.6 with faster failure handling for uncaught exceptions and fixes a dev worker CPU spin issue after CLI disconnects, improving reliability for self-hosted and local development workflows.

    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 # bun
    Self-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 Node EventEmitter (e.g. node-redis) emitting "error" with no .on("error", ...) listener escalates to uncaughtException, 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 status FAILED, 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 an uncaughtException feedback loop: a periodic IPC send via process.send would throw ERR_IPC_CHANNEL_CLOSED once the parent closed the channel, which re-entered the same handler that itself called process.send, scheduled via setImmediate and amplified by source-map-support's prepareStackTrace. Fixed by (1) silently dropping packets in ZodIpcConnection when the channel is disconnected, (2) adding a process.on("disconnect", ...) handler in dev workers so they exit cleanly when the CLI closes the IPC channel, and (3) wrapping all uncaughtException-path process.send calls in a safeSend guard that checks process.connected and 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

    Original source
Releasebot

Curated by the Releasebot team

Releasebot is an aggregator of official release notes from hundreds of software vendors and thousands of sources.

Our editorial process involves the manual review and audit of release notes procured with the help of automated systems.

Similar to Trigger.dev with recent updates: