@trigger.dev/sdk 4.8.0-webhooks.20261015065339 → 4.8.0-webhooks.20261020092920

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 (53) hide show
  1. package/dist/commonjs/v3/ai.d.ts +67 -1
  2. package/dist/commonjs/v3/ai.js +102 -29
  3. package/dist/commonjs/v3/ai.js.map +1 -1
  4. package/dist/commonjs/v3/query.d.ts +434 -1
  5. package/dist/commonjs/v3/query.js +115 -0
  6. package/dist/commonjs/v3/query.js.map +1 -1
  7. package/dist/commonjs/v3/webhooks.d.ts +8 -2
  8. package/dist/commonjs/v3/webhooks.js +2 -1
  9. package/dist/commonjs/v3/webhooks.js.map +1 -1
  10. package/dist/commonjs/version.js +1 -1
  11. package/dist/esm/v3/ai.d.ts +67 -1
  12. package/dist/esm/v3/ai.js +101 -28
  13. package/dist/esm/v3/ai.js.map +1 -1
  14. package/dist/esm/v3/query.d.ts +434 -1
  15. package/dist/esm/v3/query.js +115 -0
  16. package/dist/esm/v3/query.js.map +1 -1
  17. package/dist/esm/v3/webhooks.d.ts +8 -2
  18. package/dist/esm/v3/webhooks.js +2 -1
  19. package/dist/esm/v3/webhooks.js.map +1 -1
  20. package/dist/esm/version.js +1 -1
  21. package/docs/ai-chat/backend.mdx +6 -0
  22. package/docs/ai-chat/patterns/redacting-telemetry.mdx +117 -0
  23. package/docs/ai-chat/pending-messages.mdx +1 -1
  24. package/docs/ai-chat/reference.mdx +7 -4
  25. package/docs/ai-chat/transcript-storage.mdx +1 -1
  26. package/docs/apikeys.mdx +6 -4
  27. package/docs/cli-runs-commands.mdx +2 -2
  28. package/docs/cli-tasks-commands.mdx +95 -0
  29. package/docs/config/config-file.mdx +58 -0
  30. package/docs/config/extensions/prismaExtension.mdx +4 -4
  31. package/docs/deploy-environment-variables.mdx +4 -0
  32. package/docs/deployment/atomic-deployment.mdx +3 -3
  33. package/docs/deployment/overview.mdx +1 -1
  34. package/docs/deployment/preview-branches.mdx +1 -1
  35. package/docs/github-actions.mdx +3 -3
  36. package/docs/limits.mdx +6 -0
  37. package/docs/manual-setup.mdx +1 -1
  38. package/docs/mcp-tools.mdx +23 -3
  39. package/docs/observability/dashboards.mdx +62 -0
  40. package/docs/runs/max-duration.mdx +4 -0
  41. package/docs/self-hosting/env/supervisor.mdx +1 -0
  42. package/docs/webhooks/channels.mdx +6 -2
  43. package/docs/webhooks/connect.mdx +4 -0
  44. package/docs/webhooks/deliveries.mdx +4 -0
  45. package/docs/webhooks/filters.mdx +35 -2
  46. package/docs/webhooks/human-in-the-loop.mdx +6 -0
  47. package/docs/webhooks/linear.mdx +7 -3
  48. package/docs/webhooks/overview.mdx +4 -0
  49. package/docs/webhooks/session-routing.mdx +7 -1
  50. package/docs/webhooks/slack.mdx +12 -4
  51. package/docs/webhooks/sources.mdx +4 -0
  52. package/docs/webhooks/waiters.mdx +26 -2
  53. package/package.json +3 -2
@@ -4,6 +4,8 @@ sidebarTitle: "Backend"
4
4
  description: "Three approaches to building your chat backend — chat.agent(), session iterator, or raw task primitives."
5
5
  ---
6
6
 
7
+ import WebhooksBetaNote from "/snippets/webhooks-beta-note.mdx";
8
+
7
9
  There are three abstraction levels for a chat backend. All three speak the same wire protocol, so the [frontend transport](/ai-chat/frontend) works unchanged whichever you pick.
8
10
 
9
11
  | Capability | `chat.agent()` | `chat.createSession()` | Raw primitives |
@@ -499,6 +501,8 @@ See [Actions](/ai-chat/actions).
499
501
 
500
502
  ### Webhook events and channels
501
503
 
504
+ <WebhooksBetaNote />
505
+
502
506
  Two `chat.agent()` options wire an agent to verified inbound webhooks. `events` claims [`chat.event(...)`](/webhooks/session-routing) descriptors: each verified delivery is routed to this agent's session and arrives at `onAction` as an action (not a turn), so [session routing](/webhooks/session-routing) decides which conversation it lands on. `channels` claims channel connectors that turn an external chat surface into a frontend for the agent: an inbound message runs as a turn through `run()` and the reply is posted back. `slack()` ships in `@trigger.dev/slack`, and `chat.channels.custom(...)` builds a connector for any endpoint without a preset.
503
507
 
