Skip to content

chore: release v4.5.0-rc.0 - #3563

Merged
ericallam merged 1 commit into
mainfrom
changeset-release/main
May 21, 2026
Merged

chore: release v4.5.0-rc.0#3563
ericallam merged 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions

@github-actionsgithub-actionsBot commented May 12, 2026

Copy link
Copy Markdown
Contributor

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 APIprompt.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 integrationchat.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 SDKprompts.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 hooksonPreload, 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 injectionpendingMessages 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 primitiveschat.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 coordinationmultiTab: 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 hooksonPreload, 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 injectionpendingMessages 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 primitiveschat.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 coordinationmultiTab: 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/sdk@4.5.0-rc.0

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";exportconstsupportPrompt=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}}`,});constresolved=awaitsupportPrompt.resolve({customerName: "Alice",plan: "Pro",issue: "Can't access billing",});constresult=awaitgenerateText({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 APIprompt.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 integrationchat.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 SDKprompts.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)

    constuserContext=chat.local<{name: string;plan: string}>({id: "userContext"});exportconstmyChat=chat.agent({id: "my-chat",onBoot: async({ clientData, continuation })=>{constuser=awaitdb.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";exportconstmyChat=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";consttransport=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 hooksonPreload, 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 injectionpendingMessages 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 primitiveschat.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 coordinationmultiTab: 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.

    constpending=chat.history.getPendingToolCalls();if(pending.length>0){// an addToolOutput is expected before a new user message}
    onTurnComplete: async({ responseMessage })=>{constnewResults=chat.history.extractNewToolResults(responseMessage);for(constrofnewResults){awaitdb.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 callconst{ runId, stream }=awaittasks.triggerAndSubscribe("my-task",payload,{externalId: "user-456",});forawait(constchunkofstream){// ...}// Enumerate existing sessions (powers inbox-style UIs without a separate index)forawait(constsofsessions.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)

    constpdfSkill=skills.define({id: "pdf-extract",path: "./skills/pdf-extract"});chat.skills.set([awaitpdfSkill.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)

    constmyTool=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";importtype{myChat}from"@/trigger/chat";exportconststartChatSession=chat.createStartSessionAction<typeofmyChat>("my-chat");// In the browser, threaded from the transport's typed startSession callback:consttransport=useTriggerChatTransport<typeofmyChat>({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]=<masterQueue>) and read each run's executing region from the new region field on the response. (#3612)

  • Updated dependencies:

    • @trigger.dev/core@4.5.0-rc.0

@trigger.dev/build@4.5.0-rc.0

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)

    constpdfSkill=skills.define({id: "pdf-extract",path: "./skills/pdf-extract"});chat.skills.set([awaitpdfSkill.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/core@4.5.0-rc.0

trigger.dev@4.5.0-rc.0

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)

    constpdfSkill=skills.define({id: "pdf-extract",path: "./skills/pdf-extract"});chat.skills.set([awaitpdfSkill.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/core@4.5.0-rc.0
    • @trigger.dev/build@4.5.0-rc.0
    • @trigger.dev/schema-to-json@4.5.0-rc.0

@trigger.dev/core@4.5.0-rc.0

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)

    constpdfSkill=skills.define({id: "pdf-extract",path: "./skills/pdf-extract"});chat.skills.set([awaitpdfSkill.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";exportconstmyChat=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";consttransport=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 hooksonPreload, 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 injectionpendingMessages 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 primitiveschat.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 coordinationmultiTab: 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 callconst{ runId, stream }=awaittasks.triggerAndSubscribe("my-task",payload,{externalId: "user-456",});forawait(constchunkofstream){// ...}// Enumerate existing sessions (powers inbox-style UIs without a separate index)forawait(constsofsessions.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/plugins@4.5.0-rc.0

Patch Changes

  • The public interfaces for a plugin system. Initially consolidated authentication and authorization interfaces. (#3499)
  • Updated dependencies:
    • @trigger.dev/core@4.5.0-rc.0

@trigger.dev/python@4.5.0-rc.0

Patch Changes

  • Updated dependencies:
    • @trigger.dev/sdk@4.5.0-rc.0
    • @trigger.dev/core@4.5.0-rc.0
    • @trigger.dev/build@4.5.0-rc.0

@trigger.dev/react-hooks@4.5.0-rc.0

Patch Changes

  • Updated dependencies:
    • @trigger.dev/core@4.5.0-rc.0

@trigger.dev/redis-worker@4.5.0-rc.0

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/core@4.5.0-rc.0

@trigger.dev/rsc@4.5.0-rc.0

Patch Changes

  • Updated dependencies:
    • @trigger.dev/core@4.5.0-rc.0

@trigger.dev/schema-to-json@4.5.0-rc.0

Patch Changes

  • Updated dependencies:
    • @trigger.dev/core@4.5.0-rc.0

@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.4.7May 12, 2026

@devin-ai-integrationdevin-ai-integrationBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@github-actionsgithub-actionsBot changed the title chore: release v4.4.7chore: releaseMay 12, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 28fd35c to 9a0e7f8CompareMay 12, 2026 16:18
@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.4.7May 12, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.4.7chore: releaseMay 12, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 9a0e7f8 to e477aebCompareMay 12, 2026 17:38
@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.4.7May 12, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.4.7chore: releaseMay 13, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from e477aeb to 2dd9063CompareMay 13, 2026 22:45
@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.4.7May 13, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.4.7chore: releaseMay 14, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 2dd9063 to 7390aa8CompareMay 14, 2026 12:26
@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.4.7May 14, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.4.7chore: releaseMay 14, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 7390aa8 to 48d6326CompareMay 14, 2026 12:43
@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.5.0May 14, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0chore: releaseMay 14, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 48d6326 to 830f8c9CompareMay 14, 2026 14:31
@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.5.0May 14, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0chore: releaseMay 14, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 830f8c9 to be2f622CompareMay 14, 2026 15:25
@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.5.0May 14, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0chore: releaseMay 14, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from be2f622 to f428661CompareMay 14, 2026 16:00
@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.5.0May 14, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0chore: releaseMay 14, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch 2 times, most recently from f428661 to b5d0261CompareMay 14, 2026 16:57
@github-actionsgithub-actionsBot changed the title chore: releasechore: release v4.5.0May 14, 2026
@github-actionsgithub-actionsBot changed the title chore: release (rc)chore: release v4.5.0-rc.0May 15, 2026

@devin-ai-integrationdevin-ai-integrationBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment thread.changeset/pre.json
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0-rc.0chore: release (rc)May 17, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from bf34386 to 09b5865CompareMay 17, 2026 04:56
@github-actionsgithub-actionsBot changed the title chore: release (rc)chore: release v4.5.0-rc.0May 17, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0-rc.0chore: release (rc)May 17, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 09b5865 to 95b3159CompareMay 17, 2026 08:30
@github-actionsgithub-actionsBot changed the title chore: release (rc)chore: release v4.5.0-rc.0May 17, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0-rc.0chore: release (rc)May 18, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 95b3159 to 6b08c59CompareMay 18, 2026 08:39
@github-actionsgithub-actionsBot changed the title chore: release (rc)chore: release v4.5.0-rc.0May 18, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0-rc.0chore: release (rc)May 18, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 6b08c59 to 57bf249CompareMay 18, 2026 09:21
@github-actionsgithub-actionsBot changed the title chore: release (rc)chore: release v4.5.0-rc.0May 18, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0-rc.0chore: release (rc)May 18, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 57bf249 to 19d61afCompareMay 18, 2026 09:23
@github-actionsgithub-actionsBot changed the title chore: release (rc)chore: release v4.5.0-rc.0May 18, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0-rc.0chore: release (rc)May 18, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 19d61af to 83d28b5CompareMay 18, 2026 09:30
@github-actionsgithub-actionsBot changed the title chore: release (rc)chore: release v4.5.0-rc.0May 18, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0-rc.0chore: release (rc)May 18, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 83d28b5 to 972afb7CompareMay 18, 2026 14:00
@github-actionsgithub-actionsBot changed the title chore: release (rc)chore: release v4.5.0-rc.0May 18, 2026
@github-actionsgithub-actionsBot changed the title chore: release v4.5.0-rc.0chore: release (rc)May 18, 2026
@github-actions
github-actionsBotforce-pushed the changeset-release/main branch from 972afb7 to 2fed69bCompareMay 18, 2026 15:44
@github-actions

Copy link
Copy Markdown
ContributorAuthor

Thanks for your contribution! We require all external PRs to be opened in draft status first so you can address CodeRabbit review comments and ensure CI passes before requesting a review. Please re-open this PR as a draft. See CONTRIBUTING.md for details.

@github-actions

github-actionsBot commented May 21, 2026

Copy link
Copy Markdown
ContributorAuthor

🧭 Helm Chart Prerelease Published

Version:4.5.0-rc.0-pr3563.92a760d

Install:

helm upgrade --install trigger \
oci://ghcr.io/triggerdotdev/charts/trigger \
--version "4.5.0-rc.0-pr3563.92a760d"

⚠️ This is a prerelease for testing. Do not use in production.

@ericallamericallam mentioned this pull request May 21, 2026
2 tasks
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@ericallam