@trigger.dev/sdk 4.8.0 → 4.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/commonjs/v3/ai-shared.d.ts +6 -0
  2. package/dist/commonjs/v3/ai-shared.js +7 -1
  3. package/dist/commonjs/v3/ai-shared.js.map +1 -1
  4. package/dist/commonjs/v3/ai.d.ts +45 -0
  5. package/dist/commonjs/v3/ai.js +110 -69
  6. package/dist/commonjs/v3/ai.js.map +1 -1
  7. package/dist/commonjs/v3/auth.d.ts +2 -1
  8. package/dist/commonjs/v3/auth.js +18 -12
  9. package/dist/commonjs/v3/auth.js.map +1 -1
  10. package/dist/commonjs/v3/chat-client.d.ts +11 -2
  11. package/dist/commonjs/v3/chat-client.js +28 -10
  12. package/dist/commonjs/v3/chat-client.js.map +1 -1
  13. package/dist/commonjs/v3/chat-react.d.ts +21 -0
  14. package/dist/commonjs/v3/chat-react.js +86 -30
  15. package/dist/commonjs/v3/chat-react.js.map +1 -1
  16. package/dist/commonjs/v3/chat.d.ts +1 -0
  17. package/dist/commonjs/v3/chat.js +4 -1
  18. package/dist/commonjs/v3/chat.js.map +1 -1
  19. package/dist/commonjs/v3/managedChatResponse.d.ts +13 -5
  20. package/dist/commonjs/v3/managedChatResponse.js +36 -18
  21. package/dist/commonjs/v3/managedChatResponse.js.map +1 -1
  22. package/dist/commonjs/v3/steeringContext.d.ts +11 -0
  23. package/dist/commonjs/v3/steeringContext.js +44 -3
  24. package/dist/commonjs/v3/steeringContext.js.map +1 -1
  25. package/dist/commonjs/v3/subAgentStream.d.ts +50 -0
  26. package/dist/commonjs/v3/subAgentStream.js +154 -0
  27. package/dist/commonjs/v3/subAgentStream.js.map +1 -0
  28. package/dist/commonjs/v3/transcriptStorage.js +3 -0
  29. package/dist/commonjs/v3/transcriptStorage.js.map +1 -1
  30. package/dist/commonjs/v3/uiMessageChunks.js +5 -1
  31. package/dist/commonjs/v3/uiMessageChunks.js.map +1 -1
  32. package/dist/commonjs/version.js +1 -1
  33. package/dist/esm/v3/ai-shared.d.ts +6 -0
  34. package/dist/esm/v3/ai-shared.js +6 -0
  35. package/dist/esm/v3/ai-shared.js.map +1 -1
  36. package/dist/esm/v3/ai.d.ts +45 -0
  37. package/dist/esm/v3/ai.js +113 -72
  38. package/dist/esm/v3/ai.js.map +1 -1
  39. package/dist/esm/v3/auth.d.ts +2 -1
  40. package/dist/esm/v3/auth.js +19 -13
  41. package/dist/esm/v3/auth.js.map +1 -1
  42. package/dist/esm/v3/chat-client.d.ts +11 -2
  43. package/dist/esm/v3/chat-client.js +29 -11
  44. package/dist/esm/v3/chat-client.js.map +1 -1
  45. package/dist/esm/v3/chat-react.d.ts +21 -0
  46. package/dist/esm/v3/chat-react.js +81 -30
  47. package/dist/esm/v3/chat-react.js.map +1 -1
  48. package/dist/esm/v3/chat.d.ts +1 -0
  49. package/dist/esm/v3/chat.js +1 -0
  50. package/dist/esm/v3/chat.js.map +1 -1
  51. package/dist/esm/v3/managedChatResponse.d.ts +13 -5
  52. package/dist/esm/v3/managedChatResponse.js +36 -18
  53. package/dist/esm/v3/managedChatResponse.js.map +1 -1
  54. package/dist/esm/v3/steeringContext.d.ts +11 -0
  55. package/dist/esm/v3/steeringContext.js +44 -4
  56. package/dist/esm/v3/steeringContext.js.map +1 -1
  57. package/dist/esm/v3/subAgentStream.d.ts +50 -0
  58. package/dist/esm/v3/subAgentStream.js +149 -0
  59. package/dist/esm/v3/subAgentStream.js.map +1 -0
  60. package/dist/esm/v3/transcriptStorage.js +3 -0
  61. package/dist/esm/v3/transcriptStorage.js.map +1 -1
  62. package/dist/esm/v3/uiMessageChunks.js +5 -1
  63. package/dist/esm/v3/uiMessageChunks.js.map +1 -1
  64. package/dist/esm/version.js +1 -1
  65. package/docs/ai/prompts.mdx +9 -6
  66. package/docs/ai-chat/background-injection.mdx +2 -0
  67. package/docs/ai-chat/chat-local.mdx +4 -4
  68. package/docs/ai-chat/client-protocol.mdx +1 -0
  69. package/docs/ai-chat/fast-starts.mdx +1 -1
  70. package/docs/ai-chat/frontend.mdx +15 -0
  71. package/docs/ai-chat/overview.mdx +5 -4
  72. package/docs/ai-chat/patterns/database-persistence.mdx +3 -3
  73. package/docs/ai-chat/patterns/native-compaction.mdx +6 -6
  74. package/docs/ai-chat/patterns/sub-agents.mdx +82 -56
  75. package/docs/ai-chat/patterns/version-upgrades.mdx +3 -3
  76. package/docs/ai-chat/pending-messages.mdx +2 -0
  77. package/docs/ai-chat/quick-start.mdx +1 -1
  78. package/docs/ai-chat/reference.mdx +22 -0
  79. package/docs/ai-chat/server-chat.mdx +11 -7
  80. package/docs/ai-chat/side-channels.mdx +2 -2
  81. package/docs/ai-chat/types.mdx +5 -5
  82. package/docs/config/config-file.mdx +2 -2
  83. package/docs/database-connections.mdx +2 -2
  84. package/docs/how-to-reduce-your-spend.mdx +4 -0
  85. package/docs/introduction.mdx +104 -24
  86. package/docs/limits.mdx +41 -0
  87. package/docs/mcp-tools.mdx +5 -0
  88. package/docs/observability/query.mdx +29 -0
  89. package/docs/self-hosting/docker.mdx +62 -0
  90. package/docs/self-hosting/env/supervisor.mdx +4 -0
  91. package/docs/self-hosting/env/webapp.mdx +38 -0
  92. package/docs/self-hosting/kubernetes.mdx +2 -0
  93. package/docs/self-hosting/overview.mdx +2 -0
  94. package/docs/troubleshooting-alerts.mdx +39 -0
  95. package/docs/webhooks/deliveries.mdx +4 -0
  96. package/docs/webhooks/overview.mdx +8 -0
  97. package/docs/webhooks/sources.mdx +3 -1
  98. package/docs/webhooks/waiters.mdx +3 -3
  99. package/package.json +2 -2
  100. package/skills/trigger-chat-agent-advanced/SKILL.md +17 -7
  101. package/skills/trigger-cost-savings/SKILL.md +1 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Trigger.dev docs"