504
508
  ```ts
@@ -513,6 +517,8 @@ export const orderEvents = chat.event({
513
517
  id: "order-events",
514
518
  endpoint: stripe,
515
519
  key: "{event.data.object.customer}",
520
+ // invoices always carry a customer; events without one would have no session to go to
521
+ filter: "event.type startsWith 'invoice.'",
516
522
  type: "order.event",
517
523
  });
518
524
 
@@ -0,0 +1,117 @@
1
+ ---
2
+ title: "Redact chat content from traces"
3
+ sidebarTitle: "Redact chat content"
4
+ description: "Stop a chat agent recording user messages and clientData on its spans, turn off AI SDK prompt and response recording, or redact span content with a span processor before it leaves the worker."
5
+ ---
6
+
7
+ A chat agent's run trace records conversation content by default: the user's message and the `clientData` your frontend sends. When AI SDK telemetry is on, it also records the prompts and responses of each model call. This page covers the three controls that change that, and what they don't cover.
8
+
9
+ ## What the run trace records
10
+
11
+ | Span | Content | Control |
12
+ | --- | --- | --- |
13
+ | `chat turn N` | The last user message (`chat.user_message`) and its first 80 characters as the span preview | `telemetry.recordUserMessage` |
14
+ | `chat turn N` | The raw `clientData` (`chat.client_data`) | `telemetry.recordClientData` |
15
+ | `pending message injected` | Messages sent mid-turn (`pending.messages`) | `telemetry.recordUserMessage` |
16
+ | AI SDK model call spans, when AI SDK telemetry is on | Prompt messages, response text, tool calls | `experimental_telemetry` on the model call |
17
+ | Any span | Everything above, plus your own attributes and span events | A span processor |
18
+
19
+ ## Stop recording chat content
20
+
21
+ Set `telemetry` on the agent to stop the chat runtime recording the user's message and `clientData` on its spans. Both default to `true`.
22
+
23
+ ```ts /trigger/support-agent.ts
24
+ import { chat } from "@trigger.dev/sdk/ai";
25
+ import { anthropic } from "@ai-sdk/anthropic";
26
+
27
+ export const supportAgent = chat.agent({
28
+ id: "support-agent",
29
+ telemetry: { recordUserMessage: false, recordClientData: false },
30
+ run: async ({ messages, signal, streamText }) =>
31
+ streamText({ model: anthropic("claude-sonnet-4-5"), messages, abortSignal: signal }),
32
+ });
33
+ ```
34
+
35
+ The spans still appear in the trace with their timings and token usage. The turn spans have no preview text.
36
+
37
+ ## Stop the AI SDK recording prompts and responses
38
+
39
+ AI SDK model call spans appear when AI SDK telemetry is on: [`chat.prompt.set()`](/ai-chat/backend#using-prompts) turns it on for you, or you pass `experimental_telemetry` yourself. Those spans include prompts and responses unless you turn that off with `recordInputs` and `recordOutputs`:
40
+
41
+ ```ts /trigger/support-agent.ts
42
+ import { chat } from "@trigger.dev/sdk/ai";
43
+ import { anthropic } from "@ai-sdk/anthropic";
44
+
45
+ export const supportAgent = chat.agent({
46
+ id: "support-agent",
47
+ telemetry: { recordUserMessage: false, recordClientData: false },
48
+ run: async ({ messages, signal, streamText }) =>
49
+ streamText({
50
+ model: anthropic("claude-sonnet-4-5"),
51
+ messages,
52
+ abortSignal: signal,
53
+ // Replaces any telemetry config from chat.prompt.set(), so keep isEnabled on
54
+ experimental_telemetry: { isEnabled: true, recordInputs: false, recordOutputs: false },
55
+ }),
56
+ });
57
+ ```
58
+
59
+ If you use `chat.prompt.set()`, your `experimental_telemetry` replaces the one it adds, including the metadata that links each generation to its prompt version. To keep that link, redact with a span processor instead.
60
+
61
+ ## Redact instead of dropping
62
+
63
+ To keep the content but strip sensitive values from it, add a span processor in `trigger.config.ts`. It runs on every span before export, so one processor covers the chat runtime's spans, the AI SDK spans and your own.
64
+
65
+ ```ts trigger.config.ts
66
+ import { defineConfig } from "@trigger.dev/sdk";
67
+ import type { AttributeValue, Attributes } from "@opentelemetry/api";
68
+ import type { SpanProcessor } from "@opentelemetry/sdk-trace-base";
69
+
70
+ const EMAIL = /[\w.+-]+@[\w-]+\.[\w.]+/g;
71
+
72
+ function redact(value: AttributeValue | undefined): AttributeValue | undefined {
73
+ if (typeof value === "string") return value.replace(EMAIL, "[email]");
74
+ // Some attributes are string arrays, like the messages sent mid-turn
75
+ if (Array.isArray(value)) {
76
+ return value.map((item) =>
77
+ typeof item === "string" ? item.replace(EMAIL, "[email]") : item
78
+ ) as AttributeValue;
79
+ }
80
+ return value;
81
+ }
82
+
83
+ function scrub(attributes: Attributes) {
84
+ for (const key of Object.keys(attributes)) attributes[key] = redact(attributes[key]);
85
+ }
86
+
87
+ const redactEmails: SpanProcessor = {
88
+ onStart: () => {},
89
+ onEnding: (span) => {
90
+ scrub(span.attributes);
91
+ for (const event of span.events) scrub(event.attributes ?? {});
92
+ },
93
+ onEnd: () => {},
94
+ forceFlush: async () => {},
95
+ shutdown: async () => {},
96
+ };
97
+
98
+ export default defineConfig({
99
+ project: "<project ref>",
100
+ telemetry: { spanProcessors: [redactEmails] },
101
+ });
102
+ ```
103
+
104
+ Scrubbing every string value, rather than matching attribute names, also catches the turn preview text. See [Span processors](/config/config-file#span-processors) for when each hook runs and which attributes are kept.
105
+
106
+ ## What spans don't cover
107
+
108
+ These controls change the run trace only. Conversation content also reaches the platform in two other places:
109
+
110
+ - **Session streams.** Each message your frontend sends is written to the session's `session.in` stream, and the agent's output to `session.out`. They hold message content for their retention window, and the session view in the dashboard reads from them. See [transcript storage limits](/ai-chat/transcript-storage#guarantees-and-limits).
111
+ - **The run payload.** A chat agent run's payload includes `clientData` as `metadata`, and every `session.in` record carries it too. Send an id in `clientData` and look up the rest in `onPreload` or `run` instead of sending the values themselves.
112
+
113
+ To keep a value off the platform entirely, redact or tokenize it in your frontend or backend before it's sent. The model then sees the redacted value too, unless your tools resolve the tokens.
114
+
115
+ ## Verify it
116
+
117
+ Send a message containing a marker value (an email address, for example), then open the run in the dashboard. Select the `chat turn 1` span and check its properties: the marker is gone, or shows as `[email]` with the span processor above. The span list shows the same redacted preview.
@@ -12,7 +12,7 @@ By default (without `pendingMessages`), a message sent while the agent is respon
12
12
 
13
13
  The `pendingMessages` option enables steering instead, injecting user messages between tool-call steps via the AI SDK's `prepareStep`. Messages that arrive during streaming are queued and injected at the next step boundary. A message that is not injected becomes the next turn instead, whether that is because `shouldInject` returned `false` or because there were no more step boundaries (single-step response or final text generation). The backend handles that, so no client-side re-send is involved.
14
14
 
15
- Messages from a [channel](/webhooks/channels) such as [Slack](/webhooks/slack) are offered the same way, with `metadata.source` set to `"channel"` so `shouldInject` can tell them apart. A channel's stop control and approval clicks are never offered. The connector acknowledges a channel message as soon as it arrives (Slack reacts with 👀, Linear posts a thought), before `shouldInject` decides, so the acknowledgement is the same whether the message is folded in or answered next.
15
+ Messages from a [channel](/webhooks/channels) such as [Slack](/webhooks/slack) are offered the same way, with `metadata.source` set to `"channel"` so `shouldInject` can tell them apart. A channel's stop control and approval clicks are never offered. The connector acknowledges a channel message as soon as it arrives (Slack reacts with 👀, Linear posts a thought), before `shouldInject` decides, so the acknowledgement is the same whether the message is folded in or answered next. Channels are part of the [webhooks private beta](https://trigger.dev/webhooks-beta).
16
16
 
17
17
  Use the `streamText` passed to your agent's `run` callback. It wires up pending-message injection automatically. If you import `streamText` directly from `ai`, spread `chat.toStreamTextOptions()` into its options to connect injection.
18
18
 
@@ -48,8 +48,8 @@ Options for `chat.agent()`.
48
48
  | `hydrateMessages` | `(event: HydrateMessagesEvent) => UIMessage[] \| Promise<UIMessage[]>` | — | **Deprecated.** Load message history from backend, replacing the linear accumulator. Use `loadContext` on a `storage` instead; cannot be combined with `storage`. See [hydrateMessages](/ai-chat/lifecycle-hooks#hydratemessages) |
49
49
  | `actionSchema` | `TaskSchema` | — | Schema for validating custom actions sent via `transport.sendAction()`. See [Actions](/ai-chat/actions) |
50
50
  | `onAction` | `(event: ActionEvent) => Promise<void \| ActionTurn> \| void \| ActionTurn` | — | Handle custom actions. Actions are state edits: only `hydrateMessages` (or a storage's `loadContext`) + `onAction` fire. Return `chat.turn()` to run a turn on the edited history (`chat.turn(message)` to answer a new user message), or nothing for an edit only. See [Actions](/ai-chat/actions) |
51
- | `events` | `ChatEvent[]` | — | Webhook event descriptors (from `chat.event()`) whose verified deliveries are routed to this agent as actions and handled in `onAction`. See [session routing](/webhooks/session-routing). |
52
- | `channels` | `ChannelConnector[]` | — | Channel connectors (for example `slack()`) that turn an external chat surface into a frontend for the agent: inbound messages run as turns and the reply posts back. See [channels](/webhooks/channels). |
51
+ | `events` | `ChatEvent[]` | — | Webhook event descriptors (from `chat.event()`) whose verified deliveries are routed to this agent as actions and handled in `onAction`. See [session routing](/webhooks/session-routing). Part of the [webhooks private beta](https://trigger.dev/webhooks-beta). |
52
+ | `channels` | `ChannelConnector[]` | — | Channel connectors (for example `slack()`) that turn an external chat surface into a frontend for the agent: inbound messages run as turns and the reply posts back. See [channels](/webhooks/channels). Part of the [webhooks private beta](https://trigger.dev/webhooks-beta). |
53
53
  | `onTurnStart` | `(event: TurnStartEvent) => Promise<void> \| void` | — | Fires every turn before `run()` |
54
54
  | `onBeforeTurnComplete` | `(event: BeforeTurnCompleteEvent) => Promise<void> \| void` | — | Fires after response but before stream closes. Includes `writer`. |
55
55
  | `onTurnComplete` | `(event: TurnCompleteEvent) => Promise<void> \| void` | — | Fires after each turn completes (stream closed) |
@@ -73,6 +73,7 @@ Options for `chat.agent()`.
73
73
  | `onChatResume` | `(event: ChatResumeEvent) => Promise<void> \| void` | — | Fires right after the run resumes from suspension |
74
74
  | `exitAfterPreloadIdle` | `boolean` | `false` | Exit run after preload idle timeout instead of suspending. See [exitAfterPreloadIdle](/ai-chat/lifecycle-hooks#exitafterpreloadidle) |
75
75
  | `oomMachine` | `MachinePresetName` | — | Fallback machine when an attempt fails with OOM. Setting it enables a single OOM retry on the larger machine. See [OOM resilience](/ai-chat/patterns/oom-resilience) |
76
+ | `telemetry` | `{ recordUserMessage?: boolean; recordClientData?: boolean }` | both `true` | What the chat runtime records on its spans. `recordUserMessage: false` drops the user message and turn preview (`chat.user_message`, `pending.messages`); `recordClientData: false` drops `chat.client_data`. See [Redact chat content from traces](/ai-chat/patterns/redacting-telemetry) |
76
77
 
77
78
  Plus most standard [TaskOptions](/tasks/overview) — `queue`, `machine`, `maxDuration`, **`onWait`**, **`onResume`**, **`onComplete`**, and other lifecycle hooks. Generic `retry` is **not** exposed on `chat.agent`; use `oomMachine` for OOM recovery, or drop down to a raw [`task()`](/ai-chat/custom-agents) if you need richer retry semantics. Standard hooks use the same parameter shapes as on a normal `task()` (including `ctx`).
78
79
 
@@ -541,8 +542,8 @@ All methods available on the `chat` object from `@trigger.dev/sdk/ai`.
541
542
  | Method | Description |
542
543
  | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
543
544
  | `chat.agent(options)` | Create a chat agent |
544
- | `chat.event(options)` | Declare an inbound webhook event descriptor an agent claims via `chat.agent({ events })`. See [session routing](/webhooks/session-routing). |
545
- | `chat.channels.custom(options)` | Create a generic chat-frontend channel over any verified webhook source (you supply the egress). The `slack()` preset ships in `@trigger.dev/slack`. See [channels](/webhooks/channels). |
545
+ | `chat.event(options)` | Declare an inbound webhook event descriptor an agent claims via `chat.agent({ events })`. See [session routing](/webhooks/session-routing). Part of the [webhooks private beta](https://trigger.dev/webhooks-beta). |
546
+ | `chat.channels.custom(options)` | Create a generic chat-frontend channel over any verified webhook source (you supply the egress). The `slack()` preset ships in `@trigger.dev/slack`. See [channels](/webhooks/channels). Part of the [webhooks private beta](https://trigger.dev/webhooks-beta). |
546
547
  | `chat.createSession(payload, options)` | Create an async iterator for chat turns |
547
548
  | `chat.pipe(source, options?)` | Pipe a stream to the frontend (from anywhere inside a task) |
548
549
  | `chat.pipeAndCapture(source, options?)` | Pipe and capture the response; returns `{ message, status, error }` |
@@ -589,6 +590,8 @@ export const orderEvents = chat.event({
589
590
  id: "order-events",
590
591
  endpoint: stripe,
591
592
  key: "{event.data.object.customer}",
593
+ // invoices always carry a customer; events without one would have no session to go to
594
+ filter: "event.type startsWith 'invoice.'",
592
595
  type: "order.event",
593
596
  });
594
597
  ```
