@trigger.dev/sdk 4.5.0-rc.5 → 4.5.0-rc.7

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 (213) hide show
  1. package/dist/commonjs/v3/ai.d.ts +178 -5
  2. package/dist/commonjs/v3/ai.js +603 -119
  3. package/dist/commonjs/v3/ai.js.map +1 -1
  4. package/dist/commonjs/v3/chat-client.js +3 -0
  5. package/dist/commonjs/v3/chat-client.js.map +1 -1
  6. package/dist/commonjs/v3/chat-react.js +10 -7
  7. package/dist/commonjs/v3/chat-react.js.map +1 -1
  8. package/dist/commonjs/v3/chat-server.d.ts +8 -0
  9. package/dist/commonjs/v3/chat-server.js +32 -10
  10. package/dist/commonjs/v3/chat-server.js.map +1 -1
  11. package/dist/commonjs/v3/chat-server.test.js +51 -0
  12. package/dist/commonjs/v3/chat-server.test.js.map +1 -1
  13. package/dist/commonjs/v3/chat.js +34 -6
  14. package/dist/commonjs/v3/chat.js.map +1 -1
  15. package/dist/commonjs/v3/chat.test.js +53 -0
  16. package/dist/commonjs/v3/chat.test.js.map +1 -1
  17. package/dist/commonjs/v3/createStartSessionAction.test.js +30 -0
  18. package/dist/commonjs/v3/createStartSessionAction.test.js.map +1 -1
  19. package/dist/commonjs/v3/sessions.d.ts +11 -6
  20. package/dist/commonjs/v3/sessions.js +10 -5
  21. package/dist/commonjs/v3/sessions.js.map +1 -1
  22. package/dist/commonjs/v3/test/mock-chat-agent.d.ts +6 -0
  23. package/dist/commonjs/v3/test/mock-chat-agent.js +1 -0
  24. package/dist/commonjs/v3/test/mock-chat-agent.js.map +1 -1
  25. package/dist/commonjs/version.js +1 -1
  26. package/dist/esm/v3/ai.d.ts +178 -5
  27. package/dist/esm/v3/ai.js +603 -120
  28. package/dist/esm/v3/ai.js.map +1 -1
  29. package/dist/esm/v3/chat-client.js +3 -0
  30. package/dist/esm/v3/chat-client.js.map +1 -1
  31. package/dist/esm/v3/chat-react.js +10 -7
  32. package/dist/esm/v3/chat-react.js.map +1 -1
  33. package/dist/esm/v3/chat-server.d.ts +8 -0
  34. package/dist/esm/v3/chat-server.js +32 -10
  35. package/dist/esm/v3/chat-server.js.map +1 -1
  36. package/dist/esm/v3/chat-server.test.js +51 -0
  37. package/dist/esm/v3/chat-server.test.js.map +1 -1
  38. package/dist/esm/v3/chat.js +34 -6
  39. package/dist/esm/v3/chat.js.map +1 -1
  40. package/dist/esm/v3/chat.test.js +53 -0
  41. package/dist/esm/v3/chat.test.js.map +1 -1
  42. package/dist/esm/v3/createStartSessionAction.test.js +30 -0
  43. package/dist/esm/v3/createStartSessionAction.test.js.map +1 -1
  44. package/dist/esm/v3/sessions.d.ts +11 -6
  45. package/dist/esm/v3/sessions.js +10 -5
  46. package/dist/esm/v3/sessions.js.map +1 -1
  47. package/dist/esm/v3/test/mock-chat-agent.d.ts +6 -0
  48. package/dist/esm/v3/test/mock-chat-agent.js +1 -0
  49. package/dist/esm/v3/test/mock-chat-agent.js.map +1 -1
  50. package/dist/esm/version.js +1 -1
  51. package/docs/ai/prompts.mdx +430 -0
  52. package/docs/ai-chat/actions.mdx +115 -0
  53. package/docs/ai-chat/anatomy.mdx +71 -0
  54. package/docs/ai-chat/backend.mdx +817 -0
  55. package/docs/ai-chat/background-injection.mdx +221 -0
  56. package/docs/ai-chat/changelog.mdx +850 -0
  57. package/docs/ai-chat/chat-local.mdx +174 -0
  58. package/docs/ai-chat/client-protocol.mdx +1081 -0
  59. package/docs/ai-chat/compaction.mdx +411 -0
  60. package/docs/ai-chat/custom-agents.mdx +364 -0
  61. package/docs/ai-chat/error-handling.mdx +415 -0
  62. package/docs/ai-chat/fast-starts.mdx +672 -0
  63. package/docs/ai-chat/frontend.mdx +580 -0
  64. package/docs/ai-chat/how-it-works.mdx +230 -0
  65. package/docs/ai-chat/lifecycle-hooks.mdx +530 -0
  66. package/docs/ai-chat/mcp.mdx +101 -0
  67. package/docs/ai-chat/overview.mdx +90 -0
  68. package/docs/ai-chat/patterns/branching-conversations.mdx +284 -0
  69. package/docs/ai-chat/patterns/code-sandbox.mdx +126 -0
  70. package/docs/ai-chat/patterns/database-persistence.mdx +414 -0
  71. package/docs/ai-chat/patterns/human-in-the-loop.mdx +275 -0
  72. package/docs/ai-chat/patterns/large-payloads.mdx +169 -0
  73. package/docs/ai-chat/patterns/oom-resilience.mdx +120 -0
  74. package/docs/ai-chat/patterns/persistence-and-replay.mdx +211 -0
  75. package/docs/ai-chat/patterns/recovery-boot.mdx +230 -0
  76. package/docs/ai-chat/patterns/skills.mdx +221 -0
  77. package/docs/ai-chat/patterns/sub-agents.mdx +383 -0
  78. package/docs/ai-chat/patterns/tool-result-auditing.mdx +148 -0
  79. package/docs/ai-chat/patterns/trusted-edge-signals.mdx +337 -0
  80. package/docs/ai-chat/patterns/version-upgrades.mdx +172 -0
  81. package/docs/ai-chat/pending-messages.mdx +343 -0
  82. package/docs/ai-chat/prompt-caching.mdx +206 -0
  83. package/docs/ai-chat/quick-start.mdx +161 -0
  84. package/docs/ai-chat/reference.mdx +909 -0
  85. package/docs/ai-chat/server-chat.mdx +263 -0
  86. package/docs/ai-chat/sessions.mdx +333 -0
  87. package/docs/ai-chat/testing.mdx +682 -0
  88. package/docs/ai-chat/tools.mdx +191 -0
  89. package/docs/ai-chat/types.mdx +242 -0
  90. package/docs/ai-chat/upgrade-guide.mdx +515 -0
  91. package/docs/apikeys.mdx +54 -0
  92. package/docs/building-with-ai.mdx +261 -0
  93. package/docs/bulk-actions.mdx +49 -0
  94. package/docs/changelog.mdx +6 -0
  95. package/docs/cli-deploy-commands.mdx +9 -0
  96. package/docs/cli-dev-commands.mdx +9 -0
  97. package/docs/cli-dev.mdx +8 -0
  98. package/docs/cli-init-commands.mdx +58 -0
  99. package/docs/cli-introduction.mdx +25 -0
  100. package/docs/cli-list-profiles-commands.mdx +42 -0
  101. package/docs/cli-login-commands.mdx +33 -0
  102. package/docs/cli-logout-commands.mdx +33 -0
  103. package/docs/cli-preview-archive.mdx +59 -0
  104. package/docs/cli-promote-commands.mdx +9 -0
  105. package/docs/cli-switch.mdx +43 -0
  106. package/docs/cli-update-commands.mdx +42 -0
  107. package/docs/cli-whoami-commands.mdx +33 -0
  108. package/docs/community.mdx +6 -0
  109. package/docs/config/config-file.mdx +602 -0
  110. package/docs/config/extensions/additionalFiles.mdx +38 -0
  111. package/docs/config/extensions/additionalPackages.mdx +40 -0
  112. package/docs/config/extensions/aptGet.mdx +34 -0
  113. package/docs/config/extensions/audioWaveform.mdx +20 -0
  114. package/docs/config/extensions/custom.mdx +380 -0
  115. package/docs/config/extensions/emitDecoratorMetadata.mdx +29 -0
  116. package/docs/config/extensions/esbuildPlugin.mdx +31 -0
  117. package/docs/config/extensions/ffmpeg.mdx +45 -0
  118. package/docs/config/extensions/lightpanda.mdx +56 -0
  119. package/docs/config/extensions/overview.mdx +67 -0
  120. package/docs/config/extensions/playwright.mdx +195 -0
  121. package/docs/config/extensions/prismaExtension.mdx +1014 -0
  122. package/docs/config/extensions/puppeteer.mdx +30 -0
  123. package/docs/config/extensions/pythonExtension.mdx +182 -0
  124. package/docs/config/extensions/syncEnvVars.mdx +291 -0
  125. package/docs/context.mdx +235 -0
  126. package/docs/database-connections.mdx +213 -0
  127. package/docs/deploy-environment-variables.mdx +435 -0
  128. package/docs/deployment/atomic-deployment.mdx +172 -0
  129. package/docs/deployment/overview.mdx +257 -0
  130. package/docs/deployment/preview-branches.mdx +224 -0
  131. package/docs/errors-retrying.mdx +379 -0
  132. package/docs/github-actions.mdx +222 -0
  133. package/docs/github-integration.mdx +136 -0
  134. package/docs/github-repo.mdx +8 -0
  135. package/docs/help-email.mdx +6 -0
  136. package/docs/help-slack.mdx +11 -0
  137. package/docs/hidden-tasks.mdx +56 -0
  138. package/docs/how-it-works.mdx +454 -0
  139. package/docs/how-to-reduce-your-spend.mdx +217 -0
  140. package/docs/idempotency.mdx +504 -0
  141. package/docs/introduction.mdx +223 -0
  142. package/docs/limits.mdx +241 -0
  143. package/docs/logging.mdx +195 -0
  144. package/docs/machines.mdx +952 -0
  145. package/docs/manual-setup.mdx +632 -0
  146. package/docs/mcp-agent-rules.mdx +41 -0
  147. package/docs/mcp-introduction.mdx +385 -0
  148. package/docs/mcp-tools.mdx +273 -0
  149. package/docs/migrating-from-v3.mdx +334 -0
  150. package/docs/observability/dashboards.mdx +102 -0
  151. package/docs/observability/query.mdx +585 -0
  152. package/docs/open-source-contributing.mdx +16 -0
  153. package/docs/open-source-self-hosting.mdx +541 -0
  154. package/docs/private-networking/aws-console-setup.mdx +304 -0
  155. package/docs/private-networking/overview.mdx +144 -0
  156. package/docs/private-networking/troubleshooting.mdx +78 -0
  157. package/docs/queue-concurrency.mdx +354 -0
  158. package/docs/quick-start.mdx +97 -0
  159. package/docs/realtime/auth.mdx +208 -0
  160. package/docs/realtime/backend/overview.mdx +45 -0
  161. package/docs/realtime/backend/streams.mdx +418 -0
  162. package/docs/realtime/backend/subscribe.mdx +225 -0
  163. package/docs/realtime/how-it-works.mdx +94 -0
  164. package/docs/realtime/overview.mdx +63 -0
  165. package/docs/realtime/react-hooks/overview.mdx +73 -0
  166. package/docs/realtime/react-hooks/streams.mdx +449 -0
  167. package/docs/realtime/react-hooks/subscribe.mdx +674 -0
  168. package/docs/realtime/react-hooks/swr.mdx +87 -0
  169. package/docs/realtime/react-hooks/triggering.mdx +194 -0
  170. package/docs/realtime/react-hooks/use-wait-token.mdx +34 -0
  171. package/docs/realtime/run-object.mdx +174 -0
  172. package/docs/replaying.mdx +72 -0
  173. package/docs/request-feature.mdx +6 -0
  174. package/docs/roadmap.mdx +6 -0
  175. package/docs/run-tests.mdx +20 -0
  176. package/docs/run-usage.mdx +113 -0
  177. package/docs/runs/heartbeats.mdx +38 -0
  178. package/docs/runs/max-duration.mdx +139 -0
  179. package/docs/runs/metadata.mdx +734 -0
  180. package/docs/runs/priority.mdx +31 -0
  181. package/docs/runs.mdx +396 -0
  182. package/docs/self-hosting/docker.mdx +458 -0
  183. package/docs/self-hosting/env/supervisor.mdx +74 -0
  184. package/docs/self-hosting/env/webapp.mdx +276 -0
  185. package/docs/self-hosting/kubernetes.mdx +601 -0
  186. package/docs/self-hosting/overview.mdx +108 -0
  187. package/docs/skills.mdx +85 -0
  188. package/docs/tags.mdx +120 -0
  189. package/docs/tasks/overview.mdx +697 -0
  190. package/docs/tasks/scheduled.mdx +382 -0
  191. package/docs/tasks/schemaTask.mdx +413 -0
  192. package/docs/tasks/streams.mdx +884 -0
  193. package/docs/triggering.mdx +1320 -0
  194. package/docs/troubleshooting-alerts.mdx +385 -0
  195. package/docs/troubleshooting-debugging-in-vscode.mdx +8 -0
  196. package/docs/troubleshooting-github-issues.mdx +6 -0
  197. package/docs/troubleshooting-uptime-status.mdx +6 -0
  198. package/docs/troubleshooting.mdx +398 -0
  199. package/docs/upgrading-packages.mdx +80 -0
  200. package/docs/vercel-integration.mdx +207 -0
  201. package/docs/versioning.mdx +56 -0
  202. package/docs/video-walkthrough.mdx +23 -0
  203. package/docs/wait-for-token.mdx +540 -0
  204. package/docs/wait-for.mdx +42 -0
  205. package/docs/wait-until.mdx +53 -0
  206. package/docs/wait.mdx +18 -0
  207. package/docs/writing-tasks-introduction.mdx +33 -0
  208. package/package.json +10 -6
  209. package/skills/trigger-authoring-chat-agent/SKILL.md +296 -0
  210. package/skills/trigger-authoring-tasks/SKILL.md +254 -0
  211. package/skills/trigger-chat-agent-advanced/SKILL.md +368 -0
  212. package/skills/trigger-cost-savings/SKILL.md +116 -0
  213. package/skills/trigger-realtime-and-frontend/SKILL.md +276 -0
