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

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 (136) hide show
  1. package/dist/commonjs/v3/ai-shared.js +1 -4
  2. package/dist/commonjs/v3/ai-shared.js.map +1 -1
  3. package/dist/commonjs/v3/ai.d.ts +7 -1
  4. package/dist/commonjs/v3/ai.js +110 -44
  5. package/dist/commonjs/v3/ai.js.map +1 -1
  6. package/dist/commonjs/v3/chat-client.js +18 -14
  7. package/dist/commonjs/v3/chat-client.js.map +1 -1
  8. package/dist/commonjs/v3/chat-react.js +1 -3
  9. package/dist/commonjs/v3/chat-react.js.map +1 -1
  10. package/dist/commonjs/v3/chat-server.d.ts +69 -1
  11. package/dist/commonjs/v3/chat-server.js +162 -14
  12. package/dist/commonjs/v3/chat-server.js.map +1 -1
  13. package/dist/commonjs/v3/chat-server.test.js +156 -12
  14. package/dist/commonjs/v3/chat-server.test.js.map +1 -1
  15. package/dist/commonjs/v3/chat.js +4 -3
  16. package/dist/commonjs/v3/chat.js.map +1 -1
  17. package/dist/commonjs/v3/chat.test.js +6 -18
  18. package/dist/commonjs/v3/chat.test.js.map +1 -1
  19. package/dist/commonjs/v3/idempotencyKeys.js.map +1 -1
  20. package/dist/commonjs/v3/prompt.js +2 -6
  21. package/dist/commonjs/v3/prompt.js.map +1 -1
  22. package/dist/commonjs/v3/promptManagement.js.map +1 -1
  23. package/dist/commonjs/v3/retry.js.map +1 -1
  24. package/dist/commonjs/v3/runs.d.ts +1 -1
  25. package/dist/commonjs/v3/sessions.js +1 -0
  26. package/dist/commonjs/v3/sessions.js.map +1 -1
  27. package/dist/commonjs/v3/shared.js.map +1 -1
  28. package/dist/commonjs/v3/skill.js.map +1 -1
  29. package/dist/commonjs/v3/streams.js +2 -3
  30. package/dist/commonjs/v3/streams.js.map +1 -1
  31. package/dist/commonjs/v3/streams.test.js.map +1 -1
  32. package/dist/commonjs/v3/test/mock-chat-agent.js +1 -4
  33. package/dist/commonjs/v3/test/mock-chat-agent.js.map +1 -1
  34. package/dist/commonjs/v3/test/test-session-handle.js.map +1 -1
  35. package/dist/commonjs/v3/triggerClient.test.js +1 -1
  36. package/dist/commonjs/v3/triggerClient.test.js.map +1 -1
  37. package/dist/commonjs/v3/triggerClient.types.test.js +11 -11
  38. package/dist/commonjs/v3/triggerClient.types.test.js.map +1 -1
  39. package/dist/commonjs/version.js +1 -1
  40. package/dist/esm/v3/ai-shared.js +1 -4
  41. package/dist/esm/v3/ai-shared.js.map +1 -1
  42. package/dist/esm/v3/ai.d.ts +7 -1
  43. package/dist/esm/v3/ai.js +110 -44
  44. package/dist/esm/v3/ai.js.map +1 -1
  45. package/dist/esm/v3/chat-client.js +18 -14
  46. package/dist/esm/v3/chat-client.js.map +1 -1
  47. package/dist/esm/v3/chat-react.js +1 -3
  48. package/dist/esm/v3/chat-react.js.map +1 -1
  49. package/dist/esm/v3/chat-server.d.ts +69 -1
  50. package/dist/esm/v3/chat-server.js +162 -14
  51. package/dist/esm/v3/chat-server.js.map +1 -1
  52. package/dist/esm/v3/chat-server.test.js +156 -12
  53. package/dist/esm/v3/chat-server.test.js.map +1 -1
  54. package/dist/esm/v3/chat.js +4 -3
  55. package/dist/esm/v3/chat.js.map +1 -1
  56. package/dist/esm/v3/chat.test.js +6 -18
  57. package/dist/esm/v3/chat.test.js.map +1 -1
  58. package/dist/esm/v3/idempotencyKeys.js +1 -1
  59. package/dist/esm/v3/idempotencyKeys.js.map +1 -1
  60. package/dist/esm/v3/prompt.js +2 -6
  61. package/dist/esm/v3/prompt.js.map +1 -1
  62. package/dist/esm/v3/promptManagement.js.map +1 -1
  63. package/dist/esm/v3/retry.js.map +1 -1
  64. package/dist/esm/v3/sessions.js +1 -0
  65. package/dist/esm/v3/sessions.js.map +1 -1
  66. package/dist/esm/v3/shared.js.map +1 -1
  67. package/dist/esm/v3/skill.js.map +1 -1
  68. package/dist/esm/v3/streams.js +2 -3
  69. package/dist/esm/v3/streams.js.map +1 -1
  70. package/dist/esm/v3/streams.test.js.map +1 -1
  71. package/dist/esm/v3/test/mock-chat-agent.js +4 -7
  72. package/dist/esm/v3/test/mock-chat-agent.js.map +1 -1
  73. package/dist/esm/v3/test/test-session-handle.js.map +1 -1
  74. package/dist/esm/v3/triggerClient.test.js +1 -1
  75. package/dist/esm/v3/triggerClient.test.js.map +1 -1
  76. package/dist/esm/v3/triggerClient.types.test.js +11 -11
  77. package/dist/esm/v3/triggerClient.types.test.js.map +1 -1
  78. package/dist/esm/version.js +1 -1
  79. package/docs/ai/prompts.mdx +0 -4
  80. package/docs/ai-chat/actions.mdx +0 -4
  81. package/docs/ai-chat/anatomy.mdx +0 -4
  82. package/docs/ai-chat/backend.mdx +0 -4
  83. package/docs/ai-chat/background-injection.mdx +0 -4
  84. package/docs/ai-chat/changelog.mdx +109 -1
  85. package/docs/ai-chat/chat-local.mdx +0 -4
  86. package/docs/ai-chat/client-protocol.mdx +0 -4
  87. package/docs/ai-chat/compaction.mdx +0 -4
  88. package/docs/ai-chat/custom-agents.mdx +32 -4
  89. package/docs/ai-chat/error-handling.mdx +0 -4
  90. package/docs/ai-chat/fast-starts.mdx +86 -4
  91. package/docs/ai-chat/frontend.mdx +0 -4
  92. package/docs/ai-chat/how-it-works.mdx +0 -4
  93. package/docs/ai-chat/lifecycle-hooks.mdx +0 -4
  94. package/docs/ai-chat/mcp.mdx +0 -4
  95. package/docs/ai-chat/overview.mdx +0 -4
  96. package/docs/ai-chat/patterns/branching-conversations.mdx +0 -4
  97. package/docs/ai-chat/patterns/code-sandbox.mdx +0 -4
  98. package/docs/ai-chat/patterns/database-persistence.mdx +0 -4
  99. package/docs/ai-chat/patterns/human-in-the-loop.mdx +9 -5
  100. package/docs/ai-chat/patterns/large-payloads.mdx +0 -4
  101. package/docs/ai-chat/patterns/oom-resilience.mdx +0 -4
  102. package/docs/ai-chat/patterns/persistence-and-replay.mdx +0 -4
  103. package/docs/ai-chat/patterns/recovery-boot.mdx +0 -4
  104. package/docs/ai-chat/patterns/skills.mdx +0 -4
  105. package/docs/ai-chat/patterns/sub-agents.mdx +0 -4
  106. package/docs/ai-chat/patterns/tool-result-auditing.mdx +0 -4
  107. package/docs/ai-chat/patterns/trusted-edge-signals.mdx +0 -4
  108. package/docs/ai-chat/patterns/version-upgrades.mdx +0 -4
  109. package/docs/ai-chat/pending-messages.mdx +0 -4
  110. package/docs/ai-chat/prompt-caching.mdx +4 -4
  111. package/docs/ai-chat/quick-start.mdx +0 -4
  112. package/docs/ai-chat/reference.mdx +1 -5
  113. package/docs/ai-chat/server-chat.mdx +0 -4
  114. package/docs/ai-chat/sessions.mdx +0 -4
  115. package/docs/ai-chat/testing.mdx +0 -4
  116. package/docs/ai-chat/tools.mdx +0 -4
  117. package/docs/ai-chat/types.mdx +0 -4
  118. package/docs/ai-chat/upgrade-guide.mdx +0 -4
  119. package/docs/building-with-ai.mdx +1 -1
  120. package/docs/deploy-environment-variables.mdx +1 -1
  121. package/docs/deployment/dev-branches.mdx +92 -0
  122. package/docs/deployment/overview.mdx +1 -1
  123. package/docs/help-slack.mdx +1 -0
  124. package/docs/how-to-reduce-your-spend.mdx +14 -7
  125. package/docs/introduction.mdx +13 -13
  126. package/docs/mcp-agent-rules.mdx +1 -1
  127. package/docs/open-source-self-hosting.mdx +1 -1
  128. package/docs/self-hosting/overview.mdx +2 -1
  129. package/docs/tasks/scheduled.mdx +2 -2
  130. package/docs/troubleshooting-debugging-in-vscode.mdx +1 -0
  131. package/docs/troubleshooting-github-issues.mdx +1 -1
  132. package/docs/troubleshooting-uptime-status.mdx +1 -0
  133. package/docs/video-walkthrough.mdx +1 -1
  134. package/docs/wait-for.mdx +1 -1
  135. package/package.json +2 -2
  136. package/docs/cli-dev.mdx +0 -8