@@ -226,7 +226,7 @@ A few things to get right:
226
226
  ## Guarantees and limits
227
227
 
228
228
  - Crash recovery of a half-written answer is runtime-owned in every configuration. It comes from the durable session stream, which no application database can reconstruct. A storage holds settled turns; the runtime overlays the recovered tail and hands it to `save` like any other change.
229
- - Bringing your own database does not remove platform custody. Session streams still hold message content for their retention window.
229
+ - Bringing your own database does not remove platform custody. Session streams still hold message content for their retention window. To keep content out of the run trace, see [Redact chat content from traces](/ai-chat/patterns/redacting-telemetry).
230
230
  - The default storage rewrites the whole conversation each turn. A row-per-message storage writes only what changed. That is the reason to plug in your own.
231
231
 
232
232
  ## Migrating from hydrateMessages
package/docs/apikeys.mdx CHANGED
@@ -81,8 +81,10 @@ Access presets define what a key can do. On the Free and Hobby plans only the **
81
81
  | --- | --- |
82
82
  | **Trigger only** | Trigger runs and batches for all or selected tasks. Trigger responses include scoped public access tokens for the runs and batches they create |
83
83
  | **Task operator** | Trigger all or selected tasks and inspect or operate on their runs |
84
- | **Observer** | Read runs, tasks, batches, logs, traces, and queues |
85
- | **Operator** | Observe and operate on runs and queues, and trigger tasks |
84
+ | **Observer** | Read runs, tasks, batches, logs, traces, queues, errors, and webhooks |
85
+ | **Operator** | Observe and operate on runs, queues, errors, and webhooks, and trigger tasks |
86
+ | **Webhooks only** | Read and write [webhooks](/webhooks/overview), which are in private beta. Replaying deliveries that trigger tasks and creating webhook waiters require task or waitpoint scopes |
87
+ | **Waitpoints only** | Create, list, and retrieve [waitpoint tokens](/wait-for-token). No task or run access |
86
88
  | **Deploy only** | Deploy versions, sync environment variables, and manage Preview branches |