@@ -0,0 +1,53 @@
1
+ ---
2
+ title: "Wait until"
3
+ description: "Wait until a date, then continue execution."
4
+ ---
5
+
6
+ import PausedExecutionFree from "/snippets/paused-execution-free.mdx"
7
+
8
+ This example sends a reminder email to a user at the specified datetime.
9
+
10
+ ```ts /trigger/reminder-email.ts
11
+ export const sendReminderEmail = task({
12
+ id: "send-reminder-email",
13
+ run: async (payload: { to: string; name: string; date: string }) => {
14
+ //wait until the date
15
+ await wait.until({ date: new Date(payload.date) });
16
+
17
+ //todo send email
18
+ const { data, error } = await resend.emails.send({
19
+ from: "hello@trigger.dev",
20
+ to: payload.to,
21
+ subject: "Don't forget…",
22
+ html: `<p>Hello ${payload.name},</p><p>...</p>`,
23
+ });
24
+ },
25
+ });
26
+ ```
27
+
28
+ This allows you to write linear code without having to worry about the complexity of scheduling or managing cron jobs.
29
+
30
+ <PausedExecutionFree />
31
+
32
+ ## `throwIfInThePast`
33
+
34
+ You can optionally throw an error if the date is already in the past when the function is called:
35
+
36
+ ```ts
37
+ await wait.until({ date: new Date(date), throwIfInThePast: true });
38
+ ```
39
+
40
+ You can of course use try/catch if you want to do something special in this case.
41
+
42
+ ## Wait idempotency
43
+
44
+ You can pass an idempotency key to any wait function, allowing you to skip waits if the same idempotency key is used again. This can be useful if you want to skip waits when retrying a task, for example:
45
+
46
+ ```ts
47
+ // Specify the idempotency key and TTL when waiting until a date:
48
+ await wait.until({
49
+ date: futureDate,
50
+ idempotencyKey: "my-idempotency-key",
51
+ idempotencyKeyTTL: "1h",
52
+ });
53
+ ```
package/docs/wait.mdx ADDED
@@ -0,0 +1,18 @@
1
+ ---
2
+ title: "Wait: Overview"
3
+ sidebarTitle: "Overview"
4
+ description: "During your run you can wait for a period of time or for something to happen."
5
+ ---
6
+
7
+ import PausedExecutionFree from "/snippets/paused-execution-free.mdx";
8
+
9
+ Waiting allows you to write complex tasks as a set of async code, without having to schedule another task or poll for changes.
10
+
11
+ <PausedExecutionFree />
12
+
13
+ | Function | What it does |
14
+ | :------------------------------------------------ | :--------------------------------------------------------------- |
15
+ | [wait.for()](/wait-for) | Waits for a specific period of time, e.g. 1 day. |
16
+ | [wait.until()](/wait-until) | Waits until the provided `Date`. |
17
+ | [wait.forToken()](/wait-for-token) | Pauses runs until a token is completed. |
18
+ | [inputStream.wait()](/tasks/streams#wait--suspend-until-data-arrives) | Pauses runs until data arrives on an input stream. |
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: "Writing tasks: Overview"
3
+ sidebarTitle: "Overview"
4
+ description: "Tasks are the core of Trigger.dev. They are long-running processes that are triggered by events."
5
+ ---
6
+
7
+ import ExamplesCards from "/snippets/examples-cards.mdx";
8
+
9
+ Before digging deeper into the details of writing tasks, you should read the [fundamentals of tasks](/tasks/overview) to understand what tasks are and how they work.
10
+
11
+ ## Writing tasks
12
+
13
+ | Topic | Description |
14
+ | :------------------------------------------- | :-------------------------------------------------------------------------------------------------- |
15
+ | [Logging](/logging) | View and send logs and traces from your tasks. |
16
+ | [Errors & retrying](/errors-retrying) | How to deal with errors and write reliable tasks. |
17
+ | [Wait](/wait) | Wait for periods of time or for external events to occur before continuing. |
18
+ | [Concurrency & Queues](/queue-concurrency) | Configure what you want to happen when there is more than one run at a time. |
19
+ | [Realtime notifications](/realtime/overview) | Send realtime notifications from your task that you can subscribe to from your backend or frontend. |
20
+ | [Versioning](/versioning) | How versioning works. |
21
+ | [Machines](/machines) | Configure the CPU and RAM of the machine your task runs on |
22
+ | [Idempotency](/idempotency) | Protect against mutations happening twice. |
23
+ | [Replaying](/replaying) | You can replay a single task or many at once with a new version of your code. |
24
+ | [Max duration](/runs/max-duration) | Set a maximum duration for your task to run. |
25
+ | [Tags](/tags) | Tags allow you to easily filter runs in the dashboard and when using the SDK. |
26
+ | [Metadata](/runs/metadata) | Attach a small amount of data to a run and update it as the run progresses. |
27
+ | [Usage](/run-usage) | Get compute duration and cost from inside a run, or for a specific block of code. |
28
+ | [Context](/context) | Access the context of the task run. |
29
+ | [Bulk actions](/bulk-actions) | Run actions on many task runs at once. |
30
+ | [Priority](/runs/priority) | Specify a priority when triggering a task. |
31
+ | [Hidden tasks](/hidden-tasks) | Create tasks that are not exported from your trigger files but can still be executed. |
32
+
33
+ <ExamplesCards />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trigger.dev/sdk",
3
- "version": "4.5.0-rc.5",
3
+ "version": "4.5.0-rc.7",
4
4
  "description": "trigger.dev Node.JS SDK",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -14,7 +14,9 @@
14
14
  "type": "module",
15
15
  "sideEffects": false,
16
16
  "files": [
17
- "dist"
17
+ "dist",
18
+ "docs",
19
+ "skills"
18
20
  ],
19
21
  "tshy": {
20
22
  "selfLink": false,
@@ -64,7 +66,7 @@
64
66
  "dependencies": {
65
67
  "@opentelemetry/api": "1.9.1",
66
68
  "@opentelemetry/semantic-conventions": "1.41.1",
67
- "@trigger.dev/core": "4.5.0-rc.5",
69
+ "@trigger.dev/core": "4.5.0-rc.7",
68
70
  "chalk": "^5.2.0",
69
71
  "cronstrue": "^2.21.0",
70
72
  "debug": "^4.3.4",
@@ -205,10 +207,12 @@
205
207
  "types": "./dist/commonjs/v3/index.d.ts",
206
208
  "module": "./dist/esm/v3/index.js",
207
209
  "scripts": {
208
- "clean": "rimraf dist .tshy .tshy-build .turbo",
209
- "build": "tshy && pnpm run update-version",
210
+ "clean": "rimraf dist docs .tshy .tshy-build .turbo",
211
+ "build": "tshy && pnpm run update-version && pnpm run bundle-docs",
212
+ "bundle-docs": "tsx ../../scripts/bundleSdkDocs.ts",
210
213
  "dev": "tshy --watch",
211
- "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.ai-v7.json",
214
+ "typecheck": "tsc --noEmit",
215
+ "typecheck:ai-v7": "tsc --noEmit -p tsconfig.ai-v7.json",
212
216
  "test": "vitest",
213
217
  "update-version": "tsx ../../scripts/updateVersion.ts",
214
218
  "check-exports": "attw --pack ."
@@ -0,0 +1,296 @@
1
+ ---
2
+ name: trigger-authoring-chat-agent
3
+ description: >
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 spread ...chat.toStreamTextOptions() first, returning a StreamTextResult
6
+ vs calling chat.pipe(), the two server actions (chat.createStartSessionAction +
7
+ auth.createPublicToken), and wiring useChat to useTriggerChatTransport. Load this when building,
8
+ modifying, or debugging a chat backend (the agent task or its lifecycle hooks) or its React
9
+ transport, when declaring typed tools or custom data parts, or when migrating a plain AI SDK
10
+ streamText route to chat.agent.
11
+ type: core
12
+ library: trigger.dev
13
+ sources:
14
+ - docs/ai-chat/overview.mdx
15
+ - docs/ai-chat/quick-start.mdx
16
+ - docs/ai-chat/how-it-works.mdx
17
+ - docs/ai-chat/backend.mdx
18
+ - docs/ai-chat/frontend.mdx
19
+ - docs/ai-chat/reference.mdx
20
+ - docs/ai-chat/types.mdx
21
+ - docs/ai-chat/tools.mdx
22
+ - docs/ai-chat/lifecycle-hooks.mdx
23
+ - docs/ai-chat/error-handling.mdx
24
+ ---
25
+
26
+ # Authoring a chat agent
27
+
28
+ A `chat.agent` runs an entire conversation as one long-lived Trigger.dev task. It wakes when a
29
+ message arrives, freezes when none do, and in-memory state survives page refreshes, deploys, idle
30
+ gaps, and crashes. Your code is the loop you would write anyway: messages in, `streamText` out.
31
+ There are no API routes. The frontend talks to the agent through a `TriggerChatTransport`, so
32
+ history accumulates server-side and the client ships only the new message each turn.
33
+
34
+ Works with Vercel AI SDK v5, v6, or v7. On v7 also install `@ai-sdk/otel` so model calls are traced
35
+ (the SDK registers it for you).
36
+
37
+ ## Setup
38
+
39
+ Three pieces: the agent task, two server actions, and the frontend transport.
40
+
41
+ ### 1. Define the agent
42
+
43
+ ```ts trigger/chat.ts
44
+ import { chat } from "@trigger.dev/sdk/ai";
45
+ import { streamText, stepCountIs } from "ai";
46
+ import { anthropic } from "@ai-sdk/anthropic";
47
+
48
+ export const myChat = chat.agent({
49
+ id: "my-chat",
50
+ run: async ({ messages, signal }) =>
51
+ streamText({
52
+ // Spread this FIRST. See "Common mistakes".
53
+ ...chat.toStreamTextOptions(),
54
+ model: anthropic("claude-sonnet-4-5"),
55
+ messages,
56
+ abortSignal: signal,
57
+ stopWhen: stepCountIs(15),
58
+ }),
59
+ });
60
+ ```
61
+
62
+ `run` receives `messages` already converted to `ModelMessage[]` (the SDK converts the frontend's
63
+ `UIMessage[]` for you) plus a `signal` that aborts on stop or cancel. Returning the
64
+ `StreamTextResult` auto-pipes it to the frontend.
65
+
66
+ ### 2. Add two server actions
67
+
68
+ Both run on your server, so the browser never holds your environment secret key. This is also
69
+ where per-user / per-plan authorization and any paired DB writes live.
70
+
71
+ ```ts app/actions.ts
72
+ "use server";
73
+ import { auth } from "@trigger.dev/sdk";
74
+ import { chat } from "@trigger.dev/sdk/ai";
75
+
76
+ // Creates the Session + first run, returns a session PAT. Idempotent on (env, chatId).
77
+ export const startChatSession = chat.createStartSessionAction("my-chat");
78
+
79
+ // Pure mint. The transport calls this on 401/403 to refresh an expired token.
80
+ export async function mintChatAccessToken(chatId: string) {
81
+ return auth.createPublicToken({
82
+ scopes: { read: { sessions: chatId }, write: { sessions: chatId } },
83
+ expirationTime: "1h",
84
+ });
85
+ }
86
+ ```
87
+
88
+ ### 3. Wire the frontend
89
+
90
+ ```tsx app/components/chat.tsx
91
+ "use client";
92
+ import { useState } from "react";
93
+ import { useChat } from "@ai-sdk/react";
94
+ import { useTriggerChatTransport } from "@trigger.dev/sdk/chat/react";
95
+ import type { myChat } from "@/trigger/chat";
96
+ import { mintChatAccessToken, startChatSession } from "@/app/actions";
97
+
98
+ export function Chat() {
99
+ const transport = useTriggerChatTransport<typeof myChat>({
100
+ task: "my-chat", // typeof myChat gives compile-time task-id validation
101
+ accessToken: ({ chatId }) => mintChatAccessToken(chatId),
102
+ startSession: ({ chatId, clientData }) => startChatSession({ chatId, clientData }),
103
+ });
104
+
105
+ const { messages, sendMessage, stop, status } = useChat({ transport });
106
+ const [input, setInput] = useState("");
107
+ // render messages, a form that calls sendMessage({ text: input }),
108
+ // and a Stop button (onClick={stop}) while status === "streaming".
109
+ }
110
+ ```
111
+
112
+ The transport is memoized (created once, reused across renders). Passing `typeof myChat` flows the
113
+ agent's message type through `useChat`.
114
+
115
+ ## Core patterns
116
+
117
+ ### 1. Return vs pipe
118
+
119
+ Return the `streamText` result from `run` for the simple case. When `streamText` is called deep
120
+ inside nested helpers, call `await chat.pipe(result)` from anywhere in the task instead, and let
121
+ `run` resolve `void`.
122
+
123
+ ```ts
124
+ export const agentChat = chat.agent({
125
+ id: "agent-chat",
126
+ run: async ({ messages }) => {
127
+ await runAgentLoop(messages); // don't return; pipe inside
128
+ },
129
+ });
130
+
131
+ async function runAgentLoop(messages: ModelMessage[]) {
132
+ const result = streamText({
133
+ ...chat.toStreamTextOptions(),
134
+ model: anthropic("claude-sonnet-4-5"),
135
+ messages,
136
+ });
137
+ await chat.pipe(result); // works from anywhere in the task
138
+ }
139
+ ```
140
+
141
+ ### 2. Typed tools (declare on config AND spread back)
142
+
143
+ Declare tools on `chat.agent({ tools })`, read them back typed from the `run()` payload, and pass
144
+ that set to `chat.toStreamTextOptions({ tools })`. One declaration flows everywhere.
145
+
146
+ ```ts
147
+ import { tool, stepCountIs } from "ai";
148
+ import { z } from "zod";
149
+
150
+ const tools = {
151
+ searchDocs: tool({
152
+ description: "Search the docs.",
153
+ inputSchema: z.object({ query: z.string() }),
154
+ execute: async ({ query }) => searchIndex(query),
155
+ }),
156
+ };
157
+
158
+ export const myChat = chat.agent({
159
+ id: "my-chat",
160
+ tools, // so toModelOutput survives across turns
161
+ run: async ({ messages, tools, signal }) =>
162
+ streamText({
163
+ ...chat.toStreamTextOptions({ tools }), // same set, handed back typed
164
+ model: anthropic("claude-sonnet-4-5"),
165
+ messages,
166
+ abortSignal: signal,
167
+ stopWhen: stepCountIs(15),
168
+ }),
169
+ });
170
+ ```
171
+
172
+ `tools` also accepts a function `(event) => ToolSet` resolved per turn, where `event` carries
173
+ `chatId`, `turn`, `continuation`, and `clientData`.
174
+
175
+ ### 3. Custom data parts (persisted vs transient)
176
+
177
+ `data-*` parts written via `chat.response.write()` in `run()` (or `writer.write()` in hooks)
178
+ persist into `responseMessage.parts` and surface in `onTurnComplete`. Add `transient: true` to
179
+ stream them without persisting. Writes via `chat.stream` are always ephemeral.
180
+
181
+ ```ts
182
+ // In run() - persists, surfaces in onTurnComplete's responseMessage
183
+ chat.response.write({ type: "data-context", data: { searchResults } });
184
+
185
+ // In a hook via writer - streams but does NOT persist
186
+ writer.write({ type: "data-progress", id: "search", data: { percent: 50 }, transient: true });
187
+ ```
188
+
189
+ ### 4. Custom UIMessage type, client data, and builder hooks
190
+
191
+ For typed `data-*` parts or a tool map, build the agent through `chat.withUIMessage<T>()` and
192
+ `chat.withClientData({ schema })`. Builder methods chain in any order; builder hooks run before the
193
+ matching task hook. `streamOptions` becomes the default `uiMessageStreamOptions` (shallow-merged,
194
+ agent wins).
195
+
196
+ ```ts
197
+ export const myChat = chat
198
+ .withUIMessage<MyChatUIMessage>({ streamOptions: { sendReasoning: true } })
199
+ .withClientData({ schema: z.object({ userId: z.string() }) })
200
+ .agent({
201
+ id: "my-chat",
202
+ tools: myTools,
203
+ onTurnStart: async ({ uiMessages, writer }) => {
204
+ writer.write({ type: "data-turn-status", data: { status: "preparing" } });
205
+ },
206
+ run: async ({ messages, tools, signal }) =>
207
+ streamText({ ...chat.toStreamTextOptions({ tools }), model, messages, abortSignal: signal }),
208
+ });
209
+ ```
210
+
211
+ Build `MyChatUIMessage` as `UIMessage<unknown, MyDataTypes, InferUITools<typeof tools>>` (or, for
212
+ tools only, `InferChatUIMessageFromTools<typeof tools>` from `@trigger.dev/sdk/ai`). On the
213
+ frontend, narrow `useChat` with `InferChatUIMessage<typeof myChat>` from `@trigger.dev/sdk/chat/react`.
214
+
215
+ ### 5. Lifecycle hooks and stop
216
+
217
+ `chat.agent` accepts hooks that fire in a fixed per-turn order:
218
+
219
+ ```text
220
+ onValidateMessages -> hydrateMessages -> onChatStart (chat's first message only)
221
+ -> onTurnStart -> run() -> onBeforeTurnComplete -> onTurnComplete
222
+ ```
223
+
224
+ `onBoot` fires once per worker process (every fresh boot, including continuation runs) and is where
225
+ `chat.local`, DB connections, and per-process state belong. `onChatStart` fires only on the chat's
226
+ first message. Suspend/resume use `onChatSuspend` / `onChatResume`. Config options include
227
+ `tools`, `clientDataSchema`, `maxTurns` (100), `turnTimeout` ("1h"), `idleTimeoutInSeconds` (30),
228
+ `uiMessageStreamOptions`, and `exitAfterPreloadIdle`. There is no generic `retry`; `chat.agent`
229
+ runs with `maxAttempts: 1` internally.
230
+
231
+ Stop is load-bearing: the `signal` passed to `run` aborts on stop or cancel. Forward it as
232
+ `abortSignal` to `streamText`, or the Stop button updates the UI while the model keeps generating
233
+ server-side.
234
+
235
+ ```ts
236
+ run: async ({ messages, signal }) =>
237
+ streamText({ ...chat.toStreamTextOptions(), model, messages, abortSignal: signal, stopWhen: stepCountIs(15) });
238
+ ```
239
+
240
+ ### 6. Migrating from a plain AI SDK `streamText` route
241
+
242
+ There is no API route in this model. The transport replaces the route round-trip, so:
243
+
244
+ - Delete the route handler. Move per-request auth into the two server actions from Setup step 2.
245
+ - Move the `streamText` call into `run`. It already receives pre-converted `ModelMessage[]`.
246
+ - Return the `StreamTextResult` (it auto-pipes) and add `...chat.toStreamTextOptions()` first.
247
+ - On the client, swap the `api` URL for `useTriggerChatTransport`; `useChat` stays the same shape.
248
+
249
+ ## Common mistakes
250
+
251
+ - **CRITICAL: forgetting `...chat.toStreamTextOptions()`.**
252
+ ```ts
253
+ // Wrong - compaction / steering / background injection silently no-op
254
+ return streamText({ model, messages, abortSignal: signal });
255
+ // Correct - spread FIRST so explicit overrides win
256
+ return streamText({ ...chat.toStreamTextOptions(), model, messages, abortSignal: signal });
257
+ ```
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.
261
+
262
+ - **Declaring tools only on `streamText`.** Also declare them on `chat.agent({ tools })`, read them
263
+ back from `run`, and pass `chat.toStreamTextOptions({ tools })`. Otherwise each tool's
264
+ `toModelOutput` runs on turn 1 but is dropped when history is re-converted on later turns.
265
+
266
+ - **Not forwarding `signal` for stop.** Without `abortSignal: signal`, Stop updates the UI but the
267
+ model keeps generating server-side.
268
+
269
+ - **Initializing `chat.local` in `onChatStart`.** Initialize it in `onBoot`. `onChatStart` fires
270
+ once per chat, so continuation runs skip it and crash with
271
+ `chat.local can only be modified after initialization`. `onBoot` fires on every fresh worker.
272
+
273
+ - **Minting tokens in the browser.** Never expose the environment secret key client-side. Mint via
274
+ the two server actions; the transport calls them.
275
+
276
+ - **Clearing `lastEventId` on `chat.endRun()`.** Keep the cursor for the Session lifetime; clear it
277
+ only when the Session itself closes. It is sessionId-keyed, so clearing forces a resubscribe from
278
+ `seq_num=0` that can hit the prior turn's stale `turn-complete` and close the stream empty.
279
+
280
+ - **Returning the raw error from `uiMessageStreamOptions.onError`.** It leaks internals (keys,
281
+ stack traces). Return a sanitized string instead.
282
+
283
+ ## References
284
+
285
+ - `trigger-chat-agent-advanced` skill - lifecycle hooks in depth, sessions, raw-task primitives
286
+ (`chat.createSession`, `chat.customAgent`, `chat.stream`), compaction, HITL approvals, recovery.
287
+ - `trigger-realtime-and-frontend` skill - Realtime hooks and frontend streaming beyond the chat transport.
288
+ - `trigger-authoring-tasks` skill - base `task()` semantics, `ctx`, and standard lifecycle hooks.
289
+
290
+ Reference docs ship beside this skill in the same package, read them locally (no network), pinned to your installed version. The `sources:` frontmatter above lists every doc this skill draws from, all under `@trigger.dev/sdk/docs/ai-chat/`. Start with `quick-start.mdx`, `backend.mdx`, `tools.mdx`, `types.mdx`, `frontend.mdx`.
291
+
292
+ A `chat.agent` is a Trigger.dev task, so it builds and deploys like any other. For `trigger.config.ts` and build extensions (Prisma, Playwright, Python, FFmpeg, etc. — e.g. when a tool needs them), read the bundled config docs under `@trigger.dev/sdk/docs/config/` (extensions are in `config/extensions/`, starting with `overview.mdx`).
293
+
294
+ ## Version
295
+
296
+ This skill is bundled inside `@trigger.dev/sdk` and read directly from `node_modules`, so it always matches your installed SDK version (see the adjacent `package.json`). The full documentation for these APIs ships alongside it under `@trigger.dev/sdk/docs/`.