experimental-ash 0.42.0 → 0.44.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 (184) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/bin/ash.js +1 -0
  3. package/dist/docs/internals/mechanical-invariants.md +16 -0
  4. package/dist/docs/public/README.md +8 -8
  5. package/dist/docs/public/advanced/{auth-and-route-protection.md → auth-and-route-protection.mdx} +11 -0
  6. package/dist/docs/public/advanced/context-control.md +4 -4
  7. package/dist/docs/public/advanced/{evals.md → evals.mdx} +11 -1
  8. package/dist/docs/public/advanced/{hooks.md → hooks.mdx} +28 -40
  9. package/dist/docs/public/advanced/instrumentation.md +142 -3
  10. package/dist/docs/public/advanced/project-layout.md +5 -5
  11. package/dist/docs/public/advanced/runs-and-streaming.md +8 -2
  12. package/dist/docs/public/advanced/session-context.md +1 -1
  13. package/dist/docs/public/advanced/typescript-api.md +50 -7
  14. package/dist/docs/public/advanced/vercel-deployment.md +1 -1
  15. package/dist/docs/public/agent-ts.md +5 -5
  16. package/dist/docs/public/channels/{discord.md → discord.mdx} +11 -0
  17. package/dist/docs/public/channels/index.md +10 -10
  18. package/dist/docs/public/channels/{slack.md → slack.mdx} +11 -0
  19. package/dist/docs/public/channels/{teams.md → teams.mdx} +12 -0
  20. package/dist/docs/public/channels/{telegram.md → telegram.mdx} +11 -0
  21. package/dist/docs/public/channels/{twilio.md → twilio.mdx} +11 -0
  22. package/dist/docs/public/{connections.md → connections.mdx} +18 -6
  23. package/dist/docs/public/frontend/README.md +16 -0
  24. package/dist/docs/public/frontend/meta.json +3 -0
  25. package/dist/docs/public/frontend/nextjs.md +192 -0
  26. package/dist/docs/public/frontend/use-ash-agent.md +332 -0
  27. package/dist/docs/public/{getting-started.md → getting-started.mdx} +12 -1
  28. package/dist/docs/public/{human-in-the-loop.md → human-in-the-loop.mdx} +12 -1
  29. package/dist/docs/public/meta.json +1 -0
  30. package/dist/docs/public/sandbox.md +39 -1
  31. package/dist/docs/public/{schedules.md → schedules.mdx} +9 -0
  32. package/dist/docs/public/skills.md +2 -2
  33. package/dist/docs/public/{subagents.md → subagents.mdx} +10 -0
  34. package/dist/docs/public/{tools.md → tools.mdx} +41 -26
  35. package/dist/src/channel/adapter.d.ts +13 -0
  36. package/dist/src/channel/compiled-channel.d.ts +4 -1
  37. package/dist/src/channel/compiled-channel.js +1 -1
  38. package/dist/src/channel/instrumentation.d.ts +10 -0
  39. package/dist/src/channel/instrumentation.js +1 -0
  40. package/dist/src/channel/routes.d.ts +8 -10
  41. package/dist/src/channel/send.js +1 -1
  42. package/dist/src/channel/types.d.ts +16 -0
  43. package/dist/src/cli/commands/channels.d.ts +2 -1
  44. package/dist/src/cli/commands/channels.js +1 -1
  45. package/dist/src/compiled/.vendor-stamp.json +1 -1
  46. package/dist/src/compiled/@vercel/sandbox/index.d.ts +12 -19
  47. package/dist/src/compiled/@vercel/sandbox/network-policy.d.ts +161 -0
  48. package/dist/src/compiled/just-bash/index.d.ts +15 -2
  49. package/dist/src/compiled/just-bash/network/types.d.ts +155 -0
  50. package/dist/src/compiler/artifacts.d.ts +1 -0
  51. package/dist/src/compiler/artifacts.js +1 -1
  52. package/dist/src/compiler/channel-instrumentation-types.d.ts +8 -0
  53. package/dist/src/compiler/channel-instrumentation-types.js +2 -0
  54. package/dist/src/compiler/manifest.d.ts +13 -1
  55. package/dist/src/compiler/manifest.js +1 -1
  56. package/dist/src/compiler/module-map.js +1 -1
  57. package/dist/src/compiler/normalize-manifest.js +1 -1
  58. package/dist/src/compiler/normalize-skill.d.ts +15 -2
  59. package/dist/src/compiler/normalize-skill.js +1 -1
  60. package/dist/src/compiler/normalize-tool.js +1 -1
  61. package/dist/src/context/dynamic-skill-lifecycle.d.ts +23 -0
  62. package/dist/src/context/dynamic-skill-lifecycle.js +1 -0
  63. package/dist/src/context/dynamic-tool-lifecycle.d.ts +2 -0
  64. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  65. package/dist/src/context/hook-lifecycle.d.ts +4 -6
  66. package/dist/src/context/hook-lifecycle.js +1 -1
  67. package/dist/src/context/keys.d.ts +6 -4
  68. package/dist/src/context/keys.js +1 -1
  69. package/dist/src/context/providers/connection.d.ts +9 -0
  70. package/dist/src/context/providers/connection.js +1 -1
  71. package/dist/src/context/providers/sandbox.js +1 -1
  72. package/dist/src/execution/ash-workflow-attributes.d.ts +118 -0
  73. package/dist/src/execution/ash-workflow-attributes.js +1 -0
  74. package/dist/src/execution/channel-context.d.ts +5 -0
  75. package/dist/src/execution/channel-context.js +1 -0
  76. package/dist/src/execution/create-session-step.d.ts +28 -1
  77. package/dist/src/execution/create-session-step.js +1 -1
  78. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  79. package/dist/src/execution/durable-session-store.d.ts +7 -0
  80. package/dist/src/execution/runtime-context.js +1 -1
  81. package/dist/src/execution/sandbox/bindings/local.js +1 -1
  82. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  83. package/dist/src/execution/sandbox/prewarm.js +1 -1
  84. package/dist/src/execution/sandbox/session.d.ts +6 -1
  85. package/dist/src/execution/sandbox/session.js +1 -1
  86. package/dist/src/execution/session.d.ts +6 -0
  87. package/dist/src/execution/session.js +2 -2
  88. package/dist/src/execution/skills/instructions.d.ts +3 -2
  89. package/dist/src/execution/subagent-tool.js +1 -1
  90. package/dist/src/execution/workflow-entry.js +1 -1
  91. package/dist/src/execution/workflow-steps.js +1 -1
  92. package/dist/src/harness/attachment-staging.js +1 -1
  93. package/dist/src/harness/code-mode.d.ts +0 -5
  94. package/dist/src/harness/code-mode.js +1 -1
  95. package/dist/src/harness/emission.d.ts +1 -1
  96. package/dist/src/harness/emission.js +1 -1
  97. package/dist/src/harness/instrumentation-config.d.ts +1 -1
  98. package/dist/src/harness/instrumentation-metadata.d.ts +23 -0
  99. package/dist/src/harness/instrumentation-metadata.js +1 -0
  100. package/dist/src/harness/otel-integration.d.ts +2 -2
  101. package/dist/src/harness/otel-integration.js +1 -1
  102. package/dist/src/harness/step-hooks.js +1 -1
  103. package/dist/src/harness/tool-loop.js +1 -1
  104. package/dist/src/harness/turn-tag-state.d.ts +50 -0
  105. package/dist/src/harness/turn-tag-state.js +1 -0
  106. package/dist/src/harness/types.d.ts +11 -2
  107. package/dist/src/internal/application/package.js +1 -1
  108. package/dist/src/internal/authored-definition/schema-backed.d.ts +0 -1
  109. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  110. package/dist/src/internal/instrumentation.d.ts +39 -0
  111. package/dist/src/internal/instrumentation.js +1 -0
  112. package/dist/src/internal/workflow/builtins.d.ts +32 -0
  113. package/dist/src/internal/workflow/builtins.js +1 -1
  114. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.d.ts +1 -1
  115. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +1 -1
  116. package/dist/src/internal/workflow-bundle/workflow-core-shim.d.ts +34 -0
  117. package/dist/src/internal/workflow-bundle/workflow-core-shim.js +1 -1
  118. package/dist/src/internal/workflow-bundle/workflow-transformer.js +1 -1
  119. package/dist/src/packages/ash-scaffold/src/channels.js +1 -1
  120. package/dist/src/packages/ash-scaffold/src/steps/run-add-to-agent.js +2 -2
  121. package/dist/src/packages/ash-scaffold/src/web-template.js +1 -0
  122. package/dist/src/public/channels/discord/discordChannel.d.ts +5 -2
  123. package/dist/src/public/channels/index.d.ts +1 -1
  124. package/dist/src/public/channels/slack/attachments.js +1 -1
  125. package/dist/src/public/channels/slack/index.d.ts +1 -1
  126. package/dist/src/public/channels/slack/slackChannel.d.ts +12 -8
  127. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  128. package/dist/src/public/channels/teams/teamsChannel.d.ts +5 -2
  129. package/dist/src/public/channels/telegram/telegramChannel.d.ts +5 -2
  130. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  131. package/dist/src/public/channels/twilio/index.d.ts +1 -1
  132. package/dist/src/public/channels/twilio/twilioChannel.d.ts +12 -3
  133. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  134. package/dist/src/public/definitions/defineChannel.d.ts +17 -4
  135. package/dist/src/public/definitions/defineChannel.js +1 -1
  136. package/dist/src/public/definitions/hook.d.ts +3 -11
  137. package/dist/src/public/definitions/instrumentation.d.ts +1 -66
  138. package/dist/src/public/definitions/instrumentation.js +1 -1
  139. package/dist/src/public/definitions/skill.d.ts +5 -0
  140. package/dist/src/public/definitions/tool.d.ts +25 -66
  141. package/dist/src/public/definitions/tool.js +1 -1
  142. package/dist/src/public/instrumentation/index.d.ts +175 -1
  143. package/dist/src/public/instrumentation/index.js +1 -1
  144. package/dist/src/public/sandbox/index.d.ts +1 -0
  145. package/dist/src/public/skills/index.d.ts +2 -0
  146. package/dist/src/public/skills/index.js +1 -1
  147. package/dist/src/public/tools/index.d.ts +2 -2
  148. package/dist/src/public/tools/index.js +1 -1
  149. package/dist/src/runtime/agent/mock-model-adapter.js +4 -7
  150. package/dist/src/runtime/agent/mock-model-skill-selection.d.ts +9 -0
  151. package/dist/src/runtime/agent/mock-model-skill-selection.js +4 -0
  152. package/dist/src/runtime/attributes/emit.d.ts +73 -0
  153. package/dist/src/runtime/attributes/emit.js +1 -0
  154. package/dist/src/runtime/channels/registry.js +1 -1
  155. package/dist/src/runtime/connections/mcp-client.js +1 -1
  156. package/dist/src/runtime/framework-tools/code-mode-connection-auth.d.ts +2 -0
  157. package/dist/src/runtime/framework-tools/connection-search-dynamic.d.ts +34 -0
  158. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -0
  159. package/dist/src/runtime/framework-tools/index.d.ts +7 -5
  160. package/dist/src/runtime/framework-tools/index.js +1 -1
  161. package/dist/src/runtime/prompt/connections.js +1 -1
  162. package/dist/src/runtime/resolve-agent-graph.js +1 -1
  163. package/dist/src/runtime/resolve-agent.js +1 -1
  164. package/dist/src/runtime/resolve-channel.js +1 -1
  165. package/dist/src/runtime/resolve-dynamic-skill.d.ts +8 -0
  166. package/dist/src/runtime/resolve-dynamic-skill.js +1 -0
  167. package/dist/src/runtime/resolve-dynamic-tool.js +1 -1
  168. package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
  169. package/dist/src/runtime/sessions/runtime-context-keys.js +1 -1
  170. package/dist/src/runtime/types.d.ts +13 -4
  171. package/dist/src/shared/dynamic-tool-definition.d.ts +51 -76
  172. package/dist/src/shared/dynamic-tool-definition.js +1 -1
  173. package/dist/src/shared/guards.d.ts +14 -0
  174. package/dist/src/shared/guards.js +1 -1
  175. package/dist/src/shared/sandbox-network-policy.d.ts +23 -0
  176. package/dist/src/shared/sandbox-network-policy.js +1 -0
  177. package/dist/src/shared/sandbox-session.d.ts +15 -0
  178. package/dist/src/shared/skill-definition.d.ts +5 -4
  179. package/dist/src/shared/tool-definition.d.ts +12 -0
  180. package/package.json +2 -1
  181. package/dist/src/runtime/framework-tools/connection-search.d.ts +0 -57
  182. package/dist/src/runtime/framework-tools/connection-search.js +0 -1
  183. package/dist/src/runtime/framework-tools/connection-tools.d.ts +0 -55
  184. package/dist/src/runtime/framework-tools/connection-tools.js +0 -1