87
89
  | **Variables only** | Read and write environment variables in this environment |
88
90
  | **No restrictions** | Full access to the environment |
@@ -96,11 +98,11 @@ Set a key in `TRIGGER_ACCESS_TOKEN` to authenticate `trigger deploy` without log
96
98
  <CodeGroup>
97
99
 
98
100
  ```bash npm
99
- TRIGGER_ACCESS_TOKEN="tr_prod_sk_…" npx trigger.dev@latest deploy
101
+ TRIGGER_ACCESS_TOKEN="tr_prod_sk_…" npx trigger.dev@latest deploy --env prod
100
102
  ```
101
103
  </CodeGroup>
102
104
 
103
- The key must belong to the target environment. Use a Production key for the default deployment, a Staging key with `--env staging`, or a key from the Preview environment with `--env preview`. A Preview deployment key can create and archive Preview branches and sync their environment variables.
105
+ The key must belong to the target environment. Use a Production key with `--env prod`, a Staging key with `--env staging`, or a key from the Preview environment with `--env preview`. If you leave out `--env`, the CLI deploys to the key's environment, and a `--env` that doesn't match the key is an error. A Preview deployment key can create and archive Preview branches and sync their environment variables.
104
106
 
105
107
  <Note>
106
108
  The deploy CLI reads environment API keys from `TRIGGER_ACCESS_TOKEN`, not
