@cursor/july 0.1.29 → 0.1.31

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 (392) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +10 -5
  3. package/dist/bin/agent-serve.js +4 -4
  4. package/dist/channels/github/index.d.ts +1 -1
  5. package/dist/channels/github/index.js +1 -1
  6. package/dist/channels/slack/bot-mentions.d.ts +1 -1
  7. package/dist/channels/slack/bot-mentions.d.ts.map +1 -1
  8. package/dist/channels/slack/bot-mentions.js +1 -1
  9. package/dist/channels/slack/eval-directive.js +1 -1
  10. package/dist/channels/slack/external-policy.d.ts +1 -1
  11. package/dist/channels/slack/external-policy.js +1 -1
  12. package/dist/channels/slack/log.d.ts +1 -1
  13. package/dist/channels/slack/log.js +1 -1
  14. package/dist/channels/slack/setup.js +1 -1
  15. package/dist/channels/slack/socket-mode.js +1 -1
  16. package/dist/docs/404.html +3 -3
  17. package/dist/docs/ab.html +11 -11
  18. package/dist/docs/assets/{ab.md.BMCZ6Hd7.js → ab.md.DAQoJ-up.js} +6 -6
  19. package/dist/docs/assets/{ab.md.BMCZ6Hd7.lean.js → ab.md.DAQoJ-up.lean.js} +1 -1
  20. package/dist/docs/assets/{app.QdunVQKg.js → app.DigB_9cQ.js} +1 -1
  21. package/dist/docs/assets/building-with-agents.md.CnHqvYDd.js +13 -0
  22. package/dist/docs/assets/{building-with-agents.md.CJCtZCyi.lean.js → building-with-agents.md.CnHqvYDd.lean.js} +1 -1
  23. package/dist/docs/assets/chunks/@localSearchIndexroot.CnFFl07y.js +1 -0
  24. package/dist/docs/assets/chunks/{VPLocalSearchBox.B6EpUXYf.js → VPLocalSearchBox.BCMX25Bv.js} +1 -1
  25. package/dist/docs/assets/chunks/{theme.BOTJVqh7.js → theme.BDDWeELx.js} +2 -2
  26. package/dist/docs/assets/concepts.md.DFaQEFkA.js +4 -0
  27. package/dist/docs/assets/concepts.md.DFaQEFkA.lean.js +1 -0
  28. package/dist/docs/assets/deployment.md.9MYBuKM1.js +55 -0
  29. package/dist/docs/assets/deployment.md.9MYBuKM1.lean.js +1 -0
  30. package/dist/docs/assets/{evals.md.DYOjkRCX.js → evals.md.BIUoVZ6X.js} +13 -13
  31. package/dist/docs/assets/evals.md.BIUoVZ6X.lean.js +1 -0
  32. package/dist/docs/assets/{example-agents_approval-buddy.md.DFGBYLcc.js → example-agents_approval-buddy.md.BhEfleVx.js} +4 -4
  33. package/dist/docs/assets/{example-agents_approval-buddy.md.DFGBYLcc.lean.js → example-agents_approval-buddy.md.BhEfleVx.lean.js} +1 -1
  34. package/dist/docs/assets/example-agents_benny.md.2Et1qa8f.js +7 -0
  35. package/dist/docs/assets/{example-agents_bugbot.md.DelIdhxB.js → example-agents_bugbot.md.ByUexi5i.js} +5 -5
  36. package/dist/docs/assets/{example-agents_codebase-wiki.md.DC6sgwn0.js → example-agents_codebase-wiki.md.B4y-7ZVW.js} +6 -6
  37. package/dist/docs/assets/{example-agents_codebase-wiki.md.DC6sgwn0.lean.js → example-agents_codebase-wiki.md.B4y-7ZVW.lean.js} +1 -1
  38. package/dist/docs/assets/{example-agents_codeowners-review.md.Ku_tG2RY.js → example-agents_codeowners-review.md.D6ay4nvf.js} +6 -6
  39. package/dist/docs/assets/{example-agents_codeowners-review.md.Ku_tG2RY.lean.js → example-agents_codeowners-review.md.D6ay4nvf.lean.js} +1 -1
  40. package/dist/docs/assets/{example-agents_concierge.md.4rQTSMXt.js → example-agents_concierge.md.lL8rhYlj.js} +7 -7
  41. package/dist/docs/assets/{example-agents_fsd.md.CzgUrDfi.js → example-agents_fsd.md.DfNKQTHz.js} +5 -5
  42. package/dist/docs/assets/example-agents_index.md.DgGBwckv.js +2 -0
  43. package/dist/docs/assets/example-agents_index.md.DgGBwckv.lean.js +1 -0
  44. package/dist/docs/assets/{example-agents_knowledge-base.md.BPJiVueF.js → example-agents_knowledge-base.md.CzyZ2DCr.js} +5 -5
  45. package/dist/docs/assets/{example-agents_knowledge-base.md.BPJiVueF.lean.js → example-agents_knowledge-base.md.CzyZ2DCr.lean.js} +1 -1
  46. package/dist/docs/assets/example-agents_oncall.md.wFFXXEyW.js +10 -0
  47. package/dist/docs/assets/{example-agents_security-reviewer.md.Dhj_m7_B.js → example-agents_security-reviewer.md.Dkf1gyo6.js} +8 -8
  48. package/dist/docs/assets/example-agents_slack-agent.md.DvgvT4nn.js +5 -0
  49. package/dist/docs/assets/example-agents_weather-agent.md.Dmrcphhl.js +24 -0
  50. package/dist/docs/assets/example-agents_weather-agent.md.Dmrcphhl.lean.js +1 -0
  51. package/dist/docs/assets/{guides_agent-to-agent.md.Bpzgq2Pq.js → guides_agent-to-agent.md.Bmbxy-FA.js} +4 -4
  52. package/dist/docs/assets/guides_cloud-runtime.md.BZ2GA7Es.js +9 -0
  53. package/dist/docs/assets/{guides_github.md.DOOCpqsW.js → guides_github.md.R2QlpR75.js} +5 -5
  54. package/dist/docs/assets/{guides_human-in-the-loop.md.DlUqsp1S.js → guides_human-in-the-loop.md.BWvT7UqY.js} +1 -1
  55. package/dist/docs/assets/{guides_mcp-oauth.md.Dd8EgSem.js → guides_mcp-oauth.md.C7G7IykG.js} +5 -5
  56. package/dist/docs/assets/guides_mcp-oauth.md.C7G7IykG.lean.js +1 -0
  57. package/dist/docs/assets/guides_slack.md.zriQpU_9.js +47 -0
  58. package/dist/docs/assets/guides_slack.md.zriQpU_9.lean.js +1 -0
  59. package/dist/docs/assets/{guides_webhooks.md.wSOYas3X.js → guides_webhooks.md.DiAwSR42.js} +1 -1
  60. package/dist/docs/assets/{hillclimbing.md.DHNast08.js → hillclimbing.md.D9Y1_bYh.js} +1 -1
  61. package/dist/docs/assets/index.md.CZqbBJPB.js +20 -0
  62. package/dist/docs/assets/index.md.CZqbBJPB.lean.js +1 -0
  63. package/dist/docs/assets/{quickstart.md.BU6Iwi_9.js → quickstart.md.TnEXYgYW.js} +12 -12
  64. package/dist/docs/assets/{reference_agent-config.md.DrW2JUM8.js → reference_agent-config.md.kuN6-OxK.js} +1 -1
  65. package/dist/docs/assets/reference_cli.md.sD-IUWjg.js +73 -0
  66. package/dist/docs/assets/{reference_cli.md.ccoKOoXt.lean.js → reference_cli.md.sD-IUWjg.lean.js} +1 -1
  67. package/dist/docs/assets/{reference_connections.md.B9Q3TOve.js → reference_connections.md.DGqAsFXb.js} +3 -3
  68. package/dist/docs/assets/reference_http-api.md.CfVM_ICa.js +11 -0
  69. package/dist/docs/assets/{reference_project-layout.md.Bd_CKtNS.js → reference_project-layout.md.D8E6ZmHJ.js} +4 -4
  70. package/dist/docs/assets/{reference_project-layout.md.Bd_CKtNS.lean.js → reference_project-layout.md.D8E6ZmHJ.lean.js} +1 -1
  71. package/dist/docs/assets/{reference_schedules.md.w_F2mXB6.js → reference_schedules.md.gmfYzf_I.js} +1 -1
  72. package/dist/docs/assets/{reference_sessions.md.DLd6mvbv.js → reference_sessions.md.C_ouF_uf.js} +3 -3
  73. package/dist/docs/assets/{reference_tools.md.BRSDnTbN.js → reference_tools.md.BswAQM41.js} +3 -3
  74. package/dist/docs/assets/{scaffolding-agents.md.C3pTrmoE.js → scaffolding-agents.md.Bsr9Pwzu.js} +1 -1
  75. package/dist/docs/assets/{scaffolding-agents.md.C3pTrmoE.lean.js → scaffolding-agents.md.Bsr9Pwzu.lean.js} +1 -1
  76. package/dist/docs/assets/{storage.md.DRTdnFvd.js → storage.md.xZoiGM58.js} +3 -3
  77. package/dist/docs/assets/storage.md.xZoiGM58.lean.js +1 -0
  78. package/dist/docs/assets/troubleshooting.md.B5RVX_tL.js +1 -0
  79. package/dist/docs/assets/{troubleshooting.md.CmQkmnzC.lean.js → troubleshooting.md.B5RVX_tL.lean.js} +1 -1
  80. package/dist/docs/building-with-agents.html +12 -12
  81. package/dist/docs/concepts.html +6 -6
  82. package/dist/docs/deployment.html +32 -32
  83. package/dist/docs/evals.html +19 -19
  84. package/dist/docs/example-agents/approval-buddy.html +9 -9
  85. package/dist/docs/example-agents/benny.html +11 -11
  86. package/dist/docs/example-agents/bugbot.html +10 -10
  87. package/dist/docs/example-agents/codebase-wiki.html +11 -11
  88. package/dist/docs/example-agents/codeowners-review.html +11 -11
  89. package/dist/docs/example-agents/concierge.html +12 -12
  90. package/dist/docs/example-agents/fsd.html +10 -10
  91. package/dist/docs/example-agents/index.html +7 -7
  92. package/dist/docs/example-agents/knowledge-base.html +10 -10
  93. package/dist/docs/example-agents/oncall.html +10 -10
  94. package/dist/docs/example-agents/security-reviewer.html +13 -13
  95. package/dist/docs/example-agents/slack-agent.html +10 -10
  96. package/dist/docs/example-agents/weather-agent.html +16 -16
  97. package/dist/docs/guides/agent-to-agent.html +9 -9
  98. package/dist/docs/guides/cloud-runtime.html +7 -7
  99. package/dist/docs/guides/github.html +10 -10
  100. package/dist/docs/guides/human-in-the-loop.html +7 -7
  101. package/dist/docs/guides/mcp-oauth.html +11 -11
  102. package/dist/docs/guides/slack.html +22 -17
  103. package/dist/docs/guides/webhooks.html +7 -7
  104. package/dist/docs/hashmap.json +1 -1
  105. package/dist/docs/hillclimbing.html +7 -7
  106. package/dist/docs/index.html +9 -9
  107. package/dist/docs/quickstart.html +17 -17
  108. package/dist/docs/reference/agent-config.html +7 -7
  109. package/dist/docs/reference/channels.html +5 -5
  110. package/dist/docs/reference/cli.html +56 -48
  111. package/dist/docs/reference/connections.html +9 -9
  112. package/dist/docs/reference/hooks.html +5 -5
  113. package/dist/docs/reference/http-api.html +7 -7
  114. package/dist/docs/reference/instructions.html +5 -5
  115. package/dist/docs/reference/playground.html +5 -5
  116. package/dist/docs/reference/project-layout.html +9 -9
  117. package/dist/docs/reference/prompt.html +5 -5
  118. package/dist/docs/reference/schedules.html +7 -7
  119. package/dist/docs/reference/sessions.html +8 -8
  120. package/dist/docs/reference/skills.html +5 -5
  121. package/dist/docs/reference/subagents.html +5 -5
  122. package/dist/docs/reference/tools.html +9 -9
  123. package/dist/docs/scaffolding-agents.html +6 -6
  124. package/dist/docs/storage.html +9 -9
  125. package/dist/docs/troubleshooting.html +6 -6
  126. package/dist/evals/reporters.d.ts +1 -1
  127. package/dist/evals/reporters.js +1 -1
  128. package/dist/evals.d.ts +2 -2
  129. package/dist/files-backends/agent-store-presigned-url.d.ts +100 -0
  130. package/dist/files-backends/agent-store-presigned-url.d.ts.map +1 -0
  131. package/dist/files-backends/agent-store-presigned-url.js +347 -0
  132. package/dist/files-backends/cursor-hosted.d.ts +87 -0
  133. package/dist/files-backends/cursor-hosted.d.ts.map +1 -0
  134. package/dist/files-backends/cursor-hosted.js +540 -0
  135. package/dist/files-backends/local-fs.d.ts +33 -0
  136. package/dist/files-backends/local-fs.d.ts.map +1 -0
  137. package/dist/files-backends/local-fs.js +199 -0
  138. package/dist/files.d.ts +139 -0
  139. package/dist/files.d.ts.map +1 -0
  140. package/dist/files.js +89 -0
  141. package/dist/internal/ab-collector.js +2 -2
  142. package/dist/internal/ab-fold.js +1 -1
  143. package/dist/internal/cli-ax.d.ts +2 -2
  144. package/dist/internal/cli-ax.js +2 -2
  145. package/dist/internal/cli-deploy.d.ts +1 -1
  146. package/dist/internal/cli-deploy.d.ts.map +1 -1
  147. package/dist/internal/cli-deploy.js +7 -2
  148. package/dist/internal/cli-docs.d.ts +1 -1
  149. package/dist/internal/cli-docs.js +1 -1
  150. package/dist/internal/cli-github.js +13 -13
  151. package/dist/internal/cli-mcp-oauth.d.ts +1 -1
  152. package/dist/internal/cli-mcp-oauth.js +2 -2
  153. package/dist/internal/cli-mcp.d.ts +3 -3
  154. package/dist/internal/cli-mcp.js +4 -4
  155. package/dist/internal/cli-skills.js +1 -1
  156. package/dist/internal/cloud-turn-cost.d.ts +9 -1
  157. package/dist/internal/cloud-turn-cost.d.ts.map +1 -1
  158. package/dist/internal/cloud-turn-cost.js +14 -4
  159. package/dist/internal/cursor/account-mcp.js +5 -5
  160. package/dist/internal/cursor/backend-client.js +1 -1
  161. package/dist/internal/cursor/github-credentials.js +3 -3
  162. package/dist/internal/cursor-account-mcp-auth.d.ts +1 -1
  163. package/dist/internal/cursor-account-mcp-auth.js +1 -1
  164. package/dist/internal/cursor-event-relay.js +1 -1
  165. package/dist/internal/cursor-relay-core.d.ts +1 -1
  166. package/dist/internal/cursor-relay-core.d.ts.map +1 -1
  167. package/dist/internal/cursor-slack-relay.js +1 -1
  168. package/dist/internal/deploy-client.d.ts +6 -1
  169. package/dist/internal/deploy-client.d.ts.map +1 -1
  170. package/dist/internal/deploy-client.js +3 -2
  171. package/dist/internal/deploy-source.d.ts +2 -2
  172. package/dist/internal/deploy-source.js +2 -2
  173. package/dist/internal/discovery.js +2 -2
  174. package/dist/internal/distribution.d.ts +5 -5
  175. package/dist/internal/distribution.d.ts.map +1 -1
  176. package/dist/internal/distribution.js +6 -6
  177. package/dist/internal/docs-site.js +5 -5
  178. package/dist/internal/eval-run-store.js +8 -8
  179. package/dist/internal/evals-client.d.ts +1 -1
  180. package/dist/internal/evals-client.js +1 -1
  181. package/dist/internal/github-fanout.js +2 -2
  182. package/dist/internal/host-files.d.ts +29 -0
  183. package/dist/internal/host-files.d.ts.map +1 -0
  184. package/dist/internal/host-files.js +283 -0
  185. package/dist/internal/host-platforms.js +5 -5
  186. package/dist/internal/hosting.d.ts +1 -1
  187. package/dist/internal/hosting.js +1 -1
  188. package/dist/internal/http-channel.d.ts.map +1 -1
  189. package/dist/internal/http-channel.js +26 -0
  190. package/dist/internal/install-cursor-skills.d.ts +1 -1
  191. package/dist/internal/install-cursor-skills.d.ts.map +1 -1
  192. package/dist/internal/install-cursor-skills.js +33 -4
  193. package/dist/internal/local-control-plane.js +2 -2
  194. package/dist/internal/logs-client.d.ts +2 -2
  195. package/dist/internal/logs-client.js +2 -2
  196. package/dist/internal/mcp-endpoint.js +1 -1
  197. package/dist/internal/mcp-oauth.js +2 -2
  198. package/dist/internal/platform-schedule-sync.js +2 -2
  199. package/dist/internal/playground/toolchain.js +6 -6
  200. package/dist/internal/reminder-runner.js +13 -13
  201. package/dist/internal/resolved-connections.js +6 -6
  202. package/dist/internal/schedule-runner.js +1 -1
  203. package/dist/internal/sdk-runner.js +5 -5
  204. package/dist/internal/server.js +16 -16
  205. package/dist/internal/session-cost.d.ts +3 -2
  206. package/dist/internal/session-cost.d.ts.map +1 -1
  207. package/dist/internal/session-cost.js +7 -6
  208. package/dist/internal/session-engine.d.ts +31 -1
  209. package/dist/internal/session-engine.d.ts.map +1 -1
  210. package/dist/internal/session-engine.js +119 -31
  211. package/dist/internal/slack-provision-client.js +1 -1
  212. package/dist/internal/storage-coordinator.js +7 -7
  213. package/dist/internal/trajectory.js +2 -2
  214. package/dist/internal/turn-cost.d.ts +27 -0
  215. package/dist/internal/turn-cost.d.ts.map +1 -0
  216. package/dist/internal/turn-cost.js +83 -0
  217. package/dist/internal/update-check.d.ts +3 -3
  218. package/dist/internal/update-check.d.ts.map +1 -1
  219. package/dist/internal/update-check.js +5 -5
  220. package/dist/memory.d.ts +1 -1
  221. package/dist/memory.js +1 -1
  222. package/dist/playground/assets/index-50PKeJlG.css +1 -0
  223. package/dist/playground/assets/index-C0f2Wl1q.js +85 -0
  224. package/dist/playground/index.html +2 -2
  225. package/dist/storage.d.ts +1 -1
  226. package/dist/storage.js +1 -1
  227. package/dist/types.d.ts +120 -16
  228. package/dist/types.d.ts.map +1 -1
  229. package/docs/README.md +23 -23
  230. package/docs/ab.md +12 -12
  231. package/docs/building-with-agents.md +9 -9
  232. package/docs/concepts.md +11 -11
  233. package/docs/deployment.md +55 -43
  234. package/docs/evals.md +20 -20
  235. package/docs/example-agents/approval-buddy.md +9 -9
  236. package/docs/example-agents/benny.md +13 -13
  237. package/docs/example-agents/bugbot.md +6 -6
  238. package/docs/example-agents/codebase-wiki.md +8 -8
  239. package/docs/example-agents/codeowners-review.md +8 -8
  240. package/docs/example-agents/concierge.md +10 -10
  241. package/docs/example-agents/fsd.md +7 -7
  242. package/docs/example-agents/index.md +8 -8
  243. package/docs/example-agents/knowledge-base.md +9 -9
  244. package/docs/example-agents/oncall.md +7 -7
  245. package/docs/example-agents/security-reviewer.md +12 -12
  246. package/docs/example-agents/slack-agent.md +10 -10
  247. package/docs/example-agents/weather-agent.md +30 -26
  248. package/docs/guides/agent-to-agent.md +4 -4
  249. package/docs/guides/cloud-runtime.md +3 -3
  250. package/docs/guides/github.md +6 -6
  251. package/docs/guides/human-in-the-loop.md +1 -1
  252. package/docs/guides/mcp-oauth.md +9 -9
  253. package/docs/guides/slack.md +94 -21
  254. package/docs/guides/webhooks.md +1 -1
  255. package/docs/hillclimbing.md +3 -3
  256. package/docs/quickstart.md +18 -18
  257. package/docs/reference/agent-config.md +1 -1
  258. package/docs/reference/cli.md +110 -79
  259. package/docs/reference/connections.md +3 -3
  260. package/docs/reference/http-api.md +2 -2
  261. package/docs/reference/project-layout.md +7 -7
  262. package/docs/reference/schedules.md +1 -1
  263. package/docs/reference/sessions.md +7 -7
  264. package/docs/reference/tools.md +3 -3
  265. package/docs/scaffolding-agents.md +2 -2
  266. package/docs/storage.md +5 -5
  267. package/docs/troubleshooting.md +11 -10
  268. package/package.json +3 -1
  269. package/skills/ab/SKILL.md +5 -5
  270. package/skills/create-agent/SKILL.md +17 -17
  271. package/skills/debug/SKILL.md +10 -10
  272. package/skills/evals/SKILL.md +13 -13
  273. package/skills/framework-map/SKILL.md +3 -3
  274. package/skills/github/SKILL.md +11 -11
  275. package/skills/hillclimb/SKILL.md +9 -9
  276. package/skills/mcp-auth/SKILL.md +11 -11
  277. package/skills/setup-slack/SKILL.md +28 -28
  278. package/src/bin/agent-serve.ts +4 -4
  279. package/src/channels/github/index.ts +1 -1
  280. package/src/channels/slack/bot-mentions.ts +1 -1
  281. package/src/channels/slack/eval-directive.ts +1 -1
  282. package/src/channels/slack/external-policy.ts +1 -1
  283. package/src/channels/slack/log.ts +1 -1
  284. package/src/channels/slack/setup.ts +1 -1
  285. package/src/channels/slack/socket-mode.ts +1 -1
  286. package/src/evals/reporters.ts +1 -1
  287. package/src/evals.ts +2 -2
  288. package/src/files-backends/agent-store-presigned-url.ts +402 -0
  289. package/src/files-backends/cursor-hosted.ts +698 -0
  290. package/src/files-backends/local-fs.ts +178 -0
  291. package/src/files.ts +195 -0
  292. package/src/internal/ab-collector.ts +2 -2
  293. package/src/internal/ab-fold.ts +1 -1
  294. package/src/internal/cli-ax.ts +2 -2
  295. package/src/internal/cli-deploy.ts +7 -2
  296. package/src/internal/cli-docs.ts +1 -1
  297. package/src/internal/cli-github.ts +13 -13
  298. package/src/internal/cli-mcp-oauth.ts +2 -2
  299. package/src/internal/cli-mcp.ts +4 -4
  300. package/src/internal/cli-skills.ts +1 -1
  301. package/src/internal/cloud-turn-cost.ts +20 -4
  302. package/src/internal/cursor/account-mcp.ts +5 -5
  303. package/src/internal/cursor/backend-client.ts +1 -1
  304. package/src/internal/cursor/github-credentials.ts +3 -3
  305. package/src/internal/cursor-account-mcp-auth.ts +1 -1
  306. package/src/internal/cursor-event-relay.ts +1 -1
  307. package/src/internal/cursor-relay-core.ts +1 -1
  308. package/src/internal/cursor-slack-relay.ts +1 -1
  309. package/src/internal/deploy-client.ts +8 -2
  310. package/src/internal/deploy-source.ts +2 -2
  311. package/src/internal/discovery.ts +2 -2
  312. package/src/internal/distribution.ts +6 -6
  313. package/src/internal/docs-site.ts +5 -5
  314. package/src/internal/eval-run-store.ts +8 -8
  315. package/src/internal/evals-client.ts +1 -1
  316. package/src/internal/github-fanout.ts +2 -2
  317. package/src/internal/host-files.ts +372 -0
  318. package/src/internal/host-platforms.ts +5 -5
  319. package/src/internal/hosting.ts +1 -1
  320. package/src/internal/http-channel.ts +30 -0
  321. package/src/internal/install-cursor-skills.ts +31 -3
  322. package/src/internal/local-control-plane.ts +2 -2
  323. package/src/internal/logs-client.ts +2 -2
  324. package/src/internal/mcp-endpoint.ts +1 -1
  325. package/src/internal/mcp-oauth.ts +2 -2
  326. package/src/internal/platform-schedule-sync.ts +2 -2
  327. package/src/internal/playground/toolchain.ts +6 -6
  328. package/src/internal/reminder-runner.ts +13 -13
  329. package/src/internal/resolved-connections.ts +6 -6
  330. package/src/internal/schedule-runner.ts +1 -1
  331. package/src/internal/sdk-runner.ts +5 -5
  332. package/src/internal/server.ts +16 -16
  333. package/src/internal/session-cost.ts +7 -6
  334. package/src/internal/session-engine.ts +141 -28
  335. package/src/internal/slack-provision-client.ts +1 -1
  336. package/src/internal/storage-coordinator.ts +7 -7
  337. package/src/internal/trajectory.ts +2 -2
  338. package/src/internal/turn-cost.ts +110 -0
  339. package/src/internal/update-check.ts +6 -6
  340. package/src/memory.ts +1 -1
  341. package/src/storage.ts +1 -1
  342. package/src/types.ts +148 -16
  343. package/dist/docs/assets/building-with-agents.md.CJCtZCyi.js +0 -13
  344. package/dist/docs/assets/chunks/@localSearchIndexroot.DGe61XHA.js +0 -1
  345. package/dist/docs/assets/concepts.md.Cfb9b-k1.js +0 -4
  346. package/dist/docs/assets/concepts.md.Cfb9b-k1.lean.js +0 -1
  347. package/dist/docs/assets/deployment.md.TecHo0_2.js +0 -55
  348. package/dist/docs/assets/deployment.md.TecHo0_2.lean.js +0 -1
  349. package/dist/docs/assets/evals.md.DYOjkRCX.lean.js +0 -1
  350. package/dist/docs/assets/example-agents_benny.md.B0gjhI-p.js +0 -7
  351. package/dist/docs/assets/example-agents_index.md.D2PEVSXl.js +0 -2
  352. package/dist/docs/assets/example-agents_index.md.D2PEVSXl.lean.js +0 -1
  353. package/dist/docs/assets/example-agents_oncall.md.BG_sUMly.js +0 -10
  354. package/dist/docs/assets/example-agents_slack-agent.md.buLbgvBf.js +0 -5
  355. package/dist/docs/assets/example-agents_weather-agent.md.C9Qv-W0o.js +0 -24
  356. package/dist/docs/assets/example-agents_weather-agent.md.C9Qv-W0o.lean.js +0 -1
  357. package/dist/docs/assets/guides_cloud-runtime.md.gVzabdQL.js +0 -9
  358. package/dist/docs/assets/guides_mcp-oauth.md.Dd8EgSem.lean.js +0 -1
  359. package/dist/docs/assets/guides_slack.md.CjmJSvZS.js +0 -42
  360. package/dist/docs/assets/guides_slack.md.CjmJSvZS.lean.js +0 -1
  361. package/dist/docs/assets/index.md.CH_s5uZe.js +0 -20
  362. package/dist/docs/assets/index.md.CH_s5uZe.lean.js +0 -1
  363. package/dist/docs/assets/reference_cli.md.ccoKOoXt.js +0 -65
  364. package/dist/docs/assets/reference_http-api.md.BncLd3PZ.js +0 -11
  365. package/dist/docs/assets/storage.md.DRTdnFvd.lean.js +0 -1
  366. package/dist/docs/assets/troubleshooting.md.CmQkmnzC.js +0 -1
  367. package/dist/internal/model-pricing.d.ts +0 -49
  368. package/dist/internal/model-pricing.d.ts.map +0 -1
  369. package/dist/internal/model-pricing.js +0 -377
  370. package/dist/playground/assets/index-CquRB-l0.js +0 -85
  371. package/dist/playground/assets/index-Dj0bWpkn.css +0 -1
  372. package/src/internal/model-pricing.ts +0 -426
  373. /package/dist/docs/assets/{example-agents_benny.md.B0gjhI-p.lean.js → example-agents_benny.md.2Et1qa8f.lean.js} +0 -0
  374. /package/dist/docs/assets/{example-agents_bugbot.md.DelIdhxB.lean.js → example-agents_bugbot.md.ByUexi5i.lean.js} +0 -0
  375. /package/dist/docs/assets/{example-agents_concierge.md.4rQTSMXt.lean.js → example-agents_concierge.md.lL8rhYlj.lean.js} +0 -0
  376. /package/dist/docs/assets/{example-agents_fsd.md.CzgUrDfi.lean.js → example-agents_fsd.md.DfNKQTHz.lean.js} +0 -0
  377. /package/dist/docs/assets/{example-agents_oncall.md.BG_sUMly.lean.js → example-agents_oncall.md.wFFXXEyW.lean.js} +0 -0
  378. /package/dist/docs/assets/{example-agents_security-reviewer.md.Dhj_m7_B.lean.js → example-agents_security-reviewer.md.Dkf1gyo6.lean.js} +0 -0
  379. /package/dist/docs/assets/{example-agents_slack-agent.md.buLbgvBf.lean.js → example-agents_slack-agent.md.DvgvT4nn.lean.js} +0 -0
  380. /package/dist/docs/assets/{guides_agent-to-agent.md.Bpzgq2Pq.lean.js → guides_agent-to-agent.md.Bmbxy-FA.lean.js} +0 -0
  381. /package/dist/docs/assets/{guides_cloud-runtime.md.gVzabdQL.lean.js → guides_cloud-runtime.md.BZ2GA7Es.lean.js} +0 -0
  382. /package/dist/docs/assets/{guides_github.md.DOOCpqsW.lean.js → guides_github.md.R2QlpR75.lean.js} +0 -0
  383. /package/dist/docs/assets/{guides_human-in-the-loop.md.DlUqsp1S.lean.js → guides_human-in-the-loop.md.BWvT7UqY.lean.js} +0 -0
  384. /package/dist/docs/assets/{guides_webhooks.md.wSOYas3X.lean.js → guides_webhooks.md.DiAwSR42.lean.js} +0 -0
  385. /package/dist/docs/assets/{hillclimbing.md.DHNast08.lean.js → hillclimbing.md.D9Y1_bYh.lean.js} +0 -0
  386. /package/dist/docs/assets/{quickstart.md.BU6Iwi_9.lean.js → quickstart.md.TnEXYgYW.lean.js} +0 -0
  387. /package/dist/docs/assets/{reference_agent-config.md.DrW2JUM8.lean.js → reference_agent-config.md.kuN6-OxK.lean.js} +0 -0
  388. /package/dist/docs/assets/{reference_connections.md.B9Q3TOve.lean.js → reference_connections.md.DGqAsFXb.lean.js} +0 -0
  389. /package/dist/docs/assets/{reference_http-api.md.BncLd3PZ.lean.js → reference_http-api.md.CfVM_ICa.lean.js} +0 -0
  390. /package/dist/docs/assets/{reference_schedules.md.w_F2mXB6.lean.js → reference_schedules.md.gmfYzf_I.lean.js} +0 -0
  391. /package/dist/docs/assets/{reference_sessions.md.DLd6mvbv.lean.js → reference_sessions.md.C_ouF_uf.lean.js} +0 -0
  392. /package/dist/docs/assets/{reference_tools.md.BRSDnTbN.lean.js → reference_tools.md.BswAQM41.lean.js} +0 -0
