@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,254 @@
1
+ ---
2
+ name: trigger-authoring-tasks
3
+ description: >
4
+ Covers writing backend Trigger.dev tasks with @trigger.dev/sdk: defining task() and
5
+ schemaTask(), the run function and its ctx, retries, waits, queues and concurrency,
6
+ idempotency keys, run metadata, logging, triggering other tasks (and the Result shape),
7
+ scheduled/cron tasks, and the essentials of trigger.config.ts. Load this whenever you are
8
+ authoring or editing code inside a /trigger directory, defining a task, or writing backend
9
+ code that triggers tasks. Realtime/React hooks and AI chat are covered by separate skills.
10
+ type: core
11
+ library: trigger.dev
12
+ sources:
13
+ - docs/tasks/overview.mdx
14
+ - docs/tasks/schemaTask.mdx
15
+ - docs/tasks/scheduled.mdx
16
+ - docs/triggering.mdx
17
+ - docs/queue-concurrency.mdx
18
+ - docs/idempotency.mdx
19
+ - docs/runs/metadata.mdx
20
+ - docs/logging.mdx
21
+ - docs/errors-retrying.mdx
22
+ - docs/wait.mdx
23
+ - docs/wait-for.mdx
24
+ - docs/wait-until.mdx
25
+ - docs/wait-for-token.mdx
26
+ - docs/context.mdx
27
+ - docs/config/config-file.mdx
28
+ ---
29
+
30
+ # Authoring Trigger.dev Tasks
31
+
32
+ Tasks are functions that can run for a long time with strong resilience to failure. Define them in files under your `/trigger` directory. Always import from `@trigger.dev/sdk`. Never import from `@trigger.dev/sdk/v3` (deprecated alias) or `@trigger.dev/core`.
33
+
34
+ ## Setup
35
+
36
+ ```ts
37
+ // /trigger/hello-world.ts
38
+ import { task } from "@trigger.dev/sdk";
39
+
40
+ export const helloWorld = task({
41
+ id: "hello-world", // unique within the project
42
+ run: async (payload: { message: string }, { ctx }) => {
43
+ console.log(payload.message, "attempt", ctx.attempt.number);
44
+ return { ok: true }; // must be JSON serializable
45
+ },
46
+ });
47
+ ```
48
+
49
+ The `run` function receives the payload and a second argument with `ctx` (run context), an abort `signal`, and a deprecated `init` output. The return value is the task output and must be JSON serializable.
50
+
51
+ ## Core patterns
52
+
53
+ ### 1. Validate the payload with `schemaTask`
54
+
55
+ `schema` accepts a Zod / Yup / Superstruct / ArkType / valibot / typebox parser or a custom `(data: unknown) => T` function. A validation failure throws `TaskPayloadParsedError` and skips retrying.
56
+
57
+ ```ts
58
+ import { schemaTask } from "@trigger.dev/sdk";
59
+ import { z } from "zod";
60
+
61
+ export const createUser = schemaTask({
62
+ id: "create-user",
63
+ schema: z.object({ name: z.string(), age: z.number() }),
64
+ run: async (payload) => ({ greeting: `Hi ${payload.name}` }),
65
+ });
66
+ ```
67
+
68
+ ### 2. Configure retries and abort early
69
+
70
+ The default `maxAttempts` is 3. Throw `AbortTaskRunError` to stop retrying immediately. Task-level `retry` overrides the config-file defaults.
71
+
72
+ ```ts
73
+ import { task, AbortTaskRunError } from "@trigger.dev/sdk";
74
+
75
+ export const charge = task({
76
+ id: "charge",
77
+ retry: { maxAttempts: 5, factor: 1.8, minTimeoutInMs: 500, maxTimeoutInMs: 30_000, randomize: true },
78
+ run: async (payload: { amount: number }) => {
79
+ if (payload.amount <= 0) throw new AbortTaskRunError("Invalid amount"); // no retry
80
+ // work that may throw and retry
81
+ },
82
+ });
83
+ ```
84
+
85
+ For finer control, `catchError: async ({ payload, error, ctx, retryAt }) => {...}` can return `{ skipRetrying: true }`, `{ retryAt: Date }`, or `undefined` (use normal logic). `retry.onThrow`, `retry.fetch`, also exist for in-task retrying.
86
+
87
+ ### 3. Trigger another task and handle the Result
88
+
89
+ From inside a task use `yourTask.triggerAndWait(payload)`. The result is a Result object that you must check (`ok`), or `.unwrap()` to throw on failure.
90
+
91
+ ```ts
92
+ export const parentTask = task({
93
+ id: "parent-task",
94
+ run: async () => {
95
+ const result = await childTask.triggerAndWait({ data: "x" });
96
+ if (result.ok) return result.output; // typed child output
97
+ console.error("child failed", result.error);
98
+ // or: const output = await childTask.triggerAndWait({ data: "x" }).unwrap();
99
+ },
100
+ });
101
+ ```
102
+
103
+ `SubtaskUnwrapError` carries `runId`, `taskId`, and `cause`. For fan-out use `childTask.batchTriggerAndWait([{ payload: a }, { payload: b }])`; the result has a `.runs` array, each entry `{ ok, id, output?, error?, taskIdentifier }`.
104
+
105
+ ### 4. Trigger from backend code with a type-only import
106
+
107
+ Outside a task, import the task type only and trigger by id. Do not import the task instance into backend bundles.
108
+
109
+ ```ts
110
+ import { tasks } from "@trigger.dev/sdk";
111
+ import type { emailSequence } from "~/trigger/emails";
112
+
113
+ const handle = await tasks.trigger<typeof emailSequence>(
114
+ "email-sequence",
115
+ { to: "a@b.com", name: "Ada" },
116
+ { delay: "1h" }
117
+ );
118
+ ```
119
+
120
+ `tasks.batchTrigger` and `batch.trigger([{ id, payload }])` cover batches. Trigger options include `delay`, `ttl`, `idempotencyKey`, `idempotencyKeyTTL`, `debounce`, `queue`, `concurrencyKey`, `maxAttempts`, `tags`, `metadata`, `priority`, `region`, and `machine`. Inspect runs with `runs.retrieve`, `runs.cancel`, and `runs.reschedule`.
121
+
122
+ ### 5. Idempotency keys
123
+
124
+ `idempotencyKeys.create(key, { scope })` returns a 64-char hashed key. A raw string key defaults to `"run"` scope (v4.3.1+); for once-ever behavior use `scope: "global"`.
125
+
126
+ ```ts
127
+ import { idempotencyKeys, task } from "@trigger.dev/sdk";
128
+
129
+ export const processOrder = task({
130
+ id: "process-order",
131
+ run: async (payload: { orderId: string; email: string }) => {
132
+ const key = await idempotencyKeys.create(`confirm-${payload.orderId}`);
133
+ await sendEmail.trigger({ to: payload.email }, { idempotencyKey: key });
134
+ },
135
+ });
136
+ ```
137
+
138
+ ### 6. Waits and run metadata
139
+
140
+ `wait.for({ seconds })` and `wait.until({ date })` durably pause the run. `metadata.*` is readable and writable only inside `run()`; updates are synchronous and chainable (`set`, `del`, `replace`, `append`, `remove`, `increment`, `decrement`).
141
+
142
+ ```ts
143
+ import { task, metadata, wait } from "@trigger.dev/sdk";
144
+
145
+ export const importer = task({
146
+ id: "importer",
147
+ run: async (payload: { rows: unknown[] }) => {
148
+ metadata.set("status", "processing").set("total", payload.rows.length);
149
+ await wait.for({ seconds: 5 });
150
+ metadata.set("status", "complete");
151
+ },
152
+ });
153
+ ```
154
+
155
+ For human-in-the-loop, `wait.createToken({ timeout, tags })` returns `{ id, url, publicAccessToken, ... }`; resume with `wait.forToken<T>(token: string | { id: string })` which returns `{ ok, output?, error? }` (or `.unwrap()`), and complete it elsewhere with `wait.completeToken(tokenId, output)`. Metadata max is 256KB and is not propagated to child tasks; push values to a parent with `metadata.parent.*` / `metadata.root.*`. (`metadata.stream` is deprecated since 4.1.0 in favor of `streams.pipe()`.)
156
+
157
+ ### 7. Scheduled (cron) tasks
158
+
159
+ ```ts
160
+ import { schedules } from "@trigger.dev/sdk";
161
+
162
+ export const dailyReport = schedules.task({
163
+ id: "daily-report",
164
+ cron: { pattern: "0 5 * * *", timezone: "Asia/Tokyo" },
165
+ run: async (payload) => {
166
+ console.log("scheduled at", payload.timestamp, "next", payload.upcoming);
167
+ },
168
+ });
169
+ ```
170
+
171
+ The payload includes `timestamp`, `lastTimestamp`, `timezone`, `scheduleId`, `externalId`, and `upcoming`. Attach schedules dynamically with `schedules.create({ task, cron, timezone?, externalId?, deduplicationKey })` (the dedup key is required and per-project), plus `retrieve / list / update / activate / deactivate / del / timezones`.
172
+
173
+ ### 8. Queues and concurrency
174
+
175
+ Set `queue: { concurrencyLimit }` on a task, or share a queue across tasks:
176
+
177
+ ```ts
178
+ import { queue, task } from "@trigger.dev/sdk";
179
+
180
+ export const emails = queue({ name: "emails", concurrencyLimit: 5 });
181
+
182
+ export const sendEmail = task({ id: "send-email", queue: emails, run: async () => {} });
183
+ ```
184
+
185
+ At trigger time override with `{ queue: "queue-name" }` and add `concurrencyKey` for per-tenant queues. Manage queues with `queues.list / retrieve / pause / resume / overrideConcurrencyLimit / resetConcurrencyLimit`.
186
+
187
+ ### 9. `trigger.config.ts` essentials
188
+
189
+ ```ts
190
+ import { defineConfig } from "@trigger.dev/sdk";
191
+
192
+ export default defineConfig({
193
+ project: "<project ref>",
194
+ dirs: ["./trigger"],
195
+ machine: "small-1x",
196
+ retries: {
197
+ enabledInDev: false,
198
+ default: { maxAttempts: 3, factor: 2, minTimeoutInMs: 1000, maxTimeoutInMs: 10000, randomize: true },
199
+ },
200
+ });
201
+ ```
202
+
203
+ `build.external` controls which packages stay out of the bundle. Build extensions (`additionalFiles`, `prismaExtension`, `puppeteer`, `playwright`, `ffmpeg`, `pythonExtension`, `aptGet`, `syncEnvVars`, etc.) come from `@trigger.dev/build`. `telemetry` configures instrumentations and exporters. Each extension has its own setup doc, all bundled under `@trigger.dev/sdk/docs/config/extensions/` (start with `overview.mdx`); read the one you need before wiring it up rather than guessing the API.
204
+
205
+ ### Logging
206
+
207
+ `logger.debug / log / info / warn / error(message, dataRecord?)` write structured logs; `logger.trace(name, async (span) => {...})` adds a span. Module-level metrics use `otel.metrics.getMeter(name)`.
208
+
209
+ ## Common mistakes
210
+
211
+ 1. **CRITICAL: Treating the wait result as the output.** `triggerAndWait` and `wait.forToken` return a Result object, not the raw output.
212
+ - Wrong: `const out = await childTask.triggerAndWait(p); use(out.foo);`
213
+ - Correct: `const r = await childTask.triggerAndWait(p); if (r.ok) use(r.output.foo);` (or `.unwrap()`).
214
+
215
+ 2. **Wrapping `triggerAndWait` / `batchTriggerAndWait` / `wait` in `Promise.all`.**
216
+ - Wrong: `await Promise.all([childTask.triggerAndWait(a), childTask.triggerAndWait(b)]);`
217
+ - Correct: `await childTask.batchTriggerAndWait([{ payload: a }, { payload: b }]);` (or a sequential for-loop).
218
+
219
+ 3. **Importing the task instance into backend code.**
220
+ - Wrong: `import { emailSequence } from "~/trigger/emails";` in a route handler.
221
+ - Correct: `import type { emailSequence }` plus `tasks.trigger<typeof emailSequence>("email-sequence", payload)`.
222
+
223
+ 4. **Calling `metadata.set/get` outside `run()`.**
224
+ - Wrong: setting metadata at module scope or in unrelated backend code (a no-op; `get` returns `undefined`).
225
+ - Correct: call inside `run()` or a task lifecycle hook.
226
+
227
+ 5. **Assuming child tasks inherit the parent's queue or metadata.**
228
+ - Wrong: expecting a subtask to share the parent's `concurrencyLimit` or see its metadata.
229
+ - Correct: subtasks run on their own queue; pass metadata explicitly via `{ metadata: metadata.current() }`, or push up with `metadata.parent.*`.
230
+
231
+ 6. **Bundling native/WASM packages.**
232
+ - Wrong: leaving `sharp`, `re2`, `sqlite3`, or WASM packages in the default bundle.
233
+ - Correct: add them to `build.external` in `trigger.config.ts`.
234
+
235
+ 7. **Relying on a raw string idempotency key being global.**
236
+ - Wrong: `trigger(p, { idempotencyKey: "welcome-email" })` expecting once-ever (true only in v4.3.0 and earlier).
237
+ - Correct: `await idempotencyKeys.create("welcome-email", { scope: "global" })`.
238
+
239
+ ## References
240
+
241
+ Sibling skills:
242
+
243
+ - **trigger-realtime-and-frontend** for subscribing to runs and triggering from the frontend with React hooks.
244
+ - **trigger-authoring-chat-agent** and **trigger-chat-agent-advanced** for building AI chat agents.
245
+
246
+ 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/`. Start with:
247
+
248
+ - `@trigger.dev/sdk/docs/tasks/overview.mdx`
249
+ - `@trigger.dev/sdk/docs/triggering.mdx`
250
+ - `@trigger.dev/sdk/docs/config/config-file.mdx`
251
+
252
+ ## Version
253
+
254
+ 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/`.
@@ -0,0 +1,368 @@
1
+ ---
2
+ name: trigger-chat-agent-advanced
3
+ description: >
4
+ Advanced and operational chat.agent capabilities for Trigger.dev, loaded on demand. Load this when
5
+ working on the raw Sessions primitive (sessions / SessionHandle), a custom chat transport or the
6
+ realtime wire protocol, durable sub-agents (AgentChat, chat.stream.writer), human-in-the-loop,
7
+ steering, actions, background injection (chat.defer / chat.inject), fast starts (preload, Head
8
+ Start via @trigger.dev/sdk/chat-server), context resilience (compaction, recovery boot, OOM, large
9
+ payloads), chat.local run-scoped state, offline testing with mockChatAgent, or prerelease/version
10
+ upgrades. For the everyday chat.agent({...}) definition and the useTriggerChatTransport happy path,
11
+ use the trigger-authoring-chat-agent skill instead.
12
+ type: core
13
+ library: trigger.dev
14
+ sources:
15
+ - docs/ai-chat/sessions.mdx
16
+ - docs/ai-chat/server-chat.mdx
17
+ - docs/ai-chat/client-protocol.mdx
18
+ - docs/ai-chat/pending-messages.mdx
19
+ - docs/ai-chat/actions.mdx
20
+ - docs/ai-chat/background-injection.mdx
21
+ - docs/ai-chat/compaction.mdx
22
+ - docs/ai-chat/fast-starts.mdx
23
+ - docs/ai-chat/chat-local.mdx
24
+ - docs/ai-chat/mcp.mdx
25
+ - docs/ai-chat/testing.mdx
26
+ - docs/ai-chat/upgrade-guide.mdx
27
+ - docs/ai-chat/patterns/sub-agents.mdx
28
+ - docs/ai-chat/patterns/human-in-the-loop.mdx
29
+ - docs/ai-chat/patterns/persistence-and-replay.mdx
30
+ - docs/ai-chat/patterns/recovery-boot.mdx
31
+ - docs/ai-chat/patterns/oom-resilience.mdx
32
+ - docs/ai-chat/patterns/large-payloads.mdx
33
+ - docs/ai-chat/patterns/version-upgrades.mdx
34
+ - docs/ai-chat/tools.mdx
35
+ ---
36
+
37
+ # chat.agent: advanced and operational
38
+
39
+ `chat.agent` is built on **Sessions**: a durable, task-bound, bi-directional I/O channel pair keyed
40
+ on a stable `externalId` (e.g. `chatId`) that outlives any single run. This skill covers the layers
41
+ beneath and around the everyday agent: the raw `sessions` API, server-side `AgentChat`, durable
42
+ sub-agents, actions / background injection, fast starts, compaction and recovery, and the wire
43
+ protocol for custom transports.
44
+
45
+ Two `chat` namespaces are easy to confuse: the agent definition imports `chat` from
46
+ `@trigger.dev/sdk/ai`; Head Start / Node-listener server entries import `chat` from
47
+ `@trigger.dev/sdk/chat-server`.
48
+
49
+ ## Setup
50
+
51
+ Happy path: drive an agent from server-side code (task, webhook, or script) with `AgentChat`.
52
+
53
+ ```ts
54
+ import { AgentChat } from "@trigger.dev/sdk/chat";
55
+ import type { myAgent } from "./trigger/my-agent";
56
+
57
+ const chat = new AgentChat<typeof myAgent>({ agent: "my-chat", clientData: { userId: "user_123" } });
58
+ const stream = await chat.sendMessage("Review PR #42");
59
+ const text = await stream.text();
60
+ await chat.close();
61
+ ```
62
+
63
+ `sendMessage()` triggers a run on the first call, then reuses it via input streams. `ChatStream`
64
+ exposes `text()`, `result()` (`{ text, toolCalls, toolResults }`), `messages()` (UIMessage
65
+ snapshots), and the raw `.stream`. Other methods: `steer(text)`, `stop()`, `sendRaw(uiMessages)`,
66
+ `sendAction(action)`, `preload()`, `reconnect()`.
67
+
68
+ ## Core patterns
69
+
70
+ ### 1. Raw Sessions for non-chat, bi-directional I/O
71
+
72
+ Reach for `sessions` directly when the chat abstraction does not fit: agent inboxes, approval flows,
73
+ server-to-server pipelines. `sessions.start` is idempotent on `(env, externalId)`; `externalId`
74
+ cannot start with `session_`.
75
+
76
+ ```ts
77
+ import { sessions } from "@trigger.dev/sdk";
78
+
79
+ const { id, publicAccessToken } = await sessions.start({
80
+ type: "chat.agent",
81
+ externalId: chatId,
82
+ taskIdentifier: "my-chat",
83
+ triggerConfig: { tags: [`chat:${chatId}`], basePayload: { chatId, trigger: "preload" } },
84
+ });
85
+
86
+ const session = sessions.open(chatId); // no network call; methods are lazy
87
+ await session.out.append({ kind: "message", text: "hello" });
88
+ const next = await session.in.once<MyEvent>({ timeoutMs: 30_000 });
89
+ ```
90
+
91
+ `sessions.open(id).in` also has `send`, `on(handler)`, `peek`, `wait` (suspends the run, only inside
92
+ `task.run()`), and `waitWithIdleTimeout`. `.out` has `append`, `pipe`, `writer`, `read`,
93
+ `writeControl`, and `trimTo`. List with `sessions.list({ type, tag, status, ... })` (`for await`),
94
+ mutate with `sessions.update`, end with `sessions.close` (terminal, idempotent).
95
+
96
+ ### 2. Durable sub-agent as a streaming tool
97
+
98
+ `AgentChat` inside an AI SDK `tool()` delegates to a durable sub-agent; its response streams as
99
+ preliminary tool results. Give the tool a `toModelOutput` so the model sees a compact summary.
100
+
101
+ ```ts
102
+ import { tool } from "ai";
103
+ import { AgentChat } from "@trigger.dev/sdk/chat";
104
+ import { z } from "zod";
105
+
106
+ const researchTool = tool({
107
+ description: "Delegate research to a specialist agent.",
108
+ inputSchema: z.object({ topic: z.string() }),
109
+ execute: async function* ({ topic }, { abortSignal }) {
110
+ const chat = new AgentChat({ agent: "research-agent" });
111
+ const stream = await chat.sendMessage(topic, { abortSignal });
112
+ yield* stream.messages(); // UIMessage snapshots become preliminary tool results
113
+ await chat.close();
114
+ },
115
+ toModelOutput: ({ output: message }) => {
116
+ const lastText = message?.parts?.findLast((p: { type: string }) => p.type === "text") as
117
+ | { text?: string }
118
+ | undefined;
119
+ return { type: "text", value: lastText?.text ?? "Done." };
120
+ },
121
+ });
122
+ ```
123
+
124
+ For a subtask exposed via `execute: ai.toolExecute(task)`, stream progress to the agent's run with
125
+ `chat.stream.writer({ target: "root" })`. `target` accepts `"self" | "parent" | "root" | <runId>`.
126
+ Inside the subtask, read context with `ai.toolCallId()` and `ai.chatContextOrThrow<typeof myChat>()`
127
+ (`{ chatId, turn, continuation, clientData }`).
128
+
129
+ ```ts
130
+ import { chat, ai } from "@trigger.dev/sdk/ai";
131
+
132
+ const { waitUntilComplete } = chat.stream.writer({
133
+ target: "root",
134
+ execute: ({ write }) =>
135
+ write({ type: "data-research-status", id: partId, data: { query, status: "in-progress" } }),
136
+ });
137
+ await waitUntilComplete();
138
+ ```
139
+
140
+ ### 3. Background injection: defer + inject
141
+
142
+ `chat.defer(promise)` runs work in parallel with streaming (all deferred promises are awaited, with a
143
+ 5s timeout, before `onTurnComplete`). `chat.inject(messages)` queues `ModelMessage[]` that drain at
144
+ the next turn start or `prepareStep` boundary.
145
+
146
+ ```ts
147
+ export const myChat = chat.agent({
148
+ id: "my-chat",
149
+ onTurnComplete: async ({ messages }) => {
150
+ chat.defer(
151
+ (async () => {
152
+ const analysis = await analyzeConversation(messages);
153
+ chat.inject([{ role: "system", content: `[Analysis]\n\n${analysis}` }]);
154
+ })()
155
+ );
156
+ },
157
+ run: async ({ messages, signal }) =>
158
+ streamText({ ...chat.toStreamTextOptions({ registry }), messages, abortSignal: signal, stopWhen: stepCountIs(15) }),
159
+ });
160
+ ```
161
+
162
+ ### 4. Compaction (threshold-based)
163
+
164
+ `compaction.shouldCompact` decides when, `summarize` produces the summary that replaces the model
165
+ messages. UI messages are preserved by default (customize via `compactUIMessages`). The `prepareStep`
166
+ that performs inner-loop compaction is auto-injected by `chat.toStreamTextOptions()`; a `prepareStep`
167
+ you pass after the spread wins.
168
+
169
+ ```ts
170
+ compaction: {
171
+ shouldCompact: ({ totalTokens }) => (totalTokens ?? 0) > 80_000,
172
+ summarize: async ({ messages }) =>
173
+ (await generateText({
174
+ model: anthropic("claude-haiku-4-5"),
175
+ messages: [...messages, { role: "user", content: "Summarize concisely." }],
176
+ })).text,
177
+ },
178
+ ```
179
+
180
+ ### 5. Actions: mutate state without a turn
181
+
182
+ `actionSchema` validates; `onAction` mutates via `chat.history` (`slice`, `replace`, `rollbackTo`,
183
+ `remove`, `getPendingToolCalls`, `extractNewToolResults`). Actions fire `hydrateMessages` and
184
+ `onAction` only, never `run()` or the turn hooks. Return a `StreamTextResult`, string, or `UIMessage`
185
+ to also emit a model response.
186
+
187
+ ```ts
188
+ export const myChat = chat.agent({
189
+ id: "my-chat",
190
+ actionSchema: z.discriminatedUnion("type", [
191
+ z.object({ type: z.literal("undo") }),
192
+ z.object({ type: z.literal("rollback"), targetMessageId: z.string() }),
193
+ ]),
194
+ onAction: async ({ action }) => {
195
+ if (action.type === "undo") chat.history.slice(0, -2);
196
+ if (action.type === "rollback") chat.history.rollbackTo(action.targetMessageId);
197
+ },
198
+ run: async ({ messages, signal }) => streamText({ model: anthropic("claude-sonnet-4-5"), messages, abortSignal: signal }),
199
+ });
200
+ ```
201
+
202
+ Send from the browser with `transport.sendAction(chatId, { type: "undo" })`, or server-side with
203
+ `agentChat.sendAction({ type: "rollback", targetMessageId: "msg-3" })`.
204
+
205
+ ### 6. Fast starts: Head Start
206
+
207
+ `chat.headStart` (from `@trigger.dev/sdk/chat-server`, NOT `/ai`) returns a Web Fetch handler that
208
+ serves turn 1 from your own warm process, then hands off to the agent on turn 2+. Tools passed here
209
+ must be **schema-only** (a module importing `ai` + `zod` only); heavy executes stay in the task.
210
+
211
+ ```ts
212
+ import { chat } from "@trigger.dev/sdk/chat-server";
213
+ import { streamText, stepCountIs } from "ai";
214
+ import { anthropic } from "@ai-sdk/anthropic";
215
+ import { headStartTools } from "@/lib/chat-tools/schemas";
216
+
217
+ export const chatHandler = chat.headStart({
218
+ agentId: "my-chat",
219
+ run: async ({ chat: helper }) =>
220
+ streamText({
221
+ ...helper.toStreamTextOptions({ tools: headStartTools }),
222
+ model: anthropic("claude-sonnet-4-6"),
223
+ system: "You are helpful.",
224
+ stopWhen: stepCountIs(15),
225
+ }),
226
+ });
227
+ // Next.js: export const POST = chatHandler; Transport: headStart: "/api/chat"
228
+ ```
229
+
230
+ Node-only frameworks wrap a Web Fetch handler with `chat.toNodeListener(handler)`. Use the **same
231
+ model** on both sides to avoid a tone shift between turn 1 and turn 2+.
232
+
233
+ ### 7. chat.local: init in onBoot, not onChatStart
234
+
235
+ `chat.local<T>({ id })` is module-level, shallow-proxy, run-scoped state. Initialize it in `onBoot`
236
+ (fires on every fresh worker, including continuation runs), never `onChatStart`.
237
+
238
+ ```ts
239
+ const userContext = chat.local<{ name: string; plan: "free" | "pro" }>({ id: "userContext" });
240
+
241
+ export const myChat = chat.agent({
242
+ id: "my-chat",
243
+ onBoot: async ({ clientData }) => userContext.init({ name: "Alice", plan: "pro" }),
244
+ run: async ({ messages, signal }) => streamText({ /* ... */ }),
245
+ });
246
+ ```
247
+
248
+ ### 8. Pending messages (mid-stream user input)
249
+
250
+ A message sent while a turn is streaming should NOT cancel the stream. Configure
251
+ `pendingMessages` (`shouldInject`, `prepare`, `onReceived`, `onInjected`) on the agent so the SDK's
252
+ auto-injected `prepareStep` folds them in at the next boundary. On the frontend, `usePendingMessages`
253
+ returns `pending`, `steer(text)`, `queue(text)`, and `promoteToSteering(id)`; send via
254
+ `transport.sendPendingMessage(chatId, uiMessage, metadata?)`.
255
+
256
+ ### 9. Recovery and version upgrades
257
+
258
+ `onRecoveryBoot` fires only when a **partial assistant message exists on the tail** (interrupted
259
+ deploy, crash, OOM retry). It does NOT fire on `chat.requestUpgrade()`, which is a graceful exit with
260
+ no partial. `chat.requestUpgrade()` (called in `onTurnStart` / `onValidateMessages` to skip `run()`,
261
+ or in `run()` / `chat.defer()` to exit after the turn) rotates the Session's `currentRunId` to a run
262
+ on the latest deployment without a client reconnect. Pair it with a contract version on `clientData`.
263
+
264
+ ```ts
265
+ const SUPPORTED_VERSIONS = new Set(["v2", "v3"]);
266
+ onTurnStart: async ({ clientData }) => {
267
+ if (clientData?.protocolVersion && !SUPPORTED_VERSIONS.has(clientData.protocolVersion)) {
268
+ chat.requestUpgrade();
269
+ }
270
+ },
271
+ ```
272
+
273
+ For OOM resilience, set `oomMachine` (and `machine`) on the agent so retries land on a larger preset.
274
+
275
+ ### 10. Offline testing with mockChatAgent
276
+
277
+ `@trigger.dev/sdk/ai/test` runs the real turn loop in-memory. Import it **before** the agent module
278
+ so the resource catalog is installed. Drive with `sendMessage`, `sendRegenerate`, `sendAction`,
279
+ `sendStop`, `sendHeadStart`, `sendHandover`; seed state with `seedSnapshot` / `seedSessionOutTail` /
280
+ `seedSessionOutPartial` / `seedSessionInTail`; assert against `turn.chunks` and `harness.allChunks`.
281
+
282
+ ```ts
283
+ import { mockChatAgent } from "@trigger.dev/sdk/ai/test"; // BEFORE the agent module
284
+ import { myChatAgent } from "./my-chat.js";
285
+
286
+ const harness = mockChatAgent(myChatAgent, { chatId: "test-1", clientData: { model } });
287
+ try {
288
+ const turn = await harness.sendMessage({ id: "u1", role: "user", parts: [{ type: "text", text: "hi" }] });
289
+ // assert against turn.chunks
290
+ } finally {
291
+ await harness.close();
292
+ }
293
+ ```
294
+
295
+ Options include `mode` (`"preload" | "submit-message" | "handover-prepare" | "continuation"`),
296
+ `preload`, `continuation`, `previousRunId`, `snapshot`, `taskContext`, and `setupLocals`. Set
297
+ `taskContext.ctx.attempt.number > 1` to simulate an OOM-retry attempt. `runInMockTaskContext` drives a
298
+ non-chat task offline.
299
+
300
+ ### 11. Custom transport: the wire protocol
301
+
302
+ Endpoints: `POST /api/v1/sessions` (create), `GET /realtime/v1/sessions/{id}/out` (SSE),
303
+ `POST /realtime/v1/sessions/{id}/in/append`, `POST /api/v1/sessions/{id}/close`. `ChatInputChunk` is
304
+ `{ kind: "message"; payload: ChatTaskWirePayload } | { kind: "stop"; message? }`. The
305
+ `ChatTaskWirePayload` carries `chatId`, `trigger` (`submit-message | regenerate-message | preload |
306
+ close | action | handover-prepare`), `message?`, `metadata?`, `action?`, `continuation?`,
307
+ `previousRunId?`, and more. Control records are header-form: `trigger-control: turn-complete` (with
308
+ optional `public-access-token`, `session-in-event-id`) and `trigger-control: upgrade-required`. The
309
+ TS helpers `SSEStreamSubscription` and `controlSubtype(headers)` (documented in
310
+ `docs/ai-chat/client-protocol.mdx`) handle batch decoding and control-record filtering for you.
311
+
312
+ ## Common mistakes
313
+
314
+ - **CRITICAL: sending a follow-up by re-POSTing `POST /api/v1/sessions`.**
315
+ ```ts
316
+ // Wrong - a cached re-POST silently drops basePayload.message; basePayload is trigger config, not a channel
317
+ await fetch("/api/v1/sessions", { method: "POST", body: JSON.stringify({ ...createBody }) });
318
+ // Correct - append to the session's input channel
319
+ await fetch(`/realtime/v1/sessions/${id}/in/append`, { method: "POST", body: JSON.stringify({ kind: "message", payload }) });
320
+ ```
321
+
322
+ - **Using the wrong token for `.in` / `.out`.** Use `publicAccessToken` from the create response
323
+ body (session-scoped). The `x-trigger-jwt` response header is run-scoped and cannot subscribe.
324
+
325
+ - **Initializing `chat.local` in `onChatStart`.** It is skipped on continuation runs, so `run()`
326
+ crashes with `chat.local can only be modified after initialization`. Init in `onBoot`.
327
+
328
+ - **`chat.defer` for the message-history write.** A mid-stream refresh would read `[]`. `await` that
329
+ write inline before the model streams; reserve `chat.defer` for analytics, audit, cache warming.
330
+
331
+ - **Giving the HITL tool an `execute`.** `streamText` calls it immediately. Leave it execute-less;
332
+ the frontend supplies the answer via `addToolOutput` + `sendAutomaticallyWhen`.
333
+
334
+ - **Declaring sub-agent / heavy tools only on `streamText`.** Also declare them on
335
+ `chat.agent({ tools })` (or pass to `convertToModelMessages(uiMessages, { tools })` in a custom
336
+ agent) so `toModelOutput` re-applies on every turn.
337
+
338
+ - **Importing heavy-execute tools into the Head Start route module.** This is a build-time import
339
+ chain problem; runtime strip helpers do not fix it. Keep schemas in an `ai` + `zod`-only module.
340
+
341
+ - **Returning a megabyte tool output on the stream.** One `tool-output-available` record over ~1 MiB
342
+ throws `ChatChunkTooLargeError`. Persist to your store, write the row first, then emit only an id.
343
+
344
+ - **Setting `X-Peek-Settled: 1` on the active-send path.** It races the new turn's first chunk and
345
+ closes the stream early. Use it only on reconnect-on-reload paths.
346
+
347
+ > Note on docs vocabulary: agent-side examples in some docs still use the legacy
348
+ > `trigger:turn-complete` chunk type. That is the agent-emit vocabulary. A custom **reader** must
349
+ > filter on the `trigger-control` header, not on `chunk.type`.
350
+ >
351
+ > MCP-driven agent chats (`list_agents`, `start_agent_chat`, `send_agent_message`,
352
+ > `close_agent_chat`) are MCP server tools used from Claude Code / Cursor, not importable SDK
353
+ > functions. See `/mcp-tools#agent-chat-tools`.
354
+
355
+ ## References
356
+
357
+ - `trigger-authoring-chat-agent` skill - the everyday `chat.agent({...})` definition, lifecycle hooks, and
358
+ the `useTriggerChatTransport` happy path. Start there before reaching for this skill.
359
+ - `trigger-realtime-and-frontend` skill - Realtime hooks and frontend streaming beyond the chat transport.
360
+ - `trigger-authoring-tasks` skill - base `task()` semantics, `ctx`, and standard lifecycle hooks.
361
+
362
+ 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/` (including `patterns/`). For HITL, sessions, and sub-agents start with `sessions.mdx`, `server-chat.mdx`, `client-protocol.mdx`, `patterns/human-in-the-loop.mdx`, `patterns/sub-agents.mdx`.
363
+
364
+ For `trigger.config.ts` and build extensions a chat-agent task may need (Prisma, Playwright, Python, etc.), read the bundled config docs under `@trigger.dev/sdk/docs/config/` (`config/extensions/` for the per-extension setup).
365
+
366
+ ## Version
367
+
368
+ 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/`.