@@ -38,7 +38,7 @@ Use `agent.ts` for:
38
38
  - provider-specific model options
39
39
 
40
40
  Per-tool approval (formerly "human-in-the-loop policy") lives on each tool via `needsApproval`,
41
- not in `agent.ts`. See [Human In The Loop](./human-in-the-loop.md).
41
+ not in `agent.ts`. See [Human In The Loop](./human-in-the-loop.mdx).
42
42
 
43
43
  For OpenTelemetry configuration, use `instrumentation.ts` instead. See
44
44
  [`instrumentation.ts`](./instrumentation.md).
@@ -135,7 +135,7 @@ The shared per-run workspace is configured on the sandbox, not on `agent.ts`. Se
135
135
  ## Human In The Loop
136
136
 
137
137
  Approval policy lives on individual tools via `needsApproval` in `defineTool({...})`, not on
138
- `agent.ts`. See [Human In The Loop](./human-in-the-loop.md) for the runtime flow, `input.requested`
138
+ `agent.ts`. See [Human In The Loop](./human-in-the-loop.mdx) for the runtime flow, `input.requested`
139
139
  events, and HTTP response payloads.
140
140
 
141
141
  ## Telemetry
@@ -149,7 +149,7 @@ OpenTelemetry tracing is configured in `agent/instrumentation.ts`, not in `agent
149
149
 
150
150
  Those concerns live on the HTTP channel layer instead. See:
151
151
 
152
- - [Auth And Route Protection](./auth-and-route-protection.md)
152
+ - [Auth And Route Protection](./auth-and-route-protection.mdx)
153
153
  - [Channels](./channels/README.md)
154
154
 
155
155
  ## A Good Default
@@ -169,6 +169,6 @@ That is enough to start. Add build and compaction settings only when you need th
169
169
  ## What To Read Next
170
170
 
171
171
  - [Context Control](./context-control.md)
172
- - [Human In The Loop](./human-in-the-loop.md)
172
+ - [Human In The Loop](./human-in-the-loop.mdx)
173
173
  - [Workspace](./workspace.md)
174
- - [Auth And Route Protection](./auth-and-route-protection.md)
174
+ - [Auth And Route Protection](./auth-and-route-protection.mdx)
@@ -9,6 +9,17 @@ The Discord channel accepts HTTP Interactions: slash/application commands, messa
9
9
  modal submissions. It verifies Discord's Ed25519 signature headers before parsing the request,
10
10
  acknowledges commands immediately, and continues Ash work in the background.
11
11
 
12
+ <CopyPrompt text="Add Discord support to the user's Ash project. Ash Discord channels are authored in agent/channels/discord.ts with discordChannel, verify Discord Ed25519 interaction signatures, mount POST /ash/v1/discord by default, defer command responses, deliver replies and HITL components, and can use proactive bot-token messages. Inspect existing channels and env conventions, add the channel file, configure DISCORD_PUBLIC_KEY, DISCORD_APPLICATION_ID, and DISCORD_BOT_TOKEN or equivalent config, set the Discord Interactions Endpoint URL, register or update an application command with a string message option, verify command delivery and HITL behavior, and do not commit unless the user asks.">
13
+ Add Discord support to the user's Ash project. Ash Discord channels are authored in
14
+ agent/channels/discord.ts with discordChannel, verify Discord Ed25519 interaction signatures,
15
+ mount POST /ash/v1/discord by default, defer command responses, deliver replies and HITL
16
+ components, and can use proactive bot-token messages. Inspect existing channels and env
17
+ conventions, add the channel file, configure DISCORD_PUBLIC_KEY, DISCORD_APPLICATION_ID, and
18
+ DISCORD_BOT_TOKEN or equivalent config, set the Discord Interactions Endpoint URL, register or
19
+ update an application command with a string message option, verify command delivery and HITL
20
+ behavior, and do not commit unless the user asks.
21
+ </CopyPrompt>
22
+
12
23
  ## Add The Channel
13
24
 
14
25
  Create `agent/channels/discord.ts`:
@@ -86,7 +86,7 @@ helpers. Each route handler receives the raw `Request` and a helpers object:
86
86
  Event handlers like `"message.completed"` are declared under the `events` key on the config object.
87
87
  They receive `(eventData, ctx)` where `ctx` carries platform handles and `ctx.session`. Use
88
88
  `toolResultFrom` from `experimental-ash/tools` to narrow tool results (see
89
- [Hooks — Narrowing tool results](../hooks.md#narrowing-tool-results)).
89
+ [Hooks — Narrowing tool results](../hooks.mdx#narrowing-tool-results)).
90
90
 
91
91
  ## The Ash Channel
92
92
 
@@ -116,7 +116,7 @@ export default ashChannel({
116
116
  `exampleProductionAuth()` placeholder that throws in production until you replace it
117
117
  with end-user auth. If you delete the authored file, Ash falls back to
118
118
  `[localDev(), vercelOidc()]`; that default does not admit browser users in production.
119
- See [Auth and Route Protection](../auth-and-route-protection.md) for the full walking
119
+ See [Auth and Route Protection](../auth-and-route-protection.mdx) for the full walking
120
120
  semantics and helper reference.
121
121
 
122
122
  ## Slack Channels
@@ -239,7 +239,7 @@ slackChannel({ onAppMention?, onDirectMessage?, events?, onInteraction? })
239
239
  `slackChannel(config)` compiles down to `defineChannel` plus typed inbound parsing and event
240
240
  dispatch for app mentions, direct messages, and interactions.
241
241
 
242
- For a Slack app backed by Vercel Connect, see [Slack channel setup](./slack.md) to create the Connect client
242
+ For a Slack app backed by Vercel Connect, see [Slack channel setup](./slack.mdx) to create the Connect client
243
243
  and channel file.
244
244
 
245
245
  ## Discord Channels
@@ -263,7 +263,7 @@ longer be used. Proactive `receive(discord, { channelId })` sessions also use bo
263
263
  messages. Default progress handlers trigger Discord's short-lived typing indicator when bot auth is
264
264
  available.
265
265
 
266
- See [Discord channel setup](./discord.md) for endpoint setup, environment variables, command
266
+ See [Discord channel setup](./discord.mdx) for endpoint setup, environment variables, command
267
267
  registration, and overrides.
268
268
 
269
269
  ## Twilio Channels
@@ -287,7 +287,7 @@ different Twilio numbers. `allowFrom` accepts a single phone number, a list, or
287
287
  resolver when the allowed phone numbers come from dynamic state. Use `allowFrom: "*"` only when the
288
288
  `onText` and `onVoice` hooks perform their own incoming-number checks.
289
289
 
290
- See [Twilio channel setup](./twilio.md) for webhook URLs, environment variables, and overrides.
290
+ See [Twilio channel setup](./twilio.mdx) for webhook URLs, environment variables, and overrides.
291
291
 
292
292
  ## Telegram Channels
293
293
 
@@ -313,7 +313,7 @@ at Telegram's 4096-character limit, and uses best-effort `sendChatAction("typing
313
313
  indicators. Photos and documents are exposed as file parts and fetched through Telegram `getFile`
314
314
  when the model needs the bytes.
315
315
 
316
- See [Telegram channel setup](./telegram.md) for webhook registration, environment variables, group
316
+ See [Telegram channel setup](./telegram.mdx) for webhook registration, environment variables, group
317
317
  privacy notes, HITL behavior, attachments, and proactive sessions.
318
318
 
319
319
  ## Microsoft Teams Channels
@@ -333,7 +333,7 @@ resume by conversation id; channel and group-chat threads resume by conversation
333
333
  activity id.
334
334
 
335
335
  Proactive `receive(teams, args)` sessions require an existing conversation reference
336
- (`serviceUrl` and `conversationId`). See [Microsoft Teams channel setup](./teams.md) for Azure Bot
336
+ (`serviceUrl` and `conversationId`). See [Microsoft Teams channel setup](./teams.mdx) for Azure Bot
337
337
  setup, environment variables, proactive handoff, HITL, and file options.
338
338
 
339
339
  ## Cross-Channel Hand-off
@@ -528,10 +528,10 @@ See [Channel file uploads](./attachments.md) for the full guide.
528
528
 
529
529
  ## What To Read Next
530
530
 
531
- - [Slack channel setup](./slack.md)
532
- - [Telegram channel setup](./telegram.md)
531
+ - [Slack channel setup](./slack.mdx)
532
+ - [Telegram channel setup](./telegram.mdx)
533
533
  - [Channel file uploads](./attachments.md)
534
534
  - [Project Layout](../project-layout.md)
535
535
  - [TypeScript API](../typescript-api.md)
536
- - [Auth And Route Protection](../auth-and-route-protection.md)
536
+ - [Auth And Route Protection](../auth-and-route-protection.mdx)
537
537
  - [Ash External Agent Protocol](../../external-agent-protocol.md)
@@ -11,6 +11,17 @@ Ash Slack channels can use Vercel Connect for both outbound Slack bot tokens and
11
11
  verification. With Connect, you do not need to manage `SLACK_BOT_TOKEN` or `SLACK_SIGNING_SECRET`
12
12
  environment variables yourself.
13
13
 
14
+ <CopyPrompt text="Add a Slack channel to the user's Ash project using Vercel Connect. Ash Slack channels are authored in agent/channels/slack.ts with slackChannel, and Connect can provide both outbound bot credentials and inbound webhook verification without SLACK_BOT_TOKEN or SLACK_SIGNING_SECRET env vars. Inspect existing channel files and Vercel project context, install @vercel/connect if needed, create or verify the Slack Connect client UID, attach triggers to /ash/v1/slack, add connectSlackCredentials to the Slack channel file, preserve or customize default mention, DM, delivery, typing, and HITL behavior as needed, verify the webhook route and deployment checklist, and do not commit unless the user asks.">
15
+ Add a Slack channel to the user's Ash project using Vercel Connect. Ash Slack channels are
16
+ authored in agent/channels/slack.ts with slackChannel, and Connect can provide both outbound bot
17
+ credentials and inbound webhook verification without SLACK_BOT_TOKEN or SLACK_SIGNING_SECRET env
18
+ vars. Inspect existing channel files and Vercel project context, install @vercel/connect if
19
+ needed, create or verify the Slack Connect client UID, attach triggers to /ash/v1/slack, add
20
+ connectSlackCredentials to the Slack channel file, preserve or customize default mention, DM,
21
+ delivery, typing, and HITL behavior as needed, verify the webhook route and deployment checklist,
22
+ and do not commit unless the user asks.
23
+ </CopyPrompt>
24
+
14
25
  ## Prerequisites
15
26
 
16
27
  - A Vercel project for the agent.
@@ -9,6 +9,18 @@ The Teams channel accepts Bot Framework Activity POSTs from Microsoft Teams, ver
9
9
  Connector bearer JWTs, dispatches message activities to Ash, renders HITL prompts as Adaptive
10
10
  Cards, and delivers agent responses through the Bot Framework Connector REST API.
11
11
 
12
+ <CopyPrompt text="Add Microsoft Teams support to the user's Ash project. Ash Teams channels are authored in agent/channels/teams.ts with teamsChannel, verify Bot Connector bearer JWTs, mount POST /ash/v1/teams by default, dispatch personal messages and direct bot mentions, render HITL as Adaptive Cards, and deliver replies through the Bot Framework Connector REST API. Inspect existing channels and env conventions, add the channel file, configure MICROSOFT_APP_ID, MICROSOFT_APP_PASSWORD, and optional MICROSOFT_TENANT_ID, set the Azure Bot or Teams messaging endpoint, customize onMessage or route only if needed, verify message dispatch and HITL cards, note proactive sessions require an existing conversation reference, and do not commit unless the user asks.">
13
+ Add Microsoft Teams support to the user's Ash project. Ash Teams channels are authored in
14
+ agent/channels/teams.ts with teamsChannel, verify Bot Connector bearer JWTs, mount POST
15
+ /ash/v1/teams by default, dispatch personal messages and direct bot mentions, render HITL as
16
+ Adaptive Cards, and deliver replies through the Bot Framework Connector REST API. Inspect existing
17
+ channels and env conventions, add the channel file, configure MICROSOFT_APP_ID,
18
+ MICROSOFT_APP_PASSWORD, and optional MICROSOFT_TENANT_ID, set the Azure Bot or Teams messaging
19
+ endpoint, customize onMessage or route only if needed, verify message dispatch and HITL cards,
20
+ note proactive sessions require an existing conversation reference, and do not commit unless the
21
+ user asks.
22
+ </CopyPrompt>
23
+
12
24
  ## Add The Channel
13
25
 
14
26
  Create `agent/channels/teams.ts`:
@@ -9,6 +9,17 @@ The Telegram channel accepts Telegram Bot API webhooks. It verifies Telegram's
9
9
  `X-Telegram-Bot-Api-Secret-Token` header before parsing the update, dispatches private messages and
10
10
  addressed group messages, and sends default replies through `sendMessage`.
11
11
 
12
+ <CopyPrompt text="Add Telegram support to the user's Ash project. Ash Telegram channels are authored in agent/channels/telegram.ts with telegramChannel, verify the X-Telegram-Bot-Api-Secret-Token webhook header, mount POST /ash/v1/telegram by default, dispatch private messages plus addressed group messages, render HITL with inline keyboards or ForceReply, and can expose photos and documents as file parts. Inspect existing channels and env conventions, add the channel file, configure TELEGRAM_BOT_TOKEN, TELEGRAM_WEBHOOK_SECRET_TOKEN, and botUsername, register the deployed webhook with allowed_updates, add an upload policy if attachments are needed, verify private and group dispatch, and do not commit unless the user asks.">
13
+ Add Telegram support to the user's Ash project. Ash Telegram channels are authored in
14
+ agent/channels/telegram.ts with telegramChannel, verify the X-Telegram-Bot-Api-Secret-Token
15
+ webhook header, mount POST /ash/v1/telegram by default, dispatch private messages plus addressed
16
+ group messages, render HITL with inline keyboards or ForceReply, and can expose photos and
17
+ documents as file parts. Inspect existing channels and env conventions, add the channel file,
18
+ configure TELEGRAM_BOT_TOKEN, TELEGRAM_WEBHOOK_SECRET_TOKEN, and botUsername, register the
19
+ deployed webhook with allowed_updates, add an upload policy if attachments are needed, verify
20
+ private and group dispatch, and do not commit unless the user asks.
21
+ </CopyPrompt>
22
+
12
23
  ## Add The Channel
13
24
 
14
25
  Create `agent/channels/telegram.ts`:
@@ -10,6 +10,17 @@ with TwiML `<Gather input="speech">`; the Twilio speech transcript is then deliv
10
10
  Ash session model as SMS. The raw continuation token is the caller/sender phone number plus the
11
11
  Twilio receiver: `From:To`.
12
12
 
13
+ <CopyPrompt text="Add Twilio SMS and voice support to the user's Ash project. Ash Twilio channels are authored in agent/channels/twilio.ts with twilioChannel, verify X-Twilio-Signature, accept inbound SMS at /ash/v1/twilio/messages, answer voice calls at /ash/v1/twilio/voice, and deliver speech transcripts to the same session through /ash/v1/twilio/voice/transcription. Inspect existing channels and env conventions, add the channel file, configure allowFrom, TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, outbound messaging.from or messagingServiceSid, webhookUrl or publicBaseUrl when proxies are involved, customize onText or onVoice only if needed, verify SMS and voice webhooks, and do not commit unless the user asks.">
14
+ Add Twilio SMS and voice support to the user's Ash project. Ash Twilio channels are authored in
15
+ agent/channels/twilio.ts with twilioChannel, verify X-Twilio-Signature, accept inbound SMS at
16
+ /ash/v1/twilio/messages, answer voice calls at /ash/v1/twilio/voice, and deliver speech
17
+ transcripts to the same session through /ash/v1/twilio/voice/transcription. Inspect existing
18
+ channels and env conventions, add the channel file, configure allowFrom, TWILIO_ACCOUNT_SID,
19
+ TWILIO_AUTH_TOKEN, outbound messaging.from or messagingServiceSid, webhookUrl or publicBaseUrl
20
+ when proxies are involved, customize onText or onVoice only if needed, verify SMS and voice
21
+ webhooks, and do not commit unless the user asks.
22
+ </CopyPrompt>
23
+
13
24
  ## Add The Channel
14
25
 
15
26
  Create `agent/channels/twilio.ts`:
@@ -7,8 +7,20 @@ Ash exposes external MCP servers to the model through files in `connections/`. E
7
7
  connection; the connection's runtime name is derived from the filename (`agent/connections/linear.ts`
8
8
  is registered as `"linear"`).