@@ -1,8 +1,8 @@
1
- import{_ as a,c as s,o as t,ag as i}from"./chunks/framework.CAZyNGu9.js";const g=JSON.parse('{"title":"Build a feature wiki from merged pull requests","description":"Ingest every merged PR into per-feature wiki pages, consolidate with a daily digest schedule, and answer codebase questions with page citations.","frontmatter":{"title":"Build a feature wiki from merged pull requests","description":"Ingest every merged PR into per-feature wiki pages, consolidate with a daily digest schedule, and answer codebase questions with page citations."},"headers":[],"relativePath":"example-agents/codebase-wiki.md","filePath":"example-agents/codebase-wiki.md"}'),n={name:"example-agents/codebase-wiki.md"};function d(o,e,l,h,r,p){return t(),s("div",null,[...e[0]||(e[0]=[i(`<h1 id="build-a-feature-wiki-from-merged-pull-requests" tabindex="-1">Build a feature wiki from merged pull requests <a class="header-anchor" href="#build-a-feature-wiki-from-merged-pull-requests" aria-label="Permalink to &quot;Build a feature wiki from merged pull requests&quot;">​</a></h1><p>Codebase wiki keeps a living, feature-organized wiki of a repository. The GitHub channel acknowledges every closed pull request instantly, fetches a compact digest on the host, and spends a model turn only on merged PRs. The turn maps the change onto feature pages; a daily schedule writes a digest of what changed and rebuilds the index. Chat sessions answer codebase questions from the wiki with page citations.</p><p>Use this project when documentation should accumulate from merges instead of being regenerated from scratch. Use <a href="./knowledge-base.html">Knowledge base</a> when people should curate organizational context through conversation.</p><p><a href="./../../examples/codebase-wiki/">Browse the codebase wiki source.</a></p><h2 id="treat-prs-as-evidence-and-features-as-pages" tabindex="-1">Treat PRs as evidence and features as pages <a class="header-anchor" href="#treat-prs-as-evidence-and-features-as-pages" aria-label="Permalink to &quot;Treat PRs as evidence and features as pages&quot;">​</a></h2><p>The wiki refuses to become a merge log:</p><ul><li>The page tree is rigid: <code>index</code>, <code>features/&lt;slug&gt;</code>, and <code>digests/&lt;yyyy-mm-dd&gt;</code>. The store rejects anything else, so the wiki can&#39;t sprawl.</li><li>The <code>feature-mapping</code> skill requires a <code>wiki_search</code> before every write. A PR updates the page that owns its feature; a new page needs a genuinely new feature; chores change nothing.</li><li>Every touched page gets a dated changelog entry citing the PR number, so each fact traces back to a merge.</li></ul><p>The wiki itself is markdown on the serve host, in <code>.agent-serve/wiki/</code> by default with a <code>CODEBASE_WIKI_DIR</code> override. Sessions are disposable; the wiki is the durable state.</p><h2 id="follow-a-merged-pr" tabindex="-1">Follow a merged PR <a class="header-anchor" href="#follow-a-merged-pr" aria-label="Permalink to &quot;Follow a merged PR&quot;">​</a></h2><ol><li>GitHub delivers <code>pull_request</code> with action <code>closed</code>. The channel returns a task acknowledgement immediately.</li><li>The task fetches the digest with the host <code>gh</code> CLI: title, body, labels, changed files, and a bounded diff excerpt. No checkout.</li><li>The webhook payload can&#39;t say whether the PR merged, so the host checks <code>mergedAt</code> and skips abandoned PRs without a model turn.</li><li>For merged PRs, the task starts the turn with <code>pr/DIGEST.md</code> seeded through <code>workspaceFiles</code> and a <code>pr:&lt;owner/repo#N&gt;</code> continuation token, so redeliveries resume instead of double-ingesting.</li><li>The model follows <code>feature-mapping</code>: search, update or create feature pages, add changelog entries, and refresh <code>index</code> when pages were added.</li></ol><p>In chat, &quot;ingest PR #123&quot; runs the same flow through the <code>ingest_pr</code> tool, which writes the digest into the active session workspace.</p><h2 id="map-the-wiki-files" tabindex="-1">Map the wiki files <a class="header-anchor" href="#map-the-wiki-files" aria-label="Permalink to &quot;Map the wiki files&quot;">​</a></h2><table tabindex="0"><thead><tr><th>File</th><th>Purpose</th></tr></thead><tbody><tr><td><a href="../../examples/codebase-wiki/agent/agent.ts"><code>agent/agent.ts</code></a></td><td>Selects the cloud runtime and model.</td></tr><tr><td><a href="./../../examples/codebase-wiki/agent/instructions.html"><code>agent/instructions.md</code></a></td><td>Splits the job into merge ingestion and wiki-cited Q&amp;A.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/lib/wiki-store.ts"><code>agent/lib/wiki-store.ts</code></a></td><td>Enforces the rigid page tree and owns reads, writes, and search.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/lib/pr-digest.ts"><code>agent/lib/pr-digest.ts</code></a></td><td>Fetches PR metadata and diff, and formats <code>pr/DIGEST.md</code>.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/tools/ingest_pr.ts"><code>agent/tools/ingest_pr.ts</code></a></td><td>Exposes host digest preparation for chat-driven backfills.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/tools/wiki_read.ts"><code>agent/tools/wiki_read.ts</code></a>, <a href="../../examples/codebase-wiki/agent/tools/wiki_search.ts"><code>wiki_search.ts</code></a>, <a href="../../examples/codebase-wiki/agent/tools/wiki_write.ts"><code>wiki_write.ts</code></a></td><td>Read, search, and rewrite wiki pages.</td></tr><tr><td><a href="./../../examples/codebase-wiki/agent/skills/feature-mapping.html"><code>agent/skills/feature-mapping.md</code></a></td><td>Maps changes onto features and fixes the page and changelog shape.</td></tr><tr><td><a href="./../../examples/codebase-wiki/agent/schedules/daily-digest.html"><code>agent/schedules/daily-digest.md</code></a></td><td>Writes <code>digests/&lt;date&gt;</code>, rebuilds the index, and flags stale pages.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/channels/github.ts"><code>agent/channels/github.ts</code></a></td><td>Acknowledges closed PRs and starts merged-only ingest turns.</td></tr><tr><td><a href="../../examples/codebase-wiki/evals/ingest.eval.ts"><code>evals/ingest.eval.ts</code></a></td><td>Gates ingest decisions against the wiki filesystem.</td></tr></tbody></table><p>There is no MCP connection, subagent, hook, A/B experiment, or custom storage.</p><h2 id="prepare-credentials-and-services" tabindex="-1">Prepare credentials and services <a class="header-anchor" href="#prepare-credentials-and-services" aria-label="Permalink to &quot;Prepare credentials and services&quot;">​</a></h2><p>You need:</p><ul><li>Node 22.13 or newer.</li><li>An agent-runtime credential for model turns.</li><li><code>gh</code> on <code>PATH</code> with read access to the PRs you ingest.</li></ul><p>The channel verifies webhook signatures when <code>GITHUB_WEBHOOK_SECRET</code> is set and narrows repositories with <code>CODEBASE_WIKI_REPOS=owner/repo,owner/other</code>. The agent never writes to GitHub. Its only side effects are wiki files on the serve host.</p><h2 id="validate-the-surface" tabindex="-1">Validate the surface <a class="header-anchor" href="#validate-the-surface" aria-label="Permalink to &quot;Validate the surface&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span></span>
2
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> info</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span></code></pre></div><p>The manifest should report four server tools, one skill, one schedule, and the authored GitHub channel.</p><h2 id="ingest-without-webhook-plumbing" tabindex="-1">Ingest without webhook plumbing <a class="header-anchor" href="#ingest-without-webhook-plumbing" aria-label="Permalink to &quot;Ingest without webhook plumbing&quot;">​</a></h2><p>Replay a real merged PR as a closed delivery:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span></span>
1
+ import{_ as s,c as a,o as t,ag as i}from"./chunks/framework.CAZyNGu9.js";const g=JSON.parse('{"title":"Build a feature wiki from merged pull requests","description":"Ingest every merged PR into per-feature wiki pages, consolidate with a daily digest schedule, and answer codebase questions with page citations.","frontmatter":{"title":"Build a feature wiki from merged pull requests","description":"Ingest every merged PR into per-feature wiki pages, consolidate with a daily digest schedule, and answer codebase questions with page citations."},"headers":[],"relativePath":"example-agents/codebase-wiki.md","filePath":"example-agents/codebase-wiki.md"}'),n={name:"example-agents/codebase-wiki.md"};function d(o,e,l,h,r,p){return t(),a("div",null,[...e[0]||(e[0]=[i(`<h1 id="build-a-feature-wiki-from-merged-pull-requests" tabindex="-1">Build a feature wiki from merged pull requests <a class="header-anchor" href="#build-a-feature-wiki-from-merged-pull-requests" aria-label="Permalink to &quot;Build a feature wiki from merged pull requests&quot;">​</a></h1><p>Codebase wiki keeps a living, feature-organized wiki of a repository. The GitHub channel acknowledges every closed pull request instantly, fetches a compact digest on the host, and spends a model turn only on merged PRs. The turn maps the change onto feature pages; a daily schedule writes a digest of what changed and rebuilds the index. Chat sessions answer codebase questions from the wiki with page citations.</p><p>Use this project when documentation should accumulate from merges instead of being regenerated from scratch. Use <a href="./knowledge-base.html">Knowledge base</a> when people should curate organizational context through conversation.</p><p><a href="./../../examples/codebase-wiki/">Browse the codebase wiki source.</a></p><h2 id="treat-prs-as-evidence-and-features-as-pages" tabindex="-1">Treat PRs as evidence and features as pages <a class="header-anchor" href="#treat-prs-as-evidence-and-features-as-pages" aria-label="Permalink to &quot;Treat PRs as evidence and features as pages&quot;">​</a></h2><p>The wiki refuses to become a merge log:</p><ul><li>The page tree is rigid: <code>index</code>, <code>features/&lt;slug&gt;</code>, and <code>digests/&lt;yyyy-mm-dd&gt;</code>. The store rejects anything else, so the wiki can&#39;t sprawl.</li><li>The <code>feature-mapping</code> skill requires a <code>wiki_search</code> before every write. A PR updates the page that owns its feature; a new page needs a genuinely new feature; chores change nothing.</li><li>Every touched page gets a dated changelog entry citing the PR number, so each fact traces back to a merge.</li></ul><p>The wiki itself is markdown on the serve host, in <code>.agent-serve/wiki/</code> by default with a <code>CODEBASE_WIKI_DIR</code> override. Sessions are disposable; the wiki is the durable state.</p><h2 id="follow-a-merged-pr" tabindex="-1">Follow a merged PR <a class="header-anchor" href="#follow-a-merged-pr" aria-label="Permalink to &quot;Follow a merged PR&quot;">​</a></h2><ol><li>GitHub delivers <code>pull_request</code> with action <code>closed</code>. The channel returns a task acknowledgement immediately.</li><li>The task fetches the digest with the host <code>gh</code> CLI: title, body, labels, changed files, and a bounded diff excerpt. No checkout.</li><li>The webhook payload can&#39;t say whether the PR merged, so the host checks <code>mergedAt</code> and skips abandoned PRs without a model turn.</li><li>For merged PRs, the task starts the turn with <code>pr/DIGEST.md</code> seeded through <code>workspaceFiles</code> and a <code>pr:&lt;owner/repo#N&gt;</code> continuation token, so redeliveries resume instead of double-ingesting.</li><li>The model follows <code>feature-mapping</code>: search, update or create feature pages, add changelog entries, and refresh <code>index</code> when pages were added.</li></ol><p>In chat, &quot;ingest PR #123&quot; runs the same flow through the <code>ingest_pr</code> tool, which writes the digest into the active session workspace.</p><h2 id="map-the-wiki-files" tabindex="-1">Map the wiki files <a class="header-anchor" href="#map-the-wiki-files" aria-label="Permalink to &quot;Map the wiki files&quot;">​</a></h2><table tabindex="0"><thead><tr><th>File</th><th>Purpose</th></tr></thead><tbody><tr><td><a href="../../examples/codebase-wiki/agent/agent.ts"><code>agent/agent.ts</code></a></td><td>Selects the cloud runtime and model.</td></tr><tr><td><a href="./../../examples/codebase-wiki/agent/instructions.html"><code>agent/instructions.md</code></a></td><td>Splits the job into merge ingestion and wiki-cited Q&amp;A.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/lib/wiki-store.ts"><code>agent/lib/wiki-store.ts</code></a></td><td>Enforces the rigid page tree and owns reads, writes, and search.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/lib/pr-digest.ts"><code>agent/lib/pr-digest.ts</code></a></td><td>Fetches PR metadata and diff, and formats <code>pr/DIGEST.md</code>.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/tools/ingest_pr.ts"><code>agent/tools/ingest_pr.ts</code></a></td><td>Exposes host digest preparation for chat-driven backfills.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/tools/wiki_read.ts"><code>agent/tools/wiki_read.ts</code></a>, <a href="../../examples/codebase-wiki/agent/tools/wiki_search.ts"><code>wiki_search.ts</code></a>, <a href="../../examples/codebase-wiki/agent/tools/wiki_write.ts"><code>wiki_write.ts</code></a></td><td>Read, search, and rewrite wiki pages.</td></tr><tr><td><a href="./../../examples/codebase-wiki/agent/skills/feature-mapping.html"><code>agent/skills/feature-mapping.md</code></a></td><td>Maps changes onto features and fixes the page and changelog shape.</td></tr><tr><td><a href="./../../examples/codebase-wiki/agent/schedules/daily-digest.html"><code>agent/schedules/daily-digest.md</code></a></td><td>Writes <code>digests/&lt;date&gt;</code>, rebuilds the index, and flags stale pages.</td></tr><tr><td><a href="../../examples/codebase-wiki/agent/channels/github.ts"><code>agent/channels/github.ts</code></a></td><td>Acknowledges closed PRs and starts merged-only ingest turns.</td></tr><tr><td><a href="../../examples/codebase-wiki/evals/ingest.eval.ts"><code>evals/ingest.eval.ts</code></a></td><td>Gates ingest decisions against the wiki filesystem.</td></tr></tbody></table><p>There is no MCP connection, subagent, hook, A/B experiment, or custom storage.</p><h2 id="prepare-credentials-and-services" tabindex="-1">Prepare credentials and services <a class="header-anchor" href="#prepare-credentials-and-services" aria-label="Permalink to &quot;Prepare credentials and services&quot;">​</a></h2><p>You need:</p><ul><li>Node 22.13 or newer.</li><li>An agent-runtime credential for model turns.</li><li><code>gh</code> on <code>PATH</code> with read access to the PRs you ingest.</li></ul><p>The channel verifies webhook signatures when <code>GITHUB_WEBHOOK_SECRET</code> is set and narrows repositories with <code>CODEBASE_WIKI_REPOS=owner/repo,owner/other</code>. The agent never writes to GitHub. Its only side effects are wiki files on the serve host.</p><h2 id="validate-the-surface" tabindex="-1">Validate the surface <a class="header-anchor" href="#validate-the-surface" aria-label="Permalink to &quot;Validate the surface&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span></span>
2
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> info</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span></code></pre></div><p>The manifest should report four server tools, one skill, one schedule, and the authored GitHub channel.</p><h2 id="ingest-without-webhook-plumbing" tabindex="-1">Ingest without webhook plumbing <a class="header-anchor" href="#ingest-without-webhook-plumbing" aria-label="Permalink to &quot;Ingest without webhook plumbing&quot;">​</a></h2><p>Replay a real merged PR as a closed delivery:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span></span>
3
3
  <span class="line"></span>
4
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> github</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> replay</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> https://github.com/owner/repo/pull/123</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
5
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --action</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> closed</span></span></code></pre></div><p>The reply is a 202 acknowledgement; the ingest continues in the task. Watch the session in the playground, then read the result on disk:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">ls</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki/.agent-serve/wiki/features/</span></span></code></pre></div><p>Each ingested feature page carries an overview, a &quot;How it works&quot; section, and a changelog line citing the PR. Deterministic digest preparation works without a model turn:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> call</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ingest_pr</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
4
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> github</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> replay</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> https://github.com/owner/repo/pull/123</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
5
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --action</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> closed</span></span></code></pre></div><p>The reply is a 202 acknowledgement; the ingest continues in the task. Watch the session in the playground, then read the result on disk:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">ls</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki/.agent-serve/wiki/features/</span></span></code></pre></div><p>Each ingested feature page carries an overview, a &quot;How it works&quot; section, and a changelog line citing the PR. Deterministic digest preparation works without a model turn:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> call</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ingest_pr</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
6
6
  <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
7
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;{&quot;pr&quot;:&quot;https://github.com/owner/repo/pull/123&quot;}&#39;</span></span></code></pre></div><p>A PR closed without merging returns <code>merged: false</code> and a note telling the model to change nothing.</p><h2 id="run-the-daily-digest" tabindex="-1">Run the daily digest <a class="header-anchor" href="#run-the-daily-digest" aria-label="Permalink to &quot;Run the daily digest&quot;">​</a></h2><p>The schedule fires at 07:00 UTC. Under <code>agentkit dev</code>, trigger it by hand:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -s</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -X</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> POST</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> http://127.0.0.1:3000/codebase-wiki/v1/dev/schedules/daily-digest</span></span></code></pre></div><p>The turn reads every feature changelog, writes <code>digests/&lt;today&gt;</code> grouped by feature with PR citations, rebuilds <code>index</code>, and reports one line per page it wrote. Entries dated today always count; a digest only claims a quiet day when no entry qualifies.</p><h2 id="run-the-evals" tabindex="-1">Run the evals <a class="header-anchor" href="#run-the-evals" aria-label="Permalink to &quot;Run the evals&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --list</span></span>
8
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ingest/update-existing</span></span></code></pre></div><p>The cases seed a temp wiki through <code>CODEBASE_WIKI_DIR</code> and build digests with the same formatter the channel uses, so they run without GitHub or network access. The gates check the filesystem, not prose: a new feature page lands on a new slug, a related PR updates the existing page instead of duplicating it, an unmerged PR changes nothing, and the daily pass writes a digest naming both seeded features.</p><h2 id="reuse-the-merge-ingestion-pattern" tabindex="-1">Reuse the merge-ingestion pattern <a class="header-anchor" href="#reuse-the-merge-ingestion-pattern" aria-label="Permalink to &quot;Reuse the merge-ingestion pattern&quot;">​</a></h2><p>Copy this shape when events should accumulate into curated state:</p><ul><li>Acknowledge webhooks with a task and decide host-side whether a model turn is worth spending.</li><li>Seed evidence through <code>workspaceFiles</code> so the model never fetches.</li><li>Constrain the durable store&#39;s shape in code and its content in a skill.</li><li>Add a consolidation schedule so incremental writes stay coherent.</li></ul><h2 id="where-to-go-next" tabindex="-1">Where to go next <a class="header-anchor" href="#where-to-go-next" aria-label="Permalink to &quot;Where to go next&quot;">​</a></h2><ul><li><a href="./../guides/github.html">GitHub webhooks</a></li><li><a href="./../reference/schedules.html">Schedules</a></li><li><a href="./../reference/tools.html">Tools</a></li><li><a href="./../evals.html">Evals</a></li></ul>`,41)])])}const k=a(n,[["render",d]]);export{g as __pageData,k as default};
7
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;{&quot;pr&quot;:&quot;https://github.com/owner/repo/pull/123&quot;}&#39;</span></span></code></pre></div><p>A PR closed without merging returns <code>merged: false</code> and a note telling the model to change nothing.</p><h2 id="run-the-daily-digest" tabindex="-1">Run the daily digest <a class="header-anchor" href="#run-the-daily-digest" aria-label="Permalink to &quot;Run the daily digest&quot;">​</a></h2><p>The schedule fires at 07:00 UTC. Under <code>agent-sdk dev</code>, trigger it by hand:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -s</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -X</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> POST</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> http://127.0.0.1:3000/codebase-wiki/v1/dev/schedules/daily-digest</span></span></code></pre></div><p>The turn reads every feature changelog, writes <code>digests/&lt;today&gt;</code> grouped by feature with PR citations, rebuilds <code>index</code>, and reports one line per page it wrote. Entries dated today always count; a digest only claims a quiet day when no entry qualifies.</p><h2 id="run-the-evals" tabindex="-1">Run the evals <a class="header-anchor" href="#run-the-evals" aria-label="Permalink to &quot;Run the evals&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --list</span></span>
8
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codebase-wiki</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ingest/update-existing</span></span></code></pre></div><p>The cases seed a temp wiki through <code>CODEBASE_WIKI_DIR</code> and build digests with the same formatter the channel uses, so they run without GitHub or network access. The gates check the filesystem, not prose: a new feature page lands on a new slug, a related PR updates the existing page instead of duplicating it, an unmerged PR changes nothing, and the daily pass writes a digest naming both seeded features.</p><h2 id="reuse-the-merge-ingestion-pattern" tabindex="-1">Reuse the merge-ingestion pattern <a class="header-anchor" href="#reuse-the-merge-ingestion-pattern" aria-label="Permalink to &quot;Reuse the merge-ingestion pattern&quot;">​</a></h2><p>Copy this shape when events should accumulate into curated state:</p><ul><li>Acknowledge webhooks with a task and decide host-side whether a model turn is worth spending.</li><li>Seed evidence through <code>workspaceFiles</code> so the model never fetches.</li><li>Constrain the durable store&#39;s shape in code and its content in a skill.</li><li>Add a consolidation schedule so incremental writes stay coherent.</li></ul><h2 id="where-to-go-next" tabindex="-1">Where to go next <a class="header-anchor" href="#where-to-go-next" aria-label="Permalink to &quot;Where to go next&quot;">​</a></h2><ul><li><a href="./../guides/github.html">GitHub webhooks</a></li><li><a href="./../reference/schedules.html">Schedules</a></li><li><a href="./../reference/tools.html">Tools</a></li><li><a href="./../evals.html">Evals</a></li></ul>`,41)])])}const k=s(n,[["render",d]]);export{g as __pageData,k as default};
@@ -1 +1 @@
1
- import{_ as a,c as s,o as t,ag as i}from"./chunks/framework.CAZyNGu9.js";const g=JSON.parse('{"title":"Build a feature wiki from merged pull requests","description":"Ingest every merged PR into per-feature wiki pages, consolidate with a daily digest schedule, and answer codebase questions with page citations.","frontmatter":{"title":"Build a feature wiki from merged pull requests","description":"Ingest every merged PR into per-feature wiki pages, consolidate with a daily digest schedule, and answer codebase questions with page citations."},"headers":[],"relativePath":"example-agents/codebase-wiki.md","filePath":"example-agents/codebase-wiki.md"}'),n={name:"example-agents/codebase-wiki.md"};function d(o,e,l,h,r,p){return t(),s("div",null,[...e[0]||(e[0]=[i("",41)])])}const k=a(n,[["render",d]]);export{g as __pageData,k as default};
1
+ import{_ as s,c as a,o as t,ag as i}from"./chunks/framework.CAZyNGu9.js";const g=JSON.parse('{"title":"Build a feature wiki from merged pull requests","description":"Ingest every merged PR into per-feature wiki pages, consolidate with a daily digest schedule, and answer codebase questions with page citations.","frontmatter":{"title":"Build a feature wiki from merged pull requests","description":"Ingest every merged PR into per-feature wiki pages, consolidate with a daily digest schedule, and answer codebase questions with page citations."},"headers":[],"relativePath":"example-agents/codebase-wiki.md","filePath":"example-agents/codebase-wiki.md"}'),n={name:"example-agents/codebase-wiki.md"};function d(o,e,l,h,r,p){return t(),a("div",null,[...e[0]||(e[0]=[i("",41)])])}const k=s(n,[["render",d]]);export{g as __pageData,k as default};
@@ -1,8 +1,8 @@
1
- import{_ as a,c as t,o as i,ag as s}from"./chunks/framework.CAZyNGu9.js";const u=JSON.parse('{"title":"Route PR reviews by code ownership","description":"Map changed paths to per-area review playbooks, fan one reviewer subagent out per area, and aggregate verdicts into a single approval decision.","frontmatter":{"title":"Route PR reviews by code ownership","description":"Map changed paths to per-area review playbooks, fan one reviewer subagent out per area, and aggregate verdicts into a single approval decision."},"headers":[],"relativePath":"example-agents/codeowners-review.md","filePath":"example-agents/codeowners-review.md"}'),r={name:"example-agents/codeowners-review.md"};function o(n,e,l,d,h,p){return i(),t("div",null,[...e[0]||(e[0]=[s(`<h1 id="route-pr-reviews-by-code-ownership" tabindex="-1">Route PR reviews by code ownership <a class="header-anchor" href="#route-pr-reviews-by-code-ownership" aria-label="Permalink to &quot;Route PR reviews by code ownership&quot;">​</a></h1><p>Codeowners review gives each part of a codebase its own review. A CODEOWNERS-style table maps changed paths to review areas; each area has a markdown playbook with the team&#39;s rules for that domain; and one <code>area-reviewer</code> subagent runs per routed area, in parallel. A billing change gets the billing review, a migration gets the migration review, and an author&#39;s personal style rides along as advisory notes. The lead aggregates: approve only when every area approves.</p><p>Use this project when review quality depends on domain-specific values instead of one generic checklist.</p><p><a href="./../../examples/codeowners-review/">Browse the codeowners review source.</a></p><h2 id="keep-routing-in-code-and-judgment-in-playbooks" tabindex="-1">Keep routing in code and judgment in playbooks <a class="header-anchor" href="#keep-routing-in-code-and-judgment-in-playbooks" aria-label="Permalink to &quot;Keep routing in code and judgment in playbooks&quot;">​</a></h2><p>The pipeline separates three concerns:</p><ul><li><code>reviews/REVIEWERS</code> routes. Host code matches every changed path against the table; every matching rule applies, and unmatched paths fall back to the <code>general</code> playbook. Routing is glob code with unit tests, not model judgment.</li><li><code>reviews/&lt;area&gt;.md</code> judges. Each playbook is a severity-ordered rule list the team owns: billing mandates integer cents and idempotent webhooks, migrations forbid destructive DDL beside code changes, background jobs demand idempotency and dead-letter paths.</li><li>Subagents review. The lead reads nothing but the manifest and routes; each <code>area-reviewer</code> reads one playbook plus its files&#39; diff hunks and returns a mechanical verdict: request changes on any High finding or two Mediums.</li></ul><p>Personal styles extend the same mechanism. <code>reviews/people/&lt;login&gt;.md</code> attaches automatically, as advisory notes, whenever that person authors the PR. Adding an area or a style is a markdown file plus at most one routing line.</p><h2 id="follow-a-review" tabindex="-1">Follow a review <a class="header-anchor" href="#follow-a-review" aria-label="Permalink to &quot;Follow a review&quot;">​</a></h2><ol><li>A PR arrives: a GitHub <code>pull_request</code> event, a chat message, or a bundled fixture reference.</li><li><code>prepare_review</code> fetches metadata and the diff with the host <code>gh</code> CLI, routes every changed file, and writes the <code>pr/</code> evidence tree: <code>MANIFEST.md</code>, <code>ROUTES.md</code>, <code>diff.patch</code>, and a copy of each matched playbook.</li><li>The lead follows the <code>review-process</code> skill and issues one <code>area-reviewer</code> delegation per routed area, plus one per personal style, all in one step so they run in parallel.</li><li>Each reviewer reads its playbook, reviews only its files, and returns a verdict line with at most three findings.</li><li>The lead aggregates per-area sections and the overall verdict: APPROVE only when every non-advisory area approved.</li></ol><p>Nothing posts to GitHub. Verdicts live in the session; the <a href="./approval-buddy.html">Approval Buddy guide</a> shows how to wire a real APPROVE and commit statuses on top of the same shape.</p><h2 id="map-the-review-files" tabindex="-1">Map the review files <a class="header-anchor" href="#map-the-review-files" aria-label="Permalink to &quot;Map the review files&quot;">​</a></h2><table tabindex="0"><thead><tr><th>File</th><th>Purpose</th></tr></thead><tbody><tr><td><a href="./../../examples/codeowners-review/reviews/REVIEWERS.html"><code>reviews/REVIEWERS</code></a></td><td>Routes path patterns to review areas.</td></tr><tr><td><a href="./../../examples/codeowners-review/reviews/"><code>reviews/</code></a></td><td>Holds the area playbooks and <code>people/&lt;login&gt;.md</code> styles.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/lib/routing.ts"><code>agent/lib/routing.ts</code></a></td><td>Parses the table, matches globs, and unions areas per file.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/lib/prepare-review.ts"><code>agent/lib/prepare-review.ts</code></a></td><td>Fetches PRs or fixtures and builds the evidence tree.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/tools/prepare_review.ts"><code>agent/tools/prepare_review.ts</code></a></td><td>Exposes host preparation as a typed server tool.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/tools/list_review_areas.ts"><code>agent/tools/list_review_areas.ts</code></a></td><td>Answers routing questions deterministically.</td></tr><tr><td><a href="./../../examples/codeowners-review/agent/skills/review-process.html"><code>agent/skills/review-process.md</code></a></td><td>Fixes the fan-out procedure and the verdict rule.</td></tr><tr><td><a href="./../../examples/codeowners-review/agent/subagents/area-reviewer/"><code>agent/subagents/area-reviewer/</code></a></td><td>Defines the one-area, one-playbook reviewer contract.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/channels/github.ts"><code>agent/channels/github.ts</code></a></td><td>Reviews opened, reopened, synchronized, and undrafted PRs.</td></tr><tr><td><a href="./../../examples/codeowners-review/fixtures/"><code>fixtures/</code></a></td><td>Ships two reviewable PRs with known planted findings.</td></tr><tr><td><a href="../../examples/codeowners-review/evals/review.eval.ts"><code>evals/review.eval.ts</code></a></td><td>Gates routing, fan-out, planted bugs, and verdicts.</td></tr></tbody></table><p>There is no MCP connection, schedule, hook, A/B experiment, or custom storage.</p><h2 id="prepare-credentials-and-services" tabindex="-1">Prepare credentials and services <a class="header-anchor" href="#prepare-credentials-and-services" aria-label="Permalink to &quot;Prepare credentials and services&quot;">​</a></h2><p>You need:</p><ul><li>Node 22.13 or newer.</li><li>An agent-runtime credential for model turns.</li><li><code>gh</code> on <code>PATH</code> with read access to real PRs you review. The bundled fixtures need no network at all.</li></ul><p>The channel verifies webhook signatures when <code>GITHUB_WEBHOOK_SECRET</code> is set and narrows repositories with <code>CODEOWNERS_REVIEW_REPOS=owner/repo,owner/other</code>. Pushes re-review in the same session through the <code>pr:&lt;label&gt;</code> continuation token.</p><h2 id="validate-the-surface" tabindex="-1">Validate the surface <a class="header-anchor" href="#validate-the-surface" aria-label="Permalink to &quot;Validate the surface&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span></span>
2
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> info</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span></code></pre></div><p>The manifest should report two server tools, one skill, one subagent, and the authored GitHub channel.</p><h2 id="inspect-routing-without-a-model-turn" tabindex="-1">Inspect routing without a model turn <a class="header-anchor" href="#inspect-routing-without-a-model-turn" aria-label="Permalink to &quot;Inspect routing without a model turn&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> call</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> list_review_areas</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;{}&#39;</span></span>
1
+ import{_ as a,c as s,o as t,ag as i}from"./chunks/framework.CAZyNGu9.js";const u=JSON.parse('{"title":"Route PR reviews by code ownership","description":"Map changed paths to per-area review playbooks, fan one reviewer subagent out per area, and aggregate verdicts into a single approval decision.","frontmatter":{"title":"Route PR reviews by code ownership","description":"Map changed paths to per-area review playbooks, fan one reviewer subagent out per area, and aggregate verdicts into a single approval decision."},"headers":[],"relativePath":"example-agents/codeowners-review.md","filePath":"example-agents/codeowners-review.md"}'),r={name:"example-agents/codeowners-review.md"};function o(n,e,l,d,h,p){return t(),s("div",null,[...e[0]||(e[0]=[i(`<h1 id="route-pr-reviews-by-code-ownership" tabindex="-1">Route PR reviews by code ownership <a class="header-anchor" href="#route-pr-reviews-by-code-ownership" aria-label="Permalink to &quot;Route PR reviews by code ownership&quot;">​</a></h1><p>Codeowners review gives each part of a codebase its own review. A CODEOWNERS-style table maps changed paths to review areas; each area has a markdown playbook with the team&#39;s rules for that domain; and one <code>area-reviewer</code> subagent runs per routed area, in parallel. A billing change gets the billing review, a migration gets the migration review, and an author&#39;s personal style rides along as advisory notes. The lead aggregates: approve only when every area approves.</p><p>Use this project when review quality depends on domain-specific values instead of one generic checklist.</p><p><a href="./../../examples/codeowners-review/">Browse the codeowners review source.</a></p><h2 id="keep-routing-in-code-and-judgment-in-playbooks" tabindex="-1">Keep routing in code and judgment in playbooks <a class="header-anchor" href="#keep-routing-in-code-and-judgment-in-playbooks" aria-label="Permalink to &quot;Keep routing in code and judgment in playbooks&quot;">​</a></h2><p>The pipeline separates three concerns:</p><ul><li><code>reviews/REVIEWERS</code> routes. Host code matches every changed path against the table; every matching rule applies, and unmatched paths fall back to the <code>general</code> playbook. Routing is glob code with unit tests, not model judgment.</li><li><code>reviews/&lt;area&gt;.md</code> judges. Each playbook is a severity-ordered rule list the team owns: billing mandates integer cents and idempotent webhooks, migrations forbid destructive DDL beside code changes, background jobs demand idempotency and dead-letter paths.</li><li>Subagents review. The lead reads nothing but the manifest and routes; each <code>area-reviewer</code> reads one playbook plus its files&#39; diff hunks and returns a mechanical verdict: request changes on any High finding or two Mediums.</li></ul><p>Personal styles extend the same mechanism. <code>reviews/people/&lt;login&gt;.md</code> attaches automatically, as advisory notes, whenever that person authors the PR. Adding an area or a style is a markdown file plus at most one routing line.</p><h2 id="follow-a-review" tabindex="-1">Follow a review <a class="header-anchor" href="#follow-a-review" aria-label="Permalink to &quot;Follow a review&quot;">​</a></h2><ol><li>A PR arrives: a GitHub <code>pull_request</code> event, a chat message, or a bundled fixture reference.</li><li><code>prepare_review</code> fetches metadata and the diff with the host <code>gh</code> CLI, routes every changed file, and writes the <code>pr/</code> evidence tree: <code>MANIFEST.md</code>, <code>ROUTES.md</code>, <code>diff.patch</code>, and a copy of each matched playbook.</li><li>The lead follows the <code>review-process</code> skill and issues one <code>area-reviewer</code> delegation per routed area, plus one per personal style, all in one step so they run in parallel.</li><li>Each reviewer reads its playbook, reviews only its files, and returns a verdict line with at most three findings.</li><li>The lead aggregates per-area sections and the overall verdict: APPROVE only when every non-advisory area approved.</li></ol><p>Nothing posts to GitHub. Verdicts live in the session; the <a href="./approval-buddy.html">Approval Buddy guide</a> shows how to wire a real APPROVE and commit statuses on top of the same shape.</p><h2 id="map-the-review-files" tabindex="-1">Map the review files <a class="header-anchor" href="#map-the-review-files" aria-label="Permalink to &quot;Map the review files&quot;">​</a></h2><table tabindex="0"><thead><tr><th>File</th><th>Purpose</th></tr></thead><tbody><tr><td><a href="./../../examples/codeowners-review/reviews/REVIEWERS.html"><code>reviews/REVIEWERS</code></a></td><td>Routes path patterns to review areas.</td></tr><tr><td><a href="./../../examples/codeowners-review/reviews/"><code>reviews/</code></a></td><td>Holds the area playbooks and <code>people/&lt;login&gt;.md</code> styles.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/lib/routing.ts"><code>agent/lib/routing.ts</code></a></td><td>Parses the table, matches globs, and unions areas per file.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/lib/prepare-review.ts"><code>agent/lib/prepare-review.ts</code></a></td><td>Fetches PRs or fixtures and builds the evidence tree.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/tools/prepare_review.ts"><code>agent/tools/prepare_review.ts</code></a></td><td>Exposes host preparation as a typed server tool.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/tools/list_review_areas.ts"><code>agent/tools/list_review_areas.ts</code></a></td><td>Answers routing questions deterministically.</td></tr><tr><td><a href="./../../examples/codeowners-review/agent/skills/review-process.html"><code>agent/skills/review-process.md</code></a></td><td>Fixes the fan-out procedure and the verdict rule.</td></tr><tr><td><a href="./../../examples/codeowners-review/agent/subagents/area-reviewer/"><code>agent/subagents/area-reviewer/</code></a></td><td>Defines the one-area, one-playbook reviewer contract.</td></tr><tr><td><a href="../../examples/codeowners-review/agent/channels/github.ts"><code>agent/channels/github.ts</code></a></td><td>Reviews opened, reopened, synchronized, and undrafted PRs.</td></tr><tr><td><a href="./../../examples/codeowners-review/fixtures/"><code>fixtures/</code></a></td><td>Ships two reviewable PRs with known planted findings.</td></tr><tr><td><a href="../../examples/codeowners-review/evals/review.eval.ts"><code>evals/review.eval.ts</code></a></td><td>Gates routing, fan-out, planted bugs, and verdicts.</td></tr></tbody></table><p>There is no MCP connection, schedule, hook, A/B experiment, or custom storage.</p><h2 id="prepare-credentials-and-services" tabindex="-1">Prepare credentials and services <a class="header-anchor" href="#prepare-credentials-and-services" aria-label="Permalink to &quot;Prepare credentials and services&quot;">​</a></h2><p>You need:</p><ul><li>Node 22.13 or newer.</li><li>An agent-runtime credential for model turns.</li><li><code>gh</code> on <code>PATH</code> with read access to real PRs you review. The bundled fixtures need no network at all.</li></ul><p>The channel verifies webhook signatures when <code>GITHUB_WEBHOOK_SECRET</code> is set and narrows repositories with <code>CODEOWNERS_REVIEW_REPOS=owner/repo,owner/other</code>. Pushes re-review in the same session through the <code>pr:&lt;label&gt;</code> continuation token.</p><h2 id="validate-the-surface" tabindex="-1">Validate the surface <a class="header-anchor" href="#validate-the-surface" aria-label="Permalink to &quot;Validate the surface&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span></span>
2
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> info</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span></code></pre></div><p>The manifest should report two server tools, one skill, one subagent, and the authored GitHub channel.</p><h2 id="inspect-routing-without-a-model-turn" tabindex="-1">Inspect routing without a model turn <a class="header-anchor" href="#inspect-routing-without-a-model-turn" aria-label="Permalink to &quot;Inspect routing without a model turn&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> call</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> list_review_areas</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;{}&#39;</span></span>
3
3
  <span class="line"></span>
4
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> call</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> prepare_review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
4
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> call</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> prepare_review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
5
5
  <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
6
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;{&quot;pr&quot;:&quot;fixture:multi-area&quot;}&#39;</span></span></code></pre></div><p>The fixture routes to <code>billing</code>, <code>database-migrations</code>, and <code>frontend</code>, attaches <code>people/alice</code> because alice authored it, and returns the full evidence map. Point the same tool at a real PR URL and the routing runs against the live file list. The example table maps a hypothetical <code>src/</code> layout, so most real repositories route to <code>general</code> until you adapt <code>reviews/REVIEWERS</code>.</p><h2 id="review-the-planted-fixture" tabindex="-1">Review the planted fixture <a class="header-anchor" href="#review-the-planted-fixture" aria-label="Permalink to &quot;Review the planted fixture&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span></span></code></pre></div><p>In the playground:</p><blockquote><p>Review fixture:multi-area</p></blockquote><p>The fixture plants one violation per area: float dollar math in <code>src/billing/invoice.ts</code>, a <code>DROP COLUMN</code> plus a non-concurrent index in the migration, and a clickable <code>div</code> without loading states in the UI. The trace shows <code>prepare_review</code>, the evidence reads, four parallel <code>area-reviewer</code> cards, and an aggregated CHANGES REQUESTED verdict with each planted bug filed under its own area. The second fixture, <code>fixture:jobs-clean</code>, routes to <code>background-jobs</code> alone and ends in APPROVE.</p><p>Review a real PR the same way:</p><blockquote><p>Review <a href="https://github.com/owner/repo/pull/123" target="_blank" rel="noreferrer">https://github.com/owner/repo/pull/123</a></p></blockquote><p>Or replay one as a webhook delivery:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> github</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> replay</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> https://github.com/owner/repo/pull/123</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
7
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --action</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> opened</span></span></code></pre></div><h2 id="see-how-the-verdict-stays-mechanical" tabindex="-1">See how the verdict stays mechanical <a class="header-anchor" href="#see-how-the-verdict-stays-mechanical" aria-label="Permalink to &quot;See how the verdict stays mechanical&quot;">​</a></h2><p>The reviewer contract computes verdicts from findings instead of letting the model pick a mood: findings first, then <code>request-changes</code> if any High exists or two Mediums do, otherwise <code>approve</code>. Pre-existing issues visible in context are scoped out, at most one advisory Low. The lead applies one rule on top: the PR is APPROVE only when every non-advisory area approved.</p><h2 id="run-the-evals" tabindex="-1">Run the evals <a class="header-anchor" href="#run-the-evals" aria-label="Permalink to &quot;Run the evals&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --list</span></span>
8
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> review/multi-area</span></span></code></pre></div><p><code>review/multi-area</code> gates the whole pipeline: <code>prepare_review</code> runs, at least three subagent delegations happen, the reply carries every area section plus alice&#39;s advisory notes, the planted billing and migration bugs surface, and the verdict requests changes. <code>review/clean-approve</code> proves the approval path on the clean fixture, and <code>review/routing-question</code> gates that routing answers come from <code>list_review_areas</code>.</p><h2 id="reuse-the-ownership-routing-pattern" tabindex="-1">Reuse the ownership-routing pattern <a class="header-anchor" href="#reuse-the-ownership-routing-pattern" aria-label="Permalink to &quot;Reuse the ownership-routing pattern&quot;">​</a></h2><p>Copy this shape when different code deserves different judgment:</p><ul><li>Route with data and code, not prompt instructions. Tables and globs are testable.</li><li>Write one playbook per domain and keep each reviewer blind to the others.</li><li>Make verdicts mechanical so aggregation is arithmetic, not negotiation.</li><li>Ship fixtures with planted findings so the review quality itself is testable offline.</li></ul><h2 id="where-to-go-next" tabindex="-1">Where to go next <a class="header-anchor" href="#where-to-go-next" aria-label="Permalink to &quot;Where to go next&quot;">​</a></h2><ul><li><a href="./approval-buddy.html">Approval Buddy</a> for posting real approvals</li><li><a href="./../reference/subagents.html">Subagents</a></li><li><a href="./../guides/github.html">GitHub webhooks</a></li><li><a href="./../evals.html">Evals</a></li></ul>`,43)])])}const g=a(r,[["render",o]]);export{u as __pageData,g as default};
6
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;{&quot;pr&quot;:&quot;fixture:multi-area&quot;}&#39;</span></span></code></pre></div><p>The fixture routes to <code>billing</code>, <code>database-migrations</code>, and <code>frontend</code>, attaches <code>people/alice</code> because alice authored it, and returns the full evidence map. Point the same tool at a real PR URL and the routing runs against the live file list. The example table maps a hypothetical <code>src/</code> layout, so most real repositories route to <code>general</code> until you adapt <code>reviews/REVIEWERS</code>.</p><h2 id="review-the-planted-fixture" tabindex="-1">Review the planted fixture <a class="header-anchor" href="#review-the-planted-fixture" aria-label="Permalink to &quot;Review the planted fixture&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span></span></code></pre></div><p>In the playground:</p><blockquote><p>Review fixture:multi-area</p></blockquote><p>The fixture plants one violation per area: float dollar math in <code>src/billing/invoice.ts</code>, a <code>DROP COLUMN</code> plus a non-concurrent index in the migration, and a clickable <code>div</code> without loading states in the UI. The trace shows <code>prepare_review</code>, the evidence reads, four parallel <code>area-reviewer</code> cards, and an aggregated CHANGES REQUESTED verdict with each planted bug filed under its own area. The second fixture, <code>fixture:jobs-clean</code>, routes to <code>background-jobs</code> alone and ends in APPROVE.</p><p>Review a real PR the same way:</p><blockquote><p>Review <a href="https://github.com/owner/repo/pull/123" target="_blank" rel="noreferrer">https://github.com/owner/repo/pull/123</a></p></blockquote><p>Or replay one as a webhook delivery:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> github</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> replay</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> https://github.com/owner/repo/pull/123</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
7
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --action</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> opened</span></span></code></pre></div><h2 id="see-how-the-verdict-stays-mechanical" tabindex="-1">See how the verdict stays mechanical <a class="header-anchor" href="#see-how-the-verdict-stays-mechanical" aria-label="Permalink to &quot;See how the verdict stays mechanical&quot;">​</a></h2><p>The reviewer contract computes verdicts from findings instead of letting the model pick a mood: findings first, then <code>request-changes</code> if any High exists or two Mediums do, otherwise <code>approve</code>. Pre-existing issues visible in context are scoped out, at most one advisory Low. The lead applies one rule on top: the PR is APPROVE only when every non-advisory area approved.</p><h2 id="run-the-evals" tabindex="-1">Run the evals <a class="header-anchor" href="#run-the-evals" aria-label="Permalink to &quot;Run the evals&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --list</span></span>
8
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/codeowners-review</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> review/multi-area</span></span></code></pre></div><p><code>review/multi-area</code> gates the whole pipeline: <code>prepare_review</code> runs, at least three subagent delegations happen, the reply carries every area section plus alice&#39;s advisory notes, the planted billing and migration bugs surface, and the verdict requests changes. <code>review/clean-approve</code> proves the approval path on the clean fixture, and <code>review/routing-question</code> gates that routing answers come from <code>list_review_areas</code>.</p><h2 id="reuse-the-ownership-routing-pattern" tabindex="-1">Reuse the ownership-routing pattern <a class="header-anchor" href="#reuse-the-ownership-routing-pattern" aria-label="Permalink to &quot;Reuse the ownership-routing pattern&quot;">​</a></h2><p>Copy this shape when different code deserves different judgment:</p><ul><li>Route with data and code, not prompt instructions. Tables and globs are testable.</li><li>Write one playbook per domain and keep each reviewer blind to the others.</li><li>Make verdicts mechanical so aggregation is arithmetic, not negotiation.</li><li>Ship fixtures with planted findings so the review quality itself is testable offline.</li></ul><h2 id="where-to-go-next" tabindex="-1">Where to go next <a class="header-anchor" href="#where-to-go-next" aria-label="Permalink to &quot;Where to go next&quot;">​</a></h2><ul><li><a href="./approval-buddy.html">Approval Buddy</a> for posting real approvals</li><li><a href="./../reference/subagents.html">Subagents</a></li><li><a href="./../guides/github.html">GitHub webhooks</a></li><li><a href="./../evals.html">Evals</a></li></ul>`,43)])])}const g=a(r,[["render",o]]);export{u as __pageData,g as default};
@@ -1 +1 @@
1
- import{_ as a,c as t,o as i,ag as s}from"./chunks/framework.CAZyNGu9.js";const u=JSON.parse('{"title":"Route PR reviews by code ownership","description":"Map changed paths to per-area review playbooks, fan one reviewer subagent out per area, and aggregate verdicts into a single approval decision.","frontmatter":{"title":"Route PR reviews by code ownership","description":"Map changed paths to per-area review playbooks, fan one reviewer subagent out per area, and aggregate verdicts into a single approval decision."},"headers":[],"relativePath":"example-agents/codeowners-review.md","filePath":"example-agents/codeowners-review.md"}'),r={name:"example-agents/codeowners-review.md"};function o(n,e,l,d,h,p){return i(),t("div",null,[...e[0]||(e[0]=[s("",43)])])}const g=a(r,[["render",o]]);export{u as __pageData,g as default};
1
+ import{_ as a,c as s,o as t,ag as i}from"./chunks/framework.CAZyNGu9.js";const u=JSON.parse('{"title":"Route PR reviews by code ownership","description":"Map changed paths to per-area review playbooks, fan one reviewer subagent out per area, and aggregate verdicts into a single approval decision.","frontmatter":{"title":"Route PR reviews by code ownership","description":"Map changed paths to per-area review playbooks, fan one reviewer subagent out per area, and aggregate verdicts into a single approval decision."},"headers":[],"relativePath":"example-agents/codeowners-review.md","filePath":"example-agents/codeowners-review.md"}'),r={name:"example-agents/codeowners-review.md"};function o(n,e,l,d,h,p){return t(),s("div",null,[...e[0]||(e[0]=[i("",43)])])}const g=a(r,[["render",o]]);export{u as __pageData,g as default};
@@ -1,9 +1,9 @@
1
- import{_ as s,c as a,o as i,ag as t}from"./chunks/framework.CAZyNGu9.js";const k=JSON.parse('{"title":"Compose agents with a concierge","description":"Delegate weather requests through a peer MCP connection while each agent keeps its own instructions, tools, context, and sessions.","frontmatter":{"title":"Compose agents with a concierge","description":"Delegate weather requests through a peer MCP connection while each agent keeps its own instructions, tools, context, and sessions."},"headers":[],"relativePath":"example-agents/concierge.md","filePath":"example-agents/concierge.md"}'),n={name:"example-agents/concierge.md"};function l(h,e,o,r,p,d){return i(),a("div",null,[...e[0]||(e[0]=[t(`<h1 id="compose-agents-with-a-concierge" tabindex="-1">Compose agents with a concierge <a class="header-anchor" href="#compose-agents-with-a-concierge" aria-label="Permalink to &quot;Compose agents with a concierge&quot;">​</a></h1><p>Concierge answers general questions itself and sends every weather question to the weather agent. The connection is one file. Agentkit turns the target agent&#39;s MCP endpoint into tools the concierge can call.</p><p>Use this example when two agents are useful on their own and one should delegate a narrow class of work to the other.</p><p><a href="./../../examples/concierge/">Browse the Concierge source.</a></p><h2 id="delegate-through-a-peer-mcp-connection" tabindex="-1">Delegate through a peer MCP connection <a class="header-anchor" href="#delegate-through-a-peer-mcp-connection" aria-label="Permalink to &quot;Delegate through a peer MCP connection&quot;">​</a></h2><p>Concierge has no domain tool of its own. Its capability comes from a peer MCP connection:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineConnection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
1
+ import{_ as s,c as a,o as i,ag as t}from"./chunks/framework.CAZyNGu9.js";const k=JSON.parse('{"title":"Compose agents with a concierge","description":"Delegate weather requests through a peer MCP connection while each agent keeps its own instructions, tools, context, and sessions.","frontmatter":{"title":"Compose agents with a concierge","description":"Delegate weather requests through a peer MCP connection while each agent keeps its own instructions, tools, context, and sessions."},"headers":[],"relativePath":"example-agents/concierge.md","filePath":"example-agents/concierge.md"}'),n={name:"example-agents/concierge.md"};function l(h,e,o,r,p,d){return i(),a("div",null,[...e[0]||(e[0]=[t(`<h1 id="compose-agents-with-a-concierge" tabindex="-1">Compose agents with a concierge <a class="header-anchor" href="#compose-agents-with-a-concierge" aria-label="Permalink to &quot;Compose agents with a concierge&quot;">​</a></h1><p>Concierge answers general questions itself and sends every weather question to the weather agent. The connection is one file. The Agent SDK turns the target agent&#39;s MCP endpoint into tools the concierge can call.</p><p>Use this example when two agents are useful on their own and one should delegate a narrow class of work to the other.</p><p><a href="./../../examples/concierge/">Browse the Concierge source.</a></p><h2 id="delegate-through-a-peer-mcp-connection" tabindex="-1">Delegate through a peer MCP connection <a class="header-anchor" href="#delegate-through-a-peer-mcp-connection" aria-label="Permalink to &quot;Delegate through a peer MCP connection&quot;">​</a></h2><p>Concierge has no domain tool of its own. Its capability comes from a peer MCP connection:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineConnection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
2
2
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> agent: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;weather-agent&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
3
3
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> description:</span></span>
4
4
  <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;The weather-agent peer: delegate weather questions with ask; it runs its own tools (live Open-Meteo data) in its own context.&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
5
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>The filename <a href="../../examples/concierge/agent/mcp-connections/weather.ts"><code>weather.ts</code></a> makes the MCP server name <code>weather</code>. The <code>agent</code> field points to the sibling project&#39;s mount slug.</p><p>This differs from a subagent. A peer keeps its own:</p><ul><li>root instructions,</li><li>tools and MCP connections,</li><li>durable sessions,</li><li>playground, and</li><li>public MCP endpoint.</li></ul><p>An SDK subagent inherits the parent&#39;s execution surface and only its parent can invoke it. See <a href="./../guides/agent-to-agent.html">Agent-to-agent</a> for the full comparison.</p><h2 id="follow-a-delegated-request" tabindex="-1">Follow a delegated request <a class="header-anchor" href="#follow-a-delegated-request" aria-label="Permalink to &quot;Follow a delegated request&quot;">​</a></h2><ol><li>A user asks Concierge what to pack for Paris.</li><li><a href="./../../examples/concierge/agent/instructions.html"><code>instructions.md</code></a> classifies packing advice as weather-related.</li><li>The model calls <code>weather.ask</code> with the city, timeframe, units, and the complete question.</li><li>Agentkit creates an MCP-channel session inside <code>weather-agent</code>.</li><li>Weather agent calls its own Open-Meteo tools and returns a reply.</li><li>If the turn exceeds the bounded MCP wait, <code>ask</code> returns <code>status: &quot;running&quot;</code>. Concierge calls <code>weather.check</code> with the returned <code>sessionId</code>.</li><li>Concierge relays the result and may add one sentence of travel advice.</li></ol><p>The weather session appears in the weather agent&#39;s playground. It doesn&#39;t share Concierge&#39;s conversation history.</p><h2 id="map-the-delegation-files" tabindex="-1">Map the delegation files <a class="header-anchor" href="#map-the-delegation-files" aria-label="Permalink to &quot;Map the delegation files&quot;">​</a></h2><table tabindex="0"><thead><tr><th>File</th><th>Purpose</th></tr></thead><tbody><tr><td><a href="../../examples/concierge/agent/agent.ts"><code>agent/agent.ts</code></a></td><td>Describes the root agent and selects the local runtime.</td></tr><tr><td><a href="./../../examples/concierge/agent/instructions.html"><code>agent/instructions.md</code></a></td><td>Draws a strict weather-only delegation boundary.</td></tr><tr><td><a href="../../examples/concierge/agent/mcp-connections/weather.ts"><code>agent/mcp-connections/weather.ts</code></a></td><td>Resolves the peer by its <code>weather-agent</code> slug.</td></tr></tbody></table><p>Concierge doesn&#39;t author channels, tools, skills, subagents, schedules, hooks, A/B experiments, or evals. The built-in HTTP and MCP surfaces still exist.</p><p>Its own MCP endpoint exposes <code>ask</code> and <code>check</code>. It doesn&#39;t expose <code>call_tool</code> because Concierge has no server tools. The target weather agent does expose <code>call_tool</code>, so that tool also appears under Concierge&#39;s <code>weather</code> connection.</p><h2 id="mount-both-agents" tabindex="-1">Mount both agents <a class="header-anchor" href="#mount-both-agents" aria-label="Permalink to &quot;Mount both agents&quot;">​</a></h2><p>A peer can only resolve within a multi-agent serve host. Validating Concierge alone checks its files, but serving it alone fails because <code>weather-agent</code> isn&#39;t mounted.</p><p>From <code>packages/agent-serve</code>, validate both projects:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/concierge</span></span>
6
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/weather-agent</span></span></code></pre></div><p>Don&#39;t serve the repository&#39;s whole <code>examples/</code> directory for this proof. Several advanced examples subscribe to live GitHub events. Create an ignored two-project mount instead. Copy only the authored files needed for this proof, leaving Weather&#39;s Slack channels out:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">mkdir</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PWD</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/.agent-serve&quot;</span></span>
5
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>The filename <a href="../../examples/concierge/agent/mcp-connections/weather.ts"><code>weather.ts</code></a> makes the MCP server name <code>weather</code>. The <code>agent</code> field points to the sibling project&#39;s mount slug.</p><p>This differs from a subagent. A peer keeps its own:</p><ul><li>root instructions,</li><li>tools and MCP connections,</li><li>durable sessions,</li><li>playground, and</li><li>public MCP endpoint.</li></ul><p>An SDK subagent inherits the parent&#39;s execution surface and only its parent can invoke it. See <a href="./../guides/agent-to-agent.html">Agent-to-agent</a> for the full comparison.</p><h2 id="follow-a-delegated-request" tabindex="-1">Follow a delegated request <a class="header-anchor" href="#follow-a-delegated-request" aria-label="Permalink to &quot;Follow a delegated request&quot;">​</a></h2><ol><li>A user asks Concierge what to pack for Paris.</li><li><a href="./../../examples/concierge/agent/instructions.html"><code>instructions.md</code></a> classifies packing advice as weather-related.</li><li>The model calls <code>weather.ask</code> with the city, timeframe, units, and the complete question.</li><li>The Agent SDK creates an MCP-channel session inside <code>weather-agent</code>.</li><li>Weather agent calls its own Open-Meteo tools and returns a reply.</li><li>If the turn exceeds the bounded MCP wait, <code>ask</code> returns <code>status: &quot;running&quot;</code>. Concierge calls <code>weather.check</code> with the returned <code>sessionId</code>.</li><li>Concierge relays the result and may add one sentence of travel advice.</li></ol><p>The weather session appears in the weather agent&#39;s playground. It doesn&#39;t share Concierge&#39;s conversation history.</p><h2 id="map-the-delegation-files" tabindex="-1">Map the delegation files <a class="header-anchor" href="#map-the-delegation-files" aria-label="Permalink to &quot;Map the delegation files&quot;">​</a></h2><table tabindex="0"><thead><tr><th>File</th><th>Purpose</th></tr></thead><tbody><tr><td><a href="../../examples/concierge/agent/agent.ts"><code>agent/agent.ts</code></a></td><td>Describes the root agent and selects the local runtime.</td></tr><tr><td><a href="./../../examples/concierge/agent/instructions.html"><code>agent/instructions.md</code></a></td><td>Draws a strict weather-only delegation boundary.</td></tr><tr><td><a href="../../examples/concierge/agent/mcp-connections/weather.ts"><code>agent/mcp-connections/weather.ts</code></a></td><td>Resolves the peer by its <code>weather-agent</code> slug.</td></tr></tbody></table><p>Concierge doesn&#39;t author channels, tools, skills, subagents, schedules, hooks, A/B experiments, or evals. The built-in HTTP and MCP surfaces still exist.</p><p>Its own MCP endpoint exposes <code>ask</code> and <code>check</code>. It doesn&#39;t expose <code>call_tool</code> because Concierge has no server tools. The target weather agent does expose <code>call_tool</code>, so that tool also appears under Concierge&#39;s <code>weather</code> connection.</p><h2 id="mount-both-agents" tabindex="-1">Mount both agents <a class="header-anchor" href="#mount-both-agents" aria-label="Permalink to &quot;Mount both agents&quot;">​</a></h2><p>A peer can only resolve within a multi-agent serve host. Validating Concierge alone checks its files, but serving it alone fails because <code>weather-agent</code> isn&#39;t mounted.</p><p>From <code>packages/agent-serve</code>, validate both projects:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/concierge</span></span>
6
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/weather-agent</span></span></code></pre></div><p>Don&#39;t serve the repository&#39;s whole <code>examples/</code> directory for this proof. Several advanced examples subscribe to live GitHub events. Create an ignored two-project mount instead. Copy only the authored files needed for this proof, leaving Weather&#39;s Slack channels out:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">mkdir</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PWD</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/.agent-serve&quot;</span></span>
7
7
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">PAIR_DIR</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">mktemp</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PWD</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/.agent-serve/concierge-weather.XXXXXX&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
8
8
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">mkdir</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -p</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/concierge&quot;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/weather-agent/agent&quot;</span></span>
9
9
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cp</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -R</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/concierge/agent</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/concierge/&quot;</span></span>
@@ -14,10 +14,10 @@ import{_ as s,c as a,o as i,ag as t}from"./chunks/framework.CAZyNGu9.js";const k
14
14
  <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/weather-agent/agent/&quot;</span></span>
15
15
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cp</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -R</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/weather-agent/mcp</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/weather-agent/&quot;</span></span>
16
16
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cp</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/weather-agent/package.json</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/weather-agent/&quot;</span></span>
17
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span></span></code></pre></div><p>The host resolves the peer after it knows every mount. The local peer URL is <code>http://127.0.0.1:3000/weather-agent/v1/mcp</code>. You still need an agent-runtime credential for both model turns.</p><h2 id="exercise-delegation" tabindex="-1">Exercise delegation <a class="header-anchor" href="#exercise-delegation" aria-label="Permalink to &quot;Exercise delegation&quot;">​</a></h2><p>Send a weather request to the running Concierge:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> chat</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
17
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span></span></code></pre></div><p>The host resolves the peer after it knows every mount. The local peer URL is <code>http://127.0.0.1:3000/weather-agent/v1/mcp</code>. You still need an agent-runtime credential for both model turns.</p><h2 id="exercise-delegation" tabindex="-1">Exercise delegation <a class="header-anchor" href="#exercise-delegation" aria-label="Permalink to &quot;Exercise delegation&quot;">​</a></h2><p>Send a weather request to the running Concierge:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> chat</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
18
18
  <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --url</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> http://127.0.0.1:3000/concierge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
19
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;What should I pack for Paris tomorrow?&quot;</span></span></code></pre></div><p>Open both playgrounds:</p><ul><li><code>http://127.0.0.1:3000/concierge/playground</code></li><li><code>http://127.0.0.1:3000/weather-agent/playground</code></li></ul><p>The Concierge transcript shows the MCP call. The weather playground shows a separate session on the <code>mcp</code> channel with live weather tool calls.</p><p>Now send a general request:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> chat</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
19
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;What should I pack for Paris tomorrow?&quot;</span></span></code></pre></div><p>Open both playgrounds:</p><ul><li><code>http://127.0.0.1:3000/concierge/playground</code></li><li><code>http://127.0.0.1:3000/weather-agent/playground</code></li></ul><p>The Concierge transcript shows the MCP call. The weather playground shows a separate session on the <code>mcp</code> channel with live weather tool calls.</p><p>Now send a general request:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> chat</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
20
20
  <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --url</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> http://127.0.0.1:3000/concierge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
21
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;Give me three ideas for a quiet weekend.&quot;</span></span></code></pre></div><p>The instructions tell Concierge to answer without delegating. This contrast is the proof loop: weather goes to the peer, unrelated work stays local.</p><h2 id="preserve-peer-context" tabindex="-1">Preserve peer context <a class="header-anchor" href="#preserve-peer-context" aria-label="Permalink to &quot;Preserve peer context&quot;">​</a></h2><p><code>weather.ask</code> returns a peer <code>sessionId</code>. Passing it back to a later <code>ask</code> continues the same weather conversation. Concierge&#39;s instructions require this for follow-ups dependent on an earlier answer.</p><p>Use a fresh call when the tasks are independent. Reuse the peer session when the second question needs facts or choices from the first.</p><h2 id="keep-delegation-bounded" tabindex="-1">Keep delegation bounded <a class="header-anchor" href="#keep-delegation-bounded" aria-label="Permalink to &quot;Keep delegation bounded&quot;">​</a></h2><p>Agentkit rejects unknown peer slugs and self-references during startup. It doesn&#39;t stop a cycle across several valid peers. If agent A delegates all work to B and B delegates all work to A, they can recurse.</p><p>The prompt provides the guardrail here:</p><ul><li>delegate every weather request,</li><li>include complete context, and</li><li>never delegate unrelated work.</li></ul><p>Write similarly narrow routing rules for each peer. A tool description helps the model choose the connection, but the always-on instructions own the policy.</p><h2 id="use-peers-from-cloud-turns" tabindex="-1">Use peers from cloud turns <a class="header-anchor" href="#use-peers-from-cloud-turns" aria-label="Permalink to &quot;Use peers from cloud turns&quot;">​</a></h2><p>Local turns reach peers over loopback. A cloud VM can&#39;t reach the serve host&#39;s loopback address. Set a public URL when a cloud agent needs the peer:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> serve</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
21
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;Give me three ideas for a quiet weekend.&quot;</span></span></code></pre></div><p>The instructions tell Concierge to answer without delegating. This contrast is the proof loop: weather goes to the peer, unrelated work stays local.</p><h2 id="preserve-peer-context" tabindex="-1">Preserve peer context <a class="header-anchor" href="#preserve-peer-context" aria-label="Permalink to &quot;Preserve peer context&quot;">​</a></h2><p><code>weather.ask</code> returns a peer <code>sessionId</code>. Passing it back to a later <code>ask</code> continues the same weather conversation. Concierge&#39;s instructions require this for follow-ups dependent on an earlier answer.</p><p>Use a fresh call when the tasks are independent. Reuse the peer session when the second question needs facts or choices from the first.</p><h2 id="keep-delegation-bounded" tabindex="-1">Keep delegation bounded <a class="header-anchor" href="#keep-delegation-bounded" aria-label="Permalink to &quot;Keep delegation bounded&quot;">​</a></h2><p>The Agent SDK rejects unknown peer slugs and self-references during startup. It doesn&#39;t stop a cycle across several valid peers. If agent A delegates all work to B and B delegates all work to A, they can recurse.</p><p>The prompt provides the guardrail here:</p><ul><li>delegate every weather request,</li><li>include complete context, and</li><li>never delegate unrelated work.</li></ul><p>Write similarly narrow routing rules for each peer. A tool description helps the model choose the connection, but the always-on instructions own the policy.</p><h2 id="use-peers-from-cloud-turns" tabindex="-1">Use peers from cloud turns <a class="header-anchor" href="#use-peers-from-cloud-turns" aria-label="Permalink to &quot;Use peers from cloud turns&quot;">​</a></h2><p>Local turns reach peers over loopback. A cloud VM can&#39;t reach the serve host&#39;s loopback address. Set a public URL when a cloud agent needs the peer:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> serve</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
22
22
  <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --public-url</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> https://agents.example.com</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
23
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --bearer-token</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$AGENT_TOKEN</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span></span></code></pre></div><p>Agentkit attaches the bearer token to peer calls. Without <code>--public-url</code>, cloud turns omit peer connections and the server logs a warning.</p><h2 id="compose-your-own-pair" tabindex="-1">Compose your own pair <a class="header-anchor" href="#compose-your-own-pair" aria-label="Permalink to &quot;Compose your own pair&quot;">​</a></h2><p>To compose your own agents:</p><ol><li>Give each project a stable directory slug.</li><li>Add <code>agent/mcp-connections/&lt;name&gt;.ts</code> to the caller.</li><li>Set <code>agent</code> to the target slug.</li><li>Describe the exact work the peer owns.</li><li>Mount both projects from their parent directory.</li><li>Add evals for delegated and non-delegated requests.</li></ol><p>Keep the peer independently useful. If the specialist only makes sense inside one parent and needs no independent sessions, use a subagent instead.</p><h2 id="where-to-go-next" tabindex="-1">Where to go next <a class="header-anchor" href="#where-to-go-next" aria-label="Permalink to &quot;Where to go next&quot;">​</a></h2><ul><li><a href="./../guides/agent-to-agent.html">Agent-to-agent</a></li><li><a href="./../reference/connections.html">MCP connections</a></li><li><a href="./../reference/subagents.html">Subagents</a></li><li><a href="./../reference/sessions.html">Sessions and streaming</a></li></ul>`,52)])])}const g=s(n,[["render",l]]);export{k as __pageData,g as default};
23
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --bearer-token</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$AGENT_TOKEN</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span></span></code></pre></div><p>The Agent SDK attaches the bearer token to peer calls. Without <code>--public-url</code>, cloud turns omit peer connections and the server logs a warning.</p><h2 id="compose-your-own-pair" tabindex="-1">Compose your own pair <a class="header-anchor" href="#compose-your-own-pair" aria-label="Permalink to &quot;Compose your own pair&quot;">​</a></h2><p>To compose your own agents:</p><ol><li>Give each project a stable directory slug.</li><li>Add <code>agent/mcp-connections/&lt;name&gt;.ts</code> to the caller.</li><li>Set <code>agent</code> to the target slug.</li><li>Describe the exact work the peer owns.</li><li>Mount both projects from their parent directory.</li><li>Add evals for delegated and non-delegated requests.</li></ol><p>Keep the peer independently useful. If the specialist only makes sense inside one parent and needs no independent sessions, use a subagent instead.</p><h2 id="where-to-go-next" tabindex="-1">Where to go next <a class="header-anchor" href="#where-to-go-next" aria-label="Permalink to &quot;Where to go next&quot;">​</a></h2><ul><li><a href="./../guides/agent-to-agent.html">Agent-to-agent</a></li><li><a href="./../reference/connections.html">MCP connections</a></li><li><a href="./../reference/subagents.html">Subagents</a></li><li><a href="./../reference/sessions.html">Sessions and streaming</a></li></ul>`,52)])])}const g=s(n,[["render",l]]);export{k as __pageData,g as default};
@@ -1,15 +1,15 @@
1
- import{_ as t,c as s,o as a,ag as i}from"./chunks/framework.CAZyNGu9.js";const u=JSON.parse('{"title":"Hand PR triage to managed remote agents","description":"Coordinate local chat, per-PR remote sessions, GitHub wake buffering, workflow MCP enrollment, durable affinity, findings, and reminders.","frontmatter":{"title":"Hand PR triage to managed remote agents","description":"Coordinate local chat, per-PR remote sessions, GitHub wake buffering, workflow MCP enrollment, durable affinity, findings, and reminders."},"headers":[],"relativePath":"example-agents/fsd.md","filePath":"example-agents/fsd.md"}'),o={name:"example-agents/fsd.md"};function n(r,e,l,d,h,c){return a(),s("div",null,[...e[0]||(e[0]=[i(`<h1 id="hand-pr-triage-to-managed-remote-agents" tabindex="-1">Hand PR triage to managed remote agents <a class="header-anchor" href="#hand-pr-triage-to-managed-remote-agents" aria-label="Permalink to &quot;Hand PR triage to managed remote agents&quot;">​</a></h1><p>The remote PR coordinator keeps chat and routing on the local serve host, then hands each pull request to a managed remote agent with a real checkout. The same remote conversation resumes when a user drives the PR again, GitHub reports a change, or a merge-conflict reminder fires.</p><p>The workflow backend enrolls each remote run with a workflow MCP. Its tools and the host&#39;s findings routes read and write the same external findings service.</p><p>Use this example when repository work is too heavy or concurrent for local worktrees, but the host should still own intake, session identity, policy, and bookkeeping.</p><p><a href="./../../examples/fsd/">Browse the current coordinator source.</a></p><h2 id="resume-one-remote-agent-across-every-pr-wake" tabindex="-1">Resume one remote agent across every PR wake <a class="header-anchor" href="#resume-one-remote-agent-across-every-pr-wake" aria-label="Permalink to &quot;Resume one remote agent across every PR wake&quot;">​</a></h2><p>The coordinator uses a hybrid runtime:</p><ul><li>Ordinary playground and Slack chat run locally.</li><li>The <code>drive_pr</code> server tool creates a remote session for one PR.</li><li>The remote worker gets the repository and PR reference.</li><li>An <code>agent.bound</code> hook records the remote run id and enrolls the run into a workflow MCP.</li><li>Webhooks and reminders resume the same remote agent through durable PR-to-agent affinity.</li></ul><p>No other example moves one logical conversation across local chat, remote execution, event wakes, and timed follow-ups.</p><h2 id="follow-a-chat-request" tabindex="-1">Follow a chat request <a class="header-anchor" href="#follow-a-chat-request" aria-label="Permalink to &quot;Follow a chat request&quot;">​</a></h2><ol><li>A user asks local chat or Slack to drive a PR.</li><li>The root model calls <code>drive_pr</code> with the PR, mode, and optional hint.</li><li>The tool calls <code>ctx.send(&quot;drive&quot;, ...)</code> with a per-session <code>cloud</code> block to attach the PR.</li><li>Agentkit creates or resumes the <code>drive</code> session keyed by <code>pr:owner/repo#N</code>.</li><li>The remote runtime provisions the agent and emits <code>agent.bound</code>.</li><li>The enrollment hook writes PR affinity and calls the workflow backend to attach run-scoped MCP tools.</li><li><code>drive_pr</code> waits for remote binding, then returns the agent id and URL. If binding exceeds its wait window, those fields can be <code>null</code> while work continues.</li><li>The remote agent reads the host-prepared PR brief, checks unresolved state, and records findings through the workflow MCP.</li><li>The host forwards a validated fallback output block when MCP wasn&#39;t available for the turn.</li></ol><p>The local chat agent doesn&#39;t have the target checkout, <code>gh</code>, <code>git</code>, or the workflow MCP. Its job is coordination.</p><p>A request for a merged or closed PR finishes before provisioning. That result has <code>status: &quot;finished&quot;</code> and no remote session.</p><h2 id="map-the-framework-features" tabindex="-1">Map the framework features <a class="header-anchor" href="#map-the-framework-features" aria-label="Permalink to &quot;Map the framework features&quot;">​</a></h2><table tabindex="0"><thead><tr><th>Capability</th><th>Source</th><th>Role</th></tr></thead><tbody><tr><td>Hybrid config</td><td><a href="../../examples/fsd/agent/agent.ts"><code>agent/agent.ts</code></a></td><td>Keep chat local, set remote-runtime defaults, disable automatic PR creation, and isolate local harness workspaces.</td></tr><tr><td>Root instructions</td><td><a href="./../../examples/fsd/agent/instructions.html"><code>agent/instructions.md</code></a></td><td>Separate local coordination from remote triage and define suggest/apply policy.</td></tr><tr><td>Drive tool</td><td><a href="../../examples/fsd/agent/tools/drive_pr.ts"><code>agent/tools/drive_pr.ts</code></a></td><td>Hand a chat request to the <code>drive</code> channel and wait for remote binding.</td></tr><tr><td>Drive channel</td><td><a href="../../examples/fsd/agent/channels/drive.ts"><code>agent/channels/drive.ts</code></a></td><td>Start remote work and expose findings read/write routes.</td></tr><tr><td>GitHub channel</td><td><a href="../../examples/fsd/agent/channels/github.ts"><code>agent/channels/github.ts</code></a></td><td>Buffer PR, comment, review, check, and status wakes.</td></tr><tr><td>Slack channel</td><td><a href="../../examples/fsd/agent/channels/slack.ts"><code>agent/channels/slack.ts</code></a></td><td>Route Slack requests to the local coordinator.</td></tr><tr><td>Hooks</td><td><a href="../../examples/fsd/agent/hooks/enroll-fsd.ts"><code>agent/hooks/enroll-fsd.ts</code></a>, <a href="../../examples/fsd/agent/hooks/record-outputs.ts"><code>agent/hooks/record-outputs.ts</code></a></td><td>Bind remote identity, enroll MCP, and forward fallback findings.</td></tr><tr><td>Affinity and buffering</td><td><a href="../../examples/fsd/agent/lib/pr-affinity.ts"><code>agent/lib/pr-affinity.ts</code></a>, <a href="../../examples/fsd/agent/lib/webhook-buffer.ts"><code>agent/lib/webhook-buffer.ts</code></a></td><td>Persist PR identity, sticky mode, and pending wakes.</td></tr><tr><td>Reminders</td><td><a href="../../examples/fsd/agent/lib/merge-conflict-watch.ts"><code>agent/lib/merge-conflict-watch.ts</code></a></td><td>Recheck merge conflicts every 30 minutes.</td></tr><tr><td>Workflow client</td><td><a href="../../examples/fsd/agent/lib/fsd-platform.ts"><code>agent/lib/fsd-platform.ts</code></a></td><td>Enroll external runs and read or record findings.</td></tr></tbody></table><p>The coordinator has no authored skill, subagent, MCP connection, static schedule, A/B experiment, eval, custom storage definition, or tool approval.</p><p>The workflow MCP is dynamic. Backend enrollment attaches it to the remote run, so there is no file under <code>agent/mcp-connections/</code>.</p><h2 id="understand-local-and-remote-workspaces" tabindex="-1">Understand local and remote workspaces <a class="header-anchor" href="#understand-local-and-remote-workspaces" aria-label="Permalink to &quot;Understand local and remote workspaces&quot;">​</a></h2><p>The root config sets <code>runtime: &quot;local&quot;</code> because <code>drive_pr</code> is a server tool. It also supplies remote-runtime defaults through the <code>cloud</code> configuration:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
1
+ import{_ as t,c as s,o as a,ag as i}from"./chunks/framework.CAZyNGu9.js";const u=JSON.parse('{"title":"Hand PR triage to managed remote agents","description":"Coordinate local chat, per-PR remote sessions, GitHub wake buffering, workflow MCP enrollment, durable affinity, findings, and reminders.","frontmatter":{"title":"Hand PR triage to managed remote agents","description":"Coordinate local chat, per-PR remote sessions, GitHub wake buffering, workflow MCP enrollment, durable affinity, findings, and reminders."},"headers":[],"relativePath":"example-agents/fsd.md","filePath":"example-agents/fsd.md"}'),o={name:"example-agents/fsd.md"};function n(r,e,l,d,h,c){return a(),s("div",null,[...e[0]||(e[0]=[i(`<h1 id="hand-pr-triage-to-managed-remote-agents" tabindex="-1">Hand PR triage to managed remote agents <a class="header-anchor" href="#hand-pr-triage-to-managed-remote-agents" aria-label="Permalink to &quot;Hand PR triage to managed remote agents&quot;">​</a></h1><p>The remote PR coordinator keeps chat and routing on the local serve host, then hands each pull request to a managed remote agent with a real checkout. The same remote conversation resumes when a user drives the PR again, GitHub reports a change, or a merge-conflict reminder fires.</p><p>The workflow backend enrolls each remote run with a workflow MCP. Its tools and the host&#39;s findings routes read and write the same external findings service.</p><p>Use this example when repository work is too heavy or concurrent for local worktrees, but the host should still own intake, session identity, policy, and bookkeeping.</p><p><a href="./../../examples/fsd/">Browse the current coordinator source.</a></p><h2 id="resume-one-remote-agent-across-every-pr-wake" tabindex="-1">Resume one remote agent across every PR wake <a class="header-anchor" href="#resume-one-remote-agent-across-every-pr-wake" aria-label="Permalink to &quot;Resume one remote agent across every PR wake&quot;">​</a></h2><p>The coordinator uses a hybrid runtime:</p><ul><li>Ordinary playground and Slack chat run locally.</li><li>The <code>drive_pr</code> server tool creates a remote session for one PR.</li><li>The remote worker gets the repository and PR reference.</li><li>An <code>agent.bound</code> hook records the remote run id and enrolls the run into a workflow MCP.</li><li>Webhooks and reminders resume the same remote agent through durable PR-to-agent affinity.</li></ul><p>No other example moves one logical conversation across local chat, remote execution, event wakes, and timed follow-ups.</p><h2 id="follow-a-chat-request" tabindex="-1">Follow a chat request <a class="header-anchor" href="#follow-a-chat-request" aria-label="Permalink to &quot;Follow a chat request&quot;">​</a></h2><ol><li>A user asks local chat or Slack to drive a PR.</li><li>The root model calls <code>drive_pr</code> with the PR, mode, and optional hint.</li><li>The tool calls <code>ctx.send(&quot;drive&quot;, ...)</code> with a per-session <code>cloud</code> block to attach the PR.</li><li>The Agent SDK creates or resumes the <code>drive</code> session keyed by <code>pr:owner/repo#N</code>.</li><li>The remote runtime provisions the agent and emits <code>agent.bound</code>.</li><li>The enrollment hook writes PR affinity and calls the workflow backend to attach run-scoped MCP tools.</li><li><code>drive_pr</code> waits for remote binding, then returns the agent id and URL. If binding exceeds its wait window, those fields can be <code>null</code> while work continues.</li><li>The remote agent reads the host-prepared PR brief, checks unresolved state, and records findings through the workflow MCP.</li><li>The host forwards a validated fallback output block when MCP wasn&#39;t available for the turn.</li></ol><p>The local chat agent doesn&#39;t have the target checkout, <code>gh</code>, <code>git</code>, or the workflow MCP. Its job is coordination.</p><p>A request for a merged or closed PR finishes before provisioning. That result has <code>status: &quot;finished&quot;</code> and no remote session.</p><h2 id="map-the-framework-features" tabindex="-1">Map the framework features <a class="header-anchor" href="#map-the-framework-features" aria-label="Permalink to &quot;Map the framework features&quot;">​</a></h2><table tabindex="0"><thead><tr><th>Capability</th><th>Source</th><th>Role</th></tr></thead><tbody><tr><td>Hybrid config</td><td><a href="../../examples/fsd/agent/agent.ts"><code>agent/agent.ts</code></a></td><td>Keep chat local, set remote-runtime defaults, disable automatic PR creation, and isolate local harness workspaces.</td></tr><tr><td>Root instructions</td><td><a href="./../../examples/fsd/agent/instructions.html"><code>agent/instructions.md</code></a></td><td>Separate local coordination from remote triage and define suggest/apply policy.</td></tr><tr><td>Drive tool</td><td><a href="../../examples/fsd/agent/tools/drive_pr.ts"><code>agent/tools/drive_pr.ts</code></a></td><td>Hand a chat request to the <code>drive</code> channel and wait for remote binding.</td></tr><tr><td>Drive channel</td><td><a href="../../examples/fsd/agent/channels/drive.ts"><code>agent/channels/drive.ts</code></a></td><td>Start remote work and expose findings read/write routes.</td></tr><tr><td>GitHub channel</td><td><a href="../../examples/fsd/agent/channels/github.ts"><code>agent/channels/github.ts</code></a></td><td>Buffer PR, comment, review, check, and status wakes.</td></tr><tr><td>Slack channel</td><td><a href="../../examples/fsd/agent/channels/slack.ts"><code>agent/channels/slack.ts</code></a></td><td>Route Slack requests to the local coordinator.</td></tr><tr><td>Hooks</td><td><a href="../../examples/fsd/agent/hooks/enroll-fsd.ts"><code>agent/hooks/enroll-fsd.ts</code></a>, <a href="../../examples/fsd/agent/hooks/record-outputs.ts"><code>agent/hooks/record-outputs.ts</code></a></td><td>Bind remote identity, enroll MCP, and forward fallback findings.</td></tr><tr><td>Affinity and buffering</td><td><a href="../../examples/fsd/agent/lib/pr-affinity.ts"><code>agent/lib/pr-affinity.ts</code></a>, <a href="../../examples/fsd/agent/lib/webhook-buffer.ts"><code>agent/lib/webhook-buffer.ts</code></a></td><td>Persist PR identity, sticky mode, and pending wakes.</td></tr><tr><td>Reminders</td><td><a href="../../examples/fsd/agent/lib/merge-conflict-watch.ts"><code>agent/lib/merge-conflict-watch.ts</code></a></td><td>Recheck merge conflicts every 30 minutes.</td></tr><tr><td>Workflow client</td><td><a href="../../examples/fsd/agent/lib/fsd-platform.ts"><code>agent/lib/fsd-platform.ts</code></a></td><td>Enroll external runs and read or record findings.</td></tr></tbody></table><p>The coordinator has no authored skill, subagent, MCP connection, static schedule, A/B experiment, eval, custom storage definition, or tool approval.</p><p>The workflow MCP is dynamic. Backend enrollment attaches it to the remote run, so there is no file under <code>agent/mcp-connections/</code>.</p><h2 id="understand-local-and-remote-workspaces" tabindex="-1">Understand local and remote workspaces <a class="header-anchor" href="#understand-local-and-remote-workspaces" aria-label="Permalink to &quot;Understand local and remote workspaces&quot;">​</a></h2><p>The root config sets <code>runtime: &quot;local&quot;</code> because <code>drive_pr</code> is a server tool. It also supplies remote-runtime defaults through the <code>cloud</code> configuration:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">local</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
2
2
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> cwd</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">join</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">homedir</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;.cache&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;agent-serve&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;fsd&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
3
3
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">},</span></span>
4
4
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cloud</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
5
5
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> env</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: { </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;cloud&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
6
6
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> autoCreatePR</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
7
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">},</span></span></code></pre></div><p>The local cwd sits outside the monorepo, so inherited repository instructions don&#39;t affect coordinator chat.</p><p>Remote sessions get a repository attachment with the target PR. The worker starts from the PR base and creates an automation side branch from the PR head only when code context or a fix is needed. The serve host never checks out target code.</p><h2 id="prepare-access" tabindex="-1">Prepare access <a class="header-anchor" href="#prepare-access" aria-label="Permalink to &quot;Prepare access&quot;">​</a></h2><p>You need:</p><ul><li>Node 22.13 or newer.</li><li>An agent-runtime user credential.</li><li>Access to a managed remote runtime.</li><li>Access to the target GitHub PR.</li><li>Access to the workflow backend and findings store.</li></ul><p>Keep the affinity and webhook-buffer files on durable storage for a long-lived host.</p><h2 id="validate-without-starting-remote-work" tabindex="-1">Validate without starting remote work <a class="header-anchor" href="#validate-without-starting-remote-work" aria-label="Permalink to &quot;Validate without starting remote work&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd</span></span>
8
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> info</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span>
9
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> github</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> events</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span></code></pre></div><p>These commands inspect discovery and declared GitHub events. They don&#39;t provision a remote agent.</p><h2 id="choose-suggest-or-apply" tabindex="-1">Choose suggest or apply <a class="header-anchor" href="#choose-suggest-or-apply" aria-label="Permalink to &quot;Choose suggest or apply&quot;">​</a></h2><p>Every PR has a sticky mode:</p><table tabindex="0"><thead><tr><th>Mode</th><th>Required remote behavior</th></tr></thead><tbody><tr><td><code>suggest</code></td><td>May create verified commits on the VM&#39;s local side branch. Instructions require no pushes, comments, PR edits, or workflow actions. Records exact fixes and actions as findings for the owner.</td></tr><tr><td><code>apply</code></td><td>Pushes verified fixes to the existing PR head and may update metadata, reply to threads, mark a draft ready, rebase, or rerun CI.</td></tr></tbody></table><p>The remote instructions forbid merging, enabling auto-merge, force-pushing, and opening a new PR in both modes. <code>autoCreatePR: false</code> also disables the SDK&#39;s automatic PR creation. The other restrictions are prompt policy, not a deterministic host gate. <code>suggest</code> is the default.</p><p>The selected mode is stored beside PR affinity. Webhooks and reminders reuse it. Re-driving a PR can change the host-side mode. Backend enrollment records the mode at first enrollment, so each later host prompt repeats the current authoritative mode.</p><div class="caution custom-block github-alert"><p class="custom-block-title">CAUTION</p><p><code>apply</code> writes to the user&#39;s PR branch and triggers CI. Use <code>suggest</code> for development. Both modes provision a billed remote agent and can write structured findings to the findings service. <code>drive_pr</code> has no approval gate, and suggest/apply restrictions depend on the remote agent following its instructions.</p></div><h2 id="start-a-suggest-mode-drive" tabindex="-1">Start a suggest-mode drive <a class="header-anchor" href="#start-a-suggest-mode-drive" aria-label="Permalink to &quot;Start a suggest-mode drive&quot;">​</a></h2><p>Run the host:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd</span></span></code></pre></div><p>From chat:</p><blockquote><p>Drive <a href="https://github.com/owner/repo/pull/123" target="_blank" rel="noreferrer">https://github.com/owner/repo/pull/123</a> in suggest mode.</p></blockquote><p>Or call the coordinator tool:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agentkit</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> call</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> drive_pr</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
7
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">},</span></span></code></pre></div><p>The local cwd sits outside the monorepo, so inherited repository instructions don&#39;t affect coordinator chat.</p><p>Remote sessions get a repository attachment with the target PR. The worker starts from the PR base and creates an automation side branch from the PR head only when code context or a fix is needed. The serve host never checks out target code.</p><h2 id="prepare-access" tabindex="-1">Prepare access <a class="header-anchor" href="#prepare-access" aria-label="Permalink to &quot;Prepare access&quot;">​</a></h2><p>You need:</p><ul><li>Node 22.13 or newer.</li><li>An agent-runtime user credential.</li><li>Access to a managed remote runtime.</li><li>Access to the target GitHub PR.</li><li>Access to the workflow backend and findings store.</li></ul><p>Keep the affinity and webhook-buffer files on durable storage for a long-lived host.</p><h2 id="validate-without-starting-remote-work" tabindex="-1">Validate without starting remote work <a class="header-anchor" href="#validate-without-starting-remote-work" aria-label="Permalink to &quot;Validate without starting remote work&quot;">​</a></h2><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> validate</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd</span></span>
8
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> info</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span>
9
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> github</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> events</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span></code></pre></div><p>These commands inspect discovery and declared GitHub events. They don&#39;t provision a remote agent.</p><h2 id="choose-suggest-or-apply" tabindex="-1">Choose suggest or apply <a class="header-anchor" href="#choose-suggest-or-apply" aria-label="Permalink to &quot;Choose suggest or apply&quot;">​</a></h2><p>Every PR has a sticky mode:</p><table tabindex="0"><thead><tr><th>Mode</th><th>Required remote behavior</th></tr></thead><tbody><tr><td><code>suggest</code></td><td>May create verified commits on the VM&#39;s local side branch. Instructions require no pushes, comments, PR edits, or workflow actions. Records exact fixes and actions as findings for the owner.</td></tr><tr><td><code>apply</code></td><td>Pushes verified fixes to the existing PR head and may update metadata, reply to threads, mark a draft ready, rebase, or rerun CI.</td></tr></tbody></table><p>The remote instructions forbid merging, enabling auto-merge, force-pushing, and opening a new PR in both modes. <code>autoCreatePR: false</code> also disables the SDK&#39;s automatic PR creation. The other restrictions are prompt policy, not a deterministic host gate. <code>suggest</code> is the default.</p><p>The selected mode is stored beside PR affinity. Webhooks and reminders reuse it. Re-driving a PR can change the host-side mode. Backend enrollment records the mode at first enrollment, so each later host prompt repeats the current authoritative mode.</p><div class="caution custom-block github-alert"><p class="custom-block-title">CAUTION</p><p><code>apply</code> writes to the user&#39;s PR branch and triggers CI. Use <code>suggest</code> for development. Both modes provision a billed remote agent and can write structured findings to the findings service. <code>drive_pr</code> has no approval gate, and suggest/apply restrictions depend on the remote agent following its instructions.</p></div><h2 id="start-a-suggest-mode-drive" tabindex="-1">Start a suggest-mode drive <a class="header-anchor" href="#start-a-suggest-mode-drive" aria-label="Permalink to &quot;Start a suggest-mode drive&quot;">​</a></h2><p>Run the host:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd</span></span></code></pre></div><p>From chat:</p><blockquote><p>Drive <a href="https://github.com/owner/repo/pull/123" target="_blank" rel="noreferrer">https://github.com/owner/repo/pull/123</a> in suggest mode.</p></blockquote><p>Or call the coordinator tool:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> call</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> drive_pr</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
10
10
  <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
11
11
  <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;{&quot;pr&quot;:&quot;https://github.com/owner/repo/pull/123&quot;,&quot;mode&quot;:&quot;suggest&quot;}&#39;</span></span></code></pre></div><p>For an open PR, the tool waits up to 60 seconds for remote binding and returns:</p><ul><li>the normalized PR label,</li><li>session and continuation ids,</li><li>the remote-agent id and URL when binding completes in that window,</li><li><code>status: &quot;started&quot;</code>, and</li><li>the merge-conflict reminder id.</li></ul><p>It doesn&#39;t wait for findings. A slow binding can return <code>null</code> identifiers. Open the returned agent URL when present to follow the remote run.</p><h2 id="use-the-http-drive-surface" tabindex="-1">Use the HTTP drive surface <a class="header-anchor" href="#use-the-http-drive-surface" aria-label="Permalink to &quot;Use the HTTP drive surface&quot;">​</a></h2><p>The custom channel starts the same orchestration:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -s</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -X</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> POST</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
12
12
  <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> http://127.0.0.1:3000/fsd/v1/channels/drive/</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
13
13
  <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -H</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;content-type: application/json&#39;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
14
14
  <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -d</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;{&quot;pr&quot;:&quot;owner/repo#123&quot;,&quot;mode&quot;:&quot;suggest&quot;}&#39;</span></span></code></pre></div><p>This route returns as soon as the channel session exists. The remote-agent id can still be <code>null</code> at that point. Triage continues in the background.</p><p>Read findings later:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -s</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
15
- <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;http://127.0.0.1:3000/fsd/v1/channels/drive/findings?pr=owner/repo%23123&#39;</span></span></code></pre></div><p>The external findings service is the source of truth. The local host doesn&#39;t keep a second findings database.</p><p>The channel also exposes <code>POST /findings</code> as a testing surface. It validates outputs, then writes them to the findings service for a PR already bound by this host. The route has no approval gate. Keep it under the default loopback auth or another trusted boundary.</p><h2 id="keep-one-remote-agent-per-pr" tabindex="-1">Keep one remote agent per PR <a class="header-anchor" href="#keep-one-remote-agent-per-pr" aria-label="Permalink to &quot;Keep one remote agent per PR&quot;">​</a></h2><p>Within the <code>drive</code> channel, the stable continuation token <code>pr:owner/repo#N</code> resumes the same session. GitHub sessions are scoped to another channel, so a continuation token alone can&#39;t bridge them.</p><p>The enrollment hook closes that gap:</p><ol><li>Read the PR from the continuation token or host-authored session title.</li><li>Record PR to <code>sdkAgentId</code> affinity after <code>agent.bound</code>.</li><li>Seed later sessions with the same remote id.</li><li>Retry workflow MCP enrollment after a completed turn when the first RPC failed.</li></ol><p>This lets Slack, HTTP drive, GitHub, and reminders talk to one remote conversation without sharing one channel session.</p><h2 id="buffer-github-wakes" tabindex="-1">Buffer GitHub wakes <a class="header-anchor" href="#buffer-github-wakes" aria-label="Permalink to &quot;Buffer GitHub wakes&quot;">​</a></h2><p>The GitHub channel handles pull requests, comments, reviews, check suites, check runs, and selected status events. It doesn&#39;t send payload details to the model. It asks the remote agent to refresh live source of truth.</p><p>The buffer:</p><ul><li>groups events by PR,</li><li>waits three seconds for a burst to settle,</li><li>re-buffers while CI settles,</li><li>skips a flush when the PR session is busy,</li><li>tries to write its snapshot before acknowledging a wake, and</li><li>restores pending entries when the channel starts.</li></ul><p>Closing a PR discards its pending entry and cancels its reminders.</p><p>Snapshot persistence is best-effort. Write failures are swallowed silently, so a delivery can still be acknowledged without a durable snapshot.</p><p>This is the high-volume counterpart to a direct <code>{ auth }</code> GitHub wake. See <a href="./../guides/github.html#handle-high-event-volume">GitHub</a> for the reusable pattern.</p><h2 id="add-merge-conflict-checks" tabindex="-1">Add merge-conflict checks <a class="header-anchor" href="#add-merge-conflict-checks" aria-label="Permalink to &quot;Add merge-conflict checks&quot;">​</a></h2><p>Starting a drive arms one recurring reminder per PR. Every 30 minutes the host checks mergeability:</p><ul><li>closed or merged stops the reminder,</li><li>clean skips delivery,</li><li>conflicting sends a follow-up to the owning session, and</li><li>a busy session skips the wake.</li></ul><p>This uses runtime reminders, not a static <code>agent/schedules/</code> file. The host creates, lists, replaces, and cancels reminders through <code>host.reminders</code>. Development mode doesn&#39;t fire reminder timers automatically. Dispatch one through the dev reminder endpoint for a manual proof, or use non-dev <code>serve</code> to run the 30-minute cadence.</p><p>The reminder&#39;s <code>run</code> handler lives in memory. After a host restart, agentkit disarms it with <code>handler_lost_on_restart</code>; a later drive or webhook path can arm a fresh handler. Persisted reminder metadata alone doesn&#39;t keep the check running.</p><h2 id="record-findings-with-mcp-or-a-fallback" tabindex="-1">Record findings with MCP or a fallback <a class="header-anchor" href="#record-findings-with-mcp-or-a-fallback" aria-label="Permalink to &quot;Record findings with MCP or a fallback&quot;">​</a></h2><p>After enrollment, the remote agent receives workflow tools for:</p><ul><li>recording and updating outputs,</li><li>listing current outputs,</li><li>reading PR metadata,</li><li>reading CI state, and</li><li>reading review comments.</li></ul><p>The main output is a structured workflow suggestion or code-change reference. The remote prompt requires findings as soon as each action becomes clear.</p><p>If enrollment races or MCP is unavailable, the agent writes one fenced fallback JSON block. The host validates allowed kinds, actions, statuses, and the 140-character finding body before forwarding it to the same findings service. The output hook catches fallback blocks from webhook and reminder turns.</p><h2 id="verify-the-host-logic" tabindex="-1">Verify the host logic <a class="header-anchor" href="#verify-the-host-logic" aria-label="Permalink to &quot;Verify the host logic&quot;">​</a></h2><p>The coordinator has no filesystem evals. Its unit tests cover mode parsing, drive orchestration, affinity, webhook durability, CI settlement, output parsing, reminders, and Slack configuration:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> exec</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> vitest</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd/agent/lib</span></span></code></pre></div><p>Use those tests for host policy. Use a dedicated test PR and suggest mode for the end-to-end remote path.</p><h2 id="build-another-hybrid-coordinator" tabindex="-1">Build another hybrid coordinator <a class="header-anchor" href="#build-another-hybrid-coordinator" aria-label="Permalink to &quot;Build another hybrid coordinator&quot;">​</a></h2><p>Use this architecture when each work item needs a real checkout:</p><ol><li>Keep conversational intake local.</li><li>Open a remote session only after the request identifies a work item.</li><li>Give the work item a stable continuation key.</li><li>Persist its remote-agent id for cross-channel resume.</li><li>Coalesce noisy events before spending another turn.</li><li>Put the current mode and permissions in every host prompt.</li><li>Record outputs incrementally in a durable sink.</li><li>Add reminders for state requiring periodic rechecks.</li></ol><h2 id="where-to-go-next" tabindex="-1">Where to go next <a class="header-anchor" href="#where-to-go-next" aria-label="Permalink to &quot;Where to go next&quot;">​</a></h2><ul><li><a href="./../guides/cloud-runtime.html">Cloud runtime</a></li><li><a href="./../guides/github.html">GitHub</a></li><li><a href="./../guides/webhooks.html">Webhooks and custom channels</a></li><li><a href="./../reference/schedules.html">Schedules and reminders</a></li><li><a href="./../reference/sessions.html">Sessions and streaming</a></li><li><a href="./../deployment.html">Deployment</a></li></ul>`,84)])])}const k=t(o,[["render",n]]);export{u as __pageData,k as default};
15
+ <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;http://127.0.0.1:3000/fsd/v1/channels/drive/findings?pr=owner/repo%23123&#39;</span></span></code></pre></div><p>The external findings service is the source of truth. The local host doesn&#39;t keep a second findings database.</p><p>The channel also exposes <code>POST /findings</code> as a testing surface. It validates outputs, then writes them to the findings service for a PR already bound by this host. The route has no approval gate. Keep it under the default loopback auth or another trusted boundary.</p><h2 id="keep-one-remote-agent-per-pr" tabindex="-1">Keep one remote agent per PR <a class="header-anchor" href="#keep-one-remote-agent-per-pr" aria-label="Permalink to &quot;Keep one remote agent per PR&quot;">​</a></h2><p>Within the <code>drive</code> channel, the stable continuation token <code>pr:owner/repo#N</code> resumes the same session. GitHub sessions are scoped to another channel, so a continuation token alone can&#39;t bridge them.</p><p>The enrollment hook closes that gap:</p><ol><li>Read the PR from the continuation token or host-authored session title.</li><li>Record PR to <code>sdkAgentId</code> affinity after <code>agent.bound</code>.</li><li>Seed later sessions with the same remote id.</li><li>Retry workflow MCP enrollment after a completed turn when the first RPC failed.</li></ol><p>This lets Slack, HTTP drive, GitHub, and reminders talk to one remote conversation without sharing one channel session.</p><h2 id="buffer-github-wakes" tabindex="-1">Buffer GitHub wakes <a class="header-anchor" href="#buffer-github-wakes" aria-label="Permalink to &quot;Buffer GitHub wakes&quot;">​</a></h2><p>The GitHub channel handles pull requests, comments, reviews, check suites, check runs, and selected status events. It doesn&#39;t send payload details to the model. It asks the remote agent to refresh live source of truth.</p><p>The buffer:</p><ul><li>groups events by PR,</li><li>waits three seconds for a burst to settle,</li><li>re-buffers while CI settles,</li><li>skips a flush when the PR session is busy,</li><li>tries to write its snapshot before acknowledging a wake, and</li><li>restores pending entries when the channel starts.</li></ul><p>Closing a PR discards its pending entry and cancels its reminders.</p><p>Snapshot persistence is best-effort. Write failures are swallowed silently, so a delivery can still be acknowledged without a durable snapshot.</p><p>This is the high-volume counterpart to a direct <code>{ auth }</code> GitHub wake. See <a href="./../guides/github.html#handle-high-event-volume">GitHub</a> for the reusable pattern.</p><h2 id="add-merge-conflict-checks" tabindex="-1">Add merge-conflict checks <a class="header-anchor" href="#add-merge-conflict-checks" aria-label="Permalink to &quot;Add merge-conflict checks&quot;">​</a></h2><p>Starting a drive arms one recurring reminder per PR. Every 30 minutes the host checks mergeability:</p><ul><li>closed or merged stops the reminder,</li><li>clean skips delivery,</li><li>conflicting sends a follow-up to the owning session, and</li><li>a busy session skips the wake.</li></ul><p>This uses runtime reminders, not a static <code>agent/schedules/</code> file. The host creates, lists, replaces, and cancels reminders through <code>host.reminders</code>. Development mode doesn&#39;t fire reminder timers automatically. Dispatch one through the dev reminder endpoint for a manual proof, or use non-dev <code>serve</code> to run the 30-minute cadence.</p><p>The reminder&#39;s <code>run</code> handler lives in memory. After a host restart, the Agent SDK disarms it with <code>handler_lost_on_restart</code>; a later drive or webhook path can arm a fresh handler. Persisted reminder metadata alone doesn&#39;t keep the check running.</p><h2 id="record-findings-with-mcp-or-a-fallback" tabindex="-1">Record findings with MCP or a fallback <a class="header-anchor" href="#record-findings-with-mcp-or-a-fallback" aria-label="Permalink to &quot;Record findings with MCP or a fallback&quot;">​</a></h2><p>After enrollment, the remote agent receives workflow tools for:</p><ul><li>recording and updating outputs,</li><li>listing current outputs,</li><li>reading PR metadata,</li><li>reading CI state, and</li><li>reading review comments.</li></ul><p>The main output is a structured workflow suggestion or code-change reference. The remote prompt requires findings as soon as each action becomes clear.</p><p>If enrollment races or MCP is unavailable, the agent writes one fenced fallback JSON block. The host validates allowed kinds, actions, statuses, and the 140-character finding body before forwarding it to the same findings service. The output hook catches fallback blocks from webhook and reminder turns.</p><h2 id="verify-the-host-logic" tabindex="-1">Verify the host logic <a class="header-anchor" href="#verify-the-host-logic" aria-label="Permalink to &quot;Verify the host logic&quot;">​</a></h2><p>The coordinator has no filesystem evals. Its unit tests cover mode parsing, drive orchestration, affinity, webhook durability, CI settlement, output parsing, reminders, and Slack configuration:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> exec</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> vitest</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> run</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/fsd/agent/lib</span></span></code></pre></div><p>Use those tests for host policy. Use a dedicated test PR and suggest mode for the end-to-end remote path.</p><h2 id="build-another-hybrid-coordinator" tabindex="-1">Build another hybrid coordinator <a class="header-anchor" href="#build-another-hybrid-coordinator" aria-label="Permalink to &quot;Build another hybrid coordinator&quot;">​</a></h2><p>Use this architecture when each work item needs a real checkout:</p><ol><li>Keep conversational intake local.</li><li>Open a remote session only after the request identifies a work item.</li><li>Give the work item a stable continuation key.</li><li>Persist its remote-agent id for cross-channel resume.</li><li>Coalesce noisy events before spending another turn.</li><li>Put the current mode and permissions in every host prompt.</li><li>Record outputs incrementally in a durable sink.</li><li>Add reminders for state requiring periodic rechecks.</li></ol><h2 id="where-to-go-next" tabindex="-1">Where to go next <a class="header-anchor" href="#where-to-go-next" aria-label="Permalink to &quot;Where to go next&quot;">​</a></h2><ul><li><a href="./../guides/cloud-runtime.html">Cloud runtime</a></li><li><a href="./../guides/github.html">GitHub</a></li><li><a href="./../guides/webhooks.html">Webhooks and custom channels</a></li><li><a href="./../reference/schedules.html">Schedules and reminders</a></li><li><a href="./../reference/sessions.html">Sessions and streaming</a></li><li><a href="./../deployment.html">Deployment</a></li></ul>`,84)])])}const k=t(o,[["render",n]]);export{u as __pageData,k as default};