experimental-ash 0.55.3 → 0.57.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 (144) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +202 -0
  3. package/dist/docs/internals/compiler-and-artifacts.md +1 -1
  4. package/dist/docs/internals/context.md +3 -3
  5. package/dist/docs/public/advanced/typescript-api.md +19 -0
  6. package/dist/docs/public/advanced/vercel-deployment.md +2 -1
  7. package/dist/docs/public/channels/github.md +145 -0
  8. package/dist/docs/public/channels/index.md +23 -2
  9. package/dist/docs/public/meta.json +1 -0
  10. package/dist/docs/public/onboarding.md +7 -5
  11. package/dist/docs/public/sandbox.md +18 -3
  12. package/dist/docs/public/subagents.mdx +7 -2
  13. package/dist/docs/public/tools.mdx +10 -2
  14. package/dist/skills/agent/SKILL.md +169 -0
  15. package/dist/skills/agent/references/deployment.md +35 -0
  16. package/dist/skills/agent/references/getting-started.md +58 -0
  17. package/dist/skills/agent/references/project-layout.md +35 -0
  18. package/dist/skills/agent/references/runtime-model.md +24 -0
  19. package/dist/skills/agent/references/skills.md +26 -0
  20. package/dist/skills/agent/scripts/add-to-existing-project.sh +12 -0
  21. package/dist/skills/agent/scripts/bootstrap-from-npm.sh +9 -0
  22. package/dist/skills/agent/scripts/verify-local-agent.sh +16 -0
  23. package/dist/skills/ash-add-agent/SKILL.md +166 -0
  24. package/dist/skills/ash-add-next/SKILL.md +137 -0
  25. package/dist/skills/framework/SKILL.md +93 -0
  26. package/dist/skills/framework/references/architecture.md +14 -0
  27. package/dist/skills/framework/references/discovery-and-compilation.md +15 -0
  28. package/dist/skills/framework/references/quality-gates.md +13 -0
  29. package/dist/skills/framework/references/runtime-model.md +12 -0
  30. package/dist/skills/framework/references/workspace-and-sandbox.md +25 -0
  31. package/dist/skills/framework/scripts/framework-review-checklist.sh +13 -0
  32. package/dist/skills/framework/scripts/run-framework-gates.sh +8 -0
  33. package/dist/src/client/output-schema.js +1 -1
  34. package/dist/src/compiler/compile-from-memory.d.ts +2 -0
  35. package/dist/src/compiler/compile-from-memory.js +1 -1
  36. package/dist/src/compiler/manifest.d.ts +10 -2
  37. package/dist/src/compiler/manifest.js +1 -1
  38. package/dist/src/compiler/normalize-agent-config.js +1 -1
  39. package/dist/src/compiler/normalize-sandbox.js +1 -1
  40. package/dist/src/compiler/normalize-subagent.js +1 -1
  41. package/dist/src/compiler/normalize-tool.js +1 -1
  42. package/dist/src/context/build-dynamic-tools.js +1 -1
  43. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  44. package/dist/src/context/keys.d.ts +1 -0
  45. package/dist/src/execution/node-step.js +1 -1
  46. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  47. package/dist/src/execution/session.js +1 -1
  48. package/dist/src/execution/subagent-tool.js +1 -1
  49. package/dist/src/execution/workflow-entry.js +1 -1
  50. package/dist/src/harness/code-mode.js +1 -1
  51. package/dist/src/harness/execute-tool.d.ts +1 -0
  52. package/dist/src/harness/provider-tools.d.ts +7 -1
  53. package/dist/src/harness/provider-tools.js +1 -1
  54. package/dist/src/harness/tool-loop.js +1 -1
  55. package/dist/src/harness/tools.d.ts +2 -0
  56. package/dist/src/harness/tools.js +1 -1
  57. package/dist/src/internal/application/package.js +1 -1
  58. package/dist/src/internal/authored-definition/sandbox.d.ts +2 -1
  59. package/dist/src/internal/authored-definition/sandbox.js +1 -1
  60. package/dist/src/internal/authored-definition/schema-backed.js +1 -1
  61. package/dist/src/packages/ash-scaffold/src/channels.js +2 -2
  62. package/dist/src/packages/ash-scaffold/src/steps/run-add-to-agent.js +1 -1
  63. package/dist/src/packages/ash-scaffold/src/web-template.js +2 -2
  64. package/dist/src/public/channels/github/api.d.ts +166 -0
  65. package/dist/src/public/channels/github/api.js +1 -0
  66. package/dist/src/public/channels/github/auth.d.ts +83 -0
  67. package/dist/src/public/channels/github/auth.js +2 -0
  68. package/dist/src/public/channels/github/binding.d.ts +49 -0
  69. package/dist/src/public/channels/github/binding.js +1 -0
  70. package/dist/src/public/channels/github/checkout.d.ts +48 -0
  71. package/dist/src/public/channels/github/checkout.js +1 -0
  72. package/dist/src/public/channels/github/constants.d.ts +2 -0
  73. package/dist/src/public/channels/github/constants.js +1 -0
  74. package/dist/src/public/channels/github/defaults.d.ts +21 -0
  75. package/dist/src/public/channels/github/defaults.js +3 -0
  76. package/dist/src/public/channels/github/dispatch.d.ts +34 -0
  77. package/dist/src/public/channels/github/dispatch.js +1 -0
  78. package/dist/src/public/channels/github/githubChannel.d.ts +109 -0
  79. package/dist/src/public/channels/github/githubChannel.js +1 -0
  80. package/dist/src/public/channels/github/inbound.d.ts +183 -0
  81. package/dist/src/public/channels/github/inbound.js +2 -0
  82. package/dist/src/public/channels/github/index.d.ts +9 -0
  83. package/dist/src/public/channels/github/index.js +1 -0
  84. package/dist/src/public/channels/github/limits.d.ts +4 -0
  85. package/dist/src/public/channels/github/limits.js +2 -0
  86. package/dist/src/public/channels/github/pr-context.d.ts +45 -0
  87. package/dist/src/public/channels/github/pr-context.js +5 -0
  88. package/dist/src/public/channels/github/state.d.ts +48 -0
  89. package/dist/src/public/channels/github/state.js +1 -0
  90. package/dist/src/public/channels/github/verify.d.ts +35 -0
  91. package/dist/src/public/channels/github/verify.js +1 -0
  92. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  93. package/dist/src/public/definitions/sandbox.d.ts +3 -3
  94. package/dist/src/public/definitions/tool.d.ts +21 -1
  95. package/dist/src/public/sandbox/index.d.ts +1 -1
  96. package/dist/src/public/tools/define-bash-tool.js +1 -1
  97. package/dist/src/public/tools/define-glob-tool.js +1 -1
  98. package/dist/src/public/tools/define-grep-tool.js +1 -1
  99. package/dist/src/public/tools/define-read-file-tool.js +1 -1
  100. package/dist/src/public/tools/define-write-file-tool.js +1 -1
  101. package/dist/src/public/tools/internal.js +1 -1
  102. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  103. package/dist/src/runtime/connections/authorization-tokens.d.ts +8 -0
  104. package/dist/src/runtime/connections/authorization-tokens.js +1 -1
  105. package/dist/src/runtime/connections/mcp-client.d.ts +14 -0
  106. package/dist/src/runtime/connections/mcp-client.js +1 -1
  107. package/dist/src/runtime/connections/types.d.ts +1 -0
  108. package/dist/src/runtime/framework-tools/ask-question.d.ts +4 -0
  109. package/dist/src/runtime/framework-tools/ask-question.js +1 -1
  110. package/dist/src/runtime/framework-tools/bash.d.ts +5 -0
  111. package/dist/src/runtime/framework-tools/bash.js +1 -1
  112. package/dist/src/runtime/framework-tools/connection-search-dynamic.d.ts +1 -0
  113. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
  114. package/dist/src/runtime/framework-tools/final-output.js +1 -1
  115. package/dist/src/runtime/framework-tools/glob.d.ts +5 -0
  116. package/dist/src/runtime/framework-tools/glob.js +2 -2
  117. package/dist/src/runtime/framework-tools/grep.d.ts +5 -0
  118. package/dist/src/runtime/framework-tools/grep.js +2 -2
  119. package/dist/src/runtime/framework-tools/read-file.d.ts +5 -0
  120. package/dist/src/runtime/framework-tools/read-file.js +2 -2
  121. package/dist/src/runtime/framework-tools/skill.d.ts +2 -0
  122. package/dist/src/runtime/framework-tools/skill.js +1 -1
  123. package/dist/src/runtime/framework-tools/todo.d.ts +2 -0
  124. package/dist/src/runtime/framework-tools/todo.js +2 -2
  125. package/dist/src/runtime/framework-tools/web-fetch.d.ts +3 -0
  126. package/dist/src/runtime/framework-tools/web-fetch.js +2 -2
  127. package/dist/src/runtime/framework-tools/web-search.d.ts +17 -0
  128. package/dist/src/runtime/framework-tools/web-search.js +1 -1
  129. package/dist/src/runtime/framework-tools/write-file.d.ts +5 -0
  130. package/dist/src/runtime/framework-tools/write-file.js +2 -2
  131. package/dist/src/runtime/resolve-sandbox.js +1 -1
  132. package/dist/src/runtime/resolve-tool.js +1 -1
  133. package/dist/src/runtime/sandbox/keys.js +1 -1
  134. package/dist/src/runtime/sandbox/template-plan.d.ts +5 -0
  135. package/dist/src/runtime/sandbox/template-plan.js +1 -1
  136. package/dist/src/runtime/subagents/registry.js +1 -1
  137. package/dist/src/runtime/tools/registry.js +1 -1
  138. package/dist/src/runtime/types.d.ts +11 -2
  139. package/dist/src/shared/dynamic-tool-definition.d.ts +2 -1
  140. package/dist/src/shared/json-schema.d.ts +3 -1
  141. package/dist/src/shared/json-schema.js +1 -1
  142. package/dist/src/shared/sandbox-definition.d.ts +22 -2
  143. package/dist/src/shared/tool-definition.d.ts +10 -2
  144. package/package.json +25 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # experimental-ash