9
9
 
10
- The model sees each connection through `connection_search` and picks tools based on its
11
- `description`, so write the description for the model.
10
+ The model sees each connection through `connection__search` and picks tools based on its
11
+ `description`, so write the description for the model. Discovered tools are registered as
12
+ `connection__<connectionName>__<toolName>` (e.g. `connection__linear__list_issues`).
13
+
14
+ <CopyPrompt text="Add an external MCP connection to the user's Ash project. Ash connections live under agent/connections, and the runtime connection name comes from the filename. Inspect existing connections and environment variable conventions, then add or update the right connection file with defineMcpClientConnection from experimental-ash/connections. Choose static token auth with getToken, Vercel Connect-managed OAuth, or no auth based on the service; keep credentials in environment variables or Connect, set principalType when app-vs-user auth matters, add headers, approval, or tools allow/block filters when needed, verify discovery, and do not commit unless the user asks.">
15
+ Add an external MCP connection to the user's Ash project. Ash connections live under
16
+ agent/connections, and the runtime connection name comes from the filename. Inspect existing
17
+ connections and environment variable conventions, then add or update the right connection file
18
+ with defineMcpClientConnection from experimental-ash/connections. Choose static token auth with
19
+ getToken, Vercel Connect-managed OAuth, or no auth based on the service; keep credentials in
20
+ environment variables or Connect, set principalType when app-vs-user auth matters, add headers,
21
+ approval, or tools allow/block filters when needed, verify discovery, and do not commit unless the
22
+ user asks.
23
+ </CopyPrompt>
12
24
 