3
3
  sidebarTitle: "Introduction"
4
- description: "Build and run durable AI agents and workflows in TypeScript. Long-running tasks with retries, queues, observability, and elastic scaling. Open source and self-hostable."
4
+ description: "Build and run durable AI agents and workflows in TypeScript. Long-running tasks with retries, queues, webhooks, observability, and elastic scaling. Open source and self-hostable."
5
5
  mode: "center"
6
6
  ---
7
7
 
@@ -11,8 +11,8 @@ import AgentSetupPrompt from "/snippets/agent-setup-prompt.mdx";
11
11
  <Card title="Quick start" icon="rocket" href="/quick-start" color="#A8FF53">
12
12
  Go from zero to your first task in 3 minutes.
13
13
  </Card>
14
- <Card title="Build AI agents" icon="robot" href="/guides/ai-agents/overview" color="#a855f7">
15
- Agent patterns, worked examples, and the tools to run them in production.
14
+ <Card title="Build AI agents" icon="robot" href="/ai-chat/overview" color="#a855f7">
15
+ Durable, multi-turn agents with `chat.agent`, from your frontend to Slack and Linear.
16
16
  </Card>
17
17
  <Card title="AI coding assistants" icon="wand-magic-sparkles" href="/building-with-ai" color="#3B82F6">
18
18
  Let Claude Code, Cursor and Windsurf write correct Trigger.dev code with the MCP server, Skills and rules.
@@ -28,48 +28,124 @@ import AgentSetupPrompt from "/snippets/agent-setup-prompt.mdx";
28
28
 
29
29
  ## What is Trigger.dev?
30
30
 
31
- Trigger.dev is the open source platform for building and running durable AI agents and workflows in TypeScript. Run them for hours, configure automatic retries, control concurrency, and manage queues. There's no execution timeout, and no queue or worker infrastructure for you to build.
31
+ Trigger.dev is the open source platform for building and running durable AI agents and workflows in TypeScript. You write tasks and agents in your existing codebase, and they run on Trigger.dev with retries, queues, waits, full tracing, and elastic scaling. There's no execution timeout, and no queue or worker infrastructure for you to build.
32
32
 
33
- You write agents and tasks in your existing codebase using our CLI and SDK, and get durable execution, queues, waits, full tracing, and elastic scaling without building any of it yourself.
33
+ Trigger.dev's core is Apache-2.0 licensed. [Self-host it](/self-hosting/overview) on your own infrastructure, or let [Trigger.dev Cloud](https://cloud.trigger.dev) run it for you.
34
34
 
35
- Trigger.dev's core is Apache-2.0 licensed, a genuine OSI license. [Self-host it](/self-hosting/overview) on your own infrastructure, or let [Trigger.dev Cloud](https://cloud.trigger.dev) run it for you.
35
+ ## Build agents with `chat.agent`
36
36
 
37
- ## Core concepts
37
+ A `chat.agent` runs each conversation as one durable task. It wakes when a message arrives and idles between turns, and its state survives page refreshes, deploys, and crashes. Turn lifecycle, resuming a stream mid-reply, and approvals are handled for you, and your frontend connects with the AI SDK's `useChat`, with no API routes to write.
38
+
39
+ ```ts trigger/chat.ts
40
+ import { chat } from "@trigger.dev/sdk/ai";
41
+ import { anthropic } from "@ai-sdk/anthropic";
42
+
43
+ export const supportAgent = chat.agent({
44
+ id: "support-agent",
45
+ run: async ({ messages, signal, streamText }) =>
46
+ streamText({
47
+ model: anthropic("claude-sonnet-4-5"),
48
+ messages,
49
+ abortSignal: signal,
50
+ }),
51
+ });
52
+ ```
53
+
54
+ <CardGroup cols={3}>
55
+ <Card title="Agent quick start" icon="rocket" href="/ai-chat/quick-start">
56
+ Build a chat agent and its frontend end to end.
57
+ </Card>
58
+ <Card title="Sessions" icon="layer-group" href="/ai-chat/sessions">
59
+ Each conversation's durable state and two-way stream, across all its runs.
60
+ </Card>
61
+ <Card title="Tools" icon="screwdriver-wrench" href="/ai-chat/tools">
62
+ Declare tools on your agent and get them back typed in `run()`.
63
+ </Card>
64
+ <Card title="Human in the loop" icon="hand" href="/ai-chat/patterns/human-in-the-loop">
65
+ Pause a tool call for approval and resume when a person decides.
66
+ </Card>
67
+ <Card title="Slack agents" icon="slack" href="/webhooks/slack">
68
+ Turn an agent into a native Slack agent with `@trigger.dev/slack`.
69
+ </Card>
70
+ <Card title="Linear agents" icon="list-check" href="/webhooks/linear">
71
+ Assign Linear issues to an agent with `@trigger.dev/linear`.
72
+ </Card>
73
+ </CardGroup>
74
+
75
+ Version your [prompts](/ai/prompts) in code and change them from the dashboard, and see every model step and tool call, with tokens, cost and latency, in [AI observability](/ai/observability).
76
+
77
+ ## Run work
38
78
 
39
79
  <CardGroup cols={2}>
40
80
  <Card title="Writing tasks" icon="pen-to-square" href="/tasks/overview" color="#A8FF53">
41
- The durable functions at the core of Trigger.dev. Write them in your existing codebase, with retries and no timeouts.
81
+ The durable functions at the core of Trigger.dev, written in your existing codebase.
42
82
  </Card>
43
83
  <Card title="Triggering tasks" icon="bullseye-pointer" href="/triggering" color="#3b82f6">
44
- Trigger a task from your backend, your frontend, a schedule, or another task.
84
+ Trigger a task from your backend, your frontend, or another task.
45
85
  </Card>
46
86
  <Card title="Runs" icon="play" href="/runs" color="#28bf5c">
47
- Every execution of a task is a run, with its status, retries, and logs recorded.
87
+ Every execution of a task is a run, with its status, retries, logs and trace.
88
+ </Card>
89
+ <Card title="Realtime" icon="bolt" href="/realtime/overview" color="#F43F5E">
90
+ Stream run status and LLM output to your frontend with React hooks.
91
+ </Card>
92
+ </CardGroup>
93
+
94
+ ## React to events
95
+
96
+ <CardGroup cols={2}>
97
+ <Card title="Webhooks" icon="webhook" href="/webhooks/overview" color="#a855f7">
98
+ Hosted, verified endpoints for Stripe, GitHub and more, delivered to your tasks and agents.
99
+ </Card>
100
+ <Card title="Scheduled tasks" icon="clock" href="/tasks/scheduled" color="#f6cd46">
101
+ Run a task on a cron schedule, with timezone support.
102
+ </Card>
103
+ <Card title="Webhook waiters" icon="bell" href="/webhooks/waiters" color="#3b82f6">
104
+ Pause a run until a matching webhook arrives, like a payment confirmation.
48
105
  </Card>