2
2
 
3
+ ## 0.57.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b4d3ff0: Sandbox definitions with `bootstrap()` may now provide an optional build-time `revalidationKey()` function. Resolved revalidation keys and authored sandbox source hashes are stored in compiled artifacts so bootstrap templates can reuse stable snapshots across deploys when the revalidation key, sandbox source, and seed content match.
8
+ - ad9c3c5: Add the native GitHub channel (`experimental-ash/channels/github`). Verifies GitHub App webhooks, derives session auth from the GitHub actor, and dispatches `@mention` turns from issue comments, PR timeline comments, and inline review threads. Replies land on the native surface (timeline comment or inline review-thread reply) and acknowledge with an `eyes` reaction. Pull-request turns always inject the PR diff (with noisy files like lock files excluded from the prompt) and always check out the triggering ref into the sandbox so the built-in filesystem tools operate on the real tree. Checkout is incremental — because the sandbox persists for the session, a turn whose target commit the workspace is already on skips the fetch entirely — and brokers the installation token at the sandbox firewall (so it never enters the sandbox process) rather than embedding it in the git remote URL. Supports opt-in `onIssue`/`onPullRequest` automation hooks, an `onComment` override, a generic `ctx.github.request()` escape hatch, and proactive `receive()` sessions.
9
+ - ad9c3c5: Add `credentials.webhookVerifier` to the GitHub channel, matching the other native channels. When supplied, it replaces the built-in `X-Hub-Signature-256` HMAC check (the `GITHUB_WEBHOOK_SECRET` fallback is skipped), letting integrations like Vercel Connect authenticate forwarded webhooks out-of-band (e.g. with Vercel OIDC). Combined with the existing function-form `appId`/`privateKey`/`webhookSecret` credentials, the GitHub channel now has the same Connect integration surface as Slack, Teams, Telegram, and Discord.
10
+ - 4de5be3: Add optional `outputSchema` to subagent tool input schema for structured output. When a parent agent passes `outputSchema` to a subagent tool call, the child runs in task mode and must produce structured output matching the schema via the `final_output` tool.
11
+
12
+ ## 0.56.0
13
+
14
+ ### Minor Changes
15
+
16
+ - e5f2d97: Ship the root Ash skill packages inside the npm package under `dist/skills`. The docs site now renders those canonical `SKILL.md` files directly as skill reference pages, avoiding duplicated skill documentation.
17
+ - 80ca852: Add optional `outputSchema` support to `defineTool` and propagate tool output schemas into code mode host tools. Framework tools with fixed result shapes now declare output schemas, provider-managed `web_search` injects the selected provider's output schema at runtime, and code mode logs a warning when an exposed host tool has no output schema.
18
+
19
+ Use deterministic per-turn completion hook tokens in the workflow driver so fast subagent resumes cannot collide with a prior turn's completion hook while the Workflow SDK is still persisting disposal.
20
+
21
+ ### Patch Changes
22
+
23
+ - bdf208a: Connections now recover when the remote server rejects an already-issued
24
+ token. An MCP `401` (the bearer was revoked or expired out of band) is
25
+ classified as authorization-required: Ash evicts the stale cached token,
26
+ tears down the connection, and re-enters the sign-in flow instead of
27
+ narrating an opaque transport error. A loop guard fails the connection
28
+ terminally if a freshly authorized token is still rejected, so a broken
29
+ grant cannot trigger an endless re-authorization loop.
30
+ - f158cb2: Drop verified Slack `http_timeout` retry deliveries so delayed acknowledgements do not start duplicate sessions.
31
+ - 4d59025: Add Apache-2.0 license metadata, a root license file, and publish-time package license copies along with clearer package descriptions and discovery keywords.
32
+
3
33
  ## 0.55.3