13
25
  ## Pick An Auth Strategy
14
26
 
@@ -158,7 +170,7 @@ export default defineMcpClientConnection({
158
170
  ```
159
171
 
160
172
  `never()` allows all calls, `once()` requires approval the first time per session, `always()`
161
- requires approval every time. See [Human In The Loop](./human-in-the-loop.md) for the approval
173
+ requires approval every time. See [Human In The Loop](./human-in-the-loop.mdx) for the approval
162
174
  runtime.
163
175
 
164
176
  ## Tool Filters
@@ -174,10 +186,10 @@ export default defineMcpClientConnection({
174
186
  });
175
187
  ```
176
188
 
177
- Tools that don't pass the filter are silently excluded from `connection_search`.
189
+ Tools that don't pass the filter are silently excluded from `connection__search`.
178
190
 
179
191
  ## What To Read Next
180
192
 
181
- - [Tools](./tools.md) — authored tools live alongside connection-provided tools.
182
- - [Human In The Loop](./human-in-the-loop.md) — interactive consent and approval runtime.
193
+ - [Tools](./tools.mdx) — authored tools live alongside connection-provided tools.
194
+ - [Human In The Loop](./human-in-the-loop.mdx) — interactive consent and approval runtime.
183
195
  - [Session Context](./session-context.md) — how the active principal flows through the runtime.
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: "Overview"
3
+ description: "Wire your web app to an Ash agent."
4
+ url: /frontend
5
+ ---
6
+
7
+ Ash ships first-class helpers for the two most common ways to put an agent
8
+ behind a web UI:
9
+
10
+ - [Next.js](./nextjs.md) — `withAsh()` runs the Ash agent alongside your
11
+ Next.js app.
12
+ - [`useAshAgent`](./use-ash-agent.md) — React hook for chat and agent UIs in any
13
+ React app.
14
+
15
+ For other stacks, call Ash directly over its HTTP routes —
16
+ see [Sessions And Streaming](../runs-and-streaming.md).
@@ -0,0 +1,3 @@
1
+ {
2
+ "pages": ["README", "nextjs", "use-ash-agent"]
3
+ }
@@ -0,0 +1,192 @@
1
+ ---
2
+ title: "Next.js"
3
+ description: "Add an Ash agent to a Next.js app and call it from the browser."
4
+ ---
5
+
6
+ `experimental-ash/next` lets you ship a Next.js frontend and an Ash agent as
7
+ one project. Come in from either side: drop it into an existing Next.js app
8
+ to add an agent, or start with an agent and point a Next.js project at it.
9
+
10
+ - **One dev server.** `next dev` runs the app and the agent together.
11
+ - **One deploy.** Vercel ships them as a single project; no extra service to operate.
12
+ - **Zero URL plumbing.** `useAshAgent()` finds the mounted routes automatically; no CORS, no env vars.
13
+
14
+ ## Add Ash To Next.js
15
+
16
+ Wrap your Next.js config with `withAsh()`:
17
+
18
+ ```ts
19
+ // next.config.ts
20
+ import type { NextConfig } from "next";
21
+ import { withAsh } from "experimental-ash/next";
22
+
23
+ const nextConfig: NextConfig = {};
24
+
25
+ export default withAsh(nextConfig);
26
+ ```
27
+
28
+ By default, `withAsh()` looks for an `agent/` folder inside your Next.js
29
+ project root. Pass `ashRoot` when the agent lives somewhere else:
30
+
31
+ ```ts
32
+ export default withAsh(nextConfig, {
33
+ ashRoot: "../my-agent",
34
+ });
35
+ ```
36
+
37
+ ## Add The Ash Channel
38
+
39
+ Skip this section if the framework default channel works for you. `withAsh()`
40
+ already wires Ash up without it.
41
+
42
+ Create `agent/channels/ash.ts` when you want to choose the route auth policy
43
+ explicitly:
44
+
45
+ ```ts
46
+ // agent/channels/ash.ts
47
+ import { ashChannel } from "experimental-ash/channels/ash";
48
+ import { none } from "experimental-ash/channels/auth";
49
+
50
+ export default ashChannel({
51
+ auth: none(),
52
+ });
53
+ ```
54
+
55
+ For protected apps, replace `none()` with a channel auth helper such as
56
+ `vercelOidc()`, `oidc(...)`, or `httpBasic(...)`.
57
+
58
+ ## Use The React Hook
59
+
60
+ Once `withAsh()` is in `next.config.ts`, browser code can use
61
+ [`useAshAgent()`](./use-ash-agent.md) without a custom host:
62
+
63
+ ```tsx
64
+ "use client";
65
+
66
+ import { useAshAgent } from "experimental-ash/react";
67
+
68
+ export function Chat() {
69
+ const agent = useAshAgent();
70
+ const isBusy = agent.status === "submitted" || agent.status === "streaming";
71
+
72
+ return (
73
+ <form
74
+ onSubmit={(event) => {
75
+ event.preventDefault();
76
+ const data = new FormData(event.currentTarget);
77
+ const message = String(data.get("message") ?? "").trim();
78
+ if (message.length > 0) {
79
+ void agent.sendMessage(message);
80
+ }
81
+ }}
82
+ >
83
+ <input name="message" disabled={isBusy} />
84
+ <button type="submit" disabled={isBusy}>
85
+ Send
86
+ </button>
87
+ </form>
88
+ );
89
+ }
90
+ ```
91
+
92
+ The hook handles conversation state, streaming updates, errors, and
93
+ messages for you. See [`useAshAgent`](./use-ash-agent.md) for the full API.
94
+
95
+ ## Local Development
96
+
97
+ `pnpm dev` is enough. `withAsh()` boots the Ash dev server alongside Next.js
98
+ and rewrites the Ash routes to it, so your browser keeps talking to the
99
+ Next.js origin.
100
+
101
+ ## Vercel Deployments
102
+
103
+ On Vercel, `withAsh()` keeps the web app public and the Ash runtime tucked
104
+ behind it. Users visit the Next.js app, and the browser talks to the agent
105
+ through the same site origin.
106
+
107
+ Use `ashBuildCommand` when the agent needs a project-specific build command:
108
+
109
+ ```ts
110
+ export default withAsh(nextConfig, {
111
+ ashBuildCommand: "pnpm build:ash",
112
+ });
113
+ ```
114
+
115
+ ## Local Production Builds
116
+
117
+ When you run `next build && next start` on your own machine, `withAsh()` proxies
118
+ Ash routes to `http://127.0.0.1:4274` and serves a built `.output/server/index.mjs`
119
+ on that port. Set `ASH_NEXT_PRODUCTION_PORT` to use a different port:
120
+
121
+ ```bash
122
+ ASH_NEXT_PRODUCTION_PORT=5000 pnpm build && pnpm start
123
+ ```
124
+
125
+ ## Non-Vercel Production Hosts
126
+
127
+ If you deploy somewhere other than Vercel and the Ash service runs on a
128
+ separate origin, point Next.js at it with `ASH_NEXT_PRODUCTION_ORIGIN`:
129
+
130
+ ```bash
131
+ ASH_NEXT_PRODUCTION_ORIGIN=https://agent.example.com pnpm build
132
+ ```
133
+
134
+ ## Authenticated Requests
135
+
136
+ Because the agent runs on the same origin as your Next.js app, the auth you
137
+ already use for the rest of the app applies to it for free. Auth.js or any
138
+ cookie-based session works without extra wiring: the browser already sends
139
+ those cookies on every Ash request. The channel just reads them:
140
+
141
+ ```ts
142
+ // agent/channels/ash.ts
143
+ import { ashChannel } from "experimental-ash/channels/ash";
144
+ import { getAuthJsSession } from "@/lib/auth";
145
+
146
+ export default ashChannel({
147
+ auth: async (request) => {
148
+ const session = await getAuthJsSession(request);
149
+ if (!session) return null;
150
+ return {
151
+ attributes: {},
152
+ principalType: "user",
153
+ principalId: session.profile.sub,
154
+ authenticator: "authjs",
155
+ issuer: session.issuer,
156
+ };
157
+ },
158
+ });
159
+ ```
160
+
161
+ The `apps/nextjs-ash` example app has a full Auth.js setup.
162
+
163
+ For non-cookie schemes (bearer tokens, custom headers), attach them from the
164
+ client instead:
165
+
166
+ ```tsx
167
+ const agent = useAshAgent({
168
+ headers: async () => ({
169
+ authorization: `Bearer ${await getAccessToken()}`,
170
+ }),
171
+ });
172
+ ```
173
+
174
+ Prefer function values for short-lived credentials. Ash re-resolves them
175
+ before each HTTP request, including reconnects.
176
+
177
+ ## Add Per-Turn Page Context
178
+
179
+ `useAshAgent()` accepts a `prepareSend` callback for attaching one-turn page
180
+ state (pathname, selected ids, anything else the model should see for the
181
+ next call only). See [`useAshAgent`](./use-ash-agent.md#add-per-turn-client-context)
182
+ for the full pattern.
183
+
184
+ For server-side enrichment (policy, durable context, dynamic skills), use
185
+ runtime lifecycle hooks instead. See [Hooks](../hooks.md).
186
+
187
+ ## What To Read Next
188
+
189
+ - [`useAshAgent`](./use-ash-agent.md)
190
+ - [Auth And Route Protection](../auth-and-route-protection.md)
191
+ - [Hooks](../hooks.md)
192
+ - [Sessions And Streaming](../runs-and-streaming.md)