@cursor/july 0.1.91 → 0.1.93
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.
- package/AGENTS.md +4 -0
- package/README.md +117 -162
- package/dist/channels/deployments/deployments-channel.d.ts +7 -0
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +26 -2
- package/dist/channels/deployments/types.d.ts +8 -0
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/github-channel.d.ts +3 -0
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +28 -56
- package/dist/continuation.d.ts +1 -1
- package/dist/continuation.js +1 -1
- package/dist/docs/404.html +4 -2
- package/dist/docs/ab.html +10 -8
- package/dist/docs/ab.md +332 -0
- package/dist/docs/assets/{ab.md.CVzWxLoB.js → ab.md.DJo5r4R-.js} +4 -4
- package/dist/docs/assets/{ab.md.CVzWxLoB.lean.js → ab.md.DJo5r4R-.lean.js} +1 -1
- package/dist/docs/assets/{app.Bci6CM9E.js → app.CjWU-x0z.js} +1 -1
- package/dist/docs/assets/building-with-agents.md.DI4mEzlt.js +13 -0
- package/dist/docs/assets/{building-with-agents.md.DH8A_cHA.lean.js → building-with-agents.md.DI4mEzlt.lean.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.ChpIC3Zy.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.BCPT6xA-.js → VPLocalSearchBox.Cxy8ySFQ.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BEA8BF3c.js → theme.Dvq1Bktu.js} +2 -2
- package/dist/docs/assets/concepts.md.F6AiPorA.js +1 -0
- package/dist/docs/assets/{concepts.md.CRfU3bVg.lean.js → concepts.md.F6AiPorA.lean.js} +1 -1
- package/dist/docs/assets/{deployment.md.DX_hc3ze.js → deployment.md.DoLFAzfm.js} +6 -6
- package/dist/docs/assets/{evals.md.a0SMN6r9.js → evals.md.lfJoEVc8.js} +6 -6
- package/dist/docs/assets/{evals.md.a0SMN6r9.lean.js → evals.md.lfJoEVc8.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_approval-buddy.md.DNL83puR.js → example-agents_approval-buddy.md.DmezILPg.js} +1 -1
- package/dist/docs/assets/{example-agents_benny.md.C40vHRLc.js → example-agents_benny.md.B0kwY7D_.js} +2 -4
- package/dist/docs/assets/{example-agents_benny.md.C40vHRLc.lean.js → example-agents_benny.md.B0kwY7D_.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_codebase-wiki.md.Dftj_tPp.js → example-agents_codebase-wiki.md.BBNw9Ekr.js} +3 -3
- package/dist/docs/assets/{example-agents_codebase-wiki.md.Dftj_tPp.lean.js → example-agents_codebase-wiki.md.BBNw9Ekr.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_concierge.md.MrKpQndp.js → example-agents_concierge.md.BzB2b20R.js} +2 -3
- package/dist/docs/assets/example-agents_index.md.ChBp0AX6.js +2 -0
- package/dist/docs/assets/example-agents_index.md.ChBp0AX6.lean.js +1 -0
- package/dist/docs/assets/{example-agents_knowledge-base.md.DqKqHQ9u.js → example-agents_knowledge-base.md.CrA85ig-.js} +1 -1
- package/dist/docs/assets/{example-agents_security-reviewer.md.Bai6D0Ee.js → example-agents_security-reviewer.md.74pPpWYj.js} +1 -1
- package/dist/docs/assets/{example-agents_weather-agent.md.lVEAbWFf.js → example-agents_weather-agent.md.CaGpmw3Y.js} +2 -2
- package/dist/docs/assets/{guides_agent-to-agent.md.BCeVdJRJ.js → guides_agent-to-agent.md.B3JIaAqz.js} +1 -1
- package/dist/docs/assets/{guides_cloud-runtime.md.BSMLIBHr.js → guides_cloud-runtime.md.BnvjPiia.js} +2 -2
- package/dist/docs/assets/{guides_cloud-runtime.md.BSMLIBHr.lean.js → guides_cloud-runtime.md.BnvjPiia.lean.js} +1 -1
- package/dist/docs/assets/{guides_convert-automation.md.D06eIzea.js → guides_convert-automation.md.Bboisykk.js} +1 -1
- package/dist/docs/assets/{guides_github.md.Cdt1s2QC.js → guides_github.md.DqJhuaN1.js} +5 -5
- package/dist/docs/assets/{guides_github.md.Cdt1s2QC.lean.js → guides_github.md.DqJhuaN1.lean.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.Du0f7pGU.js → guides_mcp-oauth.md.CJvrXtkN.js} +2 -2
- package/dist/docs/assets/{guides_slack.md.DiUmk_Oi.js → guides_slack.md.mqeNKs84.js} +2 -2
- package/dist/docs/assets/{guides_webhooks.md.BpnIdO0i.js → guides_webhooks.md.DKdA43Qm.js} +2 -2
- package/dist/docs/assets/{hillclimbing.md.ywF3yDAd.js → hillclimbing.md.DhESf3OO.js} +1 -1
- package/dist/docs/assets/{index.md.BAaMXLFd.js → index.md.B-lVR4wT.js} +3 -3
- package/dist/docs/assets/{index.md.BAaMXLFd.lean.js → index.md.B-lVR4wT.lean.js} +1 -1
- package/dist/docs/assets/{quickstart.md.DsrarzEg.js → quickstart.md.BrmfrrIr.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.Bqylgw50.js → reference_agent-config.md.Cp_x38Nl.js} +3 -3
- package/dist/docs/assets/{reference_channels.md.DQZjCnyh.js → reference_channels.md.Cd2f2iyV.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.DQZjCnyh.lean.js → reference_channels.md.Cd2f2iyV.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.B7GkAJRC.js → reference_cli.md.D9KESDsD.js} +10 -11
- package/dist/docs/assets/{reference_cli.md.B7GkAJRC.lean.js → reference_cli.md.D9KESDsD.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.DYidrb-j.js → reference_connections.md.DB6SsN6U.js} +3 -3
- package/dist/docs/assets/reference_hooks.md.BxN87gCw.js +14 -0
- package/dist/docs/assets/{reference_hooks.md.B9FSgdDe.lean.js → reference_hooks.md.BxN87gCw.lean.js} +1 -1
- package/dist/docs/assets/reference_http-api.md.C68BERYr.js +11 -0
- package/dist/docs/assets/reference_http-api.md.C68BERYr.lean.js +1 -0
- package/dist/docs/assets/{reference_instructions.md.DhNCOl7r.js → reference_instructions.md.CR7XSsGk.js} +3 -3
- package/dist/docs/assets/{reference_instructions.md.DhNCOl7r.lean.js → reference_instructions.md.CR7XSsGk.lean.js} +1 -1
- package/dist/docs/assets/reference_playground.md.DnX5nL-B.js +1 -0
- package/dist/docs/assets/reference_playground.md.DnX5nL-B.lean.js +1 -0
- package/dist/docs/assets/{reference_project-layout.md.CwkSbEWT.js → reference_project-layout.md.WN9nwJht.js} +2 -2
- package/dist/docs/assets/{reference_prompt.md.DZUMtLPD.js → reference_prompt.md.DnaD5dNK.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.DNipebiG.js → reference_schedules.md.DI_JrHgq.js} +1 -1
- package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +1 -0
- package/dist/docs/assets/{reference_sessions.md.tUFzz98S.lean.js → reference_sessions.md.D0mIh4KK.lean.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.B5ZEuHfG.js → reference_skills.md.BFW9retM.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.wpaJtHn6.js → reference_tools.md.DuKvkYWG.js} +4 -4
- package/dist/docs/assets/{reference_tools.md.wpaJtHn6.lean.js → reference_tools.md.DuKvkYWG.lean.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +1 -0
- package/dist/docs/assets/{scaffolding-agents.md.CRDDUtYJ.lean.js → scaffolding-agents.md.D7UUkWw0.lean.js} +1 -1
- package/dist/docs/assets/{storage.md.JbjlHWZ6.js → storage.md.BOHeqk2M.js} +5 -5
- package/dist/docs/assets/{storage.md.JbjlHWZ6.lean.js → storage.md.BOHeqk2M.lean.js} +1 -1
- package/dist/docs/assets/{templates_agentic-owners.md.DSJSIpWU.js → templates_agentic-owners.md.DqtPdm6f.js} +2 -2
- package/dist/docs/assets/{templates_pr-autofixer.md.1HAR3RXE.js → templates_pr-autofixer.md.R4K_qytS.js} +2 -2
- package/dist/docs/assets/{templates_pr-autofixer.md.1HAR3RXE.lean.js → templates_pr-autofixer.md.R4K_qytS.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.vCWwvqcJ.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.DYECCZiJ.lean.js → troubleshooting.md.vCWwvqcJ.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +9 -7
- package/dist/docs/building-with-agents.md +118 -0
- package/dist/docs/concepts.html +7 -8
- package/dist/docs/concepts.md +169 -0
- package/dist/docs/deployment.html +13 -11
- package/dist/docs/deployment.md +462 -0
- package/dist/docs/evals.html +12 -10
- package/dist/docs/evals.md +460 -0
- package/dist/docs/example-agents/approval-buddy.html +7 -5
- package/dist/docs/example-agents/approval-buddy.md +266 -0
- package/dist/docs/example-agents/benny.html +7 -7
- package/dist/docs/example-agents/benny.md +173 -0
- package/dist/docs/example-agents/bugbot.html +6 -4
- package/dist/docs/example-agents/bugbot.md +229 -0
- package/dist/docs/example-agents/codebase-wiki.html +8 -6
- package/dist/docs/example-agents/codebase-wiki.md +167 -0
- package/dist/docs/example-agents/codeowners-review.html +6 -4
- package/dist/docs/example-agents/codeowners-review.md +192 -0
- package/dist/docs/example-agents/concierge.html +9 -8
- package/dist/docs/example-agents/concierge.md +200 -0
- package/dist/docs/example-agents/index.html +8 -6
- package/dist/docs/example-agents/index.md +99 -0
- package/dist/docs/example-agents/knowledge-base.html +8 -6
- package/dist/docs/example-agents/knowledge-base.md +168 -0
- package/dist/docs/example-agents/oncall.html +6 -4
- package/dist/docs/example-agents/oncall.md +212 -0
- package/dist/docs/example-agents/security-reviewer.html +9 -7
- package/dist/docs/example-agents/security-reviewer.md +265 -0
- package/dist/docs/example-agents/slack-agent.html +6 -4
- package/dist/docs/example-agents/slack-agent.md +142 -0
- package/dist/docs/example-agents/weather-agent.html +9 -7
- package/dist/docs/example-agents/weather-agent.md +297 -0
- package/dist/docs/guides/agent-to-agent.html +7 -5
- package/dist/docs/guides/agent-to-agent.md +113 -0
- package/dist/docs/guides/cloud-runtime.html +8 -6
- package/dist/docs/guides/cloud-runtime.md +114 -0
- package/dist/docs/guides/convert-automation.html +8 -6
- package/dist/docs/guides/convert-automation.md +171 -0
- package/dist/docs/guides/github.html +11 -9
- package/dist/docs/guides/github.md +275 -0
- package/dist/docs/guides/human-in-the-loop.html +6 -4
- package/dist/docs/guides/human-in-the-loop.md +126 -0
- package/dist/docs/guides/mcp-oauth.html +8 -6
- package/dist/docs/guides/mcp-oauth.md +159 -0
- package/dist/docs/guides/opentelemetry.html +6 -4
- package/dist/docs/guides/opentelemetry.md +209 -0
- package/dist/docs/guides/slack.html +9 -7
- package/dist/docs/guides/slack.md +337 -0
- package/dist/docs/guides/webhooks.html +8 -6
- package/dist/docs/guides/webhooks.md +463 -0
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +8 -6
- package/dist/docs/hillclimbing.md +88 -0
- package/dist/docs/index.html +8 -6
- package/dist/docs/index.md +171 -0
- package/dist/docs/llms-full.txt +10968 -0
- package/dist/docs/llms.txt +74 -0
- package/dist/docs/quickstart.html +7 -5
- package/dist/docs/quickstart.md +364 -0
- package/dist/docs/reference/agent-config.html +10 -8
- package/dist/docs/reference/agent-config.md +251 -0
- package/dist/docs/reference/artifacts.html +6 -4
- package/dist/docs/reference/artifacts.md +112 -0
- package/dist/docs/reference/channels.html +8 -6
- package/dist/docs/reference/channels.md +244 -0
- package/dist/docs/reference/cli.html +16 -15
- package/dist/docs/reference/cli.md +947 -0
- package/dist/docs/reference/connections.html +10 -8
- package/dist/docs/reference/connections.md +263 -0
- package/dist/docs/reference/hooks.html +8 -6
- package/dist/docs/reference/hooks.md +98 -0
- package/dist/docs/reference/http-api.html +9 -7
- package/dist/docs/reference/http-api.md +247 -0
- package/dist/docs/reference/instructions.html +8 -6
- package/dist/docs/reference/instructions.md +74 -0
- package/dist/docs/reference/playground.html +7 -5
- package/dist/docs/reference/playground.md +57 -0
- package/dist/docs/reference/project-layout.html +9 -7
- package/dist/docs/reference/project-layout.md +107 -0
- package/dist/docs/reference/prompt.html +8 -6
- package/dist/docs/reference/prompt.md +42 -0
- package/dist/docs/reference/schedules.html +8 -6
- package/dist/docs/reference/schedules.md +214 -0
- package/dist/docs/reference/sessions.html +7 -12
- package/dist/docs/reference/sessions.md +159 -0
- package/dist/docs/reference/skills.html +8 -6
- package/dist/docs/reference/skills.md +83 -0
- package/dist/docs/reference/subagents.html +6 -4
- package/dist/docs/reference/subagents.md +71 -0
- package/dist/docs/reference/tools.html +10 -8
- package/dist/docs/reference/tools.md +293 -0
- package/dist/docs/scaffolding-agents.html +7 -5
- package/dist/docs/scaffolding-agents.md +129 -0
- package/dist/docs/storage.html +11 -9
- package/dist/docs/storage.md +176 -0
- package/dist/docs/templates/agentic-owners.html +9 -7
- package/dist/docs/templates/agentic-owners.md +92 -0
- package/dist/docs/templates/demo.html +6 -4
- package/dist/docs/templates/demo.md +79 -0
- package/dist/docs/templates/pr-autofixer.html +8 -6
- package/dist/docs/templates/pr-autofixer.md +128 -0
- package/dist/docs/templates/security-reviewer.html +6 -4
- package/dist/docs/templates/security-reviewer.md +84 -0
- package/dist/docs/templates/triage.html +6 -4
- package/dist/docs/templates/triage.md +98 -0
- package/dist/docs/troubleshooting.html +7 -5
- package/dist/docs/troubleshooting.md +111 -0
- package/dist/internal/authored-alias-hooks.d.ts +14 -11
- package/dist/internal/authored-alias-hooks.d.ts.map +1 -1
- package/dist/internal/authored-alias-hooks.js +14 -11
- package/dist/internal/authored-loaders.d.ts +7 -6
- package/dist/internal/authored-loaders.d.ts.map +1 -1
- package/dist/internal/authored-loaders.js +14 -10
- package/dist/internal/cli-deploy.d.ts +1 -1
- package/dist/internal/cli-deploy.js +5 -5
- package/dist/internal/continuation-channel.d.ts +6 -3
- package/dist/internal/continuation-channel.d.ts.map +1 -1
- package/dist/internal/continuation-channel.js +44 -40
- package/dist/internal/continuation-identity.d.ts +17 -16
- package/dist/internal/continuation-identity.d.ts.map +1 -1
- package/dist/internal/continuation-identity.js +109 -36
- package/dist/internal/deploy-manifest.d.ts +2 -2
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +4 -9
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +3 -0
- package/dist/internal/distribution.d.ts +4 -3
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +4 -3
- package/dist/internal/hosted-delivery-protocol.d.ts +38 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -0
- package/dist/internal/hosted-delivery-protocol.js +70 -0
- package/dist/internal/hosted-delivery.d.ts +35 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -0
- package/dist/internal/hosted-delivery.js +226 -0
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +1 -1
- package/dist/internal/init-scaffold.d.ts.map +1 -1
- package/dist/internal/init-scaffold.js +1 -0
- package/dist/internal/playground/static.d.ts.map +1 -1
- package/dist/internal/playground/static.js +2 -0
- package/dist/internal/review-comments.d.ts +186 -63
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +350 -168
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +21 -3
- package/dist/internal/session-engine.d.ts +5 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +16 -4
- package/dist/internal/shallow-clone.d.ts +8 -2
- package/dist/internal/shallow-clone.d.ts.map +1 -1
- package/dist/internal/shallow-clone.js +17 -10
- package/dist/playground/assets/{index-DDvyC2z6.js → index-D9MFzhNE.js} +1 -1
- package/dist/playground/index.html +1 -1
- package/dist/types.d.ts +9 -17
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +2 -10
- package/docs/ab.md +7 -13
- package/docs/building-with-agents.md +5 -11
- package/docs/concepts.md +12 -17
- package/docs/deployment.md +8 -10
- package/docs/evals.md +16 -37
- package/docs/example-agents/approval-buddy.md +1 -1
- package/docs/example-agents/benny.md +4 -13
- package/docs/example-agents/codebase-wiki.md +5 -8
- package/docs/example-agents/concierge.md +2 -3
- package/docs/example-agents/index.md +6 -9
- package/docs/example-agents/knowledge-base.md +2 -2
- package/docs/example-agents/security-reviewer.md +5 -5
- package/docs/example-agents/weather-agent.md +4 -3
- package/docs/guides/agent-to-agent.md +1 -1
- package/docs/guides/cloud-runtime.md +8 -25
- package/docs/guides/convert-automation.md +3 -3
- package/docs/guides/github.md +11 -23
- package/docs/guides/mcp-oauth.md +4 -4
- package/docs/guides/slack.md +4 -4
- package/docs/guides/webhooks.md +3 -3
- package/docs/hillclimbing.md +1 -1
- package/docs/quickstart.md +1 -1
- package/docs/reference/agent-config.md +10 -15
- package/docs/reference/channels.md +20 -31
- package/docs/reference/cli.md +27 -37
- package/docs/reference/connections.md +9 -14
- package/docs/reference/hooks.md +10 -14
- package/docs/reference/http-api.md +18 -38
- package/docs/reference/instructions.md +1 -1
- package/docs/reference/playground.md +14 -19
- package/docs/reference/project-layout.md +2 -2
- package/docs/reference/prompt.md +1 -1
- package/docs/reference/schedules.md +1 -2
- package/docs/reference/sessions.md +8 -19
- package/docs/reference/skills.md +3 -3
- package/docs/reference/tools.md +12 -17
- package/docs/scaffolding-agents.md +4 -5
- package/docs/storage.md +37 -80
- package/docs/templates/agentic-owners.md +2 -2
- package/docs/templates/pr-autofixer.md +3 -6
- package/docs/troubleshooting.md +6 -6
- package/package.json +9 -2
- package/skills/ab/SKILL.md +3 -0
- package/skills/create-agent/SKILL.md +3 -0
- package/skills/debug/SKILL.md +3 -0
- package/skills/evals/SKILL.md +3 -0
- package/skills/framework-map/SKILL.md +3 -0
- package/skills/github/SKILL.md +3 -0
- package/skills/hillclimb/SKILL.md +3 -0
- package/skills/mcp-auth/SKILL.md +3 -0
- package/skills/otel/SKILL.md +3 -0
- package/skills/setup-slack/SKILL.md +3 -0
- package/src/channels/deployments/deployments-channel.ts +32 -2
- package/src/channels/deployments/types.ts +8 -0
- package/src/channels/github/github-channel.ts +71 -21
- package/src/continuation.ts +1 -1
- package/src/internal/authored-alias-hooks.ts +14 -11
- package/src/internal/authored-loaders.ts +14 -10
- package/src/internal/cli-deploy.ts +5 -5
- package/src/internal/continuation-channel.ts +62 -45
- package/src/internal/continuation-identity.ts +123 -38
- package/src/internal/deploy-manifest.ts +5 -9
- package/src/internal/discovery.ts +3 -0
- package/src/internal/distribution.ts +4 -3
- package/src/internal/hosted-delivery-protocol.ts +114 -0
- package/src/internal/hosted-delivery.ts +327 -0
- package/src/internal/http-channel.ts +0 -2
- package/src/internal/init-scaffold.ts +1 -0
- package/src/internal/playground/static.ts +2 -0
- package/src/internal/review-comments.ts +542 -229
- package/src/internal/server.ts +29 -2
- package/src/internal/session-engine.ts +29 -7
- package/src/internal/shallow-clone.ts +30 -16
- package/src/types.ts +9 -17
- package/dist/docs/assets/building-with-agents.md.DH8A_cHA.js +0 -13
- package/dist/docs/assets/chunks/@localSearchIndexroot.Dv-Q0XtU.js +0 -1
- package/dist/docs/assets/concepts.md.CRfU3bVg.js +0 -4
- package/dist/docs/assets/example-agents_fsd.md.ZWHWWZPE.js +0 -15
- package/dist/docs/assets/example-agents_fsd.md.ZWHWWZPE.lean.js +0 -1
- package/dist/docs/assets/example-agents_index.md.QZ8mhr6n.js +0 -2
- package/dist/docs/assets/example-agents_index.md.QZ8mhr6n.lean.js +0 -1
- package/dist/docs/assets/reference_hooks.md.B9FSgdDe.js +0 -14
- package/dist/docs/assets/reference_http-api.md.CSHVobzG.js +0 -11
- package/dist/docs/assets/reference_http-api.md.CSHVobzG.lean.js +0 -1
- package/dist/docs/assets/reference_playground.md.Dfb92yQf.js +0 -1
- package/dist/docs/assets/reference_playground.md.Dfb92yQf.lean.js +0 -1
- package/dist/docs/assets/reference_sessions.md.tUFzz98S.js +0 -8
- package/dist/docs/assets/scaffolding-agents.md.CRDDUtYJ.js +0 -1
- package/dist/docs/assets/troubleshooting.md.DYECCZiJ.js +0 -1
- package/dist/docs/example-agents/fsd.html +0 -39
- package/docs/example-agents/fsd.md +0 -334
- /package/dist/docs/assets/{deployment.md.DX_hc3ze.lean.js → deployment.md.DoLFAzfm.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_approval-buddy.md.DNL83puR.lean.js → example-agents_approval-buddy.md.DmezILPg.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_concierge.md.MrKpQndp.lean.js → example-agents_concierge.md.BzB2b20R.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_knowledge-base.md.DqKqHQ9u.lean.js → example-agents_knowledge-base.md.CrA85ig-.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_security-reviewer.md.Bai6D0Ee.lean.js → example-agents_security-reviewer.md.74pPpWYj.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_weather-agent.md.lVEAbWFf.lean.js → example-agents_weather-agent.md.CaGpmw3Y.lean.js} +0 -0
- /package/dist/docs/assets/{guides_agent-to-agent.md.BCeVdJRJ.lean.js → guides_agent-to-agent.md.B3JIaAqz.lean.js} +0 -0
- /package/dist/docs/assets/{guides_convert-automation.md.D06eIzea.lean.js → guides_convert-automation.md.Bboisykk.lean.js} +0 -0
- /package/dist/docs/assets/{guides_mcp-oauth.md.Du0f7pGU.lean.js → guides_mcp-oauth.md.CJvrXtkN.lean.js} +0 -0
- /package/dist/docs/assets/{guides_slack.md.DiUmk_Oi.lean.js → guides_slack.md.mqeNKs84.lean.js} +0 -0
- /package/dist/docs/assets/{guides_webhooks.md.BpnIdO0i.lean.js → guides_webhooks.md.DKdA43Qm.lean.js} +0 -0
- /package/dist/docs/assets/{hillclimbing.md.ywF3yDAd.lean.js → hillclimbing.md.DhESf3OO.lean.js} +0 -0
- /package/dist/docs/assets/{quickstart.md.DsrarzEg.lean.js → quickstart.md.BrmfrrIr.lean.js} +0 -0
- /package/dist/docs/assets/{reference_agent-config.md.Bqylgw50.lean.js → reference_agent-config.md.Cp_x38Nl.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.DYidrb-j.lean.js → reference_connections.md.DB6SsN6U.lean.js} +0 -0
- /package/dist/docs/assets/{reference_project-layout.md.CwkSbEWT.lean.js → reference_project-layout.md.WN9nwJht.lean.js} +0 -0
- /package/dist/docs/assets/{reference_prompt.md.DZUMtLPD.lean.js → reference_prompt.md.DnaD5dNK.lean.js} +0 -0
- /package/dist/docs/assets/{reference_schedules.md.DNipebiG.lean.js → reference_schedules.md.DI_JrHgq.lean.js} +0 -0
- /package/dist/docs/assets/{reference_skills.md.B5ZEuHfG.lean.js → reference_skills.md.BFW9retM.lean.js} +0 -0
- /package/dist/docs/assets/{templates_agentic-owners.md.DSJSIpWU.lean.js → templates_agentic-owners.md.DqtPdm6f.lean.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as e,c as
|
|
1
|
+
import{_ as e,c as i,o as a,ag as t}from"./chunks/framework.BCISBCiQ.js";const k=JSON.parse('{"title":"Evals","description":"Define repeatable checks with defineEval, run them with agent-sdk eval, and use them as regression checks.","frontmatter":{"title":"Evals","description":"Define repeatable checks with defineEval, run them with agent-sdk eval, and use them as regression checks."},"headers":[],"relativePath":"evals.md","filePath":"evals.md"}'),n={name:"evals.md"};function l(d,s,h,o,r,p){return a(),i("div",null,[...s[0]||(s[0]=[t(`<h1 id="evals" tabindex="-1">Evals <a class="header-anchor" href="#evals" aria-label="Permalink to "Evals""></a></h1><p>An eval is a repeatable check that runs your agent against a fixed input and gates the recorded trajectory: the run completed, the right tool ran, the reply has the right shape. Evals are how you know a prompt tweak helped, a refactor didn't regress the agent, and last month's fix is still holding.</p><p>Evals exercise the same surface your users hit. The runner starts (or targets) a real agent server, drives sessions over the public API, and grades what comes back. A passing eval means the agent started, accepted a message, and did what you asserted.</p><h2 id="define-evals-with-defineeval" tabindex="-1">Define evals with <code>defineEval</code> <a class="header-anchor" href="#define-evals-with-defineeval" aria-label="Permalink to "Define evals with \`defineEval\`""></a></h2><p>The Agent SDK discovers evals under the project-root <code>evals/</code> directory, in <code>.eval.ts</code> or <code>.eval.js</code> files. That's a sibling of <code>agent/</code>, never inside it (<code>agent/evals/</code> is silently ignored). TypeScript is the normal authoring format.</p><p>The file path is the eval's identity, so you don't author an id. Directories group related evals: <code>evals/builds/api.eval.ts</code> becomes id <code>builds/api</code>. An <code>index</code> filename collapses to its directory, so <code>evals/builds/index.eval.ts</code> becomes <code>builds</code>.</p><p>An eval is a single <code>async test(t)</code>. You drive the agent with <code>t</code> and assert on the run with the same <code>t</code>:</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:#6A737D;--shiki-dark:#6A737D;">// evals/readiness.eval.ts</span></span>
|
|
2
2
|
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineEval, includes } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> "@cursor/july/evals"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
|
|
3
3
|
<span class="line"></span>
|
|
4
4
|
<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;"> defineEval</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
@@ -47,8 +47,8 @@ import{_ as e,c as a,o as i,ag as t}from"./chunks/framework.BCISBCiQ.js";const k
|
|
|
47
47
|
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // timeoutMs: 180_000,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // optional project-wide default</span></span>
|
|
48
48
|
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // judge: { model: "..." },</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // default judge model for t.judge.*</span></span>
|
|
49
49
|
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // reporters: [],</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // destinations that observe every case</span></span>
|
|
50
|
-
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // maxPlaygroundRuns: 50,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // playground
|
|
51
|
-
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>The timeout order is case or file <code>timeoutMs</code>, CLI <code>--timeout-ms</code>, project config <code>timeoutMs</code>, then the 180-second runner default.</p><p>The optional fields:</p><table tabindex="0"><thead><tr><th>Option</th><th>Default</th><th>Meaning</th></tr></thead><tbody><tr><td><code>timeoutMs</code></td><td><code>180_000</code></td><td>Project-wide per-case timeout</td></tr><tr><td><code>judge</code></td><td>unset</td><td>Default judge model for <code>t.judge.*</code>; see <a href="#judge-free-form-output">Judge free-form output</a></td></tr><tr><td><code>reporters</code></td><td>unset</td><td>Destinations that observe every case; <code>--skip-report</code> suppresses them</td></tr><tr><td><code>maxPlaygroundRuns</code></td><td><code>20</code></td><td>Max batches in the playground / <code>/v1/dev/evals*</code> history (not CLI <code>eval</code>)
|
|
50
|
+
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // maxPlaygroundRuns: 50,</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // playground history only (default 20)</span></span>
|
|
51
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>The timeout order is case or file <code>timeoutMs</code>, CLI <code>--timeout-ms</code>, project config <code>timeoutMs</code>, then the 180-second runner default.</p><p>The optional fields:</p><table tabindex="0"><thead><tr><th>Option</th><th>Default</th><th>Meaning</th></tr></thead><tbody><tr><td><code>timeoutMs</code></td><td><code>180_000</code></td><td>Project-wide per-case timeout</td></tr><tr><td><code>judge</code></td><td>unset</td><td>Default judge model for <code>t.judge.*</code>; see <a href="#judge-free-form-output">Judge free-form output</a></td></tr><tr><td><code>reporters</code></td><td>unset</td><td>Destinations that observe every case; <code>--skip-report</code> suppresses them</td></tr><tr><td><code>maxPlaygroundRuns</code></td><td><code>20</code></td><td>Max batches in the playground / <code>/v1/dev/evals*</code> history (not CLI <code>eval</code>). Hard-capped at 500.</td></tr></tbody></table><p>Reporters come from <code>@cursor/july/evals/reporters</code>: <code>JUnit</code> writes a JUnit XML file for CI, <code>Artifacts</code> writes per-case files, and <code>combineReporters</code> merges several into one (<code>renderJUnitXml</code> renders the XML for a custom destination). A file or case can add its own <code>reporters</code> on top of the config list.</p><p>Playground batches survive restarts whenever <code>agent/storage.ts</code> exists with an <code>evals</code> table or a KV core providing <code>delete</code> and <code>list</code> (the table is derived over the core); see <a href="./storage.html#eval-and-a-b-tables">Storage</a>. Without storage they live in process memory and disappear when <code>serve</code> exits. Navigating away and back still works while the process is up.</p><h2 id="drive-and-assert-with-t" tabindex="-1">Drive and assert with <code>t</code> <a class="header-anchor" href="#drive-and-assert-with-t" aria-label="Permalink to "Drive and assert with \`t\`""></a></h2><p><code>t</code> is both the driver and the assertion surface. You write ordinary control flow, sending turns and asserting inline.</p><p>Drive the agent with <code>t.send(message, options?)</code>. It runs one turn and waits for the session to park or fail. Multiple sends in one case share the session, which is how you write multi-turn evals.</p><p>Each <code>t.send</code> resolves to a turn result with <code>message</code>, <code>sessionId</code>, <code>events</code>, <code>toolCalls</code>, <code>ok</code>, and <code>index</code>. The turn carries the same assertion vocabulary as <code>t</code>, scoped to that turn, so you can grade an intermediate turn before the next send overwrites <code>t.reply</code>. <code>turn.expectOk()</code> throws when the turn failed, for later steps that depend on it.</p><p>Read the full case state with <code>t.reply</code> (the last assistant text), <code>t.events</code> (session events captured so far), <code>t.turns</code> (settled turns, oldest first), and <code>t.sessionId</code>. <code>t.signal</code> aborts when the case hits its timeout; pass it to your own async work.</p><p>Assert with the gates:</p><table tabindex="0"><thead><tr><th>Gate</th><th>Checks</th></tr></thead><tbody><tr><td><code>t.succeeded()</code></td><td>the run did not fail and is not parked on an unanswered approval</td></tr><tr><td><code>t.parked()</code></td><td>the run cleanly parked on an unanswered approval request</td></tr><tr><td><code>t.messageIncludes(token)</code></td><td>the joined assistant text matches a string or <code>RegExp</code></td></tr><tr><td><code>t.calledTool(name, matcher?)</code></td><td>a matching call to <code>name</code> happened</td></tr><tr><td><code>t.notCalledTool(name)</code></td><td>no request for <code>name</code>, in any lifecycle state</td></tr><tr><td><code>t.loadedSkill(name)</code></td><td>the agent opened the skill's <code>SKILL.md</code> (read, grep, or shell <code>cat</code>)</td></tr><tr><td><code>t.toolOrder(names)</code></td><td>tool requests appear in this relative order (extra calls allowed)</td></tr><tr><td><code>t.usedNoTools()</code></td><td>no tool calls at all</td></tr><tr><td><code>t.maxToolCalls(max)</code></td><td>at most <code>max</code> tool calls</td></tr><tr><td><code>t.noFailedActions()</code></td><td>no tool call reported an error</td></tr><tr><td><code>t.calledSubagent(name, matcher?)</code></td><td>a matching subagent delegation happened</td></tr><tr><td><code>t.taggedArtifact(kind?, predicate?)</code></td><td>at least one <a href="./reference/artifacts.html">artifact</a> was tagged</td></tr><tr><td><code>t.event(type, matcher?)</code></td><td>at least one matching event of <code>type</code> occurred</td></tr><tr><td><code>t.notEvent(type, matcher?)</code></td><td>no matching event of <code>type</code> occurred</td></tr><tr><td><code>t.eventOrder(matchers)</code></td><td>matching event groups occur in this relative order</td></tr><tr><td><code>t.eventsSatisfy(label, predicate)</code></td><td>your predicate over the typed event stream</td></tr><tr><td><code>t.check(value, expectation)</code></td><td>any value, against a builder</td></tr><tr><td><code>t.score(name, value)</code></td><td>records a 0–1 score you computed; soft until you add a bar</td></tr><tr><td><code>t.requireToolCall(name, matcher?)</code></td><td>gates on a matching call and returns it, so later code can read its input and output</td></tr><tr><td><code>t.requireInputRequest(filter?)</code></td><td>gates on exactly one pending approval request and returns it</td></tr></tbody></table><p>Every gate returns a handle: <code>.soft()</code> demotes it to tracked-only, <code>.atLeast(0.7)</code> adds a soft score bar, and <code>.gate(0.8)</code> promotes a scored assertion into a hard gate.</p><p>With no matcher, <code>calledTool</code> is request-based: a requested call counts even when its result has not arrived. Pass <code>t.calledTool("inspect_pr", { status: "completed" })</code> to require the call to return. <code>input</code>, <code>output</code>, and <code>count</code> matcher fields accept a literal, a <code>RegExp</code>, or a predicate.</p><p>The expectation builders are <code>includes(string | RegExp)</code>, <code>equals(value)</code>, <code>matches(schema)</code>, <code>similarity(expected)</code>, and <code>satisfies(predicate, label)</code>. <code>includes</code> stringifies its input, <code>equals</code> compares values deeply, <code>matches</code> validates against a Standard Schema (or anything with <code>safeParse</code>, like Zod), <code>similarity</code> scores normalized text similarity, and <code>satisfies</code> runs your predicate. The plain function <code>normalizedSimilarity(actual, expected)</code> returns the same 0–1 score for use with <code>t.score</code>.</p><p>A few more context members shape a case: <code>t.require(value, expectation)</code> records a gate and stops the test body when it fails, without a duplicate execution error. <code>t.skip(reason)</code> ends the case as skipped (reported separately, never changes the exit code; call it before sending messages). <code>t.metric(name, value)</code> records a structured score for the playground case card. <code>t.log(message)</code> records a debug line for the CLI and playground result.</p><p>Three <code>t.send</code> options apply on session create (first <code>t.send</code> only):</p><ul><li><code>workspaceFiles</code>: <code>{ path: contents }</code>, seeded into the local session workspace. Prefer this over machine-local paths.</li><li><code>workspaceDir</code>: absolute harness cwd (local runtime).</li><li><code>cloud</code>: per-session cloud options merged over the agent's static <code>cloud</code> config (repos / env / …). Use a pinned <code>repos</code> override to attach a fixture repo for cloud evals without putting it on the agent's default <code>cloud.repos</code>. Cloud ignores <code>workspaceFiles</code> seeds.</li></ul><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;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> toolResults</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> t.events.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">filter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">e</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> e.type </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> "action.result"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
|
|
52
52
|
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">t.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">check</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
|
|
53
53
|
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> toolResults.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
54
54
|
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> satisfies</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">n</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (n </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">as</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> number</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"><=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> 4</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"at most 4 tool calls"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
@@ -58,7 +58,7 @@ import{_ as e,c as a,o as i,ag as t}from"./chunks/framework.BCISBCiQ.js";const k
|
|
|
58
58
|
<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;"> .</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> builds</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> search</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> # several ids or prefixes</span></span>
|
|
59
59
|
<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;"> .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --tag</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> smoke</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --tag</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> pull-request</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> # any matching tag</span></span>
|
|
60
60
|
<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;"> .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --no-stream</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> # machine-readable results</span></span>
|
|
61
|
-
<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;"> .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --verbose</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> # logs + reply snippets</span></span></code></pre></div><p>Id filters use OR semantics. Each filter selects an exact id and its descendants. For example, <code>builds</code> selects <code>builds</code>, <code>builds/checkout</code>, and every other case below that path. Repeated tags also use OR semantics. When you provide both ids and tags, a case must match both groups.</p><p><code>eval</code> boots an ephemeral server on port 0 with a temp state root outside the project, so cases don't inherit ambient monorepo rules and don't
|
|
61
|
+
<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;"> .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --verbose</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> # logs + reply snippets</span></span></code></pre></div><p>Id filters use OR semantics. Each filter selects an exact id and its descendants. For example, <code>builds</code> selects <code>builds</code>, <code>builds/checkout</code>, and every other case below that path. Repeated tags also use OR semantics. When you provide both ids and tags, a case must match both groups.</p><p><code>eval</code> boots an ephemeral server on port 0 with a temp state root outside the project, so cases don't inherit ambient monorepo rules and don't write into the project state directory. Point <code>--url</code> at a running server to eval a live agent instead:</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;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
|
|
62
62
|
<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/weather-agent</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
|
|
63
63
|
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --bearer-token</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$AGENT_TOKEN</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"</span></span></code></pre></div><p>The eval definitions still come from <code>--dir</code>; <code>--url</code> only changes the agent that receives the turns. For a locally mounted multi-agent directory, <code>--slug weather-agent</code> chooses the target. Use <code>--state-root</code> to keep ephemeral session state at a chosen path, <code>--timeout-ms</code> to override the project timeout, and <code>--no-stream</code> to keep live progress off stderr. A TTY streams turn progress by default. <code>--verbose</code> still writes <code>t.log</code> lines to stderr and adds reply snippets to text results.</p><p>Model turns need a Cursor credential from <code>agent-sdk login</code> or <code>CURSOR_API_KEY</code>.</p><p>See <a href="./reference/cli.html#eval">CLI: eval</a> for flags and exit codes.</p><h3 id="json-results" tabindex="-1">JSON results <a class="header-anchor" href="#json-results" aria-label="Permalink to "JSON results""></a></h3><p>Use <code>--json --no-stream</code> in scripts and CI. The top-level result carries the totals and one result per case:</p><div class="language-json vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">{</span></span>
|
|
64
64
|
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> "ok"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
@@ -76,10 +76,10 @@ import{_ as e,c as a,o as i,ag as t}from"./chunks/framework.BCISBCiQ.js";const k
|
|
|
76
76
|
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> "durationMs"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">12340</span></span>
|
|
77
77
|
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
78
78
|
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ]</span></span>
|
|
79
|
-
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>Each case result can also include <code>description</code>, <code>finalText</code>, <code>tools</code>, <code>error</code>, and tool arguments or output. This shape lets CI report the failed assertion without parsing terminal text.</p><h2 id="run-evals-in-the-playground" tabindex="-1">Run evals in the playground <a class="header-anchor" href="#run-evals-in-the-playground" aria-label="Permalink to "Run evals in the playground""></a></h2><p>Start the server
|
|
79
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>Each case result can also include <code>description</code>, <code>finalText</code>, <code>tools</code>, <code>error</code>, and tool arguments or output. This shape lets CI report the failed assertion without parsing terminal text.</p><h2 id="run-evals-in-the-playground" tabindex="-1">Run evals in the playground <a class="header-anchor" href="#run-evals-in-the-playground" aria-label="Permalink to "Run evals in the playground""></a></h2><p>Start the server, open the playground, and choose <strong>Evals</strong>. You can run every case or one case, watch progress, and open the resulting session trace. The Evals tab works on a normal <code>serve</code>.</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;"> .</span></span></code></pre></div><p>Playground runs target the live server instead of an ephemeral one. Their sessions appear in the session list. One eval batch can run at a time. Persistence follows the rule under <a href="#configure-eval-runs">Configure eval runs</a>. See <a href="./reference/http-api.html#playground-eval-routes">Playground eval routes</a>. The start request returns <code>202</code> while cases run in the background. Poll until the snapshot status becomes <code>completed</code>, <code>failed</code>, or <code>cancelled</code>. Configuration errors appear on a failed snapshot.</p><p>On <code>--prod</code> / <code>--url</code>, the CLI prints the Eval ID as soon as the batch is accepted (and a Playground deep link with <code>?view=evals&evalRunId=…</code>):</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;"> eval</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --prod</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --slug</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> vulnerability-scanner</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --tag</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> deepsec</span></span>
|
|
80
80
|
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># Eval ID: evalrun_…</span></span>
|
|
81
81
|
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># Cancel: agent-sdk eval cancel evalrun_… --prod --slug vulnerability-scanner</span></span>
|
|
82
82
|
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># Playground: https://…/playground?view=evals&evalRunId=evalrun_…</span></span>
|
|
83
83
|
<span class="line"></span>
|
|
84
84
|
<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:#032F62;--shiki-dark:#9ECBFF;"> cancel</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> evalrun_…</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --prod</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --slug</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> vulnerability-scanner</span></span>
|
|
85
|
-
<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:#032F62;--shiki-dark:#9ECBFF;"> status</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> evalrun_…</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --prod</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --slug</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> vulnerability-scanner</span></span></code></pre></div><
|
|
85
|
+
<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:#032F62;--shiki-dark:#9ECBFF;"> status</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> evalrun_…</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --prod</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --slug</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> vulnerability-scanner</span></span></code></pre></div><h2 id="what-good-cases-assert" tabindex="-1">What good cases assert <a class="header-anchor" href="#what-good-cases-assert" aria-label="Permalink to "What good cases assert""></a></h2><p>Gate decisions and shape, not prose. Model wording varies run to run. Tool choice, tool avoidance, and output structure are the stable contract.</p><ol><li><code>t.succeeded()</code>: always, first.</li><li>The tool decision: <code>calledTool</code> for the intended path, <code>notCalledTool</code> for the likely wrong alternative. The pair is stronger than either alone.</li><li>Output shape: a regex for the contract (<code>/ready|blocked/i</code>, a JSON marker, a findings-block fence), never exact sentences.</li><li>For structured output, parse <code>t.reply</code> and check fields with <code>satisfies</code> instead of substring-matching JSON.</li></ol><p>The common failure modes: asserting exact phrasing, packing more than about five gates into one case (split it), and cases that depend on live external state that drifts (pin the input; see fixtures).</p><h2 id="pick-fixtures-by-agent-type" tabindex="-1">Pick fixtures by agent type <a class="header-anchor" href="#pick-fixtures-by-agent-type" aria-label="Permalink to "Pick fixtures by agent type""></a></h2><p>The right fixture depends on the surface under test.</p><table tabindex="0"><thead><tr><th>Agent surface</th><th>Fixture</th></tr></thead><tbody><tr><td>Chat / domain assistant</td><td>A canonical prompt string, chosen once and frozen</td></tr><tr><td>Tool-heavy</td><td>Run <code>agent-sdk call <tool></code> first to pin what the tool returns, then freeze the prompt that triggers it</td></tr><tr><td>GitHub webhook</td><td><code>agent-sdk github replay <pr> --events '*' --dry-run --out fixtures/github</code> snapshots real payloads for offline replay (<a href="./guides/github.html">GitHub guide</a>)</td></tr><tr><td>PR reviewer with host preparation</td><td>Diff, metadata, and gold labels pinned to commit SHAs; keep any live PR matrix small</td></tr><tr><td>Workspace-dependent</td><td><code>workspaceFiles</code> in <code>t.send</code> options, never developer-machine paths</td></tr></tbody></table><p>Tag the fast, reliably passing core <code>smoke</code> and run <code>--tag smoke</code> in the inner loop. Leave slow or flaky-prone cases untagged for explicit runs.</p><h3 id="materialize-api-backed-fixtures" tabindex="-1">Materialize API-backed fixtures <a class="header-anchor" href="#materialize-api-backed-fixtures" aria-label="Permalink to "Materialize API-backed fixtures""></a></h3><p>An input that only points at external data, such as a pull request URL, snapshot id, or pair of commit SHAs, is not self-contained. Fetch it once and commit the rendered fixture before you expand the suite.</p><ol><li>Save the diff, metadata, and labels under <code>fixtures/</code> at pinned revisions.</li><li>Seed those files with <code>workspaceFiles</code>, or read them from the fixture directory.</li><li>Assert decisions and output shape against the saved evidence.</li><li>Keep a small <code>smoke</code> subset for any remaining live pipeline checks.</li></ol><p>Read committed fixtures with <code>@cursor/july/evals/loaders</code>: <code>loadJson</code>, <code>loadJsonl</code>, and <code>loadYaml</code> resolve relative paths against the project root the runner discovered, not the cwd the CLI was invoked from (<code>resolveFixturePath</code> and <code>evalFixtureRoot</code> expose the same resolution for other file formats).</p><p><code>maxConcurrency</code> limits parallel datapoints. It does not limit model or API fan-out inside one datapoint. Materialized fixtures prevent a large suite from exhausting provider and GitHub rate limits. The <a href="./../skills/evals/SKILL.html">evals skill</a> has the full fixture workflow.</p><h2 id="keep-improvements-with-regression-evals" tabindex="-1">Keep improvements with regression evals <a class="header-anchor" href="#keep-improvements-with-regression-evals" aria-label="Permalink to "Keep improvements with regression evals""></a></h2><p>Every <a href="./hillclimbing.html">hillclimb</a> round that keeps a change must land an eval that would have failed before the change. If you can't express the improvement as a gate (a <code>calledTool</code> shift, a bounded <code>action.result</code> count, an output-shape regex), the improvement is unverified, and it'll regress silently.</p><p>The rule cuts the other way too: never weaken an existing gate to make a round pass. That's the freeze line moving, and it turns your regression suite into a list of checks that no longer protect anything.</p><h2 id="compare-variants-on-live-traffic" tabindex="-1">Compare variants on live traffic <a class="header-anchor" href="#compare-variants-on-live-traffic" aria-label="Permalink to "Compare variants on live traffic""></a></h2><p>Use <code>defineAB</code> to compare variant metrics on live sessions. It is not a test runner and has no <code>agent-sdk ab</code> command. Keep <code>defineEval</code> as the regression ratchet. Eval sessions do not enroll or change live metrics. See <a href="./ab.html">Live A/B metrics</a> for assignment, behavior, collection, and inspection.</p><h2 id="what-s-next" tabindex="-1">What's next <a class="header-anchor" href="#what-s-next" aria-label="Permalink to "What's next""></a></h2><p>Continue with these pages:</p><ul><li><a href="./ab.html">Live A/B metrics</a>: sticky variants and cumulative metrics on live sessions</li><li><a href="./hillclimbing.html">Hillclimbing</a>: the loop evals make trustworthy</li><li><a href="./building-with-agents.html">Building agents with agents</a>: have a coding agent write the first suite</li><li><a href="./guides/github.html">GitHub guide</a>: deterministic webhook fixtures with <code>github replay</code></li><li><a href="./reference/sessions.html">Sessions and streaming</a>: the events <code>t.events</code> contains</li></ul>`,82)])])}const g=e(n,[["render",l]]);export{k as __pageData,g as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e,c as
|
|
1
|
+
import{_ as e,c as i,o as a,ag as t}from"./chunks/framework.BCISBCiQ.js";const k=JSON.parse('{"title":"Evals","description":"Define repeatable checks with defineEval, run them with agent-sdk eval, and use them as regression checks.","frontmatter":{"title":"Evals","description":"Define repeatable checks with defineEval, run them with agent-sdk eval, and use them as regression checks."},"headers":[],"relativePath":"evals.md","filePath":"evals.md"}'),n={name:"evals.md"};function l(d,s,h,o,r,p){return a(),i("div",null,[...s[0]||(s[0]=[t("",82)])])}const g=e(n,[["render",l]]);export{k as __pageData,g as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as a,c as t,o as s,ag as i}from"./chunks/framework.BCISBCiQ.js";const u=JSON.parse('{"title":"Keep PR approval policy deterministic with Approval Buddy","description":"Separate code-owned eligibility from model-owned review, then connect GitHub, Slack, subagents, durable storage, and evals.","frontmatter":{"title":"Keep PR approval policy deterministic with Approval Buddy","description":"Separate code-owned eligibility from model-owned review, then connect GitHub, Slack, subagents, durable storage, and evals."},"headers":[],"relativePath":"example-agents/approval-buddy.md","filePath":"example-agents/approval-buddy.md"}'),o={name:"example-agents/approval-buddy.md"};function r(l,e,n,d,p,h){return s(),t("div",null,[...e[0]||(e[0]=[i(`<h1 id="keep-pr-approval-policy-deterministic-with-approval-buddy" tabindex="-1">Keep PR approval policy deterministic with Approval Buddy <a class="header-anchor" href="#keep-pr-approval-policy-deterministic-with-approval-buddy" aria-label="Permalink to "Keep PR approval policy deterministic with Approval Buddy""></a></h1><p>Approval Buddy approves eligible pull requests from a fixed roster and declines every other request. GitHub still blocks self-approval when the stamp identity authored the PR. Code decides eligibility. The model prepares evidence, runs two specialist reviews, and passes their findings to the approval tool without changing the policy decision.</p><p>Use this example when an agent can make a judgment inside a workflow, but authorization and the final side effect must stay in deterministic code.</p><p><a href="./../../examples/approval-buddy/">Browse the Approval Buddy source.</a></p><h2 id="keep-approval-policy-in-code" tabindex="-1">Keep approval policy in code <a class="header-anchor" href="#keep-approval-policy-in-code" aria-label="Permalink to "Keep approval policy in code""></a></h2><p>Approval Buddy draws three hard boundaries:</p><ul><li><code>prepare_review</code> and <code>approve_pr</code> re-read the live PR and apply the same eligibility rules.</li><li>Two subagents inspect prepared evidence, but their findings never grant or block approval.</li><li>Only <code>approve_pr</code> posts the GitHub review.</li></ul><p>A spoofed webhook, Slack message, or model claim can't add someone to the buddy roster. The mutating tool checks the source of truth immediately before it acts.</p><h2 id="follow-the-intended-stamp-flow" tabindex="-1">Follow the intended stamp flow <a class="header-anchor" href="#follow-the-intended-stamp-flow" aria-label="Permalink to "Follow the intended stamp flow""></a></h2><p>The root instructions ask the model to run this sequence for a qualifying PR:</p><ol><li>A non-draft <code>pull_request</code> event arrives with action <code>opened</code>, <code>reopened</code>, or <code>ready_for_review</code>.</li><li>The GitHub channel checks its repository allowlist and starts a session.</li><li><code>turn.started</code> posts a pending commit status.</li><li>The model calls <code>prepare_review</code>.</li><li>Host code fetches the live PR. It checks the author, open state, merged state, and draft state.</li><li>A qualifying PR gets <code>pr/MANIFEST.md</code>, <code>pr/meta.json</code>, and <code>pr/diff.patch</code> in the session workspace. Diffs above 2,000,000 characters are truncated and marked in metadata.</li><li>The model calls both review subagents through the built-in <code>task</code> tool.</li><li>It concatenates their contracted replies and calls <code>approve_pr</code>.</li><li><code>approve_pr</code> re-runs eligibility, posts an <code>APPROVE</code> review, and returns the outcome.</li><li>The channel posts a final commit status. A self-approval block also gets a short timeline comment because no approval review can appear.</li></ol><p>Ineligible PRs skip evidence and subagents. The model still calls <code>approve_pr</code> so the deterministic tool returns the formal decline reason.</p><p>Steps 4 through 9 are prompt-driven. The channel doesn't enforce tool order or prove both subagents ran, and <code>approve_pr</code> accepts missing findings. A failed turn clears the pending status with a green non-blocking result without approving the PR.</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 "Map the framework features""></a></h2><table tabindex="0"><thead><tr><th>Capability</th><th>Source</th><th>Role</th></tr></thead><tbody><tr><td>Root agent and policy prompt</td><td><a href="../../examples/approval-buddy/agent/agent.ts"><code>agent/agent.ts</code></a>, <a href="./../../examples/approval-buddy/agent/instructions.html"><code>agent/instructions.md</code></a></td><td>Configure the local agent and describe orchestration order.</td></tr><tr><td>GitHub channel</td><td><a href="../../examples/approval-buddy/agent/channels/github.ts"><code>agent/channels/github.ts</code></a></td><td>Filter wakes, lease GitHub access, and publish status events.</td></tr><tr><td>Slack channel</td><td><a href="../../examples/approval-buddy/agent/channels/slack.ts"><code>agent/channels/slack.ts</code></a></td><td>Accept approval-bot stamp and qualification requests.</td></tr><tr><td>Server tools</td><td><a href="./../../examples/approval-buddy/agent/tools/"><code>agent/tools/</code></a></td><td>Prepare evidence, approve, list buddies, and search GIFs.</td></tr><tr><td>Deterministic policy</td><td><a href="../../examples/approval-buddy/agent/lib/approve.ts"><code>agent/lib/approve.ts</code></a>, <a href="../../examples/approval-buddy/agent/lib/buddies.ts"><code>agent/lib/buddies.ts</code></a></td><td>Own the roster and live eligibility checks.</td></tr><tr><td>Review subagents</td><td><a href="./../../examples/approval-buddy/agent/subagents/"><code>agent/subagents/</code></a></td><td>Run deep audit and code-quality passes over the same evidence.</td></tr><tr><td>Storage</td><td><a href="../../examples/approval-buddy/agent/storage.ts"><code>agent/storage.ts</code></a></td><td>Persist sessions and events with <code>cursorHostedStorage</code
|
|
1
|
+
import{_ as a,c as t,o as s,ag as i}from"./chunks/framework.BCISBCiQ.js";const u=JSON.parse('{"title":"Keep PR approval policy deterministic with Approval Buddy","description":"Separate code-owned eligibility from model-owned review, then connect GitHub, Slack, subagents, durable storage, and evals.","frontmatter":{"title":"Keep PR approval policy deterministic with Approval Buddy","description":"Separate code-owned eligibility from model-owned review, then connect GitHub, Slack, subagents, durable storage, and evals."},"headers":[],"relativePath":"example-agents/approval-buddy.md","filePath":"example-agents/approval-buddy.md"}'),o={name:"example-agents/approval-buddy.md"};function r(l,e,n,d,p,h){return s(),t("div",null,[...e[0]||(e[0]=[i(`<h1 id="keep-pr-approval-policy-deterministic-with-approval-buddy" tabindex="-1">Keep PR approval policy deterministic with Approval Buddy <a class="header-anchor" href="#keep-pr-approval-policy-deterministic-with-approval-buddy" aria-label="Permalink to "Keep PR approval policy deterministic with Approval Buddy""></a></h1><p>Approval Buddy approves eligible pull requests from a fixed roster and declines every other request. GitHub still blocks self-approval when the stamp identity authored the PR. Code decides eligibility. The model prepares evidence, runs two specialist reviews, and passes their findings to the approval tool without changing the policy decision.</p><p>Use this example when an agent can make a judgment inside a workflow, but authorization and the final side effect must stay in deterministic code.</p><p><a href="./../../examples/approval-buddy/">Browse the Approval Buddy source.</a></p><h2 id="keep-approval-policy-in-code" tabindex="-1">Keep approval policy in code <a class="header-anchor" href="#keep-approval-policy-in-code" aria-label="Permalink to "Keep approval policy in code""></a></h2><p>Approval Buddy draws three hard boundaries:</p><ul><li><code>prepare_review</code> and <code>approve_pr</code> re-read the live PR and apply the same eligibility rules.</li><li>Two subagents inspect prepared evidence, but their findings never grant or block approval.</li><li>Only <code>approve_pr</code> posts the GitHub review.</li></ul><p>A spoofed webhook, Slack message, or model claim can't add someone to the buddy roster. The mutating tool checks the source of truth immediately before it acts.</p><h2 id="follow-the-intended-stamp-flow" tabindex="-1">Follow the intended stamp flow <a class="header-anchor" href="#follow-the-intended-stamp-flow" aria-label="Permalink to "Follow the intended stamp flow""></a></h2><p>The root instructions ask the model to run this sequence for a qualifying PR:</p><ol><li>A non-draft <code>pull_request</code> event arrives with action <code>opened</code>, <code>reopened</code>, or <code>ready_for_review</code>.</li><li>The GitHub channel checks its repository allowlist and starts a session.</li><li><code>turn.started</code> posts a pending commit status.</li><li>The model calls <code>prepare_review</code>.</li><li>Host code fetches the live PR. It checks the author, open state, merged state, and draft state.</li><li>A qualifying PR gets <code>pr/MANIFEST.md</code>, <code>pr/meta.json</code>, and <code>pr/diff.patch</code> in the session workspace. Diffs above 2,000,000 characters are truncated and marked in metadata.</li><li>The model calls both review subagents through the built-in <code>task</code> tool.</li><li>It concatenates their contracted replies and calls <code>approve_pr</code>.</li><li><code>approve_pr</code> re-runs eligibility, posts an <code>APPROVE</code> review, and returns the outcome.</li><li>The channel posts a final commit status. A self-approval block also gets a short timeline comment because no approval review can appear.</li></ol><p>Ineligible PRs skip evidence and subagents. The model still calls <code>approve_pr</code> so the deterministic tool returns the formal decline reason.</p><p>Steps 4 through 9 are prompt-driven. The channel doesn't enforce tool order or prove both subagents ran, and <code>approve_pr</code> accepts missing findings. A failed turn clears the pending status with a green non-blocking result without approving the PR.</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 "Map the framework features""></a></h2><table tabindex="0"><thead><tr><th>Capability</th><th>Source</th><th>Role</th></tr></thead><tbody><tr><td>Root agent and policy prompt</td><td><a href="../../examples/approval-buddy/agent/agent.ts"><code>agent/agent.ts</code></a>, <a href="./../../examples/approval-buddy/agent/instructions.html"><code>agent/instructions.md</code></a></td><td>Configure the local agent and describe orchestration order.</td></tr><tr><td>GitHub channel</td><td><a href="../../examples/approval-buddy/agent/channels/github.ts"><code>agent/channels/github.ts</code></a></td><td>Filter wakes, lease GitHub access, and publish status events.</td></tr><tr><td>Slack channel</td><td><a href="../../examples/approval-buddy/agent/channels/slack.ts"><code>agent/channels/slack.ts</code></a></td><td>Accept approval-bot stamp and qualification requests.</td></tr><tr><td>Server tools</td><td><a href="./../../examples/approval-buddy/agent/tools/"><code>agent/tools/</code></a></td><td>Prepare evidence, approve, list buddies, and search GIFs.</td></tr><tr><td>Deterministic policy</td><td><a href="../../examples/approval-buddy/agent/lib/approve.ts"><code>agent/lib/approve.ts</code></a>, <a href="../../examples/approval-buddy/agent/lib/buddies.ts"><code>agent/lib/buddies.ts</code></a></td><td>Own the roster and live eligibility checks.</td></tr><tr><td>Review subagents</td><td><a href="./../../examples/approval-buddy/agent/subagents/"><code>agent/subagents/</code></a></td><td>Run deep audit and code-quality passes over the same evidence.</td></tr><tr><td>Storage</td><td><a href="../../examples/approval-buddy/agent/storage.ts"><code>agent/storage.ts</code></a></td><td>Persist sessions and events with <code>cursorHostedStorage</code>. See <a href="./../storage.html">Storage</a>.</td></tr><tr><td>Live A/B experiment</td><td><a href="../../examples/approval-buddy/agent/ab.ts"><code>agent/ab.ts</code></a></td><td>Compare baseline responses with a concise, presentation-only treatment (<code>concise-results</code>).</td></tr><tr><td>Evals and unit tests</td><td><a href="./../../examples/approval-buddy/evals/"><code>evals/</code></a>, <a href="./../../examples/approval-buddy/agent/lib/"><code>agent/lib/</code></a></td><td>Protect routing, output contracts, policy, and GitHub behavior.</td></tr></tbody></table><p>There are no authored skills, MCP connections, schedules, reminders, hooks, sandbox seeds, or tool approvals.</p><h2 id="prepare-credentials" tabindex="-1">Prepare credentials <a class="header-anchor" href="#prepare-credentials" aria-label="Permalink to "Prepare credentials""></a></h2><p>You need:</p><ul><li>Node 22.13 or newer.</li><li>An agent-runtime credential.</li><li>GitHub access to read PRs, post reviews, create commit statuses, and post the self-approval visibility comment.</li></ul><p>Optional GIF selection uses:</p><ul><li><code>GIPHY_API_KEY</code> or <code>APPROVAL_BUDDY_GIPHY_API_KEY</code>,</li><li><code>APPROVAL_BUDDY_STAMP_GIF</code>, or</li><li>severity-specific <code>APPROVAL_BUDDY_STAMP_GIF_<LEVEL></code> variables.</li></ul><p>If you enable Giphy in a hosted copy, declare its secret and <code>api.giphy.com</code> egress.</p><h2 id="validate-without-approving-a-pr" tabindex="-1">Validate without approving a PR <a class="header-anchor" href="#validate-without-approving-a-pr" aria-label="Permalink to "Validate without approving a PR""></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/approval-buddy</span></span>
|
|
2
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/approval-buddy</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span></code></pre></div><p>List the deterministic roster:</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;"> list_buddies</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
|
|
3
3
|
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/approval-buddy</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
|
|
4
4
|
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '{}'</span></span></code></pre></div><p>Set a known merged PR, then run the read-only precheck:</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:#24292E;--shiki-dark:#E1E4E8;">MERGED_PR_URL</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">https://github.com/your-org/your-repo/pull/123</span></span>
|
package/dist/docs/assets/{example-agents_benny.md.C40vHRLc.js → example-agents_benny.md.B0kwY7D_.js}
RENAMED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import{_ as a,c as t,o as s,ag as
|
|
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:#032F62;--shiki-dark:#9ECBFF;">".agent-serve/harness"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
3
|
-
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>Each harness workspace lands under <code>examples/benny/.agent-serve/harness/<sessionId></code>. Walking up the directory tree reaches the host repository and its inherited playbook directory.</p><p>Those playbooks are inherited context. <code>agent-sdk info</code> reports zero authored skills for the agent. Copying this project into another repository removes its main procedures unless you copy or replace the skill library too.</p><h2 id="connect-both-slack-paths" tabindex="-1">Connect both Slack paths <a class="header-anchor" href="#connect-both-slack-paths" aria-label="Permalink to "Connect both Slack paths""></a></h2><p>The account-linked path needs an agent-runtime login and a connected Slack account:</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;"> login</span></span>
|
|
1
|
+
import{_ as a,c as t,o as s,ag as o}from"./chunks/framework.BCISBCiQ.js";const k=JSON.parse('{"title":"Route Slack work through repository playbooks","description":"Combine account-linked chat, allowlisted Socket Mode channel watching, inherited repository skills, and a custom local workspace.","frontmatter":{"title":"Route Slack work through repository playbooks","description":"Combine account-linked chat, allowlisted Socket Mode channel watching, inherited repository skills, and a custom local workspace."},"headers":[],"relativePath":"example-agents/benny.md","filePath":"example-agents/benny.md"}'),i={name:"example-agents/benny.md"};function n(l,e,r,h,d,c){return s(),t("div",null,[...e[0]||(e[0]=[o(`<h1 id="route-slack-work-through-repository-playbooks" tabindex="-1">Route Slack work through repository playbooks <a class="header-anchor" href="#route-slack-work-through-repository-playbooks" aria-label="Permalink to "Route Slack work through repository playbooks""></a></h1><p>This agent is a Slack teammate for a product team. Mentions and direct messages reach it through an account-linked transport. New top-level posts in an allowlisted issue channel reach it through a dedicated Slack app, even without a mention. The agent then selects a repository playbook for triage, reproduction, fixes, reviews, on-call work, or design critique.</p><p>Use this example when Slack is the intake surface and your durable procedures already live as repository skills.</p><p><a href="./../../examples/benny/">Browse the current playbook-router source.</a></p><h2 id="combine-two-slack-transports-with-repo-skills" tabindex="-1">Combine two Slack transports with repo skills <a class="header-anchor" href="#combine-two-slack-transports-with-repo-skills" aria-label="Permalink to "Combine two Slack transports with repo skills""></a></h2><p>The playbook router uniquely combines three decisions:</p><ul><li>Two Slack transports serve different engagement modes.</li><li><code>local.cwd</code> keeps session workspaces inside the monorepo.</li><li>Instructions route work to inherited repository playbooks instead of authored <code>agent/skills/</code>.</li></ul><p>The result is a thin agent project over a mature procedure library.</p><h2 id="follow-an-issue-report" tabindex="-1">Follow an issue report <a class="header-anchor" href="#follow-an-issue-report" aria-label="Permalink to "Follow an issue report""></a></h2><ol><li>A teammate creates a top-level post in the allowlisted issue channel.</li><li>The dedicated Socket Mode channel accepts the allowlisted channel.</li><li>A 15-second debounce lets edits settle. Deleting the post during that window cancels the dispatch.</li><li>The Agent SDK creates a thread-scoped session and sends the report to the playbook router.</li><li>The instructions select the matching triage playbook.</li><li>The harness finds the repository root, opens the inherited playbook, and follows its procedure.</li><li>The agent posts only in the source thread and reports the evidence it gathered.</li></ol><p>Mentions and direct messages follow the same agent instructions. They don't need the watched-channel path.</p><h2 id="map-the-playbook-router-files" tabindex="-1">Map the playbook router files <a class="header-anchor" href="#map-the-playbook-router-files" aria-label="Permalink to "Map the playbook router files""></a></h2><table tabindex="0"><thead><tr><th>File</th><th>Purpose</th></tr></thead><tbody><tr><td><a href="../../examples/benny/agent/agent.ts"><code>agent/agent.ts</code></a></td><td>Names the agent, selects its model, and points the harness at a project-local cwd so inherited playbooks load.</td></tr><tr><td><a href="./../../examples/benny/agent/instructions.html"><code>agent/instructions.md</code></a></td><td>Defines engagement rules, evidence policy, and the playbook routing map.</td></tr><tr><td><a href="../../examples/benny/agent/channels/slack.ts"><code>agent/channels/slack.ts</code></a></td><td>Handles account-linked mentions and direct messages.</td></tr><tr><td><a href="../../examples/benny/agent/channels/slack-app.ts"><code>agent/channels/slack-app.ts</code></a></td><td>Runs the dedicated app and watches one allowlisted channel.</td></tr><tr><td><a href="../../examples/benny/agent/storage.ts"><code>agent/storage.ts</code></a></td><td>Persists sessions and events with <code>cursorHostedStorage</code>.</td></tr><tr><td><a href="../../examples/benny/evals/evals.config.ts"><code>evals/evals.config.ts</code></a></td><td>Caps eval run concurrency.</td></tr><tr><td><a href="../../examples/benny/evals/smoke.eval.ts"><code>evals/smoke.eval.ts</code></a></td><td>Checks the agent identity and expected triage route.</td></tr></tbody></table><p>The playbook router authors no tools, MCP connections, subagents, schedules, hooks, A/B experiments, or sandbox seeds.</p><h2 id="see-why-local-cwd-matters" tabindex="-1">See why <code>local.cwd</code> matters <a class="header-anchor" href="#see-why-local-cwd-matters" aria-label="Permalink to "See why \`local.cwd\` matters""></a></h2><p>The Agent SDK normally keeps an ephemeral <code>run</code> or <code>eval</code> workspace outside a large monorepo. This prevents ancestor instruction and repository-rule files from leaking into an unrelated agent.</p><p>The playbook router needs the opposite. Its procedures live at the repository root, so <code>agent.ts</code> points <code>local.cwd</code> at a harness directory under the project. Each harness workspace is a child of that directory. Walking up reaches the host repository and its inherited playbook directory.</p><p>Those playbooks are inherited context. <code>agent-sdk info</code> reports zero authored skills for the agent. Copying this project into another repository removes its main procedures unless you copy or replace the skill library too.</p><h2 id="connect-both-slack-paths" tabindex="-1">Connect both Slack paths <a class="header-anchor" href="#connect-both-slack-paths" aria-label="Permalink to "Connect both Slack paths""></a></h2><p>The account-linked path needs an agent-runtime login and a connected Slack account:</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;"> login</span></span>
|
|
4
2
|
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> whoami</span></span></code></pre></div><p>It routes explicit mentions without a dedicated Slack token on the host.</p><p>For the watched-channel path, configure a dedicated Socket Mode app with:</p><ul><li>subscribe to <code>message.channels</code> and <code>message.groups</code>,</li><li>have an App-Level Token with <code>connections:write</code>, and</li><li>be a member of the watched channel.</li></ul><p>Run <code>agent-sdk slack create --dir examples/benny --channel-posts</code> for a dedicated Socket Mode app, then <code>agent-sdk slack doctor</code>.</p><p>Missing dedicated-app tokens leave that channel idle. They don't stop the account-linked channel.</p><h2 id="validate-and-start-the-server" tabindex="-1">Validate and start the server <a class="header-anchor" href="#validate-and-start-the-server" aria-label="Permalink to "Validate and start the server""></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/benny</span></span>
|
|
5
3
|
<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/benny</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span>
|
|
6
4
|
<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/benny</span></span></code></pre></div><p>The info output should show two Slack channels and no authored skill. That combination confirms the example is using inherited playbooks.</p><h2 id="exercise-each-engagement-mode" tabindex="-1">Exercise each engagement mode <a class="header-anchor" href="#exercise-each-engagement-mode" aria-label="Permalink to "Exercise each engagement mode""></a></h2><p>Test the explicit account-linked path by asking:</p><blockquote><p>Which playbook would you use to triage a product UI bug?</p></blockquote><p>Test the dedicated app:</p><ol><li>Create a top-level post in the allowlisted issue channel.</li><li>Don't mention the bot.</li><li>Wait for the debounce window.</li><li>Confirm the agent replies in the post's thread.</li></ol><p>Thread replies don't trigger the proactive watch. Mentions still use Slack's normal mention path. Bot-authored posts are ignored to prevent loops.</p><p>The channel uses the default handler after filtering. It doesn't apply a second code-level classifier, so every accepted top-level post spends a model turn and reaches the prompt.</p><h2 id="inspect-thread-continuity" tabindex="-1">Inspect thread continuity <a class="header-anchor" href="#inspect-thread-continuity" aria-label="Permalink to "Inspect thread continuity""></a></h2><p>The Agent SDK keys Slack sessions by channel and thread timestamp. A follow-up in the same thread resumes the conversation and workspace. A new top-level issue gets a new session.</p><p>This lets a playbook gather evidence over several turns without mixing two reports. The playground shows both the account-linked and dedicated-app sessions while the dev server runs.</p><h2 id="run-the-smoke-eval" tabindex="-1">Run the smoke eval <a class="header-anchor" href="#run-the-smoke-eval" aria-label="Permalink to "Run the smoke eval""></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/benny</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --list</span></span>
|
|
7
|
-
<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/benny</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> smoke</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span></code></pre></div><p>The case asks for the agent identity and the playbook used for issue triage. It checks the configured identity and route label.</p><p>This is a lexical smoke test. It doesn't prove Slack delivery, skill selection, skill loading, procedure execution, or thread-only behavior. Add fixture-backed evals around the playbooks when you reuse this design.</p><h2 id="build-a-playbook-routed-teammate" tabindex="-1">Build a playbook-routed teammate <a class="header-anchor" href="#build-a-playbook-routed-teammate" aria-label="Permalink to "Build a playbook-routed teammate""></a></h2><p>Use this structure when your organization already has tested skills:</p><ol><li>Put the playbooks under a stable repository path.</li><li>Set <code>local.cwd</code> so harness workspaces can inherit that path.</li><li>Write a short routing table in <code>instructions.md</code>.</li><li>Use account-linked Slack for explicit requests.</li><li>Add a dedicated app only for allowlisted proactive intake.</li><li>Keep the channel allowlist narrow and debounce edited posts.</li><li>Add an eval for every important request-to-playbook route.</li></ol><p>If the procedures should ship with the agent, put them under <code>agent/skills/</code> instead. Authored skills appear in the manifest and travel with the project.</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 "Where to go next""></a></h2><ul><li><a href="./../guides/slack.html">Slack</a></li><li><a href="./../reference/agent-config.html">Agent config</a></li><li><a href="./../reference/skills.html">Skills</a></li><li><a href="./../reference/sessions.html">Sessions and streaming</a></li><li><a href="./../evals.html">Evals</a></li></ul>`,
|
|
5
|
+
<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/benny</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> smoke</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --json</span></span></code></pre></div><p>The case asks for the agent identity and the playbook used for issue triage. It checks the configured identity and route label.</p><p>This is a lexical smoke test. It doesn't prove Slack delivery, skill selection, skill loading, procedure execution, or thread-only behavior. Add fixture-backed evals around the playbooks when you reuse this design.</p><h2 id="build-a-playbook-routed-teammate" tabindex="-1">Build a playbook-routed teammate <a class="header-anchor" href="#build-a-playbook-routed-teammate" aria-label="Permalink to "Build a playbook-routed teammate""></a></h2><p>Use this structure when your organization already has tested skills:</p><ol><li>Put the playbooks under a stable repository path.</li><li>Set <code>local.cwd</code> so harness workspaces can inherit that path.</li><li>Write a short routing table in <code>instructions.md</code>.</li><li>Use account-linked Slack for explicit requests.</li><li>Add a dedicated app only for allowlisted proactive intake.</li><li>Keep the channel allowlist narrow and debounce edited posts.</li><li>Add an eval for every important request-to-playbook route.</li></ol><p>If the procedures should ship with the agent, put them under <code>agent/skills/</code> instead. Authored skills appear in the manifest and travel with the project.</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 "Where to go next""></a></h2><ul><li><a href="./../guides/slack.html">Slack</a></li><li><a href="./../reference/agent-config.html">Agent config</a></li><li><a href="./../reference/skills.html">Skills</a></li><li><a href="./../reference/sessions.html">Sessions and streaming</a></li><li><a href="./../evals.html">Evals</a></li></ul>`,49)])])}const u=a(i,[["render",n]]);export{k as __pageData,u as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as a,c as t,o as s,ag as
|
|
1
|
+
import{_ as a,c as t,o as s,ag as o}from"./chunks/framework.BCISBCiQ.js";const k=JSON.parse('{"title":"Route Slack work through repository playbooks","description":"Combine account-linked chat, allowlisted Socket Mode channel watching, inherited repository skills, and a custom local workspace.","frontmatter":{"title":"Route Slack work through repository playbooks","description":"Combine account-linked chat, allowlisted Socket Mode channel watching, inherited repository skills, and a custom local workspace."},"headers":[],"relativePath":"example-agents/benny.md","filePath":"example-agents/benny.md"}'),i={name:"example-agents/benny.md"};function n(l,e,r,h,d,c){return s(),t("div",null,[...e[0]||(e[0]=[o("",49)])])}const u=a(i,[["render",n]]);export{k as __pageData,u as default};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{_ as
|
|
1
|
+
import{_ as a,c as s,o as t,ag as i}from"./chunks/framework.BCISBCiQ.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,r,l,h,c){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 "Build a feature wiki from merged pull requests""></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 "Treat PRs as evidence and features as pages""></a></h2><p>The wiki refuses to become a merge log:</p><ul><li>The page tree is rigid: <code>index</code>, <code>features/<slug></code>, and <code>digests/<yyyy-mm-dd></code>. The store rejects anything else, so the wiki can'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 a wiki directory 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 "Follow a merged PR""></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'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:<owner/repo#N></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, "ingest PR #123" 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 "Map the wiki files""></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 local 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&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/<date></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/agent/storage.ts"><code>agent/storage.ts</code></a></td><td>Persists sessions and events with <code>cursorHostedStorage</code>.</td></tr><tr><td><a href="../../examples/codebase-wiki/evals/evals.config.ts"><code>evals/evals.config.ts</code></a></td><td>Caps eval run concurrency.</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, or A/B experiment.</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 "Prepare credentials and services""></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 "Validate the surface""></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
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 "Ingest without webhook plumbing""></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
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
|
|
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 open the wiki directory on the serve host. Feature pages land under <code>features/</code>.</p><p>Each ingested feature page carries an overview, a "How it works" 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
7
|
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --input</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '{"pr":"https://github.com/owner/repo/pull/123"}'</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 "Run the daily digest""></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/<today></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 "Run the evals""></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 "Reuse the merge-ingestion pattern""></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'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 "Where to go next""></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>`,
|
|
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 "Reuse the merge-ingestion pattern""></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'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 "Where to go next""></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>`,40)])])}const k=a(n,[["render",d]]);export{g as __pageData,k as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as
|
|
1
|
+
import{_ as a,c as s,o as t,ag as i}from"./chunks/framework.BCISBCiQ.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,r,l,h,c){return t(),s("div",null,[...e[0]||(e[0]=[i("",40)])])}const k=a(n,[["render",d]]);export{g as __pageData,k as default};
|
|
@@ -2,9 +2,8 @@ import{_ as s,c as a,o as i,ag as t}from"./chunks/framework.BCISBCiQ.js";const k
|
|
|
2
2
|
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> agent: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"weather-agent"</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;"> "The weather-agent peer: delegate weather questions with ask; it runs its own tools (live Open-Meteo data) in its own context."</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'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'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 "Follow a delegated request""></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: "running"</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's playground. It doesn't share Concierge'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 "Map the delegation files""></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><tr><td><a href="../../examples/concierge/agent/storage.ts"><code>agent/storage.ts</code></a></td><td>Persists sessions and events with <code>cursorHostedStorage</code>.</td></tr></tbody></table><p>Concierge doesn'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'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'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 "Mount both agents""></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't mounted.</p><p>From
|
|
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't serve the repository'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'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;">
|
|
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;"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PWD</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/.agent-serve/concierge-weather.XXXXXX"</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'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'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 "Follow a delegated request""></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: "running"</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's playground. It doesn't share Concierge'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 "Map the delegation files""></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><tr><td><a href="../../examples/concierge/agent/storage.ts"><code>agent/storage.ts</code></a></td><td>Persists sessions and events with <code>cursorHostedStorage</code>.</td></tr></tbody></table><p>Concierge doesn'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'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'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 "Mount both agents""></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't mounted.</p><p>From this package, 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't serve the repository'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'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:#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;"> "\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">TMPDIR</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:-/</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">tmp</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}/concierge-weather.XXXXXX"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
8
7
|
<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;"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/concierge"</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/weather-agent/agent"</span></span>
|
|
9
8
|
<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;"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/concierge/"</span></span>
|
|
10
9
|
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">cp</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> examples/concierge/package.json</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> "</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAIR_DIR</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">/concierge/"</span></span>
|