@@ -84,8 +84,8 @@ npx trigger.dev@latest runs cancel run_abc123
84
84
 
85
85
  <ConfigFileOptions />
86
86
  <ProjectRefOptions />
87
- <ParamField body="Preview branch" type="--branch | -b">
88
- Required when using `--env preview`. Specify the branch, e.g. `--branch my-branch` or `-b my-branch`.
87
+ <ParamField body="Branch" type="--branch | -b">
88
+ Required when using `--env preview`. Specify the branch, e.g. `--branch my-branch` or `-b my-branch`. With `--env dev`, it defaults to the same [dev branch](/deployment/dev-branches) as the dev command.
89
89
  </ParamField>
90
90
 
91
91
  ### Common options
@@ -0,0 +1,95 @@
1
+ ---
2
+ title: "CLI tasks commands"
3
+ sidebarTitle: "tasks"
4
+ description: "Use these commands to trigger tasks from your terminal."
5
+ ---
6
+
7
+ import CommonOptions from "/snippets/cli-options-common.mdx";
8
+ import ConfigFileOptions from "/snippets/cli-options-config-file.mdx";
9
+ import ProjectRefOptions from "/snippets/cli-options-project-ref.mdx";
10
+
11
+ ## tasks trigger
12
+
13
+ Triggers a task and prints the run ID and its dashboard URL. It runs in the `dev` environment unless you pass `--env`, so start the [dev command](/cli-dev-commands) first.
14
+
15
+ <CodeGroup>
16
+
17
+ ```bash npm
18
+ npx trigger.dev@latest tasks trigger hello-world --payload '{"name":"Ada"}'
19
+ ```
20
+
21
+ ```bash pnpm
22
+ pnpm dlx trigger.dev@latest tasks trigger hello-world --payload '{"name":"Ada"}'
23
+ ```
24
+
25
+ ```bash yarn
26
+ yarn dlx trigger.dev@latest tasks trigger hello-world --payload '{"name":"Ada"}'
27
+ ```
28
+
29
+ </CodeGroup>
30
+
31
+ Add `--wait` to wait for the run to finish. It prints the run's output, or its error and exits with code 1 if the run failed, which makes it useful in scripts and for coding agents testing a task:
32
+
33
+ ```bash
34
+ npx trigger.dev@latest tasks trigger hello-world --payload '{"name":"Ada"}' --wait
35
+ ```
36
+
37
+ The command fails without creating a run if the current version has no task with that ID. In `dev`, it warns you when the dev command isn't running, because the run waits in the queue until it starts.
38
+
39
+ <ParamField body="Payload" type="--payload">
40
+ The payload as JSON, e.g. `--payload '{"name":"Ada"}'`. Without it, the task gets no payload.
41
+ </ParamField>
42
+
43
+ <ParamField body="Payload file" type="--payload-file">
44
+ Read the payload from a JSON file instead.
45
+ </ParamField>
46
+
47
+ <ParamField body="Wait" type="--wait">
48
+ Wait for the run to finish, then print its output or error.
49
+ </ParamField>
50
+
51
+ <ParamField body="Timeout" type="--timeout">
52
+ With `--wait`, stop waiting after this many seconds and exit with code 1.
53
+ </ParamField>
54
+
55
+ <ParamField body="Tag" type="--tag">
56
+ A tag to add to the run. Repeat it to add more than one, e.g. `--tag cli --tag test`.
57
+ </ParamField>
58
+
59
+ <ParamField body="Idempotency key" type="--idempotency-key">
60
+ If a run with this key already exists, return it instead of creating a new one. See [idempotency](/idempotency).
61
+ </ParamField>
62
+
63
+ <ParamField body="Delay" type="--delay">
64
+ Wait before running, e.g. `30s`, `5m` or an ISO 8601 date.
65
+ </ParamField>
66
+
67
+ <ParamField body="TTL" type="--ttl">
68
+ Expire the run if it hasn't started within this time, e.g. `10m`.
69
+ </ParamField>
70
+
71
+ <ParamField body="Queue" type="--queue">
72
+ The queue to run in, instead of the queue set on the task.
73
+ </ParamField>
74
+
75
+ <ParamField body="Machine" type="--machine">
76
+ The machine to run on, e.g. `small-2x`. See [machines](/machines). Has no effect in `dev`.
77
+ </ParamField>
78
+
79
+ ## Options
80
+
81
+ <ParamField body="Environment" type="--env | -e">
82
+ The environment to use: `dev`, `prod`, `staging` or `preview`. Defaults to `dev`.
83
+ </ParamField>
84
+
85
+ <ConfigFileOptions />
86
+ <ProjectRefOptions />
87
+ <ParamField body="Branch" type="--branch | -b">
88
+ The branch to use. Required with `--env preview`. In `dev`, it defaults to the same [dev branch](/deployment/dev-branches) as the dev command.
89
+ </ParamField>
90
+
91
+ ### Common options
92
+
93
+ These options are available on most commands.
94
+
95
+ <CommonOptions />
@@ -267,6 +267,64 @@ export default defineConfig({
267
267
  });