@@ -30,45 +30,45 @@ describe("TriggerClient surface — curated subsets", () => {
30
30
  it("instance.tasks drops inside-task-only and definition-time helpers", () => {
31
31
  expectTypeOf().toEqualTypeOf();
32
32
  // @ts-expect-error — triggerAndWait is not on the instance surface.
33
- client.tasks.triggerAndWait;
33
+ void client.tasks.triggerAndWait;
34
34
  // @ts-expect-error — batchTriggerAndWait is not on the instance surface.
35
- client.tasks.batchTriggerAndWait;
35
+ void client.tasks.batchTriggerAndWait;
36
36
  // @ts-expect-error — triggerAndSubscribe requires a task context; not on the instance surface.
37
- client.tasks.triggerAndSubscribe;
37
+ void client.tasks.triggerAndSubscribe;
38
38
  // @ts-expect-error — hooks like onStart are task-definition-time, not on the client.
39
- client.tasks.onStart;
39
+ void client.tasks.onStart;
40
40
  });
41
41
  it("instance.batch drops the *AndWait variants that depend on the runtime", () => {
42
42
  expectTypeOf().toEqualTypeOf();
43
43
  // @ts-expect-error
44
- client.batch.triggerAndWait;
44
+ void client.batch.triggerAndWait;
45
45
  // @ts-expect-error
46
- client.batch.triggerByTaskAndWait;
46
+ void client.batch.triggerByTaskAndWait;
47
47
  // The module-level export still has them — sanity check we didn't change that.
48
48
  expectTypeOf(batch).toHaveProperty("triggerAndWait");
49
49
  });
50
50
  it("instance.schedules drops `task` definition helper and `timezones` stateless helper", () => {
51
51
  expectTypeOf().toEqualTypeOf();
52
52
  // @ts-expect-error
53
- client.schedules.task;
53
+ void client.schedules.task;
54
54
  // @ts-expect-error
55
- client.schedules.timezones;
55
+ void client.schedules.timezones;
56
56
  // Module-level export still has them.
57
57
  expectTypeOf(schedules).toHaveProperty("task");
58
58
  expectTypeOf(schedules).toHaveProperty("timezones");
59
59
  });
60
60
  it("instance.prompts drops `define`", () => {
61
61
  // @ts-expect-error
62
- client.prompts.define;
62
+ void client.prompts.define;
63
63
  // Module-level export still has it.
64
64
  expectTypeOf(prompts).toHaveProperty("define");
65
65
  });
66
66
  it("instance.auth is the public-token subset only (no configure/withAuth)", () => {
67
67
  expectTypeOf().toEqualTypeOf();
68
68
  // @ts-expect-error — configure is global-only, not on the instance.
69
- client.auth.configure;
69
+ void client.auth.configure;
70
70
  // @ts-expect-error — withAuth is global-only.
71
- client.auth.withAuth;
71
+ void client.auth.withAuth;
72
72
  // Module-level export still has them.
73
73
  expectTypeOf(auth).toHaveProperty("configure");
74
74
  expectTypeOf(auth).toHaveProperty("withAuth");
@@ -1 +1 @@
1
- {"version":3,"file":"triggerClient.types.test.js","sourceRoot":"","sources":["../../../src/v3/triggerClient.types.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"triggerClient.types.test.js","sourceRoot":"","sources":["../../../src/v3/triggerClient.types.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEpD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMnD,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;AAE1D,QAAQ,CAAC,+CAA+C,EAAE,GAAG,EAAE;IAC7D,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAKhE,YAAY,EAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QACvD,YAAY,EAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,sEAAsE;QACtE,2EAA2E;QAC3E,kEAAkE;QAClE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAc,OAAO,CAAC,CAAC;QAC1D,YAAY,CAAC,MAAM,CAAC,CAAC,aAAa,EAAiD,CAAC;QACpF,qFAAqF;QACrF,YAAY,CAAC,MAAM,CAAC,CAAC,aAAa,EAAoB,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,eAAe;QACf,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACvE,sEAAsE;QACtE,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACvD,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAE3E,YAAY,EAAQ,CAAC,aAAa,EAA8B,CAAC;QACjE,oEAAoE;QACpE,KAAK,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC;QACjC,yEAAyE;QACzE,KAAK,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC;QACtC,+FAA+F;QAC/F,KAAK,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC;QACtC,qFAAqF;QACrF,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAE/E,YAAY,EAAQ,CAAC,aAAa,EAA4C,CAAC;QAC/E,mBAAmB;QACnB,KAAK,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC;QACjC,mBAAmB;QACnB,KAAK,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC;QACvC,+EAA+E;QAC/E,YAAY,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oFAAoF,EAAE,GAAG,EAAE;QAE5F,YAAY,EAAQ,CAAC,aAAa,EAE/B,CAAC;QACJ,mBAAmB;QACnB,KAAK,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;QAC3B,mBAAmB;QACnB,KAAK,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;QAChC,sCAAsC;QACtC,YAAY,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC/C,YAAY,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,mBAAmB;QACnB,KAAK,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAC3B,oCAAoC;QACpC,YAAY,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAE/E,YAAY,EAAQ,CAAC,aAAa,EAE/B,CAAC;QACJ,oEAAoE;QACpE,KAAK,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QAC3B,8CAA8C;QAC9C,KAAK,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC1B,sCAAsC;QACtC,YAAY,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC/C,YAAY,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+DAA+D,EAAE,GAAG,EAAE;IAC7E,yEAAyE;IACzE,6EAA6E;IAC7E,eAAe;IACf,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAe,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,aAAa,EAAkB,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +1,2 @@
1
- export const VERSION = "4.5.0-rc.7";
1
+ export const VERSION = "4.5.0";
2
2
  //# sourceMappingURL=version.js.map
@@ -4,10 +4,6 @@ sidebarTitle: "Prompts"
4
4
  description: "Define prompt templates as code, version them on deploy, and override from the dashboard without redeploying."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  ## Overview
12
8
 
13
9
  AI Prompts let you define prompt templates in your codebase alongside your tasks. When you deploy, Trigger.dev automatically versions your prompts. You can then:
@@ -4,10 +4,6 @@ sidebarTitle: "Actions"
4
4
  description: "Custom commands sent from the frontend that mutate chat state without consuming a turn — undo, rollback, edit, regenerate."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  ## Overview
12
8
 
13
9
  Custom actions let the frontend send structured commands (undo, rollback, edit, regenerate) that modify the conversation state. **Actions are not turns**: they fire `hydrateMessages` (if set) and `onAction` only. No turn lifecycle hooks (`onTurnStart` / `prepareMessages` / `onBeforeTurnComplete` / `onTurnComplete`), no `run()`, no turn-counter increment. The trace span is named `chat action`.
@@ -4,10 +4,6 @@ sidebarTitle: "Anatomy"
4
4
  description: "The moving parts of a chat agent — the agent task, the session, the frontend transport — and which page covers each."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  **A chat agent is three parts: a long-lived agent task that runs the turn loop, a durable Session carrying messages in and the response stream out, and a frontend transport that plugs the session into `useChat`.** The pages in this section each own one part of that picture. This page is the map — if you'd rather read mechanics end to end, skip to [How it works](/ai-chat/how-it-works).
12
8
 
13
9
  ```mermaid
@@ -4,10 +4,6 @@ sidebarTitle: "Backend"
4
4
  description: "Three approaches to building your chat backend — chat.agent(), session iterator, or raw task primitives."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  There are three abstraction levels for a chat backend. All three speak the same wire protocol, so the [frontend transport](/ai-chat/frontend) works unchanged whichever you pick.
12
8
 
13
9
  | Capability | `chat.agent()` | `chat.createSession()` | Raw primitives |
@@ -4,10 +4,6 @@ sidebarTitle: "Background injection"
4
4
  description: "Inject context from background work into the agent's conversation — self-review, RAG augmentation, or any async analysis."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  ## Overview
12
8
 
13
9
  `chat.inject()` queues model messages for injection into the conversation. Messages are picked up at the start of the next turn or at the next `prepareStep` boundary (between tool-call steps).
@@ -1,9 +1,117 @@
1
1
  ---
2
2
  title: "Changelog"
3
3
  sidebarTitle: "Changelog"
4
- description: "Pre-release updates for AI chat agents."
4
+ description: "Changelog for the AI Agents SDK."
5
5
  ---
6
6
 
7
+ <Update label="July 2, 2026" description="4.5.0" tags={["SDK", "Bug fix"]}>
8
+
9
+ ## Point chat sessions at a different project or environment
10
+
11
+ [`chat.headStart`](/ai-chat/fast-starts#head-start) and [`chat.createStartSessionAction`](/ai-chat/sessions) now take an `apiClient` option (`baseURL` + `accessToken`). The server that creates the session and triggers the run can target a different project or environment than its ambient Trigger config, without setting a global `TRIGGER_SECRET_KEY`. Useful when your `chat.agent` lives in a separate project from the app serving the route, or when one server starts chats across more than one environment. Your LLM provider keys stay in the `run` callback and are unaffected. ([#4018](https://github.com/triggerdotdev/trigger.dev/pull/4018))
12
+
13
+ ```ts
14
+ export const POST = chat.headStart({
15
+ agentId: "my-agent",
16
+ apiClient: { baseURL, accessToken },
17
+ run: async ({ chat }) =>
18
+ streamText({ ...chat.toStreamTextOptions({ tools }), model: anthropic("claude-sonnet-4-6") }),
19
+ });
20
+ ```
21
+
22
+ ```ts
23
+ const startSession = chat.createStartSessionAction("my-chat", {
24
+ apiClient: { baseURL, accessToken },
25
+ });
26
+
27
+ await startSession({ chatId, clientData });
28
+ ```
29
+
30
+ ## Fix: chat agents on preview branches
31
+
32
+ Messaging a `chat.agent` (or `AgentChat`) deployed to a preview branch failed with `x-trigger-branch header required for preview env`. The realtime message-append and stream-subscribe calls now send the `x-trigger-branch` header, resolved the same way `sessions.start` resolves it, so preview-branch chat agents work. ([#4018](https://github.com/triggerdotdev/trigger.dev/pull/4018))
33
+
34
+ ## Fix: Head Start handovers with a prepareMessages hook
35
+
36
+ A [Head Start](/ai-chat/fast-starts#head-start) handover passes the first turn's pending tool call to the agent as a tool-approval round whose trailing tool message must reach the model untouched. A `prepareMessages` hook that rewrites the last message (for example the recommended [prompt-caching](/ai-chat/prompt-caching) breakpoint) could disturb that tail, so the turn failed with `tool_use ids were found without tool_result`. The agent now preserves the approval tail across `prepareMessages`, so prompt caching and Head Start compose cleanly. ([#4018](https://github.com/triggerdotdev/trigger.dev/pull/4018))
37
+
38
+ </Update>
39
+
40
+ <Update label="June 17, 2026" description="4.5.0-rc.7" tags={["SDK", "CLI", "Bug fix"]}>
41
+
42
+ ## chat.headStart now works for custom agents and sessions
43
+
44
+ [Head Start](/ai-chat/fast-starts#head-start) — running the first `streamText` step in your warm server while the agent boots in parallel — now works with the `chat.customAgent` and `chat.createSession` backends, not just the managed `chat.agent`. The warm step-1 response hands over to your loop the same way it does for a managed agent. ([#3963](https://github.com/triggerdotdev/trigger.dev/pull/3963))
45
+
46
+ In a `chat.customAgent` loop, consume the handover on turn 0:
47
+
48
+ ```ts
49
+ const conversation = new chat.MessageAccumulator();
50
+ const { isFinal, skipped } = await conversation.consumeHandover({ payload });
51
+ if (skipped) return; // warm handler aborted, so exit without a turn
52
+ if (isFinal) {
53
+ await chat.writeTurnComplete(); // step 1 is the response, no streamText
54
+ } else {
55
+ const result = streamText({ model, messages: conversation.modelMessages, tools });
56
+ // Pass originalMessages so the handed-over tool round merges into the
57
+ // step-1 assistant instead of starting a new message.
58
+ const response = await chat.pipeAndCapture(result, {
59
+ originalMessages: conversation.uiMessages,
60
+ });
61
+ if (response) await conversation.addResponse(response);
62
+ }
63
+ ```
64
+
65
+ With `chat.createSession`, the iterator surfaces it as `turn.handover`; call `turn.complete()` with no argument on a final handover. The lower-level `chat.waitForHandover()` and `accumulator.applyHandover()` are also exported for hand-rolled loops. See [Handover with custom agents](/ai-chat/fast-starts#handover-with-custom-agents).
66
+
67
+ ## Cache your system prompt with Anthropic prompt caching
68
+
69
+ `chat.toStreamTextOptions()` can now emit the system prompt as a cacheable message when you opt in, so a large, stable system block is billed at cache-read rates on every turn instead of full price. Without an option, `system` stays a plain string. ([#3952](https://github.com/triggerdotdev/trigger.dev/pull/3952))
70
+
71
+ ```ts
72
+ // at the streamText call site (Anthropic sugar)
73
+ streamText({
74
+ ...chat.toStreamTextOptions({ cacheControl: { type: "ephemeral" } }),
75
+ messages,
76
+ });
77
+
78
+ // provider-agnostic equivalent
79
+ chat.toStreamTextOptions({
80
+ systemProviderOptions: { anthropic: { cacheControl: { type: "ephemeral" } } },
81
+ });
82
+
83
+ // or where the prompt is defined
84
+ chat.prompt.set(SYSTEM_PROMPT, {
85
+ providerOptions: { anthropic: { cacheControl: { type: "ephemeral" } } },
86
+ });
87
+ ```
88
+
89
+ Pairs with a `prepareMessages` cache breakpoint to cache the conversation prefix across turns too. See the [Prompt caching](/ai-chat/prompt-caching) guide.
90
+
91
+ ## Custom agent loop fixes
92
+
93
+ Three fixes for custom agent loops (`chat.customAgent`, `chat.createSession`, and hand-rolled `MessageAccumulator` loops): ([#3936](https://github.com/triggerdotdev/trigger.dev/pull/3936))
94
+
95
+ - **Continuations no longer replay answered messages.** The `.in` resume cursor is now seeded before any listener attaches (the same boot logic `chat.agent` uses), so a chat that continues after a cancel, crash, or upgrade only sees genuinely new messages.
96
+ - **Steering mid-stream keeps the in-flight response.** `chat.pipeAndCapture` now stamps a server-generated message id on the stream, so a `prepareStep` injection keeps the partial text instead of replacing the message.
97
+ - **Task-backed tools work from custom loops.** `ai.toolExecute` now threads the parent's session to the child run, so child tasks can stream progress into the chat with `chat.stream.writer({ target: "root" })` instead of failing with "session handle is not initialized".
98
+
99
+ See [Custom agents](/ai-chat/custom-agents).
100
+
101
+ ## trigger skills: namespacing, docs bundling, and a cost-savings skill
102
+
103
+ Follow-ups to the [`trigger skills`](/ai-chat/patterns/skills) command shipped in rc.6:
104
+
105
+ - The skills installed into your coding assistant are now namespaced with a `trigger-` prefix (e.g. `trigger-authoring-tasks`, `trigger-getting-started`) so they don't collide with unrelated skills in your skills directory. ([#3970](https://github.com/triggerdotdev/trigger.dev/pull/3970))
106
+ - `@trigger.dev/sdk` now bundles the Trigger.dev agent skills and the full Trigger.dev documentation those skills reference. The installed skills read this content from `node_modules`, so the guidance your AI assistant follows is pinned to the SDK version in your project and stays current across upgrades instead of going stale until the next reinstall. ([#3937](https://github.com/triggerdotdev/trigger.dev/pull/3937), [#3970](https://github.com/triggerdotdev/trigger.dev/pull/3970))
107
+ - New `trigger-cost-savings` skill for auditing and reducing compute spend — right-sizing machines, `maxDuration`, batching, and debounce. ([#3970](https://github.com/triggerdotdev/trigger.dev/pull/3970))
108
+
109
+ ```bash
110
+ npx trigger.dev@4.5.0-rc.7 skills
111
+ ```
112
+
113
+ </Update>
114
+
7
115
  <Update label="June 12, 2026" description="4.5.0-rc.6" tags={["SDK", "CLI", "Bug fix"]}>
8
116
 
9
117
  ## chat.agent reliability fixes
@@ -4,10 +4,6 @@ sidebarTitle: "chat.local"
4
4
  description: "Typed, run-scoped data accessible from hooks, run(), tools, and subtasks. Survives across turns, auto-cleared between runs, auto-hydrated into subtasks."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  Use `chat.local` to create typed, run-scoped data that persists across turns and is accessible from anywhere — the run function, tools, nested helpers. Each run gets its own isolated copy, and locals are automatically cleared between runs.
12
8
 
13
9
  Lifecycle hooks and **`run`** also receive **`ctx`** ([`TaskRunContext`](/ai-chat/reference#task-context-ctx)) — the same object as on a standard `task()` — for tags, metadata, and cleanup that needs the full run record.
@@ -4,10 +4,6 @@ sidebarTitle: "Client Protocol"
4
4
  description: "The wire protocol for building custom chat transports — how clients communicate with chat agents over Sessions and SSE."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  This page documents the protocol that chat clients use to communicate with `chat.agent()` tasks. Use this if you're building a custom transport (e.g., for a Slack bot, CLI tool, or native app) instead of using the built-in `TriggerChatTransport` or `AgentChat`.
12
8
 
13
9
  <Note>
@@ -4,10 +4,6 @@ sidebarTitle: "Compaction"
4
4
  description: "Automatic context compaction to keep long conversations within token limits."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  ## Overview
12
8
 
13
9
  Long conversations accumulate tokens across turns. Eventually the context window fills up, causing errors or degraded responses. Compaction solves this by automatically summarizing the conversation when token usage exceeds a threshold, then using that summary as the context for future turns.
@@ -4,10 +4,6 @@ sidebarTitle: "Custom agents"
4
4
  description: "Build chat agents without chat.agent()'s managed lifecycle: register with chat.customAgent(), then drive turns with the createSession iterator or a hand-rolled loop."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  **A custom agent is a task you register with `chat.customAgent()` and drive yourself — either with the managed turn iterator from `chat.createSession()`, or with a fully hand-rolled loop over the raw chat primitives.** You give up `chat.agent()`'s lifecycle hooks and automatic continuation recovery; you gain inline control over every turn, and (at the lowest level) full control over the stream conversion.
12
8
 
13
9
  See the [comparison table](/ai-chat/backend) before dropping down. The frontend is unchanged either way: all levels speak the same wire protocol, so [`useTriggerChatTransport`](/ai-chat/frontend) points at a custom agent exactly like a `chat.agent()`.
@@ -179,6 +175,38 @@ for await (const turn of session) {
179
175
  }
180
176
  ```
181
177
 
178
+ ## Stopping generation
179
+
180
+ The frontend stops a turn with [`transport.stopGeneration(chatId)`](/ai-chat/frontend#stop-generation), which writes a stop signal to the session's input stream. It aborts the current turn's generation but keeps the run alive, so the next message continues on the same session.
181
+
182
+ `turn.signal` is a combined stop-and-cancel `AbortSignal`, fresh each turn. Pass it to `streamText` so the stop reaches the model, then let `turn.complete()` finish the turn:
183
+
184
+ ```ts trigger/my-chat.ts
185
+ for await (const turn of session) {
186
+ const result = streamText({
187
+ model: anthropic("claude-sonnet-4-5"),
188
+ messages: turn.messages,
189
+ abortSignal: turn.signal, // fires on a user stop OR a run cancel
190
+ stopWhen: stepCountIs(15),
191
+ });
192
+
193
+ await turn.complete(result);
194
+
195
+ if (turn.stopped) {
196
+ // user stopped this turn — the partial response is already accumulated
197
+ }
198
+ }
199
+ ```
200
+
201
+ On a stop, `turn.complete()` cleans up the aborted parts of the partial response, accumulates it as its own assistant message, and writes turn-complete. The run does not end — the loop continues to the next turn.
202
+
203
+ Read `turn.stopped` to tell a user stop from a full run cancel:
204
+
205
+ - **User stop** (`transport.stopGeneration`): `turn.signal` aborts, `turn.stopped` is `true`, the partial response is accumulated, and the run stays alive for the next message.
206
+ - **Run cancel** (cancelled, expired, or `maxDuration` exceeded): `turn.signal` aborts, `turn.stopped` is `false`, and `turn.complete()` returns without accumulating because the run is ending.
207
+
208
+ A hand-rolled loop wires this itself with `chat.createStopSignal()` and `chat.cleanupAbortedParts()`. Two things `createSession` handles for you are easy to get wrong there — see the [hand-rolled loop checklist](#hand-rolled-loop-checklist).
209
+
182
210
  ## Hand-rolled loop with primitives
183
211
 
184
212
  For full control, skip `createSession` and compose the primitives directly:
@@ -4,10 +4,6 @@ sidebarTitle: "Error handling"
4
4
  description: "How errors flow through chat.agent — stream errors, hook errors, run failures — and how to recover."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  `chat.agent` errors fall into four layers, each with different recovery semantics. The default behavior is **conversation-preserving**: a thrown error in a hook or `run()` does not kill the chat. The current turn ends with an error chunk, and the agent waits for the user's next message.
12
8
 
13
9
  ## Error layers at a glance
@@ -4,10 +4,6 @@ sidebarTitle: "Fast starts"
4
4
  description: "Two ways to cut first-turn TTFC: Preload eagerly triggers the run before the first message; Head Start runs step 1 in your warm server while the agent boots in parallel."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  The first turn of a brand-new conversation pays for the chat.agent run's cold start: dequeue, process boot, `onPreload` / `onChatStart` hooks, and only then the LLM call. Two features address this from different angles.
12
8
 
13
9
  ## Picking an approach
@@ -112,6 +108,8 @@ Head Start runs step 1's LLM call in your warm server process while the agent ru
112
108
 
113
109
  `chat.headStart` returns a standard [Web Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) handler — `(req: Request) => Promise<Response>` — so it slots into any runtime that speaks Web Fetch.
114
110
 
111
+ Drive it one of two ways: wire the handler into the transport's [`headStart` option](#the-transport-option) so the browser's first message POSTs to it (the setup below), or call [`chat.startHeadStart`](#detached-head-start) from a backend that creates the chat and triggers the run in one request, then resumes on a separate page.
112
+
115
113
  **Verified runtimes:** Node 18+, Bun, Deno, Cloudflare Workers, Vercel (Node and Edge), Netlify (Functions and Edge). The handler uses only `fetch` and Web `ReadableStream` / `TransformStream` (no `node:*` imports), and the S2 streaming dependency picks the right transport for each runtime automatically (HTTP/2 on Node/Deno, HTTP/1.1 on Bun/Workers/browsers).
116
114
 
117
115
  **Compatible frameworks (native Web Fetch):** Next.js App Router, Hono, SvelteKit, Remix, React Router v7, TanStack Start, Astro, Nitro/Nuxt, Elysia. Mount the handler directly.
@@ -545,6 +543,10 @@ Head Start composes with [`hydrateMessages`](/ai-chat/lifecycle-hooks#hydratemes
545
543
 
546
544
  Your hydrate hook shapes **model context**, not the transcript — dropping reasoning-only entries or unresolved tool rows from the returned chain is fine and does not affect what `onTurnComplete` persists or what the UI renders.
547
545
 
546
+ #### With `prepareMessages`
547
+
548
+ When the first turn's handover carries a pending tool call, the runtime reshapes it into a tool-approval round: the partial assistant gets a `tool-approval-request` and the chain ends with a `tool` message holding the matching `tool-approval-response`. The agent's `streamText` reads that trailing row to execute the handed-over call before step 2. `chat.agent` keeps that tail intact across your [`prepareMessages`](/ai-chat/reference#chatagentoptions) hook, so the common [prompt-caching](/ai-chat/prompt-caching) pattern of rolling a cache breakpoint onto the last message is safe on a resume turn (the breakpoint lands on the next user or assistant message instead). If you hand-roll a backend with [`chat.customAgent`](#chatcustomagent) or [`chat.createSession`](#chatcreatesession), preserve that trailing approval row yourself.
549
+
548
550
  ### Handover with custom agents
549
551
 
550
552
  The route handler is backend-agnostic: `agentId` can point at a `chat.agent`, a [`chat.customAgent`](/ai-chat/custom-agents), or a [`chat.createSession`](/ai-chat/custom-agents#managed-loop-chatcreatesession) loop. With `chat.agent` the handover is consumed for you (the steps above). The two hand-rolled backends consume it explicitly on turn 0.
@@ -655,6 +657,86 @@ Optional. When set, the FIRST message of a brand-new chat (no existing session s
655
657
 
656
658
  This is **not** a stock `useChat` `endpoint` — it's not the canonical request URL for every turn, just the first-turn shortcut.
657
659
 
660
+ ### Detached head start
661
+
662
+ `chat.startHeadStart` runs the same head start as the [`chat.headStart` handler above](#setup); the difference is how step 1 reaches the browser. `chat.headStart` streams step 1 back over the live connection the browser opens when it sends the first message. `chat.startHeadStart` has no open browser connection to stream to, so it drains step 1 into the durable session stream and the browser **resumes** it when the chat page loads.
663
+
664
+ Use it when there's no open connection at first-turn time, because the first message is captured outside the chat UI and the conversation renders on a separate page. A typical flow: a "new chat" form posts the prompt to your backend, which creates the chat row, starts the run with `chat.startHeadStart`, and returns a `chatId`; the browser then navigates to `/chats/{chatId}` and resumes. You still get the first-turn TTFC win; the browser picks step 1 up on resume instead of live.
665
+
666
+ **1. Start the head start in your create endpoint.** Call `chat.startHeadStart`, keep `completion` alive past the response (`waitUntil` / Next.js `after`), and return the `chatId`.
667
+
668
+ ```ts app/api/chat/create/route.ts (your backend)
669
+ import { chat } from "@trigger.dev/sdk/chat-server";
670
+ import { streamText } from "ai";
671
+ import { anthropic } from "@ai-sdk/anthropic";
672
+ import { after } from "next/server";
673
+ // Schema-only tools; same bundle-isolation rule as chat.headStart.
674
+ import { headStartTools } from "@/lib/chat-tools/schemas";
675
+
676
+ export async function POST(req: Request) {
677
+ const { chatId, messages } = await req.json();
678
+ // Persist your own chat row + the first user message here.
679
+
680
+ const { completion } = await chat.startHeadStart({
681
+ agentId: "my-chat",
682
+ chatId, // session externalId; reuse it on the destination page
683
+ messages, // first-turn user history
684
+ run: async ({ chat: helper }) =>
685
+ streamText({
686
+ ...helper.toStreamTextOptions({ tools: headStartTools }),
687
+ model: anthropic("claude-sonnet-4-6"),
688
+ system: "You are a helpful assistant.",
689
+ }),
690
+ });
691
+
692
+ // Keep the function warm until step 1 drains and the handover dispatches.
693
+ after(completion);
694
+
695
+ return Response.json({ chatId });
696
+ }
697
+ ```
698
+
699
+ **2. Resume the chat on the destination page.** Set no `headStart` and no `startSession`: the run is already in flight, so the transport resumes `session.out` and replays step 1 (warm) then step 2+ (agent) under one assistant message.
700
+
701
+ ```tsx app/chats/[chatId]/page.tsx
702
+ import { useTriggerChatTransport } from "@trigger.dev/sdk/chat/react";
703
+ import { useChat } from "@ai-sdk/react";
704
+
705
+ const transport = useTriggerChatTransport({
706
+ task: "my-chat",
707
+ accessToken: ({ chatId }) => mintChatAccessToken(chatId),
708
+ });
709
+
710
+ const { messages } = useChat({ id: chatId, transport, resume: true });
711
+ ```
712
+
713
+ <Warning>
714
+ `completion` must run to completion, or step 1 never finishes draining and the turn stalls. On serverless, hand it to the platform's run-after-response primitive (`waitUntil`, Next.js `after`). On a long-lived server you can ignore it; it runs in the background.
715
+ </Warning>
716
+
717
+ <Warning>
718
+ If you hydrate the transport's session state yourself (the `sessions` option, e.g. so the same page can also resume already-stored chats from your session store), a head-started session is still mid-turn, so mark it `isStreaming: true`. A session hydrated as not streaming is treated as settled: the transport skips reconnecting to `session.out`, so the browser never sees the turn even though the run completed. The minimal example above sidesteps this by not hydrating a session at all (`resume: true` alone reconnects).
719
+ </Warning>
720
+
721
+ The `run` callback and bundle-isolation rule are the same as `chat.headStart`. Pass `metadata` to attach auth tokens or context to the run; it never reaches the browser. The cost over the transport-routed handler is one extra round trip: the create request, then the resume.
722
+
723
+ #### The `chat.startHeadStart` API
724
+
725
+ ```ts
726
+ chat.startHeadStart<TTools>({
727
+ agentId: string, // chat.agent / chat.customAgent / chat.createSession id
728
+ chatId: string, // session externalId; reuse on the destination page
729
+ messages: UIMessage[], // first-turn user history
730
+ run: (args: HeadStartRunArgs<TTools>) => Promise<StreamTextResult<any, any>>,
731
+ idleTimeoutInSeconds?: number, // how long the agent waits for the handover signal. Default: 60
732
+ triggerConfig?: Partial<SessionTriggerConfig>, // tags, queue, machine, …
733
+ apiClient?: ApiClientConfiguration, // when the agent lives in another project/env
734
+ metadata?: Record<string, unknown>, // merged into the run payload; never sent to the browser
735
+ }): Promise<{ chatId: string; completion: Promise<void> }>
736
+ ```
737
+
738
+ `completion` resolves once the head start finishes; `await` it or hand it to `waitUntil`. It rejects if the warm step or the dispatch fails.
739
+
658
740
  ### Limitations
659
741
 
660
742
  - **First turn only.** Step 2+ and turn 2+ run on the trigger side. There's no per-turn "head start every turn" mode — the win comes from amortizing agent boot across the LLM call once.
@@ -4,10 +4,6 @@ sidebarTitle: "Frontend"
4
4
  description: "Transport setup, session management, client data, and frontend patterns for AI Chat."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  ## How the transport works
12
8
 
13
9
  Vanilla `useChat` expects an `api` URL — it POSTs the conversation to your own Next.js route handler, which terminates the stream. `useTriggerChatTransport` replaces that round-trip: instead of an `api` URL, you pass a custom [`ChatTransport`](https://ai-sdk.dev/docs/ai-sdk-ui/transport) that talks directly to the Trigger.dev cloud (or your self-hosted webapp) on behalf of `useChat`.
@@ -4,10 +4,6 @@ sidebarTitle: "How it works"
4
4
  description: "End-to-end mechanics of a chat.agent turn: the two durable channels per session, the long-lived task that reads and writes them, and how a chat survives refreshes, deploys, and idle gaps."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  This page explains how `chat.agent` is put together, what each piece does on a single turn, and how a chat survives across turns. It is not an API tour — for that, see [Backend](/ai-chat/backend), [Frontend](/ai-chat/frontend), and the [Reference](/ai-chat/reference). For the byte-level wire format, see [Client Protocol](/ai-chat/client-protocol).
12
8
 
13
9
  <Note>
@@ -4,10 +4,6 @@ sidebarTitle: "Lifecycle hooks"
4
4
  description: "Hook into every stage of a chat agent's run: preload, turn start, turn complete, suspend, resume, and more."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  `chat.agent({ ... })` accepts a set of lifecycle hooks for persisting state, validating input, transforming messages, and reacting to suspension and resumption. They fire at well-defined points in the chat agent's lifetime.
12
8
 
13
9
  **Once per worker process (every fresh run boot):** `onBoot` → `onPreload` (preloaded runs only).
@@ -4,10 +4,6 @@ sidebarTitle: "MCP Server"
4
4
  description: "Chat with your agents from any AI coding tool using the Trigger.dev MCP server."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  The Trigger.dev MCP server includes tools for having conversations with your chat agents directly from AI coding tools like Claude Code, Cursor, Windsurf, and others. This lets your AI assistant interact with your agents without writing any code.
12
8
 
13
9
  ## Available tools
@@ -4,10 +4,6 @@ sidebarTitle: "Overview"
4
4
  description: "Durable multi-turn AI chats — one Trigger.dev task per conversation, surviving refreshes, deploys, and crashes."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  An AI chat isn't a request — it's a session. `chat.agent` runs every conversation as a single long-lived Trigger.dev task: you write the loop, it wakes up when a message arrives, freezes when none do, and the same in-memory state and on-disk workspace survive across page refreshes, deploys, idle gaps, and crashes. The substrate handles the parts most teams stitch together by hand — turn lifecycle, mid-stream resume, recovery from cancel/crash/OOM, HITL approvals, deploy upgrades — so your code is the loop you'd write anyway: messages in, `streamText` out.
12
8
 
13
9
  ## A minimal example
@@ -4,10 +4,6 @@ sidebarTitle: "Branching conversations"
4
4
  description: "Build ChatGPT-style conversation trees with edit, regenerate, undo, and branch switching using hydrateMessages, chat.history, and actions."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  Most chat UIs treat conversations as linear sequences. But real conversations branch — users edit previous messages, regenerate responses, undo exchanges, and explore alternative paths. This pattern shows how to build a branching conversation system using `hydrateMessages`, `chat.history`, and custom actions.
12
8
 
13
9
  ## Data model
@@ -4,10 +4,6 @@ sidebarTitle: "Code sandbox"
4
4
  description: "Warm an isolated sandbox on each chat turn, run an AI SDK executeCode tool, and tear down right before the run suspends — using chat.agent hooks and chat.local."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  Use a **hosted code sandbox** (for example [E2B](https://e2b.dev)) when the model should run short scripts to analyze tool output (PostHog queries, CSV-like data, math) without executing arbitrary code on the Trigger worker host.
12
8
 
13
9
  This page describes a **durable chat** pattern that fits `chat.agent()`:
@@ -4,10 +4,6 @@ sidebarTitle: "Database persistence"
4
4
  description: "Split conversation state and live session metadata across hooks — preload, turn start, turn complete — without tying the pattern to a specific ORM or schema."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  Durable chat runs can span **hours** and **many turns**. You usually want:
12
8
 
13
9
  1. **Conversation state** — full **`UIMessage[]`** (or equivalent) keyed by **`chatId`**, so reloads and history views work.
@@ -4,10 +4,6 @@ sidebarTitle: "Human-in-the-loop"
4
4
  description: "Pause the agent mid-response to ask the user a clarifying question, then resume with their answer."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  Some turns need to stop and ask the user something before they can finish — picking between options, confirming a destructive action, or clarifying an ambiguous request. The AI SDK calls this **human-in-the-loop** (HITL), and the building block is a tool with no `execute` function.
12
8
 
13
9
  When the LLM calls a tool that has no `execute`, `streamText` ends with the tool call still pending. The turn completes cleanly, the frontend renders UI to collect the answer, and when the user responds, a new turn resumes with the answer merged into the same assistant message.
@@ -20,7 +16,7 @@ Turn N:
20
16
  LLM streams text → calls askUser tool (no execute)
21
17
  streamText ends with tool-call in `input-available` state
22
18
  onTurnComplete fires (finishReason = "tool-calls")
23
- Agent idle
19
+ Agent suspends (compute freed) — maxDuration does not tick while paused
24
20
 
25
21
  Frontend:
26
22
  Renders question + option buttons from tool input
@@ -36,6 +32,14 @@ Turn N+1:
36
32
 
37
33
  The AI SDK's `toUIMessageStream` automatically reuses the assistant message ID across the pause (we pass `originalMessages` internally), so `responseMessage` in the post-resume `onTurnComplete` is the **full merged message** — the original text, the completed tool call, and any follow-up content — not just the new parts.
38
34
 
35
+ ## Duration and cost while paused
36
+
37
+ A pause doesn't hold compute. After the model calls a no-execute tool, the turn finishes and the run stays warm for `idleTimeoutInSeconds` (default 30s), then **suspends** and frees its compute, the same way [`wait.for`](/wait-for) does. The user's `addToolOutput` wakes it back up.
38
+
39
+ Because the run is suspended while it waits, the human's thinking time is not billed and does **not** count against [`maxDuration`](/runs/max-duration). `maxDuration` measures active CPU time and excludes suspended waitpoint time, exactly like `wait.for`, so a user can take minutes, hours, or days to answer without the run hitting `maxDuration`. The only time that counts is each turn's actual compute plus the short warm window before each suspend.
40
+
41
+ You don't need to raise `maxDuration` or end the run to support long human waits. How long a single suspended pause stays open is governed by the run's suspend timeout, not `maxDuration`; if a wait outlives it the run ends, and the next `addToolOutput` boots a fresh continuation that picks up the resolved tool result.
42
+
39
43
  ## Backend: define the tool
40
44
 
41
45
  A HITL tool has an `inputSchema` describing what the model can ask, but **no `execute` function**. When the LLM calls it, `streamText` returns control to your agent.
@@ -4,10 +4,6 @@ sidebarTitle: "Large payloads"
4
4
  description: "Why a single chunk on the chat stream is capped at ~1 MiB, what error you'll see, and how to work around it with ID references."
5
5
  ---
6
6
 
7
- import RcBanner from "/snippets/ai-chat-rc-banner.mdx";
8
-
9
- <RcBanner />
10
-
11
7
  The realtime stream that backs `chat.agent` enforces a **per-record cap of ~1 MiB** (`1048576` bytes minus a small envelope reserve). Anything written through the chat output — auto-piped LLM chunks, `chat.response.write`, custom `writer.write` parts — counts as one record per chunk and is rejected if it crosses the cap.
12
8
 
13
9
  This is a platform-level limit and cannot be raised per project or per stream.