3 new features, 5 improvements, and 12 server changes.
Highlights
Hosted webhooks
Declare a webhook endpoint once and Trigger.dev hosts its URL, verifies every request against the provider's signature, and delivers each event to the tasks and agents subscribed to it. Subscribe a task with webhook() and a type-safe filter:
import { webhook, webhooks } from "@trigger.dev/sdk";export const stripe = webhooks.endpoint.define({ id: "stripe", source: webhooks.stripe(),});export const fulfill = webhook({ id: "fulfill", endpoint: stripe, filter: "event.type == 'checkout.session.completed'", onEvent: async ({ event }) => { // fulfill the order },});
To pause a run until a matching event arrives, create a waiter and wait on it:
const waiter = await webhooks.waiter.create(stripe, { match: { "event.data.object.metadata.orderId": order.id },});const { event } = await webhooks.waiter.wait(waiter).unwrap();
Sources cover Stripe, GitHub, Clerk, Shopify, Svix, Discord, Hookdeck and more, and webhooks.custom<T>(config) handles any other provider. Retries are deduplicated on the provider's own event or delivery ID, and every delivery can be inspected and replayed from the dashboard or the API. Agents can subscribe to the same endpoint: chat.event({ endpoint, key }) routes events into an agent session, and chat.channels.custom({ endpoint }) connects any chat surface.
Slack agents
@trigger.dev/slack turns a chat.agent into a native Slack agent. Each DM or channel thread is a durable session: the reply streams into the thread with the turn's tool calls shown as a plan, approvals are Approve and Deny buttons, and Slack's stop button stops the turn.
import { webhooks } from "@trigger.dev/sdk";import { chat } from "@trigger.dev/sdk/ai";import { appMentions, slack, webhookSource } from "@trigger.dev/slack";import { anthropic } from "@ai-sdk/anthropic";const slackEvents = webhooks.endpoint.define({ id: "slack", source: webhookSource(),});export const support = chat.agent({ id: "support", channels: [ slack({ id: "slack", endpoint: slackEvents, token: process.env.SLACK_BOT_TOKEN!, startOn: appMentions(), }), ], run: async ({ messages, signal, streamText }) => streamText({ model: anthropic("claude-sonnet-4-5"), messages, abortSignal: signal }),});
startOn decides which channel messages start a session, and appMentions() answers when the agent is @mentioned. Images and PDFs people share reach the model, and messages sent while the agent is answering are folded into the reply.
Linear agents
@trigger.dev/linear turns a chat.agent into a Linear agent. Assign it an issue or @mention it, and Linear's agent session becomes a durable Trigger.dev session: the reply posts back to Linear, tool calls show as activities, and approvals are Approve and Deny options that resume the run.
import { webhooks } from "@trigger.dev/sdk";import { chat } from "@trigger.dev/sdk/ai";import { linear, webhookSource } from "@trigger.dev/linear";import { anthropic } from "@ai-sdk/anthropic";const linearEvents = webhooks.endpoint.define({ id: "linear", source: webhookSource(),});export const triage = chat.agent({ id: "triage", channels: [ linear({ id: "linear", endpoint: linearEvents, token: process.env.LINEAR_ACCESS_TOKEN!, }), ], run: async ({ messages, signal, streamText }) => streamText({ model: anthropic("claude-sonnet-4-5"), messages, abortSignal: signal }),});
The first turn gets the issue's context and earlier comments, and images and PDFs in the issue reach the model. linearPlanTool() keeps the plan Linear shows as a checklist up to date, and a Stop in Linear winds the turn down.
Improvements
- Add
webhooks.hookdeck(), a source for deliveries relayed through a Hookdeck connection. It verifiesx-hookdeck-signature, keeps verifying while the secret is rolled (Hookdeck sends the previous secret's signature inx-hookdeck-signature-2), and deduplicates retries onx-hookdeck-eventid. Pass the original provider's event type, for examplewebhooks.hookdeck<Stripe.Event>(). (51b39fb) - HMAC webhook verifier configs accept
additionalSignatureHeaders: more headers that can carry a signature, matched as alternatives tosignatureHeader, so providers that send a second signature during a secret rotation keep verifying. (08d1ddb) - The
generate_webhook_secretandset_webhook_secretMCP tools take an optionalpreviousSecretTtlSecondsto keep accepting the old signing secret while the provider switches to the new one (up to 7 days), and report when the old secret stops working. (98adb66) - The
streamTextpassed to achat.agent'srun()now turns AI SDK telemetry on by default, so each model step and tool call shows up as a span in the run trace. Withtelemetry: { recordUserMessage: false }the spans are kept without prompt and response content. Passexperimental_telemetry: { isEnabled: false }to turn them off. (bd7cc35) - Realtime streams now reconnect and resume when the stream backend reports a failed read mid-stream, instead of ending early as if the stream had finished. This affects
runs.subscribeToRunwith streams,useRealtimeRunWithStreams, and chat streams. (23730b0)
Server changes
These changes are included in the v4.8.0 Docker image and are already live on Trigger.dev Cloud:
- Rotating a webhook endpoint's signing secret can keep the old one valid for a while, so deliveries still signed with it keep verifying. The rotate and regenerate dialogs let you choose how long (up to 7 days, 24 hours by default), and the
rotate-secretandsecretendpoints acceptpreviousSecretTtlSecondsand returnpreviousSecretExpiresAt. With no value, the old secret stops working immediately, as before. - Runs now get a
TRIGGER_DASHBOARD_URLenvironment variable with the dashboard's address, so a task can link to its own run:${TRIGGER_DASHBOARD_URL}/runs/${ctx.run.id}. ATRIGGER_DASHBOARD_URLyou set on the project takes precedence. - Run traces and the trace APIs load faster for older runs.
- Runs whose deployment has no compute template now go straight to containers when triggered, instead of first passing through the compute worker queue.
- When regenerating an environment's API key, you can now revoke the previous key immediately instead of keeping it working for 24 hours. Use this when a key may have leaked.
- The API keys page now always lists your root API key, masked to its last 4 characters when it's hidden, so you can regenerate it and revoke the previous key.
- Alerts are now checked every minute instead of every 5 to 10 minutes, so they raise and recover sooner.
- Creating an alert no longer needs the dashboard agent.
- Small fixes to creating and editing alerts.
- Alerts sent to Slack channels connected through a removed Slack installation deliver again.
- Set
KUBERNETES_POD_RESERVED_SOURCE_PORTSon the supervisor (for example50080,50081) to stop runs using those ports for outbound connections, which avoids port clashes on the node. - The supervisor no longer trusts certificates issued under the compromised emSign (eMudhra) certificate authorities.
How to upgrade
Update the trigger.dev/* packages to v4.8.0 using your package manager:
npx trigger.dev@latest update # npmpnpm dlx trigger.dev@latest update # pnpmyarn dlx trigger.dev@latest update # yarnbunx trigger.dev@latest update # bun
Self-hosted users: update your Docker image to ghcr.io/triggerdotdev/trigger.dev:v4.8.0.




