@trigger.dev/sdk 0.0.0-prerelease-20260908122921 → 0.0.0-prerelease-streamfix-20260909094302

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 (106) hide show
  1. package/dist/commonjs/imports/ai-runtime-cjs.cjs.map +1 -1
  2. package/dist/commonjs/imports/ai-runtime.js +0 -2
  3. package/dist/commonjs/v3/ai.d.ts +16 -199
  4. package/dist/commonjs/v3/ai.js +102 -983
  5. package/dist/commonjs/v3/ai.js.map +1 -1
  6. package/dist/commonjs/v3/chat-client.d.ts +2 -3
  7. package/dist/commonjs/v3/chat-client.js +5 -31
  8. package/dist/commonjs/v3/chat-client.js.map +1 -1
  9. package/dist/commonjs/v3/chat-react.d.ts +0 -34
  10. package/dist/commonjs/v3/chat-react.js +1 -47
  11. package/dist/commonjs/v3/chat-react.js.map +1 -1
  12. package/dist/commonjs/v3/chat-server.d.ts +6 -42
  13. package/dist/commonjs/v3/chat-server.js +7 -52
  14. package/dist/commonjs/v3/chat-server.js.map +1 -1
  15. package/dist/commonjs/v3/chat.d.ts +10 -81
  16. package/dist/commonjs/v3/chat.js +46 -292
  17. package/dist/commonjs/v3/chat.js.map +1 -1
  18. package/dist/commonjs/v3/sessions.d.ts +2 -15
  19. package/dist/commonjs/v3/sessions.js +1 -12
  20. package/dist/commonjs/v3/sessions.js.map +1 -1
  21. package/dist/commonjs/v3/shared.js +36 -30
  22. package/dist/commonjs/v3/shared.js.map +1 -1
  23. package/dist/commonjs/v3/test/mock-chat-agent.d.ts +0 -43
  24. package/dist/commonjs/v3/test/mock-chat-agent.js +0 -90
  25. package/dist/commonjs/v3/test/mock-chat-agent.js.map +1 -1
  26. package/dist/commonjs/v3/test/test-session-handle.js +0 -6
  27. package/dist/commonjs/v3/test/test-session-handle.js.map +1 -1
  28. package/dist/commonjs/version.js +1 -1
  29. package/dist/esm/imports/ai-runtime.d.ts +2 -2
  30. package/dist/esm/imports/ai-runtime.js +2 -2
  31. package/dist/esm/imports/ai-runtime.js.map +1 -1
  32. package/dist/esm/v3/ai.d.ts +16 -199
  33. package/dist/esm/v3/ai.js +103 -984
  34. package/dist/esm/v3/ai.js.map +1 -1
  35. package/dist/esm/v3/chat-client.d.ts +2 -3
  36. package/dist/esm/v3/chat-client.js +5 -31
  37. package/dist/esm/v3/chat-client.js.map +1 -1
  38. package/dist/esm/v3/chat-react.d.ts +0 -34
  39. package/dist/esm/v3/chat-react.js +1 -46
  40. package/dist/esm/v3/chat-react.js.map +1 -1
  41. package/dist/esm/v3/chat-server.d.ts +6 -42
  42. package/dist/esm/v3/chat-server.js +8 -53
  43. package/dist/esm/v3/chat-server.js.map +1 -1
  44. package/dist/esm/v3/chat.d.ts +10 -81
  45. package/dist/esm/v3/chat.js +47 -293
  46. package/dist/esm/v3/chat.js.map +1 -1
  47. package/dist/esm/v3/sessions.d.ts +2 -15
  48. package/dist/esm/v3/sessions.js +1 -11
  49. package/dist/esm/v3/sessions.js.map +1 -1
  50. package/dist/esm/v3/shared.js +23 -17
  51. package/dist/esm/v3/shared.js.map +1 -1
  52. package/dist/esm/v3/test/mock-chat-agent.d.ts +0 -43
  53. package/dist/esm/v3/test/mock-chat-agent.js +2 -92
  54. package/dist/esm/v3/test/mock-chat-agent.js.map +1 -1
  55. package/dist/esm/v3/test/test-session-handle.js +0 -6
  56. package/dist/esm/v3/test/test-session-handle.js.map +1 -1
  57. package/dist/esm/version.js +1 -1
  58. package/docs/ai-chat/actions.mdx +23 -55
  59. package/docs/ai-chat/anatomy.mdx +3 -3
  60. package/docs/ai-chat/backend.mdx +48 -125
  61. package/docs/ai-chat/background-injection.mdx +19 -67
  62. package/docs/ai-chat/client-protocol.mdx +4 -5
  63. package/docs/ai-chat/compaction.mdx +7 -11
  64. package/docs/ai-chat/custom-agents.mdx +0 -23
  65. package/docs/ai-chat/fast-starts.mdx +20 -27
  66. package/docs/ai-chat/frontend.mdx +14 -17
  67. package/docs/ai-chat/migrating-from-a-route-handler.mdx +14 -16
  68. package/docs/ai-chat/patterns/skills.mdx +10 -7
  69. package/docs/ai-chat/patterns/version-upgrades.mdx +6 -79
  70. package/docs/ai-chat/pending-messages.mdx +3 -3
  71. package/docs/ai-chat/prompt-caching.mdx +25 -23
  72. package/docs/ai-chat/quick-start.mdx +11 -11
  73. package/docs/ai-chat/reference.mdx +5 -12
  74. package/docs/ai-chat/sessions.mdx +1 -6
  75. package/docs/ai-chat/testing.mdx +1 -2
  76. package/docs/ai-chat/tools.mdx +13 -18
  77. package/docs/ai-chat/upgrade-guide.mdx +2 -2
  78. package/docs/apikeys.mdx +45 -27
  79. package/docs/deployment/overview.mdx +8 -4
  80. package/docs/deployment/preview-branches.mdx +4 -4
  81. package/docs/deployment/version-skew-protection.mdx +0 -62
  82. package/docs/manual-setup.mdx +7 -7
  83. package/docs/mcp-tools.mdx +0 -9
  84. package/docs/quick-start.mdx +3 -3
  85. package/docs/realtime/auth.mdx +1 -1
  86. package/docs/self-hosting/security.mdx +0 -5
  87. package/docs/tasks/scheduled.mdx +0 -24
  88. package/docs/triggering.mdx +1 -1
  89. package/package.json +4 -4
  90. package/skills/trigger-authoring-chat-agent/SKILL.md +27 -38
  91. package/skills/trigger-chat-agent-advanced/SKILL.md +12 -31
  92. package/dist/commonjs/v3/chatVersionSkew.d.ts +0 -12
  93. package/dist/commonjs/v3/chatVersionSkew.js +0 -30
  94. package/dist/commonjs/v3/chatVersionSkew.js.map +0 -1
  95. package/dist/commonjs/v3/externalDeploymentId.d.ts +0 -23
  96. package/dist/commonjs/v3/externalDeploymentId.js +0 -43
  97. package/dist/commonjs/v3/externalDeploymentId.js.map +0 -1
  98. package/dist/esm/v3/chatVersionSkew.d.ts +0 -12
  99. package/dist/esm/v3/chatVersionSkew.js +0 -27
  100. package/dist/esm/v3/chatVersionSkew.js.map +0 -1
  101. package/dist/esm/v3/externalDeploymentId.d.ts +0 -23
  102. package/dist/esm/v3/externalDeploymentId.js +0 -38
  103. package/dist/esm/v3/externalDeploymentId.js.map +0 -1
  104. package/docs/ai-chat/patterns/native-compaction.mdx +0 -310
  105. package/docs/reports.mdx +0 -157
  106. package/docs/troubleshooting-zod.mdx +0 -158