4
34
 
5
35
  ### Patch Changes
package/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -33,7 +33,7 @@ Discovery avoids executing authored code. The module map is the handoff — it s
33
33
 
34
34
  **`compiled-agent-manifest.json`** — the normalized runtime-facing manifest. Preserves config, prompt, skill, sandbox, schedule, and tool metadata; flattened subagent nodes with explicit `subagentEdges`; manifest kind and version. `sandbox` is `null` or one entry, and `sandboxWorkspaces` is an array of size 0 or 1 (single-sandbox model).
35
35
 
36
- **`compile-metadata.json`** — artifact paths, SHA-256 digests, diagnostics summary, compile status, generator version, and `sourceGraphHash`. The `sourceGraphHash` drives sandbox template cache invalidation runtime and Vercel build-time prewarm both derive template keys from it.
36
+ **`compile-metadata.json`** — artifact paths, SHA-256 digests, diagnostics summary, compile status, generator version, and `sourceGraphHash`. Runtime and Vercel build-time prewarm derive sandbox template keys from compiled artifacts: seed-only templates use workspace content hashes, bootstrap templates use the optional resolved authored `revalidationKey()` plus authored sandbox source and workspace content, and source-graph fallback paths use `sourceGraphHash`.
37
37
 
38
38
  **`module-map.mjs`** — frozen object keyed by `(nodeId, sourceId)`. Authored sandbox modules are indexed directly (runtime needs their lifecycle hooks); `lib/` modules come in transitively.