49
- <Card title="Idempotency" icon="fingerprint" href="/idempotency" color="#F43F5E">
50
- Use an idempotency key so a retried or duplicated trigger runs once, not twice.
106
+ <Card title="Waits" icon="hourglass" href="/wait" color="#28bf5c">
107
+ Pause a run for a duration, until a date, or until a token is completed. A waiting run doesn't use compute.
51
108
  </Card>
52
109
  </CardGroup>
53
110
 
54
- ## Build with agents
111
+ ## Run in production
55
112
 
56
- Build durable, multi-turn agents with the [chat agent](/ai-chat/overview): one long-running task per conversation, with the tools it can call, streaming, and resumability handled for you. Add human-in-the-loop approval by pausing a run on a [waitpoint](/wait-for-token) until a person signs off, and a waiting run doesn't consume compute. Stream run status and LLM output straight to your frontend with the [Realtime API](/realtime/overview) and React hooks, and record your Vercel AI SDK calls as spans with the model, token counts, cost and latency using [AI observability](/ai/observability). Version your [prompts](/ai/prompts) in code, then edit the text or swap the model from the dashboard without redeploying.
113
+ <CardGroup cols={2}>
114
+ <Card title="Queues & concurrency" icon="layer-group" href="/queues" color="#3b82f6">
115
+ Control how many runs execute at once, globally or per tenant.
116
+ </Card>
117
+ <Card title="Machines" icon="microchip" href="/machines" color="#a855f7">
118
+ Choose the CPU and memory each task runs on.
119
+ </Card>
120
+ <Card title="Deployment" icon="cloud-arrow-up" href="/deployment/overview" color="#28bf5c">
121
+ Atomic, versioned deploys, with preview branches and environments.
122
+ </Card>
123
+ <Card title="Errors & retries" icon="arrows-rotate" href="/errors-retrying" color="#F43F5E">
124
+ Retry failed attempts automatically, and decide what happens when a task throws.
125
+ </Card>
126
+ <Card title="Logs, traces & metrics" icon="chart-line" href="/logging" color="#f6cd46">
127
+ A full trace of every run, with your logs and spans.
128
+ </Card>
129
+ <Card title="Query & dashboards" icon="table" href="/observability/query" color="#A8FF53">
130
+ Query your runs with TRQL, and build dashboards from the results.
131
+ </Card>
132
+ </CardGroup>
57
133
 
58
- ## Scale and scheduling
134
+ ## Frequently asked questions
59
135
 
60
- Set how many runs of a task execute at once, globally or per tenant, with [concurrency](/concurrency) and [queues](/queues). Run a task on a [cron schedule](/tasks/scheduled) with timezone support, choose the CPU and memory each task runs on with [machines](/machines), and control what happens when a task throws with [errors and retries](/errors-retrying).
136
+ **Can I use Trigger.dev for background jobs, not just AI?** Yes. The same durable tasks, queues, retries, and [cron schedules](/tasks/scheduled) run any background job or workflow, with or without AI.
61
137
 
62
- ## Self-hosting
138
+ **How long can a run take?** As long as it needs. Runs have no maximum duration by default, and you can set a [`maxDuration`](/runs/max-duration) for a project, a task, or a single run to cap it.
63
139
 
64
- Trigger.dev is open source and you can self-host. Read the [overview guide](/self-hosting/overview), or how to do it with [Docker](/self-hosting/docker) or [Kubernetes](/self-hosting/kubernetes).
140
+ **Do my serverless function timeouts apply?** No. Tasks run on Trigger.dev, not inside your serverless functions, so your platform's function timeout isn't in the execution path. Your backend triggers the task and returns.
65
141
 
66
- ## Frequently asked questions
142
+ **Can I receive webhooks without running a server?** Yes. Declare a [webhook endpoint](/webhooks/overview) in your code, and Trigger.dev hosts its URL, verifies each request, and delivers the event to your tasks and agents.
67
143
 