package/docs/apikeys.mdx CHANGED
@@ -10,35 +10,17 @@ description: "Authenticate backend requests with environment-specific API keys."
10
10
  environment variable, never commit them to source control, and never expose them in frontend code.
11
11
  </Warning>
12
12
 
13
- ## Create an API key
13
+ ## Find your API keys
14
14
 
15
- Create a separate named key for each service or integration that accesses Trigger.dev.
15
+ Open your project in the dashboard, select an environment, and open the [**API keys**](https://cloud.trigger.dev/_/apikeys) page.
16
16
 
17
- API keys belong to one environment. A Development key cannot access Production, and a Production key cannot access Staging. Every team member has their own Development environment, so create local-development keys in your own environment.
17
+ API keys belong to one environment. A Development key cannot access Production, and a Production key cannot access Staging.
18
18
 
19
19
  <Note>
20
- Creating and revoking keys requires permission to manage API keys for the selected environment.
21
- The dashboard disables these actions when your role does not have permission.
20
+ Every team member has their own Development environment and keys. Copy the Development key from
21
+ your own API keys page so local requests run against your machine.
22
22
  </Note>
23
23
 
24
- <Steps titleSize="h3">
25
- <Step title="Open the API keys page">
26
- Select the project and environment the integration needs to access, then open [**API keys**](https://cloud.trigger.dev/_/apikeys).
27
- </Step>
28
- <Step title="Create the key">
29
- Click **New API key**, enter a descriptive name, and optionally set an expiration date. Names can
30
- contain up to 64 characters.
31
- </Step>
32
- <Step title="Choose its access">
33
- Select the narrowest access preset that supports the integration. For task-aware presets, choose
34
- all tasks or up to 10 task identifiers.
35
- </Step>
36
- <Step title="Copy and store the secret">
37
- Copy the key into your secret manager or backend environment. Trigger.dev shows the complete
38
- value only once.
39
- </Step>
40
- </Steps>
41
-
42
24
  ## Configure the SDK
43
25
 
44
26
  Set `TRIGGER_SECRET_KEY` in your backend environment. The SDK reads it automatically for operations such as triggering tasks and retrieving runs.
@@ -67,12 +49,38 @@ await tasks.trigger<typeof sendEmail>("send-email", {
67
49
  If you self-host Trigger.dev, set `TRIGGER_API_URL` or pass `baseURL` to `configure`:
68
50
 
69
51
  ```bash .env
70
- TRIGGER_SECRET_KEY="tr_prod_sk_…"
52
+ TRIGGER_SECRET_KEY="tr_prod_…"
71
53
  TRIGGER_API_URL="https://trigger.example.com"
72
54
  ```
73
55
 
74
56
  The default API URL is `https://api.trigger.dev`.
75
57
 
58
+ ## Create a key
59
+
60
+ Create a separate key for each service or integration that accesses Trigger.dev.
61
+
62
+ <Note>
63
+ Creating and revoking keys requires permission to manage API keys for the selected environment.
64
+ The dashboard disables these actions when your role does not have permission.
65
+ </Note>
66
+
67
+ <Steps titleSize="h3">
68
+ <Step title="Open the API keys page">
69
+ Select the project and environment the integration needs to access, then open [**API keys**](https://cloud.trigger.dev/_/apikeys).
70
+ </Step>
71
+ <Step title="Create the key">
72
+ Click **New API key**, enter a descriptive name, and optionally set an expiration date. Names can
73
+ contain up to 64 characters.
74
+ </Step>
75
+ <Step title="Choose its access">
76
+ Select an access preset. For task-aware presets, choose all tasks or up to 10 task identifiers.
77
+ </Step>
78
+ <Step title="Copy and store the secret">
79
+ Copy the key into your secret manager or backend environment. Trigger.dev shows the complete
80
+ value only once.
81
+ </Step>
82
+ </Steps>
83
+
76
84
  ## Access presets
77
85
 
78
86
  Access presets define what a key can do. Some presets require a paid plan. The dashboard shows which presets your organization can use — see [pricing](https://trigger.dev/pricing).
@@ -116,18 +124,28 @@ Revoking a key takes effect immediately and cannot be reversed. Requests using t
116
124
 
117
125
  Removing a team member does not revoke keys they created. Review and revoke their keys separately when their access changes.
118
126
 
127
+ ## Root keys
128
+
129
+ <Warning>
130
+ Root keys are legacy, and are likely to be deprecated in the future. We recommend against using them.
131
+ </Warning>
132
+
133
+ Each environment has a single legacy root key. It can be regenerated, which creates a new value immediately. The previous root key remains valid for 24 hours so you can update services without downtime, then stops authenticating.
134
+
135
+ Public access tokens signed with the previous root key remain valid until the earlier of their own expiration and the end of the 24-hour grace period.
136
+
119
137
  ## Create public access tokens
120
138
 
121
139
  API keys can be used to create scoped [Public Access Tokens](/realtime/auth) using `auth.createPublicToken()`.
122
140
 
123
- Use `@trigger.dev/sdk` version 4.5.8 or later to create public tokens with environment API keys. Public tokens have the following restrictions:
141
+ To do so with the newer non-root keys, you must use `@trigger.dev/sdk` version 4.5.8 or later. Creating public tokens with non-root keys has the following restrictions:
124
142
 
125
143
  - The token must request at least one scope.
126
144
  - Its scopes cannot exceed the key's access.
127
145
  - Its expiration cannot exceed 30 days.
128
146
 
129
147
  <Note>
130
- Revoking or expiring an API key does not revoke tokens it already created. Those tokens remain valid until their own expiration.
148
+ Revoking or expiring an API key does not revoke tokens it already created. Those tokens remain valid until their own expiration, unless the environment's root key is regenerated.
131
149
  </Note>
132
150
 
133
151
  ## Target Preview and Development branches
@@ -145,7 +163,7 @@ The SDK sends the branch automatically. When calling the API directly, send the
145
163
 
146
164
  Self-hosted installations support multiple keys with **No restrictions**. The restricted access presets are available in Trigger.dev Cloud.
147
165
 
148
- Keep your instance and SDK current before creating keys. Calling a public-token API with a key on a server that does not support server-minted tokens returns an upgrade error. Upgrade the instance before creating public tokens with an environment API key.
166
+ Keep your instance and SDK current before creating keys. Calling a public-token API with a key on a server that does not support server-minted tokens returns an upgrade error; use the root key until the server is upgraded.
149
167
 
150
168
  ## Security recommendations
151
169
 
@@ -69,10 +69,14 @@ Now if you visit your Trigger.dev dashboard you should see the new version deplo
69
69
 
70
70
  ## Triggering deployed tasks
71
71
 
72
- Once you have deployed your tasks, open the API Keys page for the Production environment and create a named key with **Trigger only** access. Set the key as `TRIGGER_SECRET_KEY` in your backend environment. Tasks triggered with this key run against the deployed Production version:
72
+ Once you have deployed your tasks, you can trigger tasks exactly the same way you did locally, but with the "PROD" API key:
73
+
74
+ ![Trigger.dev dashboard showing the API key](/deployment/api-key.png)
75
+
76
+ Copy the API key from the dashboard and set the `TRIGGER_SECRET_KEY` environment variable, and then any tasks you trigger will run against the deployed version:
73
77
 
74
78
  ```txt .env
75
- TRIGGER_SECRET_KEY="tr_prod_sk_abc123"
79
+ TRIGGER_SECRET_KEY="tr_prod_abc123"
76
80
  ```
77
81
 
78
82
  Now you can trigger your tasks:
@@ -176,10 +180,10 @@ This will create an entirely new version of your tasks for the `staging` environ
176
180
 
177
181
  ![Trigger.dev dashboard showing the staging environment](/deployment/staging-deploy.png)
178
182
 
179
- To trigger tasks against Staging, create a named key in the Staging environment with **Trigger only** access and set it as `TRIGGER_SECRET_KEY`:
183
+ Now you can trigger tasks against the staging environment by setting the `TRIGGER_SECRET_KEY` environment variable to the staging API key:
180
184
 
181
185
  ```txt .env
182
- TRIGGER_SECRET_KEY="tr_stg_sk_abcd123"
186
+ TRIGGER_SECRET_KEY="tr_stg_abcd123"
183
187
  ```
184
188
 
185
189
  For additional environments beyond `prod` and `staging`, you can use [preview branches](/deployment/preview-branches), which allow you to create isolated environments for each branch of your code.
@@ -15,7 +15,7 @@ The process to use preview branches looks like this:
15
15
 
16
16
  1. Create a preview branch
17
17
  2. Deploy to the preview branch (1+ times)
18
- 3. Create a named **Trigger only** API key in the Preview environment, then trigger runs using the key (`TRIGGER_SECRET_KEY`) and branch name (`TRIGGER_PREVIEW_BRANCH`).
18
+ 3. Trigger runs using your Preview API key (`TRIGGER_SECRET_KEY`) and the branch name (`TRIGGER_PREVIEW_BRANCH`).
19
19
  4. Archive the preview branch when the branch is done.
20
20
 
21
21
  There are two main ways to do this:
@@ -41,12 +41,12 @@ For full details see our [pricing page](https://trigger.dev/pricing).
41
41
 
42
42
  ## Triggering runs and using the SDK
43
43
 
44
- Create a named API key in the Preview environment and set it as `TRIGGER_SECRET_KEY`. Set `TRIGGER_PREVIEW_BRANCH` to select the branch that receives the runs.
44
+ Before we talk about how to deploy to preview branches, one important thing to understand is that you must set the `TRIGGER_PREVIEW_BRANCH` environment variable as well as the `TRIGGER_SECRET_KEY` environment variable.
45
45
 
46
46
  When deploying to somewhere that supports `process.env` (like Node.js runtimes) you can just set the environment variables:
47
47
 
48
48
  ```bash
49
- TRIGGER_SECRET_KEY="tr_preview_sk_1234567890"
49
+ TRIGGER_SECRET_KEY="tr_preview_1234567890"
50
50
  TRIGGER_PREVIEW_BRANCH="your-branch-name"
51
51
  ```
52
52
 
@@ -57,7 +57,7 @@ import { configure } from "@trigger.dev/sdk";
57
57
  import { myTask } from "./trigger/myTasks";
58
58
 
59
59
  configure({
60
- secretKey: "tr_preview_sk_1234567890", // WARNING: Never actually hardcode your secret key like this
60
+ secretKey: "tr_preview_1234567890", // WARNING: Never actually hardcode your secret key like this
61
61
  previewBranch: "your-branch-name",
62
62
  });
63
63
 
@@ -276,68 +276,6 @@ An empty or whitespace-only value counts as "not supplied" rather than an error,
276
276
 
277
277
  Batch triggers carry the id too. `batchTrigger` resolves it per item exactly as `trigger` does, and it survives the asynchronous materialisation of batch items — so a large batch triggered during a deploy waits and releases item by item, each pinned to the deployment its calling code came from.
278
278
 
279
- ## Chat sessions
280
-
281
- [Chat agents](/ai-chat/overview) are covered by the same mechanism, with one difference: the id belongs to the **session**, not to a single trigger. It is resolved wherever you start the session — your server action, your route handler, `sessions.start()` — using the same order of precedence as a task trigger, and stored on the session. Every run that session goes on to schedule carries it: the first run, each continuation after an idle suspend, and each recovery after a crash.
282
-
283
- That is what you want for a conversation. A chat started by one release of your app keeps talking to the agent build that release shipped with, however many turns and however many runs that takes.
284
-
285
- Chats need the same two halves as tasks, and no more: a deployment carrying an id, and an app that sends the same one (explicitly, through `TRIGGER_EXTERNAL_DEPLOYMENT_ID`, or through [automatic discovery](#automatic-discovery)). There is nothing chat-specific to switch on, so an app already pinning its task runs gets pinned chats with no code change.
286
-
287
- ```ts
288
- // app/actions.ts
289
- "use server";
290
- import { chat } from "@trigger.dev/sdk/ai";
291
- import type { myChat } from "@/trigger/chat";
292
-
293
- // No chat-specific setup: the id is discovered per call, exactly as it is for `trigger()`.
294
- export const startChatSession = chat.createStartSessionAction<typeof myChat>("my-chat");
295
- ```
296
-
297
- Three things follow from the pin living on the session:
298
-
299
- - **Starting the session again refreshes it, and the conversation follows.** `sessions.start()` is idempotent on `chatId` and rewrites the stored config, so when your transport calls `startSession` after a redeploy, the session re-pins. A **running** agent then hands the conversation over at the next turn boundary, so the next message is answered by the deployment you just named — not several turns later when the old run happens to end. The turn already in flight finishes on the code it started on. Set [`versionSkew: "hold"`](/ai-chat/patterns/version-upgrades#staying-put) on an agent that should stay put instead.
300
- - **There is one pin per `chatId`.** If the same conversation is open in two tabs on two different releases of your app, whichever called `startSession` most recently sets the pin for both.
301
- - **A parked chat is waiting, not broken.** A run pinned to a deployment that hasn't landed parks, and every message sent meanwhile is stored durably and delivered once the deployment arrives. Nothing is lost — but nothing answers either, so tell the user. Re-pinning does not release a parked run: it keeps waiting for the deployment it was created for. If that deployment never lands, the run waits until its park deadline elapses, and the next message after that starts a fresh run on the session's current pin. Pass `pendingVersion` through your `startSession` callback and the transport emits a `run-pending-version` event:
302
-
303
- ```tsx
304
- const transport = useTriggerChatTransport({
305
- task: "my-chat",
306
- accessToken: ({ chatId }) => mintChatAccessToken(chatId),
307
- startSession: ({ chatId, clientData }) => startChatSession({ chatId, clientData }),
308
- onEvent: (event) => {
309
- if (event.type === "run-pending-version") setDeploying(true);
310
- if (event.type === "first-chunk") setDeploying(false);
311
- },
312
- });
313
- ```
314
-
315
- The event repeats on every message sent while the chat is parked, so a notice driven off it stays accurate. Its `source` says where the park was learned: `start` from creating the session, `send` from an append, `head-start` from the route's response header, and `upgrade` when a session followed its pin onto a deployment that hasn't landed yet — that last one arrives as soon as the handoff happens, without waiting for another message.
316
-
317
- [Head Start](/ai-chat/fast-starts#head-start) softens this considerably: turn 1 runs in your own warm process, so a parked deployment costs nothing until step 2. The handover signal is durable, so the agent picks the turn up where it left off once the deployment lands. The transport emits `run-pending-version` with `source: "head-start"` for that case, and `chat.startHeadStart` returns `pendingVersion` for the detached flow.
318
-
319
- ### Opting a chat out
320
-
321
- Pass `null` and that chat is never pinned, whatever the environment says:
322
-
323
- ```ts
324
- export const startChatSession = chat.createStartSessionAction<typeof myChat>("my-chat", {
325
- triggerConfig: { externalDeploymentId: null },
326
- });
327
- ```
328
-
329
- Use this for a conversation that should always run on the current version — a long-lived support thread, say — while the rest of your chats stay pinned. To turn pinning off everywhere instead, set `TRIGGER_AUTOMATIC_SKEW_VERSION_PROTECTION` to `0` and don't set `TRIGGER_EXTERNAL_DEPLOYMENT_ID`.
330
-
331
- ### Escaping the pin from inside the agent
332
-
333
- [`chat.requestUpgrade()`](/ai-chat/patterns/version-upgrades) clears the session's external deployment id as part of the handoff, so the new run is free to land on the current version. Pass a target to move to a specific deployment instead:
334
-
335
- ```ts
336
- chat.requestUpgrade({ externalDeploymentId: clientData.commitSha });
337
- ```
338
-
339
- Either way the change is persisted on the session, so the next continuation doesn't fall back to the id the agent just rejected. `lockToVersion` is a separate, explicit pin and is never cleared — `requestUpgrade()` cannot escape it, which is also why a session using it never follows its external deployment id automatically.
340
-
341
279
  ## Waiting and expiry
342
280
 
343
281
  When a run arrives with an id that isn't deployed yet, it doesn't fail — it **waits**. This is the ordinary case, not an edge case: your app frequently goes live a few seconds before your task build finishes.
@@ -55,15 +55,15 @@ bun add -D @trigger.dev/build@latest
55
55
 
56
56
  ## Environment variables
57
57
 
58
- For local development, create a named environment API key and set it as `TRIGGER_SECRET_KEY`:
58
+ For local development, you need to set up the `TRIGGER_SECRET_KEY` environment variable. This key authenticates your application with Trigger.dev.
59
59
 
60
- 1. Open your project's Development environment in the Trigger.dev dashboard.
61
- 2. Open the **API Keys** page.
62
- 3. Click **New API key**, give it a descriptive name, and select **Trigger only** access.
63
- 4. Copy the key and add it to your local environment file. Trigger.dev shows the complete value only once.
60
+ 1. Go to your project dashboard in Trigger.dev
61
+ 2. Navigate to the "API Keys" page
62
+ 3. Copy the **DEV** secret key
63
+ 4. Add it to your local environment file:
64
64
 
65
- ```bash .env
66
- TRIGGER_SECRET_KEY=tr_dev_sk_xxxxxxxxxx
65
+ ```bash
66
+ TRIGGER_SECRET_KEY=tr_dev_xxxxxxxxxx
67
67
  ```
68
68
 
69
69
  ### Self-hosted instances
@@ -189,15 +189,6 @@ Execute a single widget query from a built-in dashboard. Use `list_dashboards` f
189
189
  - `"Run the total runs widget from the overview dashboard"`
190
190
  - `"Show me the LLM cost over time from the AI dashboard"`
191
191
 
192
- ### get_report
193
-
194
- 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.
195
-
196
- **Example usage:**
197
- - `"Is my production project healthy?"`
198
- - `"Run the health report for the last 24 hours"`
199
- - `"Why are my runs backing up?"`
200
-
201
192
  ## Dev Server Tools
202
193
 
203
194
  ### start_dev_server
@@ -26,7 +26,7 @@ Help me add Trigger.dev to this project.
26
26
  - Install the "Hello World" example task when prompted.
27
27
  3. Run `npx trigger.dev@latest dev` to start the dev server.
28
28
  4. Once the dev server is running, test the example task from the Trigger.dev dashboard.
29
- 5. Create a named API key in my Development environment with **Trigger only** access. Set it as TRIGGER_SECRET_KEY in my .env file (or .env.local for Next.js).
29
+ 5. Set TRIGGER_SECRET_KEY in my .env file (or .env.local for Next.js). I can find it on the API Keys page in the dashboard.
30
30
  6. Ask me what framework I'm using and show me how to trigger the task from my backend code.
31
31
 
32
32
  If I've already run init and want the MCP server, run: npx trigger.dev@latest install-mcp
@@ -70,10 +70,10 @@ Sign up at [Trigger.dev Cloud](https://cloud.trigger.dev) (or [self-host](/self-
70
70
 
71
71
  ## Triggering tasks from your app
72
72
 
73
- The test page in the dashboard verifies that your task works. To trigger tasks from your own code, open the API Keys page for your Development environment and create a named key with **Trigger only** access. Set the key as `TRIGGER_SECRET_KEY` in your `.env` file.
73
+ The test page in the dashboard is great for verifying your task works. To trigger tasks from your own code, you'll need to set the `TRIGGER_SECRET_KEY` environment variable. Grab it from the API Keys page in the dashboard and add it to your `.env` file.
74
74
 
75
75
  ```bash .env
76
- TRIGGER_SECRET_KEY=tr_dev_sk_...
76
+ TRIGGER_SECRET_KEY=tr_dev_...
77
77
  ```
78
78
 
79
79
  See [Triggering](/triggering) for the full guide, or jump straight to framework-specific setup for [Next.js](/guides/frameworks/nextjs), [Remix](/guides/frameworks/remix), or [Node.js](/guides/frameworks/nodejs).
@@ -131,7 +131,7 @@ const publicToken = await auth.createPublicToken({
131
131
  - If `expirationTime` is a number, it will be treated as a Unix timestamp in **seconds**
132
132
  - If `expirationTime` is a `Date`, it will be treated as a date
133
133
 
134
- Public Access Tokens cannot expire more than 30 days in the future.
134
+ When using non-root API keys (recommended), the expiration cannot be more than 30 days in the future.
135
135
 
136
136
  The format used for a time span is the same as the [jose package](https://github.com/panva/jose), which is a number followed by a unit. Valid units are: "sec", "secs", "second", "seconds", "s", "minute", "minutes", "min", "mins", "m", "hour", "hours", "hr", "hrs", "h", "day", "days", "d", "week", "weeks", "w", "year", "years", "yr", "yrs", and "y". It is not possible to specify months. 365.25 days is used as an alias for a year. If the string is suffixed with "ago", or prefixed with a "-", the resulting time span gets subtracted from the current unix timestamp. A "from now" suffix can also be used for readability when adding to the current unix timestamp.
137
137
 
@@ -6,11 +6,6 @@ sidebarTitle: "Security"
6
6
 
7
7
  We take the security of Trigger.dev seriously, for both Cloud and self-hosted deployments. This page covers how to report a vulnerability, what to expect, and how to stay informed about security releases.
8
8
 
9
- <Note>
10
- Unlike Trigger.dev Cloud, the self-hosted setup is optimized for single-tenant use, with code and
11
- users you trust. It is not designed to run untrusted code or untrusted payloads.
12
- </Note>
13
-
14
9
  <Warning>
15
10
  Do not report security vulnerabilities through public GitHub issues, pull requests, or Discord. Use one of the private channels below.
16
11
  </Warning>
@@ -184,30 +184,6 @@ const createdSchedule = await schedules.create({
184
184
  is the assigned time the run will actually start.
185
185
  </Note>
186
186
 
187
- ### Free-plan minimum window
188
-
189
- Schedules created while an organization is on a free plan run no more than once per hour and use a minimum 60-minute window.
190
-
191
- - The minimum applies to the **cron cadence**: creating or deploying a schedule whose cron fires more often than once an hour is rejected with an actionable error. Change the cron expression or upgrade before saving.
192
- - Omitted, zero (`"0m"` / `"0%"`), or smaller windows are treated as the 60-minute minimum. A larger configured window still wins, subject to the usual cap at the next cron occurrence.
193
- - The policy applies to **all environment types**, including Development.
194
- - It is captured when the schedule is created. Existing schedules — and schedules created while paid, even after a later downgrade — are **grandfathered** and keep running unchanged.
195
- - Upgrading does not immediately rewrite existing schedules. A free-created restriction is cleared the next time the schedule is saved (imperative/dashboard) or redeployed (declarative) while the organization is paying.
196
- - No runs are ever skipped or coalesced: unsupported high-frequency schedules are rejected at create/update time rather than silently thinned out.
197
- - Self-hosted deployments, and any case where the billing plan can't be determined, are unrestricted.
198
-
199
- When a schedule is subject to this policy, the API returns an `appliedSchedulePolicy` object alongside the configured `window`:
200
-
201
- ```json
202
- {
203
- "window": "0m",
204
- "appliedSchedulePolicy": {
205
- "minimumWindowSeconds": 3600,
206
- "reason": "free_schedule"
207
- }
208
- }
209
- ```
210
-
211
187
  ## Supported cron syntax
212
188
 
213
189
  ```
@@ -27,7 +27,7 @@ Trigger tasks **from inside a another task**:
27
27
 
28
28
  ## Triggering from your backend
29
29
 
30
- When you trigger a task from your backend code, create a named API key with **Trigger only** access in the environment you want to target and set it as `TRIGGER_SECRET_KEY`. If you're [using a preview branch](/deployment/preview-branches), also set `TRIGGER_PREVIEW_BRANCH`. [More info on API keys](/apikeys).
30
+ When you trigger a task from your backend code, you need to set the `TRIGGER_SECRET_KEY` environment variable. If you're [using a preview branch](/deployment/preview-branches), you also need to set the `TRIGGER_PREVIEW_BRANCH` environment variable. You can find the value on the API keys page in the Trigger.dev dashboard. [More info on API keys](/apikeys).
31
31
 
32
32
  If a single process needs to trigger across multiple projects, environments, or preview branches, use [`new TriggerClient({...})`](/management/multiple-clients) for each target instead of relying on the global env vars.
33
33
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trigger.dev/sdk",
3
- "version": "0.0.0-prerelease-20260908122921",
3
+ "version": "0.0.0-prerelease-streamfix-20260909094302",
4
4
  "description": "trigger.dev Node.JS SDK",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -69,7 +69,7 @@
69
69
  "dependencies": {
70
70
  "@opentelemetry/api": "1.9.1",
71
71
  "@opentelemetry/semantic-conventions": "1.41.1",
72
- "@trigger.dev/core": "0.0.0-prerelease-20260908122921",
72
+ "@trigger.dev/core": "0.0.0-prerelease-streamfix-20260909094302",
73
73
  "uncrypto": "^0.1.3"
74
74
  },
75
75
  "devDependencies": {
@@ -82,13 +82,13 @@
82
82
  "tshy": "^4.1.3",
83
83
  "tsx": "4.17.0",
84
84
  "typescript": "7.0.2",
85
- "zod": "4.5.4"
85
+ "zod": "3.25.76"
86
86
  },
87
87
  "peerDependencies": {
88
88
  "@ai-sdk/otel": ">=1.0.0-0 <2",
89
89
  "ai": "^5.0.0 || ^6.0.0 || >=7.0.0-canary <8",
90
90
  "react": "^18.0 || ^19.0",
91
- "zod": "^3.25.56 || ^4.0.0"
91
+ "zod": "^3.0.0 || ^4.0.0"
92
92
  },
93
93
  "peerDependenciesMeta": {
94
94
  "@ai-sdk/otel": {
@@ -2,8 +2,8 @@
2
2
  name: trigger-authoring-chat-agent
3
3
  description: >
4
4
  Author and run a durable AI chat agent with chat.agent from @trigger.dev/sdk/ai: the per-turn
5
- run loop, why you MUST take streamText from the run argument rather than importing it from ai,
6
- returning a StreamTextResult vs calling chat.pipe(), the two server actions (chat.createStartSessionAction +
5
+ run loop, why you MUST spread ...chat.toStreamTextOptions() first, returning a StreamTextResult
6
+ vs calling chat.pipe(), the two server actions (chat.createStartSessionAction +
7
7
  auth.createPublicToken), and wiring useChat to useTriggerChatTransport. Load this when building,
8
8
  modifying, or debugging a chat backend (the agent task or its lifecycle hooks) or its React
9
9
  transport, when declaring typed tools or custom data parts, or when migrating a plain AI SDK
@@ -47,9 +47,10 @@ import { anthropic } from "@ai-sdk/anthropic";
47
47
 
48
48
  export const myChat = chat.agent({
49
49
  id: "my-chat",
50
- // `streamText` below is the SDK's, from the run argument. See "Common mistakes".
51
- run: async ({ messages, signal, streamText }) =>
50
+ run: async ({ messages, signal }) =>
52
51
  streamText({
52
+ // Spread this FIRST. See "Common mistakes".
53
+ ...chat.toStreamTextOptions(),
53
54
  model: anthropic("claude-sonnet-4-5"),
54
55
  messages,
55
56
  abortSignal: signal,
@@ -120,22 +121,16 @@ inside nested helpers, call `await chat.pipe(result)` from anywhere in the task
120
121
  `run` resolve `void`.
121
122
 
122
123
  ```ts
123
- import { chat, type ChatStreamText } from "@trigger.dev/sdk/ai";
124
- import { anthropic } from "@ai-sdk/anthropic";
125
- import type { ModelMessage } from "ai";
126
-
127
124
  export const agentChat = chat.agent({
128
125
  id: "agent-chat",
129
- run: async ({ messages, streamText }) => {
130
- await runAgentLoop(messages, streamText); // don't return; pipe inside
126
+ run: async ({ messages }) => {
127
+ await runAgentLoop(messages); // don't return; pipe inside
131
128
  },
132
129
  });
133
130
 
134
- // A loop factored out of `run` takes `streamText` as an argument, so it keeps the
135
- // managed options. `ChatStreamText` (from `@trigger.dev/sdk/ai`) types the parameter.
136
- // `chat.toStreamTextOptions()` is the alternative when threading it down is impractical.
137
- async function runAgentLoop(messages: ModelMessage[], streamText: ChatStreamText) {
131
+ async function runAgentLoop(messages: ModelMessage[]) {
138
132
  const result = streamText({
133
+ ...chat.toStreamTextOptions(),
139
134
  model: anthropic("claude-sonnet-4-5"),
140
135
  messages,
141
136
  });
@@ -143,10 +138,10 @@ async function runAgentLoop(messages: ModelMessage[], streamText: ChatStreamText
143
138
  }
144
139
  ```
145
140
 
146
- ### 2. Typed tools (declare on config AND pass back)
141
+ ### 2. Typed tools (declare on config AND spread back)
147
142
 
148
143
  Declare tools on `chat.agent({ tools })`, read them back typed from the `run()` payload, and pass
149
- that set as `tools`. One declaration flows everywhere.
144
+ that set to `chat.toStreamTextOptions({ tools })`. One declaration flows everywhere.
150
145
 
151
146
  ```ts
152
147
  import { tool, stepCountIs } from "ai";
@@ -163,11 +158,11 @@ const tools = {
163
158
  export const myChat = chat.agent({
164
159
  id: "my-chat",
165
160
  tools, // so toModelOutput survives across turns
166
- run: async ({ messages, tools, signal, streamText }) =>
161
+ run: async ({ messages, tools, signal }) =>
167
162
  streamText({
163
+ ...chat.toStreamTextOptions({ tools }), // same set, handed back typed
168
164
  model: anthropic("claude-sonnet-4-5"),
169
165
  messages,
170
- tools, // same set, handed back typed
171
166
  abortSignal: signal,
172
167
  stopWhen: stepCountIs(15),
173
168
  }),
@@ -208,8 +203,8 @@ export const myChat = chat
208
203
  onTurnStart: async ({ uiMessages, writer }) => {
209
204
  writer.write({ type: "data-turn-status", data: { status: "preparing" } });
210
205
  },
211
- run: async ({ messages, tools, signal, streamText }) =>
212
- streamText({ model, messages, tools, abortSignal: signal }),
206
+ run: async ({ messages, tools, signal }) =>
207
+ streamText({ ...chat.toStreamTextOptions({ tools }), model, messages, abortSignal: signal }),
213
208
  });
214
209
  ```
215
210
 
@@ -233,13 +228,13 @@ first message. Suspend/resume use `onChatSuspend` / `onChatResume`. Config optio
233
228
  `uiMessageStreamOptions`, and `exitAfterPreloadIdle`. There is no generic `retry`; `chat.agent`
234
229
  runs with `maxAttempts: 1` internally.
235
230
 
236
- Stop depends on it: the `signal` passed to `run` aborts on stop or cancel. Forward it as
231
+ Stop is load-bearing: the `signal` passed to `run` aborts on stop or cancel. Forward it as
237
232
  `abortSignal` to `streamText`, or the Stop button updates the UI while the model keeps generating
238
233
  server-side.
239
234
 
240
235
  ```ts
241
- run: async ({ messages, signal, streamText }) =>
242
- streamText({ model, messages, abortSignal: signal, stopWhen: stepCountIs(15) });
236
+ run: async ({ messages, signal }) =>
237
+ streamText({ ...chat.toStreamTextOptions(), model, messages, abortSignal: signal, stopWhen: stepCountIs(15) });
243
238
  ```
244
239
 
245
240
  ### 6. Migrating from a plain AI SDK `streamText` route
@@ -248,30 +243,24 @@ There is no API route in this model. The transport replaces the route round-trip
248
243
 
249
244
  - Delete the route handler. Move per-request auth into the two server actions from Setup step 2.
250
245
  - Move the `streamText` call into `run`. It already receives pre-converted `ModelMessage[]`.
251
- - Return the `StreamTextResult` (it auto-pipes) and take `streamText` from `run`'s argument, not from `ai`.
246
+ - Return the `StreamTextResult` (it auto-pipes) and add `...chat.toStreamTextOptions()` first.
252
247
  - On the client, swap the `api` URL for `useTriggerChatTransport`; `useChat` stays the same shape.
253
248
 
254
249
  ## Common mistakes
255
250
 
256
- - **CRITICAL: calling the `streamText` imported from `ai`.**
251
+ - **CRITICAL: forgetting `...chat.toStreamTextOptions()`.**
257
252
  ```ts
258
253
  // Wrong - compaction / steering / background injection silently no-op
259
- import { streamText } from "ai";
260
- run: async ({ messages, signal }) => streamText({ model, messages, abortSignal: signal });
261
- // Correct - the run argument's streamText carries the managed options
262
- run: async ({ messages, signal, streamText }) => streamText({ model, messages, abortSignal: signal });
254
+ return streamText({ model, messages, abortSignal: signal });
255
+ // Correct - spread FIRST so explicit overrides win
256
+ return streamText({ ...chat.toStreamTextOptions(), model, messages, abortSignal: signal });
263
257
  ```
264
- The SDK's one carries the `prepareStep` behind compaction, mid-turn steering and background
265
- injection, the system prompt from `chat.prompt()` or `chat.agent({ system })`, the registry-resolved
266
- model, and telemetry. The imported one carries none of it, with no error.
267
- `...chat.toStreamTextOptions()` does the same job by hand, and is what a custom agent has to use,
268
- since it has no `run` argument. A `chat.headStart` route gets a bound `streamText` too, and there it
269
- also owns `messages`, `prompt`, `stopWhen` and `abortSignal`. Spreading it and then re-setting
270
- `tools` or `prepareStep` replaces the managed ones; the run argument's `streamText` merges `tools`
271
- and composes `prepareStep` instead.
258
+ It wires the `prepareStep` callback behind compaction, mid-turn steering, and background
259
+ injection, injects the system prompt from `chat.prompt()`, resolves the registry model, and adds
260
+ telemetry. Omitting it makes all of those silently no-op with no error.
272
261
 
273
262
  - **Declaring tools only on `streamText`.** Also declare them on `chat.agent({ tools })`, read them
274
- back from `run`, and pass that set as `tools`. Otherwise each tool's
263
+ back from `run`, and pass `chat.toStreamTextOptions({ tools })`. Otherwise each tool's
275
264
  `toModelOutput` runs on turn 1 but is dropped when history is re-converted on later turns.
276
265
 
277
266
  - **Not forwarding `signal` for stop.** Without `abortSignal: signal`, Stop updates the UI but the