39
39
 
@@ -80,9 +80,9 @@ Authored hook stream-event dispatch runs inside step (4)'s ALS scope.
80
80
  Event hooks receive `(event, ctx)`. See [Hooks](./hooks.md) for the
81
81
  full pipeline.
82
82
 
83
- `StepInput.modelContext` is provided by channels through
84
- `SendPayload.modelContext`. The messages are visible to the next model
85
- call only and are never persisted to durable session history.
83
+ `StepInput.context` is provided by channels through `SendPayload.context`.
84
+ Each entry is appended as a `role: "user"` message to durable session
85
+ history before the delivery message.
86
86
 
87
87
  ## Channel Context
88
88
 
@@ -118,6 +118,24 @@ Channel and Slack types exported from `experimental-ash/channels/slack`:
118
118
  - `Card`, `Button`, `Actions`, `Section`, `Modal`, `Table`, etc. - card builders re-exported for
119
119
  rendering Slack messages
120
120
 
121
+ Channel and GitHub types exported from `experimental-ash/channels/github`:
122
+
123
+ - `githubChannel` - GitHub App webhook channel factory for issue/PR comments, review comments,
124
+ and opt-in issue/pull-request hooks
125
+ - `GitHubChannelConfig` - config type for credentials, route, bot mention trigger, PR diff
126
+ exclusions, reaction acknowledgement, and the `onComment`/`onIssue`/`onPullRequest` handlers
127
+ - `GitHubInboundContext` - pre-dispatch context for inbound hooks (`thread`, `github`,
128
+ `repository`, `sender`, `delivery`)
129
+ - `GitHubEventContext` - event-handler context (`thread`, `github`, mutable `state`,
130
+ repository/conversation metadata, and channel session operations)
131
+ - `GitHubHandle` - GitHub helper handle: `request()` plus `installationId` and `repository`
132
+ - `GitHubThread` - conversation-scoped operations: `post` and `react`
133
+ - `GitHubComment`, `GitHubIssueEvent`, and `GitHubPullRequestEvent` - parsed inbound payload types
134
+ - `GitHubIssueAction` / `GitHubPullRequestAction` - typed webhook action unions
135
+ - `GitHubPullRequestContextConfig` - PR diff exclusion config (`excludedFiles`)
136
+ - `GitHubReceiveTarget` - target accepted by proactive `receive(github, ...)`
137
+ - `defaultGitHubAuth` - default GitHub actor-to-session-auth projection
138
+
121
139
  Channel and Twilio types exported from `experimental-ash/channels/twilio`:
122
140
 
123
141
  - `twilioChannel` - Twilio channel factory for SMS and speech-transcribed voice webhooks
@@ -203,6 +221,7 @@ import { defineAgent } from "experimental-ash";
203
221
  import { defineChannel, POST, GET } from "experimental-ash/channels";
204
222
  import { ashChannel } from "experimental-ash/channels/ash";
205
223
  import { vercelOidc } from "experimental-ash/channels/auth";
224
+ import { githubChannel } from "experimental-ash/channels/github";
206
225
  import { slackChannel } from "experimental-ash/channels/slack";
207
226
  import { telegramChannel } from "experimental-ash/channels/telegram";