68
- **How do I add human-in-the-loop approval to an agent?** Pause the run on a [waitpoint](/wait-for-token) until a person approves the action. A waiting run doesn't consume compute, so it can wait minutes or days.
144
+ **How do I add human-in-the-loop approval?** Pause the run on a [waitpoint](/wait-for-token) until a person approves, or use a [chat agent's approvals](/ai-chat/patterns/human-in-the-loop) for tool calls. A waiting run doesn't use compute, so it can wait minutes or days.
69
145
 
70
146
  **Does Trigger.dev support tool calling and MCP?** Yes. Agents call the tools you define, and the [MCP server](/building-with-ai) lets AI coding assistants trigger tasks, deploy, and read run traces.
71
147
 
72
- **Can I use Trigger.dev for background jobs, not just AI?** Yes. The same durable tasks, queues, retries, and [cron schedules](/tasks/scheduled) run any background job or workflow, with or without AI.
148
+ **Can I self-host?** Yes. Trigger.dev is open source. Read the [self-hosting overview](/self-hosting/overview), or set it up with [Docker](/self-hosting/docker) or [Kubernetes](/self-hosting/kubernetes).
73
149
 
74
150
  ## Getting help
75
151
 
@@ -85,7 +161,7 @@ We'd love to hear from you or give you a hand getting started. Here are some way
85
161
  Our Discord is the best place to get help with any questions about Trigger.dev.
86
162
  </Card>
87
163
  <Card
88
- title="Follow us on X (Twitter)"
164
+ title="Follow us on X"
89
165
  icon={
90
166
  <svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 512 512">
91
167
  <path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z" />
@@ -112,7 +188,7 @@ We'd love to hear from you or give you a hand getting started. Here are some way
112
188
  href="https://github.com/triggerdotdev/trigger.dev"
113
189
  color="#fbbf24"
114
190
  >
115
- Check us out our GitHub repo and give us a star if you like what we're doing.
191
+ Check out our GitHub repo, and give us a star if you like what we're doing.
116
192
  </Card>
117
193
  </CardGroup>
118
194
 
@@ -122,12 +198,16 @@ We'd love to hear from you or give you a hand getting started. Here are some way
122
198
 
123
199
  **Current major version:** v4 (`@trigger.dev/sdk` 4.x). Documentation under `/docs/v2` and `/docs/v3` describes superseded versions and should not be used.
124
200
 
125
- **Execution model:** tasks run on Trigger.dev infrastructure, not inside your serverless functions, so a platform function timeout is not in the execution path. A task runs until it finishes; you can cap runtime with `maxDuration` (minimum 5 seconds).
201
+ **Execution model:** tasks run on Trigger.dev infrastructure, not inside your serverless functions, so a platform function timeout is not in the execution path. Runs have no maximum duration by default; `maxDuration` caps a run's compute time for a project, a task, or a single run, and `timeout.None` removes the cap.
126
202
 
127
203
  **Deploys:** each deploy is an atomic version. A run already in progress is not affected by code shipped after it started.
128
204
 
129
205
  **Durability and retries:** retries are automatic and configurable. A failed attempt is retried according to the task's retry settings; once retries are exhausted the run ends terminally as `FAILED`, and some crashes (for example out of memory) end the run as `CRASHED` without a retry. Idempotency keys deduplicate the task triggers and waits you key, so the same key runs once instead of again.
130
206
 
207
+ **Agents:** `chat.agent` is imported from `@trigger.dev/sdk/ai`, not from `@trigger.dev/sdk`. Inside `run()`, call the `streamText` passed in the run options. It records each model step and tool call as a span by default. Slack and Linear agents use the `@trigger.dev/slack` and `@trigger.dev/linear` packages, and `slack()` requires a `startOn` filter (`appMentions()` answers @mentions).
208
+
209
+ **Webhooks:** `webhooks.endpoint.define()` declares a hosted, verified endpoint that syncs on `trigger dev` and on deploy; `webhook()` subscribes a task with a filter, and `webhooks.waiter` pauses a run until a matching event arrives. Both come from `@trigger.dev/sdk`.
210
+
131
211
  **License:** the platform core is Apache-2.0 and the `@trigger.dev/sdk` package is MIT, permissive open source, not fair-code or source-available. Some features are gated, but the open source core is not relicensed or held back.
132
212
 
133
213
  **LLM observability coverage:** only Vercel AI SDK calls (`generateText`, `streamText`, `generateObject`) are recorded as spans. Raw `fetch` calls and provider SDKs used directly are not captured.
package/docs/limits.mdx CHANGED
@@ -178,6 +178,47 @@ All of an environment's endpoints also share a per-environment limit, counted in
178
178
  | Pro | 3,000 every 10 sec |
179
179
  | Enterprise | Set per organization |
180
180
 
181
+ ## Webhook waiters
182
+
183
+ A [waiter](/webhooks/waiters) is a run paused until a matching webhook arrives. The per-endpoint limit is also the most waiting runs one delivery can resume.
184
+
185
+ | Pricing tier | Live waiters per environment | Live waiters per endpoint |
186
+ | :----------- | :--------------------------- | :------------------------ |
187
+ | Free | 500 | 100 |
188
+ | Hobby | 2,000 | 1,000 |
189
+ | Pro | 25,000 | 10,000 |
190
+ | Enterprise | Set per organization | Set per organization |
191
+
192
+ A waiter can wait for up to 90 days.
193
+
194
+ ## Webhook processing concurrency
195
+
196
+ This limit controls how many webhook deliveries and waiter resumes are processed at once per environment. Additional deliveries wait their turn. It is not a limit on the runs those deliveries start, which use your normal [concurrency limits](#concurrency-limits).
197
+
198
+ | Pricing tier | Limit |
199
+ | :----------- | :----------------------- |
200
+ | Free | 5 concurrent deliveries |
201
+ | Hobby | 10 concurrent deliveries |
202
+ | Pro | 50 concurrent deliveries |
203
+ | Enterprise | Set per organization |
204
+
205
+ ## Webhook delivery retention
206
+
207
+ How long [deliveries](/webhooks/deliveries) stay visible in the dashboard and the API.
208
+
209
+ | Pricing tier | Limit |
210
+ | :----------- | :--------------------------- |
211
+ | Free | 3 days |
212
+ | Hobby | 7 days |
213
+ | Pro | 30 days |
214
+ | Enterprise | 90, 180 or 365 days |
215
+
216
+ By default, deliveries are stored for at least 30 days, so upgrading your plan shows older deliveries that are still stored. An organization can ask us to store deliveries only for its retention period instead. Deliveries past that period are then deleted and can't be shown again after an upgrade.
217
+
218
+ ## Webhook subscribers
219
+
220
+ An endpoint can have up to 25 subscribers (tasks, agent sessions and channels) on every plan.
221
+
181
222
  ## Log retention
182
223
 
183
224
  | Pricing tier | Limit |
@@ -411,6 +411,10 @@ Generate a new signing secret for an endpoint and return it once, for providers
411
411
 
412
412
  **Parameters:**
413
413
  - `endpointId` (required): the endpoint's declared id (such as `payments`) or `wh_` id
414
+ - `previousSecretTtlSeconds` (optional): keep accepting the replaced secret for this many seconds (up to 604800, 7 days) while the provider switches to the new one. Omit it, or pass `0`, to replace the secret immediately, for example when it leaked. The response says when the old secret stops working.
415
+
416
+ **Example usage:**
417
+ - `"Rotate the GitHub endpoint's secret and keep the old one working for a day"`
414
418
 
415
419
  ### set_webhook_secret
416
420
 
@@ -419,6 +423,7 @@ Store a signing secret or public key the provider issued, such as Stripe's `whse
419
423
  **Parameters:**
420
424
  - `endpointId` (required): the endpoint's declared id (such as `payments`) or `wh_` id
421
425
  - `secret` (required): the secret or public key
426
+ - `previousSecretTtlSeconds` (optional): keep accepting the replaced secret for this many seconds (up to 604800, 7 days) while the provider switches to the new one. Omit it, or pass `0`, to replace the secret immediately, for example when it leaked. The response says when the old secret stops working.
422
427
 
423
428
  <Callout type="warning">
424
429
  `replay_webhook_delivery`, `generate_webhook_secret` and `set_webhook_secret` are write operations and are not available in readonly mode.
@@ -57,6 +57,35 @@ ORDER BY minute
57
57
  LIMIT 1000
58
58
  ```
59
59
 
60
+ #### Platform limit metrics
61
+
62
+ The `metrics` table also records how close your environment is to platform limits. These are the metrics behind [Limits alerts](/troubleshooting-alerts#limits-alerts):
63
+
64
+ | Metric | What it shows |
65
+ | ------------------------------- | ------------------------------------------------ |
66
+ | `queue.size.queued` | Runs currently queued in the environment |
67
+ | `queue.size.limit` | The environment's maximum queued runs |
68
+ | `webhook.processing.in_flight` | Webhooks being processed now |
69
+ | `webhook.processing.limit` | The webhook processing concurrency limit |
70
+ | `webhook.ingress.denied` | Incoming webhooks rejected by a rate limit |
71
+ | `webhook.ingress.remaining_min` | The lowest remaining rate limit allowance seen |
72
+ | `webhook.ingress.limit.tokens` | The rate limit's allowance per window |
73
+ | `webhook.waiters.live` | Runs currently waiting for a webhook |
74
+ | `webhook.waiters.limit.env` | The environment's maximum webhook waiters |
75
+ | `webhook.waiters.refused` | New webhook waiters that were refused |
76
+
77
+ ```sql
78
+ SELECT
79
+ timeBucket(),
80
+ maxIf(metric_value, metric_name = 'queue.size.queued') AS queued,
81
+ maxIf(metric_value, metric_name = 'queue.size.limit') AS queue_limit
82
+ FROM metrics
83
+ WHERE metric_name LIKE 'queue.size.%'
84
+ GROUP BY timeBucket
85
+ ORDER BY timeBucket
86
+ LIMIT 1000
87
+ ```
88
+
60
89
  ### `prettyFormat()`
61
90
 
62
91
  Use `prettyFormat()` to format metric values for display:
@@ -389,6 +389,68 @@ EVENT_REPOSITORY_DEFAULT_STORE=clickhouse_v2
389
389
 
390
390
  This only affects new runs; existing runs continue to read from wherever their events were originally stored.
391
391
 
392
+ ### Move from the legacy clickhouse store
393
+
394
+ The legacy `clickhouse` store (the `task_events_v1` table) is retired. If you set `EVENT_REPOSITORY_DEFAULT_STORE=clickhouse`, your webapp now writes and reads `clickhouse_v2` instead and logs a warning at startup. Events recorded in `task_events_v1` stay there but no longer show in the dashboard until you copy them over.
395
+
396
+ <Steps titleSize="h4">
397
+ <Step title="Switch to clickhouse_v2">
398
+ Switch the store in your `.env` and restart the webapp:
399
+
400
+ ```bash .env
401
+ EVENT_REPOSITORY_DEFAULT_STORE=clickhouse_v2
402
+ ```
403
+ </Step>
404
+ <Step title="List the days to copy">
405
+ List the days that hold legacy events. The bundled ClickHouse container already sets `CLICKHOUSE_USER` and `CLICKHOUSE_PASSWORD`, and `clickhouse-client` reads them, so no credentials are needed:
406
+
407
+ ```bash
408
+ docker compose exec clickhouse clickhouse-client -q \
409
+ "SELECT toDate(start_time) AS day, count() FROM trigger_dev.task_events_v1 GROUP BY day ORDER BY day"
410
+ ```
411
+ </Step>
412
+ <Step title="Save the copy query">
413
+ Save the copy query as `copy-task-events-v1.sql`. It copies one day and skips events already in `task_events_v2`, so it's safe to run again if it's interrupted:
414
+
415
+ ```sql copy-task-events-v1.sql
416
+ INSERT INTO trigger_dev.task_events_v2
417
+ (environment_id, organization_id, project_id, task_identifier, run_id, start_time,
418
+ trace_id, span_id, parent_span_id, message, kind, status, attributes_text,
419
+ metadata, duration, expires_at, inserted_at)
420
+ SELECT
421
+ environment_id, organization_id, project_id, task_identifier, run_id, start_time,
422
+ trace_id, span_id, parent_span_id, message, kind, status, attributes_text,
423
+ metadata, duration, expires_at, toDateTime64(start_time, 3)
424
+ FROM trigger_dev.task_events_v1
425
+ WHERE toDate(start_time) = {day:Date}
426
+ AND (trace_id, span_id, start_time, kind, status) NOT IN (
427
+ SELECT trace_id, span_id, start_time, kind, status
428
+ FROM trigger_dev.task_events_v2
429
+ WHERE inserted_at >= {day:Date} AND inserted_at < {day:Date} + INTERVAL 8 DAY
430
+ AND toDate(start_time) = {day:Date}
431
+ );
432
+ ```
433
+ </Step>
434
+ <Step title="Copy each day">
435
+ Run it once per day from step 2, oldest first:
436
+
437
+ ```bash
438
+ docker compose exec -T clickhouse clickhouse-client --param_day=2026-08-01 \
439
+ --multiquery < copy-task-events-v1.sql
440
+ ```
441
+ </Step>
442
+ <Step title="Check a copied run">
443
+ Open a run from one of the copied days and check its trace and logs show.
444
+ </Step>
445
+ </Steps>
446
+
447
+ Copying one day at a time keeps memory use bounded on large tables. A future release removes `task_events_v1`, so copy anything you want to keep before then.
448
+
449
+ <Note>
450
+ `EVENT_REPOSITORY_V1_REROUTE_ENABLED=0` keeps the legacy store while you migrate. It's
451
+ temporary and will be removed in a future release.
452
+ </Note>
453
+
392
454
  ## Realtime streams
393
455
 
394
456
  Realtime streams power AI-agent token streaming and run streams. They default to **v2**, backed by the bundled `s2` service — [s2-lite](https://s2.dev), the open-source, self-hostable S2 server. It stores stream data in a persistent volume and is preconfigured in the webapp compose file, so no setup is required.
@@ -33,6 +33,9 @@ mode: "wide"
33
33
  | `TRIGGER_DEQUEUE_INTERVAL_MS` | No | 250 | Dequeue interval (ms). |
34
34
  | `TRIGGER_DEQUEUE_IDLE_INTERVAL_MS` | No | 1000 (1s) | Dequeue idle interval (ms). |
35
35
  | `TRIGGER_DEQUEUE_MAX_CONSUMER_COUNT` | No | 1 | Max dequeue consumer count. |
36
+ | `RELEASE_UNSTARTED_RUNS_ENABLED` | No | false | Set to true to requeue a run straight away when its container or pod can't be created, rather than after the pending execution timeout. Limited by `RUN_RELEASES_PER_MINUTE`. |
37
+ | `RELEASE_FAILED_POD_RUNS_ENABLED` | No | false | Set to true to requeue a run straight away when its pod fails before the run starts, rather than after the pending execution timeout. Independent of `RELEASE_UNSTARTED_RUNS_ENABLED`; the two share `RUN_RELEASES_PER_MINUTE`. Needs `FAILED_POD_HANDLER_ENABLED`. |
38
+ | `RUN_RELEASES_PER_MINUTE` | No | 5 | Different runs released within a minute, by either release flag, past which every release waits for the timeout again until a slot frees, a run already released included. 0 withholds every release; blank means the default. |
36
39
  | **Docker settings** | | | |
37
40
  | `DOCKER_API_VERSION` | No | v1.41 | Docker API version. You should probably not touch this. |
38
41
  | `DOCKER_STRIP_IMAGE_DIGEST` | No | true | Strip image digest in Docker. Turning off can cause issues. |
@@ -52,6 +55,7 @@ mode: "wide"
52
55
  | `KUBERNETES_IMAGE_PULL_SECRETS` | No | — | Image pull secrets (CSV). |
53
56
  | `KUBERNETES_EPHEMERAL_STORAGE_SIZE_LIMIT` | No | 10Gi | Ephemeral storage size limit. Applies to all runs. |
54
57
  | `KUBERNETES_EPHEMERAL_STORAGE_SIZE_REQUEST` | No | 2Gi | Ephemeral storage size request. Applies to all runs. |
58
+ | `KUBERNETES_POD_RESERVED_SOURCE_PORTS` | No | — | Ports runs never use as the source port of an outbound connection, so they can't clash with services on those ports. CSV of ports or ranges, e.g. `50080,50081` or `50080-50090`. Sets the pod's `net.ipv4.ip_local_reserved_ports` sysctl. |
55
59
  | **Metrics** | | | |
56
60
  | `METRICS_ENABLED` | No | true | Enable metrics. |
57
61
  | `METRICS_COLLECT_DEFAULTS` | No | true | Collect default metrics. |
@@ -88,6 +88,11 @@ mode: "wide"
88
88
  | `API_RATE_LIMIT_METRICS_MAX_ENTRIES` | No | 10000 | Cap on distinct (environment, bucket) entries held between flushes. |
89
89
  | `API_RATE_LIMIT_METRICS_WAIT_FOR_ASYNC_INSERT` | No | 0 | Wait for ClickHouse to write each async insert of API rate limit metrics, surfacing write failures. |
90
90
  | `API_RATE_LIMIT_METRICS_INSERT_BUSY_TIMEOUT_MS` | No | 10000 | How long ClickHouse buffers API rate limit metric inserts before writing a part. |
91
+ | `WEBHOOK_METRICS_FLUSH_INTERVAL_MS` | No | 10000 | How often aggregated webhook limit metrics are flushed to ClickHouse. |
92
+ | `WEBHOOK_METRICS_MAX_ENTRIES` | No | 10000 | Cap on distinct (environment, bucket) entries held between flushes. |
93
+ | `WEBHOOK_METRICS_MAX_ENDPOINTS` | No | 500 | Cap on endpoints with their own webhook metric rows per environment and bucket; environment totals still count all. |
94
+ | `QUEUE_SIZE_METRICS_INTERVAL_SEC` | No | 30 | Queue size sampling interval in seconds; must divide 60. |
95
+ | `QUEUE_SIZE_METRICS_MAX_ENVS` | No | 2000 | Most environments sampled per interval. |
91
96
  | `DEPLOYMENT_RATE_LIMIT_REFILL_INTERVAL` | No | 10s | Deployment endpoints rate limit refill interval. |
92
97
  | `DEPLOYMENT_RATE_LIMIT_MAX` | No | 1500 | Deployment endpoints rate limit max. |
93
98
  | `DEPLOYMENT_RATE_LIMIT_REFILL_RATE` | No | 500 | Deployment endpoints rate limit refill rate. |
@@ -123,6 +128,14 @@ mode: "wide"
123
128
  | `ARTIFACTS_OBJECT_STORE_ACCESS_KEY_ID` | No | — | Optional artifacts store access key. |
124
129
  | `ARTIFACTS_OBJECT_STORE_SECRET_ACCESS_KEY` | No | — | Optional artifacts store secret key. |
125
130
  | `ARTIFACTS_OBJECT_STORE_REGION` | No | — | Optional artifacts store region. |
131
+ | `DEPLOYMENT_INDEX_OBJECT_STORE_BASE_URL` | No | — | Optional separate store for deployment index snapshots. If not set, uses main object store. |
132
+ | `DEPLOYMENT_INDEX_OBJECT_STORE_BUCKET` | No | — | Deployment index store bucket. Required together with the base URL. |
133
+ | `DEPLOYMENT_INDEX_OBJECT_STORE_ACCESS_KEY_ID` | No | — | Deployment index store access key. |
134
+ | `DEPLOYMENT_INDEX_OBJECT_STORE_SECRET_ACCESS_KEY` | No | — | Deployment index store secret key. |
135
+ | `DEPLOYMENT_INDEX_OBJECT_STORE_REGION` | No | — | Deployment index store region. |
136
+ | `DEPLOYMENT_INDEX_OBJECT_STORE_SERVICE` | No | s3 | Deployment index store service. |
137
+ | `DEPLOYMENT_INDEX_UPLOAD_MAX_ATTEMPTS` | No | 4 | Attempts to store a deployment's index before the deploy fails. |
138
+ | `DEPLOYMENT_INDEX_CAPTURE_ENABLED` | No | false | Set to true to store each deployment's full index in object storage when it deploys. |
126
139
  | **Alerts** | | | |
127
140
  | `ORG_SLACK_INTEGRATION_CLIENT_ID` | No | — | Slack client ID. Required for Slack alerts. |
128
141
  | `ORG_SLACK_INTEGRATION_CLIENT_SECRET` | No | — | Slack client secret. Required for Slack alerts. |
@@ -160,6 +173,7 @@ mode: "wide"
160
173
  | `SERVER_OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` | No | 8192 | OTel span attribute value length limit. |
161
174
  | **Task events** | | | |
162
175
  | `EVENT_REPOSITORY_DEFAULT_STORE` | No | postgres | Where to store task events. Set to `clickhouse_v2` to store in ClickHouse (recommended for production). |
176
+ | `EVENT_REPOSITORY_V1_REROUTE_ENABLED` | No | 1 | Routes the retired `clickhouse` store to `clickhouse_v2`, for new events and for reads. Set `EVENT_REPOSITORY_DEFAULT_STORE=clickhouse_v2` and [copy older events](/self-hosting/docker#move-from-the-legacy-clickhouse-store) to keep them. `0` keeps the legacy store temporarily and will be removed. |
163
177
  | `EVENT_REPOSITORY_POSTGRES_WRITES_DISABLED` | No | 0 | Skip all PostgreSQL task-event writes (set to `1`). Only enable when `EVENT_REPOSITORY_DEFAULT_STORE` is `clickhouse_v2`, otherwise task events are lost. |
164
178
  | **Realtime** | | | |
165
179
  | `REALTIME_BACKEND_NATIVE_ENABLED` | No | 0 | Set to `1` to enable native realtime run subscriptions and change notifications. When `0`, subscriptions use Electric. The Helm chart sets this to `1`. |
@@ -192,6 +206,18 @@ mode: "wide"
192
206
  | `RUN_ENGINE_DEFAULT_MAX_TTL` | No | — | Maximum TTL for all runs (e.g. "14d"). Runs without a TTL use this as default; runs with a larger TTL are clamped. |
193
207
  | `MAXIMUM_DEV_QUEUE_SIZE` | No | — | Maximum queued runs per queue in development environments. |
194
208
  | `MAXIMUM_DEPLOYED_QUEUE_SIZE` | No | — | Maximum queued runs per queue in deployed (staging/prod) environments. |
209
+ | **Webhooks** | | | |
210
+ | `WEBHOOK_ENABLED` | No | 0 | Set to `1` to run hosted webhooks: ingest, delivery and waiters. See [Webhooks](#webhooks). |
211
+ | `WEBHOOK_REDIS_HOST` | No | localhost | A node of the Redis cluster webhooks use for their queue and waiters. It must run in cluster mode. |
212
+ | `WEBHOOK_REDIS_PORT` | No | 6379 | Port of that node. |
213
+ | `WEBHOOK_REDIS_USERNAME` | No | — | Webhooks Redis username. |
214
+ | `WEBHOOK_REDIS_PASSWORD` | No | — | Webhooks Redis password. |
215
+ | `WEBHOOK_REDIS_TLS_DISABLED` | No | `REDIS_TLS_DISABLED` | Set to `true` to connect to the webhooks Redis without TLS. |
216
+ | `WEBHOOK_INGRESS_ORIGIN` | No | `API_ORIGIN` | Public origin of the webhook URLs, for when you serve them from their own host. |
217
+ | `WEBHOOK_INGRESS_BODY_SIZE_LIMIT_MB` | No | 1 | Largest webhook request body accepted, in MB. |
218
+ | `WEBHOOK_DATABASE_URL` | No | `DATABASE_URL` | A separate PostgreSQL database for webhook endpoints and deliveries. |
219
+ | `WEBHOOK_DELIVERY_RETENTION_DAYS` | No | 30 | How many days of deliveries the dashboard and API show. It doesn't delete anything: deliveries are kept for `WEBHOOK_DELIVERY_STORAGE_DAYS`, or longer when this is higher. |
220
+ | `WEBHOOK_DELIVERY_STORAGE_DAYS` | No | 30 | How long deliveries are stored before they're deleted. Must be one of `3`, `7`, `30`, `90`, `180` or `365`; any other value stops the webapp from starting. |
195
221
  | **Misc** | | | |
196
222
  | `TRIGGER_TELEMETRY_DISABLED` | No | — | Disable telemetry. |
197
223
  | `NODE_MAX_OLD_SPACE_SIZE` | No | 8192 | Maximum memory allocation for Node.js heap in MiB (e.g. "4096" for 4GB). |
@@ -202,6 +228,18 @@ mode: "wide"
202
228
  | `ADMIN_DASHBOARD_ENABLED` | No | 1 | Set to anything other than `1` or `true` to disable the admin dashboard and user impersonation on this instance. |
203
229
  | `EVENT_LOOP_MONITOR_ENABLED` | No | 1 | Node.js event loop lag monitor. |
204
230
 
231
+ ## Webhooks
232
+
233
+ Hosted webhooks are off on a self-hosted instance until you turn them on:
234
+
235
+ 1. Run a Redis (or Valkey) cluster for webhooks and point `WEBHOOK_REDIS_HOST` and `WEBHOOK_REDIS_PORT` at one of its nodes. The webhook engine connects in cluster mode, so a standalone Redis won't work.
236
+ 2. Set `WEBHOOK_ENABLED=1` on the webapp.
237
+ 3. Give organizations access with the `hasWebhooksAccess` feature flag: turn it on for everyone on the admin dashboard's **Global Feature Flags** page, or for one organization from its feature flags on the **Organizations** page. An organization without it doesn't see Webhooks in the dashboard, and its deploys don't sync endpoints.
238
+
239
+ Webhook URLs are served from `WEBHOOK_INGRESS_ORIGIN`, which defaults to `API_ORIGIN`, so providers need to reach that origin from the internet.
240
+
241
+ The Docker Compose setup only passes the variables listed under the webapp service's `environment` in `hosting/docker/webapp/docker-compose.yml`, so add the webhook variables there. With the Helm chart, set them in `webapp.extraEnvVars`.
242
+
205
243
  ## Multi-Provider Object Storage
206
244
 
207
245
  The object storage system supports multiple S3-compatible providers (R2, S3, GCS, MinIO, etc.) using protocol prefixes. This enables migrating between providers without breaking existing runs.
@@ -679,6 +679,8 @@ webapp:
679
679
 
680
680
  This only affects new runs; existing runs continue to read from wherever their events were originally stored.
681
681
 
682
+ If you set `EVENT_REPOSITORY_DEFAULT_STORE` to the legacy `clickhouse` store, switch it to `clickhouse_v2`. To keep events recorded before the switch, follow [Move from the legacy clickhouse store](/self-hosting/docker#move-from-the-legacy-clickhouse-store) and run the queries with `kubectl exec` against your ClickHouse pod.
683
+
682
684
  ### Realtime streams
683
685
 
684
686
  Realtime streams power AI-agent token streaming and run streams. They default to **v2**, backed by the bundled `s2` deployment — [s2-lite](https://s2.dev), the open-source, self-hostable S2 server. The chart deploys it with a persistent volume, so no extra services are required.
@@ -121,6 +121,8 @@ You own a custom base image. It must provide:
121
121
 
122
122
  A `DEPLOY_BUILD_BASE_IMAGES` image needs everything the base image provides, plus `python3`, `make` and `g++`. Build extensions that add image instructions are replayed on it. Without an entry, the build stage uses the published build image, except for projects whose build extensions add image instructions: those build from your base image and install the toolchain with `apt-get`, so that base must be Debian-based. To avoid the published images entirely, set both variables.
123
123
 
124
+ A custom image is yours to harden. Deploys on the published images remove trust in publicly compromised certificate authorities and point Node.js and Python at the OS trust store. Stages built on a custom image get neither, and run with the certificate settings the image ships with. Keeping a custom image patched, trust store included, is your responsibility.
125
+
124
126
  <Warning>
125
127
  `image.pkgs` and build extensions that run `apt-get` (such as `aptGet` and `playwright`) assume a
126
128
  Debian base. On other distributions, install those packages in your base image instead.
@@ -3,6 +3,8 @@ title: "Alerts"
3
3
  description: "Get alerted when runs or deployments fail, or when deployments succeed."
4
4
  ---
5
5
 
6
+ import { PrivateBeta } from "/snippets/feature-status.jsx";
7
+
6
8
  We support receiving alerts for the following events:
7
9
  - Run fails
8
10
  - Deployment fails
@@ -44,6 +46,43 @@ Click on the triple dot menu on the right side of the table row and select "Disa
44
46
  </Steps>
45
47
 
46
48
 
49
+ ## Limits alerts
50
+
51
+ <PrivateBeta flag="alertsEnabled" />
52
+
53
+ A **Limits** alert watches limits that can interrupt or degrade runtime flow. Pick one limit for a single alert, or several (or "Watch all limits") for one combined alert.
54
+
55
+ | Group | What you can watch |
56
+ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
57
+ | Platform | API rate limit running out, Environment concurrency filling up, Queue size nearing its limit |
58
+ | Webhooks | Webhook processing saturating, Webhook ingress getting rate-limited, Webhook endpoint getting rate-limited, Webhook waiters running out |
59
+
60
+ ### Signals
61
+
62
+ Each limit has up to two signals. Choose one or both:
63
+
64
+ - **Limit reached**: the limit is already affecting traffic, for example requests are being rejected.
65
+ - **Approaching the limit**: usage has reached a share of the limit. The default is 80%, and you can change it.
66
+
67
+ Queue size only has the approaching signal.
68
+
69
+ ### Any or all
70
+
71
+ When you watch more than one limit, choose when the alert raises:
72
+
73
+ - **Any**: raise when at least one selected limit is true.
74
+ - **All**: raise only when every selected limit is true at the same time.
75
+
76
+ ### Queue metrics
77
+
78
+ Environment concurrency and queue size need queue metrics for your environment. If they aren't available, they aren't offered when you create the alert.
79
+
80
+ ### No data
81
+
82
+ A limit shows "No data" until its metrics exist, for example before your environment has made any API requests or received any webhooks. You can query these metrics yourself, see [Platform limit metrics](/observability/query#platform-limit-metrics).
83
+
84
+ You can also create these alerts with the [API](/management/alerts/create).
85
+
47
86
  ## Error group alerts
48
87
 
49
88
  Error group alerts are **issue-based**, not run-based. They are created from the **Errors** page in the dashboard (the "Configure alerts…" button), not from the New alert modal on the Alerts page. Once created they show up in the Alerts table alongside your other alerts, labelled "Error group".
@@ -70,6 +70,10 @@ The [MCP server](/mcp-introduction) has `list_webhook_deliveries` (filter by end
70
70
  | [`GET /api/v1/webhooks/deliveries/{deliveryId}`](/management/webhooks/retrieve-delivery) | Reads a delivery, with a `targets` entry per subscriber and one for waiting runs. |
71
71
  | [`POST /api/v1/webhooks/deliveries/{deliveryId}/replay`](/management/webhooks/replay-delivery) | Replays it, as above. The key needs permission to trigger every task the replay starts, and to write sessions if it reaches an agent's subscriber. |
72
72
 
73
+ ## Retention
74
+
75
+ Deliveries stay visible for 3 days on Free, 7 days on Hobby, 30 days on Pro, and 90, 180 or 365 days on Enterprise. See [Limits](/limits#webhook-delivery-retention).
76
+
73
77
  ## Deduplication
74
78
 
75
79
  Trigger.dev uses the endpoint and idempotency key to deduplicate incoming events. Delivery records and task runs have separate deduplication windows:
@@ -83,6 +83,14 @@ The CLI finds your endpoints and subscribers during `trigger dev` and deployment
83
83
 
84
84
  A request must pass verification before anything else happens. Provider handshakes are answered directly and create no delivery. A verified request is checked for duplicates, recorded, and then routed: each subscriber's filter is checked, matching subscribers run, and waiting runs whose match fits the event are resumed. The delivery records a result per subscriber.
85
85
 
86
+ ## Pricing and limits
87
+
88
+ Webhooks have no separate charge on Trigger.dev Cloud. Receiving, verifying, filtering and recording deliveries is included in every plan. The runs a delivery starts or resumes are billed like any other run: a per-run invocation cost plus compute time. See [pricing](https://trigger.dev/pricing).
89
+
90
+ A delivery that no subscriber's filter matches starts no run for any subscriber, so it costs nothing. A run already waiting for that webhook still resumes. A run [waiting](/webhooks/waiters) for a webhook is suspended, so it uses no compute until the webhook arrives.
91
+
92
+ Each plan sets limits on the ingest rate, waiting runs, processing concurrency and how long deliveries are kept. See [Limits](/limits#webhook-ingest-rate-limits).
93
+
86
94
  ## Connect it
87
95
 
88
96
  Every endpoint can produce a setup prompt for an AI coding agent. It holds the URL, the events your subscribers filter on, and the steps for registering the endpoint and its signing secret with the provider. Copy it from the endpoints list or the endpoint's page, or read it with the MCP server's `get_webhook_endpoint_details` tool. See [Connect a provider](/webhooks/connect).
@@ -106,6 +106,8 @@ Supabase database webhooks aren't signed, so `supabase()` checks a shared secret
106
106
 
107
107
  Slack also ships as a chat channel in `@trigger.dev/slack`.
108
108
 
109
+ For a complete project built on `resend()`, see the [Resend email agent example](https://github.com/triggerdotdev/examples/tree/main/resend-slack-email-agent). It drafts replies to a Resend inbox and waits for your approval in Slack before sending them.
110
+
109
111
  ### Hookdeck
110
112
 
111
113
  `hookdeck()` verifies requests that a [Hookdeck](https://hookdeck.com) connection forwards to the endpoint. Hookdeck forwards the original provider's body unchanged, so pass that provider's event type:
@@ -242,7 +244,7 @@ Custom sources support these schemes:
242
244
  | `hmac` | Computes an HMAC over the raw body or a signing template and compares it with a request header. |
243
245
  | `shared-secret` | Compares a static token supplied in a header, bearer token, basic authentication, or request body. |
244
246
  | `url-secret` | Compares a token in a URL query parameter. Hosted endpoints don't support path placement. |
245
- | `asymmetric` | Verifies an Ed25519, ECDSA, or RSA signature using the provider's public key. |
247
+ | `asymmetric` | Verifies an Ed25519, ECDSA (P-256 with SHA-256, P-384 with SHA-384), or RSA-SHA256 signature using the provider's public key. Set `prehash: "sha256"` when the provider signs a SHA-256 digest of the signing string instead of the string itself. |
246
248
 
247
249
  <Warning>
248
250
  Query parameters can appear in access logs, proxies, and traces. Prefer a header-based scheme when
@@ -178,13 +178,13 @@ if (!result.cancelled) {
178
178
 
179
179
  | Limit | Default |
180
180
  | --- | --- |
181
- | Live waiters per endpoint | 10,000. This is also the most one delivery can resume. |
182
- | Live waiters per environment | 1,000,000 on self-hosted installs. |
181
+ | Live waiters per endpoint | Depends on your plan on Trigger.dev Cloud, 10,000 on self-hosted installs. This is also the most one delivery can resume. |
182
+ | Live waiters per environment | Depends on your plan on Trigger.dev Cloud, 1,000,000 on self-hosted installs. |
183
183
  | Distinct sets of `match` paths per endpoint | 25 |
184
184
  | Paths per `match` | 5 |
185
185
  | Tags per waiter | 10 |
186
186
  | Timeout | 24 hours by default, 90 days at most |
187
187
 
188
- On Trigger.dev Cloud the per-endpoint and per-environment limits depend on your plan. Self-hosted installs can change them with `WEBHOOK_WAITER_MAX_PER_ENDPOINT`, `WEBHOOK_WAITER_MAX_PER_ENVIRONMENT` and `WEBHOOK_WAITER_MAX_SHAPES`.
188
+ On Trigger.dev Cloud the per-endpoint and per-environment limits depend on your plan: see [Limits](/limits#webhook-waiters). Self-hosted installs can change them with `WEBHOOK_WAITER_MAX_PER_ENDPOINT`, `WEBHOOK_WAITER_MAX_PER_ENVIRONMENT` and `WEBHOOK_WAITER_MAX_SHAPES`.
189
189
 
190
190
  A delivery that resumes waiters shows one **Waiting runs** row on its [delivery page](/webhooks/deliveries#where-a-delivery-went) with how many matched, resumed and failed. A delivery that arrives while runs are waiting but matches none of them, and no subscriber takes, is `UNMATCHED`.