268
268
  ```
269
269
 
270
+ ### Span processors
271
+
272
+ Span processors run on every span before it is exported, to Trigger.dev and to any `exporters` you configure. Use them to redact or drop span content before it reaches the run trace.
273
+
274
+ ```ts trigger.config.ts
275
+ import { defineConfig } from "@trigger.dev/sdk";
276
+ import type { AttributeValue, Attributes } from "@opentelemetry/api";
277
+ import type { SpanProcessor } from "@opentelemetry/sdk-trace-base";
278
+
279
+ const EMAIL = /[\w.+-]+@[\w-]+\.[\w.]+/g;
280
+
281
+ function redact(value: AttributeValue | undefined): AttributeValue | undefined {
282
+ if (typeof value === "string") return value.replace(EMAIL, "[email]");
283
+ // Some attributes are string arrays, like the messages sent mid-turn
284
+ if (Array.isArray(value)) {
285
+ return value.map((item) =>
286
+ typeof item === "string" ? item.replace(EMAIL, "[email]") : item
287
+ ) as AttributeValue;
288
+ }
289
+ return value;
290
+ }
291
+
292
+ function scrub(attributes: Attributes) {
293
+ for (const key of Object.keys(attributes)) attributes[key] = redact(attributes[key]);
294
+ }
295
+
296
+ const redactEmails: SpanProcessor = {
297
+ onStart: () => {},
298
+ // The span is complete here and still writable
299
+ onEnding: (span) => {
300
+ scrub(span.attributes);
301
+ for (const event of span.events) scrub(event.attributes ?? {});
302
+ },
303
+ onEnd: () => {},
304
+ forceFlush: async () => {},
305
+ shutdown: async () => {},
306
+ };
307
+
308
+ export default defineConfig({
309
+ project: "<project ref>",
310
+ telemetry: {
311
+ spanProcessors: [redactEmails],
312
+ },
313
+ });
314
+ ```
315
+
316
+ Your processors run ahead of ours, so they also see the in-progress copy of each span that the dashboard shows while a span is open. Redact in `onEnding`:
317
+
318
+ - `onStart` runs before we add the run context, so it sees only the attributes the span was started with.
319
+ - In `onEnd` the span is read-only and `setAttribute` does nothing. Writing to `span.attributes` directly still works.
320
+ - Content can also sit in span events (exceptions, for example). Events are on `span.events`.
321
+
322
+ After each call we restore the few attributes we use to link a span to its run, such as the run, task and attempt ids. Everything else can be redacted, including run tags and idempotency keys. If a processor throws, the error is reported and the span is still exported.
323
+
324
+ <Note>
325
+ Span processors only change span content. Run payloads and outputs, and the messages on a chat agent's session streams, are stored as sent. For chat agents, see [Redact chat content from traces](/ai-chat/patterns/redacting-telemetry).
326
+ </Note>
327
+
270
328
  ## Runtime
271
329
 
272
330
  If you don't set a `runtime`, your tasks run on the current Node.js LTS. Setting `runtime: "node"` does the same thing — see the Node.js versions section below to pin a specific version instead.
@@ -189,7 +189,7 @@ prismaExtension({
189
189
  "scripts": {
190
190
  "prebuild": "prisma generate",
191
191
  "dev": "trigger dev",
192
- "deploy": "trigger deploy"
192
+ "deploy": "trigger deploy --env prod"
193
193
  }
194
194
  }
195
195
  ```
@@ -331,7 +331,7 @@ steps:
331
331
  - name: Generate Prisma client
332
332
  run: npx prisma@6.19.0 generate
333
333
  - name: Deploy Trigger.dev
334
- run: npx trigger.dev@4.1.1 deploy
334
+ run: npx trigger.dev@4.1.1 deploy --env prod
335
335
  env:
336
336
  TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
337
337
  ```
@@ -902,7 +902,7 @@ datasource db {
902
902
  "scripts": {
903
903
  "generate": "prisma generate",
904
904
  "dev": "pnpm generate && trigger dev",
905
- "deploy": "trigger deploy"
905
+ "deploy": "trigger deploy --env prod"
906
906
  }
907
907
  }
908
908
  ```
@@ -975,7 +975,7 @@ export default defineConfig({
975
975
  "scripts": {
976
976
  "generate": "prisma generate",
977
977
  "dev": "pnpm generate && trigger dev",
978
- "deploy": "trigger deploy"
978
+ "deploy": "trigger deploy --env prod"
979
979
  }
980
980
  }
981
981
  ```
@@ -3,6 +3,8 @@ title: "Environment Variables"
3
3
  description: "Any environment variables used in your tasks need to be added so the deployed code will run successfully."
4
4
  ---
5
5
 
6
+ import { RollingOut } from "/snippets/feature-status.jsx";
7
+
6
8
  An environment variable in Node.js is accessed in your code using `process.env.MY_ENV_VAR`.
7
9
 
8
10
  We deploy your tasks and scale them up and down when they are triggered. So any environment variables you use in your tasks need to accessible to us so your code will run successfully.
@@ -43,6 +45,8 @@ When creating an environment variable, you can mark it as a **Secret**. Secret v
43
45
 
44
46
  You can edit an environment variable's values. You cannot edit the key name, you must delete and create a new one.
45
47
 
48
+ <RollingOut flag="allowEmptyEnvironmentVariableValues" />
49
+
46
50
  <Note>
47
51
  An empty string is a valid value. Saving a variable with an empty value stores it as an empty
48
52
  string (your task sees the variable set to `""`), which is different from deleting the variable
@@ -60,7 +60,7 @@ The id is free-form and opaque to Trigger.dev — a commit SHA, a release tag, a
60
60
  <Step title="Deploy your tasks with an external id">
61
61
 
62
62
  ```bash
63
- npx trigger.dev@latest deploy --external-id "$(git rev-parse HEAD)"
63
+ npx trigger.dev@latest deploy --env prod --external-id "$(git rev-parse HEAD)"
64
64
  ```
65
65
 
66
66
  </Step>
@@ -240,7 +240,7 @@ Read the commit in the place where it *is* available, and write it into both hal
240
240
 
241
241
  ```bash
242
242
  # 1. Deploy side — name the deployment after the commit.
243
- npx trigger.dev@latest deploy --external-id "$(git rev-parse HEAD)"
243
+ npx trigger.dev@latest deploy --env prod --external-id "$(git rev-parse HEAD)"
244
244
 
245
245
  # 2. Application side — give the running app the same value.
246
246
  TRIGGER_EXTERNAL_DEPLOYMENT_ID=<the-same-commit-sha>
@@ -385,7 +385,7 @@ If you filter deploys by path, derive the id from the same filter on both sides
385
385
 
386
386
  ```bash
387
387
  TASK_ID=$(git log -1 --format=%H -- trigger/)
388
- npx trigger.dev@latest deploy --external-id "$TASK_ID"
388
+ npx trigger.dev@latest deploy --env prod --external-id "$TASK_ID"
389
389
  ```
390
390
 
391
391
  Compute the same value where you set your app's variable. In GitHub Actions this needs `fetch-depth: 0` on `actions/checkout` — the default shallow clone can't see far enough back.
@@ -162,7 +162,7 @@ To keep your app and tasks in sync without coordinating promotion at all, see [a
162
162
 
163
163
  ## Staging deploys
164
164
 
165
- By default, the `deploy` command will deploy to the `prod` environment. If you want to deploy to a different environment, you can use the `--env` flag:
165
+ Use the `--env` flag to choose the environment you deploy to. If you don't pass it, the `deploy` command deploys to the `prod` environment, unless `TRIGGER_ACCESS_TOKEN` holds an API key for another environment. To deploy to staging:
166
166
 
167
167
  ```bash
168
168
  npx trigger.dev deploy --env staging
@@ -147,7 +147,7 @@ Creating and deploying a preview branch manually is easy:
147
147
  npx trigger.dev@latest deploy --env preview
148
148
  ```
149
149
 
150
- This will create and deploy a preview branch, automatically detecting the git branch. If for some reason the auto-detection doesn't work it will let you know and tell you do this:
150
+ This will create and deploy a preview branch, automatically detecting the git branch. When your CI checks out a detached HEAD, the branch is read from the CI provider's branch variable instead (GitLab, Bitbucket, CircleCI, Buildkite, Travis CI, Jenkins and Azure Pipelines are supported). If for some reason the auto-detection doesn't work it will let you know and tell you do this:
151
151
 
152
152
  ```bash
153
153
  npx trigger.dev@latest deploy --env preview --branch your-branch-name
@@ -47,7 +47,7 @@ jobs:
47
47
  env:
48
48
  TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
49
49
  run: |
50
- npx trigger.dev@latest deploy --external-id ${{ github.sha }}
50
+ npx trigger.dev@latest deploy --env prod --external-id ${{ github.sha }}
51
51
  ```
52
52
 
53
53
  ```yaml .github/workflows/release-trigger-staging.yml
@@ -184,7 +184,7 @@ Tip: add the `trigger.dev` CLI to your `devDependencies` and the deploy command
184
184
  ```json
185
185
  {
186
186
  "scripts": {
187
- "deploy:trigger-prod": "trigger deploy",
187
+ "deploy:trigger-prod": "trigger deploy --env prod",
188
188
  "deploy:trigger": "trigger deploy --env staging"
189
189
  },
190
190
  "devDependencies": {
@@ -254,7 +254,7 @@ jobs:
254
254
  TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }}
255
255
  TRIGGER_API_URL: ${{ secrets.TRIGGER_API_URL }}
256
256
  run: |
257
- npx trigger.dev@latest deploy
257
+ npx trigger.dev@latest deploy --env prod
258
258
  ```
259
259
 
260
260
  </CodeGroup>
package/docs/limits.mdx CHANGED
@@ -12,6 +12,12 @@ You can view your current limits, quotas, and rate limit usage in real-time by v
12
12
  [Billing limits and alerts](/billing-limits).
13
13
  </Note>
14
14
 
15
+ ## Run duration
16
+
17
+ Runs have no maximum duration. You set a default `maxDuration` for your project and can override it per task or per run, or set it to `timeout.None` to let a run execute indefinitely.
18
+
19
+ Trigger is built for long running AI agents and workflows and we have seen Trigger.dev users with runs lasting more than six months.
20
+
15
21
  ## Concurrency limits
16
22
 
17
23
  Concurrency is allocated **per environment**, not as a single figure for the whole organization. Each plan sets a separate default for production, staging, preview and development:
@@ -109,7 +109,7 @@ Then add scripts to your `package.json`:
109
109
  {
110
110
  "scripts": {
111
111
  "dev:trigger": "trigger dev",
112
- "deploy:trigger": "trigger deploy"
112
+ "deploy:trigger": "trigger deploy --env prod"
113
113
  }
114
114
  }
115
115
  ```
@@ -4,6 +4,8 @@ sidebarTitle: "Tools"
4
4
  description: "Learn about how to use the tools available in the Trigger.dev MCP Server"
5
5
  ---
6
6
 
7
+ import WebhooksBetaNote from "/snippets/webhooks-beta-note.mdx";
8
+
7
9
  ## Documentation and Search Tools
8
10
 
9
11
  ### search_docs
@@ -189,7 +191,7 @@ Execute a TRQL query against your Trigger.dev data. TRQL is a SQL-style query la
189
191
 
190
192
  ### list_dashboards
191
193
 
192
- List available built-in dashboards with their widgets. Each dashboard contains pre-built queries for common metrics.
194
+ List the built-in dashboards and your organization's custom dashboards, with their widgets.
193
195
 
194
196
  **Example usage:**
195
197
  - `"What dashboards are available?"`
@@ -197,12 +199,28 @@ List available built-in dashboards with their widgets. Each dashboard contains p
197
199
 
198
200
  ### run_dashboard_query
199
201
 
200
- Execute a single widget query from a built-in dashboard. Use `list_dashboards` first to see available dashboards and widget IDs.
202
+ Execute a single widget query from a built-in or custom dashboard. Use `list_dashboards` first to see available dashboards and widget IDs.
201
203
 
202
204
  **Example usage:**
203
205
  - `"Run the total runs widget from the overview dashboard"`
204
206
  - `"Show me the LLM cost over time from the AI dashboard"`
205
207
 
208
+ ### create_dashboard
209
+
210
+ Create a custom dashboard, optionally with widgets. Each widget has a title, a TRQL query and a display: a table, a bar or line chart, a big number, or a section title. Queries are checked when the dashboard is saved.
211
+
212
+ **Example usage:**
213
+ - `"Make a dashboard for the email tasks with total runs, failures and runs per day"`
214
+ - `"Create a dashboard that charts p95 duration by task"`
215
+
216
+ ### set_dashboard_widgets
217
+
218
+ Replace every widget on a custom dashboard, and optionally rename it.
219
+
220
+ **Example usage:**
221
+ - `"Add a failed runs widget to the email dashboard"`
222
+ - `"Change the runs per day chart to a line chart"`
223
+
206
224
  ### get_report
207
225
 
208
226
  Render an interpreted [health report](/reports) — a deterministic verdict, not a raw panel — as text with sparklines. The `health` report answers whether work is flowing, whether the runs that start are healthy, and whether the telemetry is fresh, with a headline verdict and a suggested next action. Returns markdown by default, or ANSI when `color` is set. Read-only.
@@ -239,7 +257,7 @@ Check the status of the dev server and view recent output. Shows whether it is s
239
257
  - `"Are there any build errors?"`
240
258
 
241
259
  <Callout type="warning">
242
- The deploy and list_preview_branches tools are not available when the MCP server is running with the `--dev-only` flag. The `--readonly` flag hides deploy, trigger_task, cancel_run, and replay_run.
260
+ The deploy and list_preview_branches tools are not available when the MCP server is running with the `--dev-only` flag. The `--readonly` flag hides deploy, trigger_task, cancel_run, replay_run, create_dashboard, and set_dashboard_widgets.
243
261
  </Callout>
244
262
 
245
263
  ## Agent Chat Tools
@@ -334,6 +352,8 @@ Append one record to a named side channel's `in` stream. Sends control input to
334
352
 
335
353
  ## Webhook Tools
336
354
 
355
+ <WebhooksBetaNote />
356
+
337
357
  Set up and debug [hosted webhook endpoints](/webhooks/overview). Endpoint ids start with `wh_` and delivery ids with `whd_`; endpoint tools also accept an endpoint's declared id. The same operations are on the [Webhooks API](/management/webhooks/list-endpoints).
338
358
 
339
359
  ### list_webhook_endpoints