208
227
  ```
@@ -63,7 +63,8 @@ Important behavior:
63
63
  - Ash skips prewarm for sandboxes with no `bootstrap()` and no workspace seed files
64
64
  - seed-only templates are keyed by skills and workspace file contents, so unchanged seeds can reuse
65
65
  a template across deploys
66
- - sandboxes with `bootstrap()` remain deployment-scoped
66
+ - sandboxes with `bootstrap()` are keyed by the optional resolved `revalidationKey()` value plus
67
+ authored sandbox source and seed contents, so matching inputs can reuse a template across deploys
67
68
  - the build log labels each template `reused cached` or `built`, so a reuse across deploys is visible
68
69
  - `onSession()` still runs later at runtime
69
70
  - if build-time prewarm fails, the build fails
@@ -0,0 +1,145 @@
1
+ ---
2
+ title: "GitHub channel setup"
3
+ description: "Create a GitHub App-backed Ash channel with automatic PR context and sandbox checkout."
4
+ type: integration
5
+ related:
6
+ - /channels
7
+ - /sandbox
8
+ ---
9
+
10
+ Ash GitHub channels receive GitHub App webhooks at `/ash/v1/github`, verify the webhook signature,
11
+ derive auth from the GitHub actor, and deliver responses back to the native GitHub surface.
12
+
13
+ ## Add The Channel File
14
+
15
+ Create `agent/channels/github.ts`:
16
+
17
+ ```ts
18
+ import { githubChannel } from "experimental-ash/channels/github";
19
+
20
+ export default githubChannel({
21
+ botName: "my-agent",
22
+ credentials: {
23
+ appId: process.env.GITHUB_APP_ID,
24
+ privateKey: process.env.GITHUB_APP_PRIVATE_KEY,
25
+ webhookSecret: process.env.GITHUB_WEBHOOK_SECRET,
26
+ },
27
+ });
28
+ ```
29
+
30
+ Configure the GitHub App webhook URL to `https://<deployment>/ash/v1/github`. Subscribe to
31
+ `issue_comment` and `pull_request_review_comment` for mention-driven turns. Subscribe to `issues`
32
+ and `pull_request` when you configure their opt-in hooks.
33
+
34
+ The agent starts a turn whenever a comment or inline review comment `@mention`s `botName`.
35
+
36
+ Each field has an environment-variable fallback, so the `credentials` block above is optional when
37
+ those variables are set: `appId` reads `GITHUB_APP_ID`, `privateKey` reads `GITHUB_APP_PRIVATE_KEY`,
38
+ `webhookSecret` reads `GITHUB_WEBHOOK_SECRET`, and `botName` reads `GITHUB_APP_SLUG`. `appId`,
39
+ `privateKey`, and `webhookSecret` also accept a function that resolves the value lazily (e.g. from a
40
+ secret manager).
41
+
42
+ ## Acknowledgement & Replies
43
+
44
+ The channel manages the GitHub-native side of a turn for you:
45
+
46
+ - When a turn starts it adds an `eyes` reaction to the triggering comment so the user knows the agent
47
+ picked it up. Disable the reaction with `progress: { reactions: false }`.
48
+ - The agent's reply is posted back to the conversation as a comment (issue/PR timeline comments reply
49
+ on the issue or PR; inline review comments reply in the review thread). Long replies are split
50
+ across multiple comments to stay within GitHub's size limit.
51
+ - If a turn or session fails, the channel posts a short error comment with an error id instead of
52
+ going silent.
53
+
54
+ ## Pull Request Context
55
+
56
+ When the agent is summoned on a pull request, it always sees the PR. The channel injects PR metadata
57
+ and the changed-file diff as `context` strings appended to the turn before the comment. There is no
58
+ flag to disable it — seeing the diff is the point.
59
+
60
+ Large, generated files (lock files, minified bundles, source maps, snapshots) are excluded from the
61
+ diff loaded into the prompt: they are still listed with their stats, but their patch body is omitted.
62
+ Add your own globs with `excludedFiles` (they extend the built-in list):
63
+
64
+ ```ts
65
+ export default githubChannel({
66
+ botName: "my-agent",
67
+ pullRequestContext: {
68
+ excludedFiles: ["**/*.generated.ts", "docs/**/*.svg"],
69
+ },
70
+ });
71
+ ```
72
+
73
+ Excluded files are still on disk via the checkout, so the agent can `read_file` one if it needs the
74
+ contents. Custom inbound hooks can also return their own `context`; Ash prepends the
75
+ channel-generated PR diff first, then your hook context.
76
+
77
+ ## Sandbox Checkout
78
+
79
+ Every triggered turn checks out the relevant ref into the sandbox before the first model call, so the
80
+ built-in `read_file`, `glob`, `grep`, and `bash` tools operate on the real tree:
81
+
82
+ - issue comments and `onIssue` turns check out the repository default branch.
83
+ - PR comments, inline review comments, and `onPullRequest` turns check out the PR head, and also
84
+ fetch the base ref so `git diff <base>...HEAD` works.
85
+
86
+ Checkout brokers a fresh installation token at the sandbox firewall: `git` fetches a clean,
87
+ token-free URL and the platform injects an `Authorization` header on egress to `github.com`, so the
88
+ token never enters the sandbox process. This requires a firewall-capable backend (the Vercel
89
+ backend); the local backend cannot broker, so checkout is skipped there (the failure is logged and
90
+ the turn proceeds with the PR diff still in context).
91
+
92
+ The sandbox persists for the life of the session, so checkout is incremental: when a later turn in
93
+ the same session targets a commit the workspace is already on, the turn skips the fetch entirely
94
+ (no installation token is minted and nothing is downloaded).
95
+
96
+ ## Inbound Hooks
97
+
98
+ Three optional hooks let you customize dispatch. Each returns `{ auth }` to dispatch or `null` to
99
+ ignore.
100
+
101
+ Derive session auth from the GitHub actor with `defaultGitHubAuth(ctx)`.
102
+
103
+ ```ts
104
+ import { defaultGitHubAuth, githubChannel } from "experimental-ash/channels/github";
105
+
106
+ export default githubChannel({
107
+ botName: "my-agent",
108
+
109
+ // Replaces the default `@mention` gate for issue/PR/review comments.
110
+ // ctx.conversation.kind is "issue" | "pull_request" | "review_thread".
111
+ async onComment(ctx, comment) {
112
+ const context: string[] | undefined = comment.body.includes("/grammar")
113
+ ? ["Review only prose, comments, and documentation."]
114
+ : undefined;
115
+ return { auth: defaultGitHubAuth(ctx), context };
116
+ },
117
+
118
+ // Opt in to act on issues. There is no default dispatch on this event.
119
+ onIssue(ctx, issue) {
120
+ if (issue.action !== "opened") return null;
121
+ return { auth: defaultGitHubAuth(ctx) };
122
+ },
123
+
124
+ // Opt in to act on pull requests. There is no default dispatch on this event.
125
+ onPullRequest(ctx, pullRequest) {
126
+ if (pullRequest.action !== "opened") return null;
127
+ return { auth: defaultGitHubAuth(ctx) };
128
+ },
129
+ });
130
+ ```
131
+
132
+ `issue.action` and `pullRequest.action` are typed unions of the common GitHub webhook actions
133
+ (`opened`, `closed`, `edited`, `synchronize`, …) and stay open to any action GitHub sends.
134
+
135
+ ## Arbitrary GitHub API Calls
136
+
137
+ For anything the channel does not wrap, use `ctx.github.request()` with installation-token auth:
138
+
139
+ ```ts
140
+ await ctx.github.request({
141
+ method: "POST",
142
+ path: `/repos/${ctx.repository.fullName}/issues/${issueNumber}/labels`,
143
+ body: { labels: ["triaged"] },
144
+ });
145
+ ```
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: "Channels"
3
- description: "Deliver your agent over HTTP, Slack, Discord, Twilio, Telegram, Microsoft Teams, and custom transports."
3
+ description: "Deliver your agent over HTTP, Slack, GitHub, Discord, Twilio, Telegram, Microsoft Teams, and custom transports."
4
4
  url: /channels
5
5
  ---
6
6
 
@@ -23,7 +23,7 @@ Ash ships the public HTTP protocol as channels:
23
23
  - `ashChannel({ auth })` for the built-in Ash protocol channel
24
24
 
25
25
  Ash also supports authored channels under `agent/channels/` for platform-specific integrations such
26
- as Slack, Discord, Twilio, Telegram, Microsoft Teams, or custom webhooks.
26
+ as Slack, GitHub, Discord, Twilio, Telegram, Microsoft Teams, or custom webhooks.
27
27
 
28
28
  ## Filesystem Shape
29
29
 
@@ -283,6 +283,26 @@ dispatch for app mentions, direct messages, and interactions.
283
283
  For a Slack app backed by Vercel Connect, see [Slack channel setup](./slack.mdx) to create the Connect client
284
284
  and channel file.
285
285
 
286
+ ## GitHub Channels
287
+
288
+ GitHub channels are authored with `githubChannel()`:
289
+
290
+ ```ts
291
+ import { githubChannel } from "experimental-ash/channels/github";
292
+
293
+ export default githubChannel({
294
+ botName: "my-agent",
295
+ });
296
+ ```
297
+
298
+ The channel verifies GitHub App webhooks at `/ash/v1/github`, dispatches bot-directed issue/PR
299
+ comments and pull-request review comments, can opt into issue and pull-request hooks, exposes
300
+ GitHub-native issue, PR, reaction, and checkout helpers, and injects bounded PR metadata,
301
+ file lists, and patch text as turn `context`.
302
+
303
+ See [GitHub channel setup](./github.md) for GitHub App permissions, PR context, checkout, and
304
+ custom inbound hooks.
305
+
286
306
  ## Discord Channels
287
307
 
288
308
  Discord channels are authored with `discordChannel()`:
@@ -632,6 +652,7 @@ See [Channel file uploads](./attachments.md) for the full guide.
632
652
  ## What To Read Next
633
653
 
634
654
  - [Slack channel setup](./slack.mdx)
655
+ - [GitHub channel setup](./github.md)
635
656
  - [Telegram channel setup](./telegram.mdx)
636
657
  - [Channel file uploads](./attachments.md)
637
658
  - [Project Layout](../project-layout.md)
@@ -15,6 +15,7 @@
15
15
  "connections",
16
16
  "---",
17
17
  "advanced",
18
+ "guides",
18
19
  "---",
19
20
  "research"
20
21
  ]
@@ -28,8 +28,8 @@ Collect these up front. A capable agent should use a structured question UI (suc
28
28
  4. **Model provider** — how the agent reaches a model:
29
29
  - Vercel project (default) — create a project, or pass `--project <slug>` to link an existing one, and use AI Gateway via OIDC.
30
30
  - API key override — pass `--gateway-api-key <key>` to write `AI_GATEWAY_API_KEY` to `.env.local`.
31
- - Local only — pass `--local-only` for web/REPL-only setups that should scaffold without a Vercel project; the agent will not reach a model until you add a provider. Slack still requires a Vercel project.
32
- 5. **Deploy** — whether to deploy to Vercel production now. Required for Slack to receive events; pass `--no-deploy` to skip.
31
+ - Skip Vercel — pass `--skip-vercel` for web/REPL-only setups that should scaffold without a Vercel project or Vercel Services config; the agent will not reach a model until you add a provider. Slack still requires a Vercel project.
32
+ 5. **Deploy** — whether to deploy to Vercel production now. Required for Slack to receive events; pass `--skip-deploy` to skip only the final deployment.
33
33
 
34
34
  ## Step 1 — Scaffold (non-interactive)
35
35
 
@@ -42,13 +42,15 @@ npx create-experimental-ash-agent@latest <name> \
42
42
  [--team <slug>] \
43
43
  [--project <slug>] \
44
44
  [--gateway-api-key <key>] \
45
- [--local-only] \
46
- [--no-deploy] \
45
+ [--skip-vercel] \
46
+ [--skip-deploy] \
47
47
  --target-dir <parent-dir> \
48
48
  --yes --json
49
49
  ```
50
50
 
51
- By default the CLI creates a Vercel project named `<name>`, links it non-interactively, and pulls the project's AI Gateway environment. Use `--project <slug>` when the user picked an existing project, `--team <slug>` when they picked a non-current Vercel team, `--gateway-api-key <key>` when they want a pasted key in `.env.local`, and `--local-only` only for web/REPL-only setups where they explicitly do not want Vercel provisioning.
51
+ By default the CLI creates a Vercel project named `<name>`, links it non-interactively, and pulls the project's AI Gateway environment. Use `--project <slug>` when the user picked an existing project, `--team <slug>` when they picked a non-current Vercel team, `--gateway-api-key <key>` when they want a pasted key in `.env.local`, and `--skip-vercel` only for web/REPL-only setups where they explicitly do not want Vercel provisioning or Vercel Services config.
52
+
53
+ To scaffold into an existing directory instead of creating `<parent-dir>/<name>`, omit `<name>` and pass `--in-place --target-dir <dir>`. Add `-y` / `--yes` only when replacing existing Ash scaffold files is intended; the CLI logs every overwritten file.
52
54
 
53
55
  The CLI advances as far as it can without human input. When it reaches a login or browser step, it emits an `action-required` record and exits cleanly instead of blocking on a prompt:
54
56
 
@@ -29,6 +29,7 @@ author a sandbox definition module:
29
29
  import { defineSandbox } from "experimental-ash/sandbox";
30
30
 
31
31
  export default defineSandbox({
32
+ revalidationKey: () => "jq-bootstrap-v1",
32
33
  async bootstrap({ use }) {
33
34
  const sandbox = await use();
34
35
  await sandbox.run({ command: "apt-get install -y jq" });
@@ -52,6 +53,9 @@ The public lifecycle surface is intentionally small:
52
53
 
53
54
  - `bootstrap({ use })` — template-scoped setup (runs once when the template is built). Call `use()`
54
55
  to get a `SandboxSession` for filesystem setup. Only filesystem state survives snapshotting.
56
+ - `revalidationKey()` — optional build-time function for external inputs that affect
57
+ `bootstrap()` output. Authored sandbox source and framework-managed seed contents are included
58
+ automatically.
55
59
  - `onSession({ use })` — durable-session-scoped setup (runs once per session). Call `use(opts?)` to
56
60
  get a `SandboxSession`; `opts` are forwarded to the backend's update path (the Vercel SDK's
57
61
  `sandbox.update(...)`) before the session is returned. `onSession`'s `use()` never creates a
@@ -190,6 +194,13 @@ Inside a subagent's authored code, `ctx.getSandbox()` binds to the subagent's ow
190
194
  Call `use()` to get a `SandboxSession`. Only filesystem state survives — configuration changes
191
195
  like network policy or resource allocation do not persist into the snapshot.
192
196
 
197
+ When external inputs can change `bootstrap()` output, define
198
+ `revalidationKey: () => string | Promise<string>`. Ash evaluates `revalidationKey()` during
199
+ compile/build, stores the resolved string in compiled artifacts, and uses that frozen value for both
200
+ build-time prewarm and runtime session creation. Authored sandbox source and framework-managed seed
201
+ contents are included automatically, so use `revalidationKey()` only for inputs outside that source,
202
+ such as a git commit, lockfile hash, base snapshot version, or daily rotation string.
203
+
193
204
  Framework-managed seed files (compiled skills, authored `workspace/` entries) are written into the
194
205
  template before the authored `bootstrap` runs, so your bootstrap can read them.
195
206
 
@@ -246,6 +257,7 @@ import { defineSandbox, vercelBackend } from "experimental-ash/sandbox";
246
257
 
247
258
  export default defineSandbox({
248
259
  backend: vercelBackend({ runtime: "node24", resources: { vcpus: 2 } }),
260
+ revalidationKey: () => "repo-bootstrap-v1",
249
261
  async bootstrap({ use }) {
250
262
  const sandbox = await use();
251
263
  await sandbox.run({ command: "git clone https://example.com/repo.git repo" });
@@ -322,8 +334,8 @@ also work and follow the same rules. When `source.type === "snapshot"`, the Verc
322
334
  `runtime`, and TypeScript enforces that at the factory call site.
323
335
 
324
336
  Ash does not detect changes to an external snapshot. If you rebuild your snapshot and want Ash to
325
- pick it up, force a template rebuild — for example, by changing the sandbox definition so its
326
- template key changes.
337
+ pick it up, force a template rebuild by changing the `revalidationKey()` value used by your
338
+ bootstrap template.
327
339
 
328
340
  ### Deferring Backend Construction
329
341
 
@@ -473,7 +485,10 @@ On hosted Vercel builds, Ash can prewarm the authored sandbox template during `a
473
485
 
474
486
  Ash skips template prewarm for sandboxes that have no `bootstrap()` and no workspace seed files.
475
487
  Seed-only sandboxes use a content-addressed template key, so matching skills and workspace files can
476
- reuse an existing template across deploys. Sandboxes with `bootstrap()` remain deployment-scoped.
488
+ reuse an existing template across deploys. Sandboxes with `bootstrap()` use the optional resolved
489
+ `revalidationKey` plus authored sandbox source and workspace seed content, so matching inputs can
490
+ reuse an existing template across deploys. Changing `revalidationKey()` or sandbox source only takes
491
+ effect after rebuilding compiled artifacts.
477
492
 
478
493
  Important behavior:
479
494
 
@@ -74,7 +74,7 @@ export default defineRemoteAgent({
74
74
  });
75
75
  ```
76
76
 
77
- Remote agents use the same lowered `{ message: string }` tool shape as local subagents. The
77
+ Remote agents use the same lowered `{ message, outputSchema? }` tool shape as local subagents. The
78
78
  difference is dispatch: the parent starts a task-mode session on the remote agent's
79
79
  `POST /ash/v1/session`, passes a framework callback URL, parks the parent turn, and resumes when
80
80
  the remote agent posts a terminal callback back to the parent. The parent sees the same
@@ -98,11 +98,12 @@ owns redelivery instead of marking the remote task complete.
98
98
 
99
99
  Ash lowers every subagent into a model-visible tool on the parent agent.
100
100
 
101
- The lowered tool always exposes the same single parameter:
101
+ The lowered tool exposes:
102
102
 
103
103
  ```ts
104
104
  {
105
105
  message: string;
106
+ outputSchema?: object;
106
107
  }
107
108
  ```
108
109
 
@@ -110,6 +111,10 @@ The parent fills `message` with everything the subagent needs to run the task
110
111
  not see the parent's history. This mirrors the public message API used to invoke the parent agent
111
112
  itself, so prompt-engineering a delegation feels the same as prompt-engineering an initial run.
112
113
 
114
+ When `outputSchema` is provided, the subagent runs in task mode and must produce structured output
115
+ matching the given JSON Schema via the `final_output` tool. The structured output becomes the tool
116
+ result returned to the parent.
117
+
113
118
  ## What The Subagent Gets
114
119
 
115
120
  Subagent execution gets: