@cursor/july 0.1.113 → 0.1.114
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/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.CAeK13eM.js → app.BqkJwOZ-.js} +4 -4
- package/dist/docs/assets/chunks/@localSearchIndexroot.BnSgidYE.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.C9LbPHod.js → VPLocalSearchBox.BJAi2KiV.js} +1 -1
- package/dist/docs/assets/chunks/{arc.CmMq2zmS.js → arc.BZpXTgvV.js} +1 -1
- package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CCXB8Uj5.js → architectureDiagram-Q4EWVU46.WYI-7F-Y.js} +1 -1
- package/dist/docs/assets/chunks/{baseUniq.CyQo6eLe.js → baseUniq.CZaUPpg0.js} +1 -1
- package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.JYq6w91N.js → blockDiagram-DXYQGD6D.D6UES2pD.js} +1 -1
- package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.BRV8GPJJ.js → c4Diagram-AHTNJAMY.cwebIe4i.js} +1 -1
- package/dist/docs/assets/chunks/channel.DdM5EfNW.js +1 -0
- package/dist/docs/assets/chunks/{chunk-4BX2VUAB.Bv4ooYQR.js → chunk-4BX2VUAB.fVyFnjxg.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-4TB4RGXK.t4JtKPcj.js → chunk-4TB4RGXK.BanufG1c.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-55IACEB6.34lCHj9Y.js → chunk-55IACEB6.VaSMz5-2.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-EDXVE4YY.BSwrPNrt.js → chunk-EDXVE4YY.CN2diZOM.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-FMBD7UC4.Beeun-R-.js → chunk-FMBD7UC4.g4ivypu3.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-OYMX7WX6.BUUFUcJc.js → chunk-OYMX7WX6.GZXKn9JJ.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-QZHKN3VN.B2XjHzN_.js → chunk-QZHKN3VN.itXxJZCd.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-YZCP3GAM.CLYG8znk.js → chunk-YZCP3GAM.-rw2GfvX.js} +1 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.CjfGHeg2.js +1 -0
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.CjfGHeg2.js +1 -0
- package/dist/docs/assets/chunks/clone.wSOICb_f.js +1 -0
- package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.DVEa6fZp.js → cose-bilkent-S5V4N54A.CmaI5br0.js} +1 -1
- package/dist/docs/assets/chunks/{dagre-KV5264BT.C9PZQK-S.js → dagre-KV5264BT.4wY9S4Kt.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-5BDNPKRD.DoN0uv3Y.js → diagram-5BDNPKRD.Pc3c0u9W.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.Czv3duqx.js → diagram-G4DWMVQ6.CYrWz-nj.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-MMDJMWI5.BinJ5kWb.js → diagram-MMDJMWI5.Bgj5hukb.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-TYMM5635.DW326M4K.js → diagram-TYMM5635.DGMEXalS.js} +1 -1
- package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.U2pR_OA7.js → erDiagram-SMLLAGMA.GepTV9Im.js} +1 -1
- package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.ByWJXeYK.js → flowDiagram-DWJPFMVM.DVKywg3j.js} +1 -1
- package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.OquF0Rtg.js → ganttDiagram-T4ZO3ILL.C7qt9Mlo.js} +1 -1
- package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.Bpn01P7X.js → gitGraphDiagram-UUTBAWPF.U30_r82P.js} +1 -1
- package/dist/docs/assets/chunks/{graph.CNRB6ETL.js → graph.CyyMyAWv.js} +1 -1
- package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.CqhknMWi.js → infoDiagram-42DDH7IO.Dn9ACW3y.js} +1 -1
- package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.C6xpR2af.js → ishikawaDiagram-UXIWVN3A.DlIdIGOA.js} +1 -1
- package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.Cg5f7oB3.js → journeyDiagram-VCZTEJTY.DZj4vy4E.js} +1 -1
- package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.Cx9YTwlU.js → kanban-definition-6JOO6SKY.Dl63eMUV.js} +1 -1
- package/dist/docs/assets/chunks/{layout.ljS-wFtK.js → layout.BLHZLWPH.js} +1 -1
- package/dist/docs/assets/chunks/{linear.jSxNrsFC.js → linear.aXKGKaNw.js} +1 -1
- package/dist/docs/assets/chunks/{min.Cum8AlQw.js → min.zWnFcpcc.js} +1 -1
- package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.BLiysLpe.js → mindmap-definition-QFDTVHPH.Qs4MQBea.js} +1 -1
- package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.BoIDyuKF.js → pieDiagram-DEJITSTG.BmPHgsk7.js} +1 -1
- package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.DLkpDytR.js → quadrantDiagram-34T5L4WZ.D5MQ3gwA.js} +1 -1
- package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.DqTVqSu2.js → requirementDiagram-MS252O5E.CkdUFrO7.js} +1 -1
- package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.CG_6FF7j.js → sankeyDiagram-XADWPNL6.KZrljrAV.js} +1 -1
- package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.BIp9602K.js → sequenceDiagram-FGHM5R23.XMoEW-Lx.js} +1 -1
- package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.COSXsD9I.js → stateDiagram-FHFEXIEX.BmTzePLj.js} +1 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.Cu5X28zZ.js +1 -0
- package/dist/docs/assets/chunks/{theme.CXJ7PNwy.js → theme.BfQzpxsg.js} +2 -2
- package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.CXdVqkLq.js → timeline-definition-GMOUNBTQ.Dug0oamp.js} +1 -1
- package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.CZxGuc4r.js → vennDiagram-DHZGUBPP.BOTHrEFu.js} +1 -1
- package/dist/docs/assets/chunks/{wardley-RL74JXVD.3oVgfqQk.js → wardley-RL74JXVD.DXy2i1LS.js} +1 -1
- package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.6_irCgGJ.js → wardleyDiagram-NUSXRM2D.CoXKdfi6.js} +1 -1
- package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.TRPe92m3.js → xychartDiagram-5P7HB3ND.DXoSCjAW.js} +1 -1
- package/dist/docs/assets/{deployment.md.D2jQZuFx.js → deployment.md.D2YX7u_I.js} +1 -1
- package/dist/docs/assets/{guides_agent-to-agent.md.CD4T5FIl.js → guides_agent-to-agent.md.C6kPY8nu.js} +2 -2
- package/dist/docs/assets/{guides_cloud-agents.md.Cp1O3u-X.js → guides_cloud-agents.md.BPJqTZjT.js} +1 -1
- package/dist/docs/assets/{guides_grokbot-agents.md.CMhZNdEU.js → guides_grokbot-agents.md.CzV715v8.js} +1 -1
- package/dist/docs/assets/guides_hooks.md.BT9GLwEp.js +50 -0
- package/dist/docs/assets/guides_hooks.md.BT9GLwEp.lean.js +1 -0
- package/dist/docs/assets/{guides_jev.md.F5fAkkfN.js → guides_jev.md.DeSCqMaO.js} +6 -44
- package/dist/docs/assets/guides_jev.md.DeSCqMaO.lean.js +1 -0
- package/dist/docs/assets/reference_agent-config.md.BRxAlnRy.js +36 -0
- package/dist/docs/assets/{reference_agent-config.md.DGPyw7ms.lean.js → reference_agent-config.md.BRxAlnRy.lean.js} +1 -1
- package/dist/docs/assets/reference_artifacts.md.KRX0sAdt.js +18 -0
- package/dist/docs/assets/reference_artifacts.md.KRX0sAdt.lean.js +1 -0
- package/dist/docs/assets/reference_channels.md.DZr14vm7.js +23 -0
- package/dist/docs/assets/reference_channels.md.DZr14vm7.lean.js +1 -0
- package/dist/docs/assets/{reference_connections.md.Je9dMsdd.js → reference_connections.md.DJGUCxrr.js} +18 -30
- package/dist/docs/assets/{reference_connections.md.Je9dMsdd.lean.js → reference_connections.md.DJGUCxrr.lean.js} +1 -1
- package/dist/docs/assets/{reference_evals.md.DNJzM_yf.js → reference_evals.md.C6umwNC6.js} +6 -7
- package/dist/docs/assets/reference_evals.md.C6umwNC6.lean.js +1 -0
- package/dist/docs/assets/{reference_extensions.md.Cv5aLCz_.js → reference_extensions.md.DbNYu-DP.js} +3 -3
- package/dist/docs/assets/{reference_extensions.md.Cv5aLCz_.lean.js → reference_extensions.md.DbNYu-DP.lean.js} +1 -1
- package/dist/docs/assets/reference_hooks.md.BfOkhTU0.js +45 -0
- package/dist/docs/assets/{reference_hooks.md.B7uzNENk.lean.js → reference_hooks.md.BfOkhTU0.lean.js} +1 -1
- package/dist/docs/assets/reference_http-api.md.DdwtBeCj.js +11 -0
- package/dist/docs/assets/{reference_http-api.md.CduHavZ2.lean.js → reference_http-api.md.DdwtBeCj.lean.js} +1 -1
- package/dist/docs/assets/reference_instructions.md.B2mcIzT6.js +14 -0
- package/dist/docs/assets/reference_instructions.md.B2mcIzT6.lean.js +1 -0
- package/dist/docs/assets/reference_playground.md.CyrQD_n3.js +1 -0
- package/dist/docs/assets/reference_playground.md.CyrQD_n3.lean.js +1 -0
- package/dist/docs/assets/reference_project-layout.md.BEMzxAkq.js +19 -0
- package/dist/docs/assets/{reference_project-layout.md.BGhgpy9V.lean.js → reference_project-layout.md.BEMzxAkq.lean.js} +1 -1
- package/dist/docs/assets/reference_prompt.md.BFrqjHFL.js +9 -0
- package/dist/docs/assets/reference_prompt.md.BFrqjHFL.lean.js +1 -0
- package/dist/docs/assets/reference_schedules.md.BB9N3tRR.js +47 -0
- package/dist/docs/assets/reference_schedules.md.BB9N3tRR.lean.js +1 -0
- package/dist/docs/assets/reference_sessions.md.BBp-GIt-.js +1 -0
- package/dist/docs/assets/{reference_sessions.md.1_6Vyv7x.lean.js → reference_sessions.md.BBp-GIt-.lean.js} +1 -1
- package/dist/docs/assets/reference_skills.md.BVmi3UJ_.js +15 -0
- package/dist/docs/assets/{reference_skills.md.DjQkRefx.lean.js → reference_skills.md.BVmi3UJ_.lean.js} +1 -1
- package/dist/docs/assets/reference_subagents.md.DRoRy2Uj.js +10 -0
- package/dist/docs/assets/{reference_subagents.md.Dl16gcBj.lean.js → reference_subagents.md.DRoRy2Uj.lean.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.B1dH1lpa.js → reference_tools.md.CgocLDX1.js} +9 -6
- package/dist/docs/assets/{reference_tools.md.B1dH1lpa.lean.js → reference_tools.md.CgocLDX1.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.HY95rCCz.js +1 -0
- package/dist/docs/building-with-agents.html +35 -35
- package/dist/docs/deployment.html +37 -37
- package/dist/docs/deployment.md +1 -1
- package/dist/docs/evals.html +35 -35
- package/dist/docs/guides/agent-to-agent.html +38 -38
- package/dist/docs/guides/agent-to-agent.md +11 -12
- package/dist/docs/guides/bitbucket.html +35 -35
- package/dist/docs/guides/cloud-agents.html +36 -36
- package/dist/docs/guides/cloud-agents.md +1 -1
- package/dist/docs/guides/convert-automation.html +35 -35
- package/dist/docs/guides/github.html +35 -35
- package/dist/docs/guides/gitlab.html +35 -35
- package/dist/docs/guides/grokbot-agents.html +37 -37
- package/dist/docs/guides/grokbot-agents.md +1 -1
- package/dist/docs/guides/hooks.html +109 -0
- package/dist/docs/guides/hooks.md +111 -0
- package/dist/docs/guides/improve.html +35 -35
- package/dist/docs/guides/jev.html +42 -80
- package/dist/docs/guides/jev.md +22 -79
- package/dist/docs/guides/mcp-oauth.html +36 -36
- package/dist/docs/guides/opentelemetry.html +35 -35
- package/dist/docs/guides/slack.html +35 -35
- package/dist/docs/guides/webhooks.html +35 -35
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +35 -35
- package/dist/docs/index.html +35 -35
- package/dist/docs/llms-full.txt +993 -1303
- package/dist/docs/llms.txt +8 -7
- package/dist/docs/quickstart.html +35 -35
- package/dist/docs/reference/agent-config.html +42 -46
- package/dist/docs/reference/agent-config.md +48 -81
- package/dist/docs/reference/artifacts.html +39 -40
- package/dist/docs/reference/artifacts.md +71 -70
- package/dist/docs/reference/channels.html +41 -61
- package/dist/docs/reference/channels.md +134 -201
- package/dist/docs/reference/cli.html +35 -35
- package/dist/docs/reference/connections.html +54 -66
- package/dist/docs/reference/connections.md +92 -128
- package/dist/docs/reference/evals.html +42 -43
- package/dist/docs/reference/evals.md +42 -50
- package/dist/docs/reference/extensions.html +38 -38
- package/dist/docs/reference/extensions.md +9 -13
- package/dist/docs/reference/hooks.html +39 -67
- package/dist/docs/reference/hooks.md +72 -146
- package/dist/docs/reference/http-api.html +39 -39
- package/dist/docs/reference/http-api.md +137 -161
- package/dist/docs/reference/instructions.html +39 -39
- package/dist/docs/reference/instructions.md +21 -36
- package/dist/docs/reference/playground.html +36 -36
- package/dist/docs/reference/playground.md +26 -43
- package/dist/docs/reference/project-layout.html +38 -38
- package/dist/docs/reference/project-layout.md +12 -17
- package/dist/docs/reference/prompt.html +42 -42
- package/dist/docs/reference/prompt.md +18 -13
- package/dist/docs/reference/schedules.html +56 -91
- package/dist/docs/reference/schedules.md +52 -99
- package/dist/docs/reference/sessions.html +36 -36
- package/dist/docs/reference/sessions.md +36 -40
- package/dist/docs/reference/skills.html +38 -38
- package/dist/docs/reference/skills.md +15 -26
- package/dist/docs/reference/subagents.html +38 -38
- package/dist/docs/reference/subagents.md +20 -30
- package/dist/docs/reference/tools.html +44 -41
- package/dist/docs/reference/tools.md +45 -64
- package/dist/docs/templates/agentic-owners.html +35 -35
- package/dist/docs/templates/pr-autofixer.html +35 -35
- package/dist/docs/templates/security-reviewer.html +35 -35
- package/dist/docs/templates/thermo-quality-review.html +35 -35
- package/dist/docs/templates/thermo-review.html +35 -35
- package/dist/docs/templates/triage.html +35 -35
- package/dist/docs/troubleshooting.html +36 -36
- package/dist/docs/troubleshooting.md +1 -1
- package/dist/playground/assets/{index-DSMAewbx.css → index-C61EWMBK.css} +1 -1
- package/dist/playground/index.html +2 -2
- package/docs/deployment.md +1 -1
- package/docs/guides/agent-to-agent.md +11 -12
- package/docs/guides/cloud-agents.md +1 -1
- package/docs/guides/grokbot-agents.md +1 -1
- package/docs/guides/hooks.md +116 -0
- package/docs/guides/jev.md +23 -80
- package/docs/reference/agent-config.md +48 -81
- package/docs/reference/artifacts.md +72 -71
- package/docs/reference/channels.md +135 -202
- package/docs/reference/connections.md +93 -129
- package/docs/reference/evals.md +43 -51
- package/docs/reference/extensions.md +9 -13
- package/docs/reference/hooks.md +72 -146
- package/docs/reference/http-api.md +137 -161
- package/docs/reference/instructions.md +22 -37
- package/docs/reference/playground.md +26 -43
- package/docs/reference/project-layout.md +12 -17
- package/docs/reference/prompt.md +20 -15
- package/docs/reference/schedules.md +52 -99
- package/docs/reference/sessions.md +36 -40
- package/docs/reference/skills.md +15 -26
- package/docs/reference/subagents.md +20 -30
- package/docs/reference/tools.md +45 -64
- package/docs/troubleshooting.md +1 -1
- package/package.json +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.Ck9E52Ls.js +0 -1
- package/dist/docs/assets/chunks/channel.BHiYmnZ4.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Degh8l90.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Degh8l90.js +0 -1
- package/dist/docs/assets/chunks/clone.BIywbczV.js +0 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.qrxrbFsX.js +0 -1
- package/dist/docs/assets/guides_jev.md.F5fAkkfN.lean.js +0 -1
- package/dist/docs/assets/reference_agent-config.md.DGPyw7ms.js +0 -40
- package/dist/docs/assets/reference_artifacts.md.Bu_4HmsD.js +0 -19
- package/dist/docs/assets/reference_artifacts.md.Bu_4HmsD.lean.js +0 -1
- package/dist/docs/assets/reference_channels.md.nFWbzAic.js +0 -43
- package/dist/docs/assets/reference_channels.md.nFWbzAic.lean.js +0 -1
- package/dist/docs/assets/reference_evals.md.DNJzM_yf.lean.js +0 -1
- package/dist/docs/assets/reference_hooks.md.B7uzNENk.js +0 -73
- package/dist/docs/assets/reference_http-api.md.CduHavZ2.js +0 -11
- package/dist/docs/assets/reference_instructions.md.CU1My5My.js +0 -14
- package/dist/docs/assets/reference_instructions.md.CU1My5My.lean.js +0 -1
- package/dist/docs/assets/reference_playground.md.Ch2d0Iqi.js +0 -1
- package/dist/docs/assets/reference_playground.md.Ch2d0Iqi.lean.js +0 -1
- package/dist/docs/assets/reference_project-layout.md.BGhgpy9V.js +0 -19
- package/dist/docs/assets/reference_prompt.md.Ccp0R53H.js +0 -1
- package/dist/docs/assets/reference_prompt.md.Ccp0R53H.lean.js +0 -1
- package/dist/docs/assets/reference_schedules.md.B2Nm6FaD.js +0 -82
- package/dist/docs/assets/reference_schedules.md.B2Nm6FaD.lean.js +0 -1
- package/dist/docs/assets/reference_sessions.md.1_6Vyv7x.js +0 -1
- package/dist/docs/assets/reference_skills.md.DjQkRefx.js +0 -15
- package/dist/docs/assets/reference_subagents.md.Dl16gcBj.js +0 -10
- package/dist/docs/assets/troubleshooting.md.mnfFG2Em.js +0 -1
- /package/dist/docs/assets/{deployment.md.D2jQZuFx.lean.js → deployment.md.D2YX7u_I.lean.js} +0 -0
- /package/dist/docs/assets/{guides_agent-to-agent.md.CD4T5FIl.lean.js → guides_agent-to-agent.md.C6kPY8nu.lean.js} +0 -0
- /package/dist/docs/assets/{guides_cloud-agents.md.Cp1O3u-X.lean.js → guides_cloud-agents.md.BPJqTZjT.lean.js} +0 -0
- /package/dist/docs/assets/{guides_grokbot-agents.md.CMhZNdEU.lean.js → guides_grokbot-agents.md.CzV715v8.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.mnfFG2Em.lean.js → troubleshooting.md.HY95rCCz.lean.js} +0 -0
- /package/dist/playground/assets/{index-De_lpFxE.js → index-CrMWlgUU.js} +0 -0
package/dist/docs/llms-full.txt
CHANGED
|
@@ -331,7 +331,7 @@ per-caller and channel-specific auth.
|
|
|
331
331
|
|
|
332
332
|
Use `agent-sdk logs --prod` for runtime output,
|
|
333
333
|
[OpenTelemetry](/docs/guides/opentelemetry.md) for traces and metrics, and
|
|
334
|
-
[session traces](/docs/reference/sessions.md#
|
|
334
|
+
[session traces](/docs/reference/sessions.md#inspect-a-saved-event-stream)
|
|
335
335
|
for one conversation.
|
|
336
336
|
|
|
337
337
|
## Related
|
|
@@ -682,8 +682,8 @@ await ctx.host.mcp.callTool("weather", "check", {
|
|
|
682
682
|
});
|
|
683
683
|
```
|
|
684
684
|
|
|
685
|
-
The peer owns this session
|
|
686
|
-
|
|
685
|
+
The peer owns this session, so follow-ups continue the specialist's
|
|
686
|
+
context.
|
|
687
687
|
|
|
688
688
|
## Call a deterministic peer tool
|
|
689
689
|
|
|
@@ -728,14 +728,13 @@ complete agent you would also run, inspect, or expose on its own.
|
|
|
728
728
|
|
|
729
729
|
## Affinity
|
|
730
730
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
only that caller can continue or check the session.
|
|
731
|
+
Those turns show up in the peer's playground. Only the session owner
|
|
732
|
+
can continue or check them.
|
|
734
733
|
|
|
735
734
|
## Practices
|
|
736
735
|
|
|
737
|
-
- Give each caller a one-way routing rule
|
|
738
|
-
|
|
736
|
+
- Give each caller a one-way routing rule, and don't configure reciprocal
|
|
737
|
+
routes for the same request.
|
|
739
738
|
|
|
740
739
|
- Prefer `ask` when the specialist should reason. Use `call_tool` when
|
|
741
740
|
host code already knows which server tool to run.
|
|
@@ -746,12 +745,12 @@ only that caller can continue or check the session.
|
|
|
746
745
|
|
|
747
746
|
## Other hosts
|
|
748
747
|
|
|
749
|
-
Peers
|
|
750
|
-
|
|
748
|
+
Peers require the default multi-agent layout; unknown slugs and
|
|
749
|
+
self-references fail at startup.
|
|
751
750
|
|
|
752
|
-
|
|
753
|
-
and protect it with `--bearer-token`.
|
|
754
|
-
[Deployment guide](/docs/deployment.md) owns that hosting setup.
|
|
751
|
+
If a cloud-runtime turn needs a self-hosted peer, set `--public-url` to
|
|
752
|
+
the shared host's reachable URL and protect it with `--bearer-token`.
|
|
753
|
+
The [Deployment guide](/docs/deployment.md) owns that hosting setup.
|
|
755
754
|
|
|
756
755
|
## Related
|
|
757
756
|
|
|
@@ -1064,7 +1063,7 @@ agent, keep talking while it works, inspect the result, and steer or
|
|
|
1064
1063
|
stop the same branch.
|
|
1065
1064
|
|
|
1066
1065
|
This is different from choosing
|
|
1067
|
-
[`runtime: "cloud"`](/docs/reference/agent-config.md#
|
|
1066
|
+
[`runtime: "cloud"`](/docs/reference/agent-config.md#runtime).
|
|
1068
1067
|
That setting moves this agent's turns to a cloud VM; this extension lets
|
|
1069
1068
|
the agent delegate separate coding tasks.
|
|
1070
1069
|
|
|
@@ -2161,11 +2160,127 @@ directory and disable that tool. See
|
|
|
2161
2160
|
overlays
|
|
2162
2161
|
- [Tool approvals](/docs/reference/tools.md#gate-a-tool-on-human-approval):
|
|
2163
2162
|
approve asks
|
|
2164
|
-
- [Agent config](/docs/reference/agent-config.md#
|
|
2163
|
+
- [Agent config](/docs/reference/agent-config.md#runtime): local
|
|
2165
2164
|
and hosted runtimes
|
|
2166
2165
|
|
|
2167
2166
|
---
|
|
2168
2167
|
|
|
2168
|
+
Source: /docs/guides/hooks.md
|
|
2169
|
+
|
|
2170
|
+
# Hooks
|
|
2171
|
+
|
|
2172
|
+
Hooks observe session events after they are recorded and run side effects such
|
|
2173
|
+
as updating metrics or sending alerts. They never change the turn, prompt, or
|
|
2174
|
+
reply. Author them under `agent/hooks/` with `defineHook` from
|
|
2175
|
+
`@cursor/july/hooks`.
|
|
2176
|
+
|
|
2177
|
+
## Meter token usage
|
|
2178
|
+
|
|
2179
|
+
With [OpenTelemetry](/docs/guides/opentelemetry.md) configured, this hook adds a live
|
|
2180
|
+
turn's reported input and output tokens to your counters. Eval runs stay quiet,
|
|
2181
|
+
so the dashboard reflects live traffic instead of the test suite.
|
|
2182
|
+
|
|
2183
|
+
```ts
|
|
2184
|
+
// agent/hooks/usage.ts
|
|
2185
|
+
import { defineHook } from "@cursor/july/hooks";
|
|
2186
|
+
|
|
2187
|
+
export default defineHook({
|
|
2188
|
+
events: {
|
|
2189
|
+
async "turn.completed"(event, ctx) {
|
|
2190
|
+
if (ctx.session.purpose === "eval") {
|
|
2191
|
+
return;
|
|
2192
|
+
}
|
|
2193
|
+
if (event.data.usage === undefined) {
|
|
2194
|
+
return;
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
const { inputTokens, outputTokens } = event.data.usage;
|
|
2198
|
+
ctx.host.otel.increment("acme.tokens.input", inputTokens);
|
|
2199
|
+
ctx.host.otel.increment("acme.tokens.output", outputTokens);
|
|
2200
|
+
},
|
|
2201
|
+
},
|
|
2202
|
+
});
|
|
2203
|
+
```
|
|
2204
|
+
|
|
2205
|
+
## Alert on failure
|
|
2206
|
+
|
|
2207
|
+
Set `PAGER_WEBHOOK_URL` to your pager's webhook. When a live turn fails, this
|
|
2208
|
+
hook posts the agent, session, and failure message there. Eval runs and
|
|
2209
|
+
interrupted turns stay quiet, so tests and preemptions do not page anyone.
|
|
2210
|
+
|
|
2211
|
+
```ts
|
|
2212
|
+
// agent/hooks/page-on-failure.ts
|
|
2213
|
+
import { defineHook } from "@cursor/july/hooks";
|
|
2214
|
+
|
|
2215
|
+
export default defineHook({
|
|
2216
|
+
events: {
|
|
2217
|
+
async "turn.failed"(event, ctx) {
|
|
2218
|
+
if (ctx.session.purpose === "eval") {
|
|
2219
|
+
return;
|
|
2220
|
+
}
|
|
2221
|
+
if (event.data.message === "turn interrupted") {
|
|
2222
|
+
return;
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
const pagerUrl = process.env.PAGER_WEBHOOK_URL;
|
|
2226
|
+
if (pagerUrl === undefined) {
|
|
2227
|
+
return;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
await fetch(pagerUrl, {
|
|
2231
|
+
method: "POST",
|
|
2232
|
+
headers: { "content-type": "application/json" },
|
|
2233
|
+
body: JSON.stringify({
|
|
2234
|
+
agent: ctx.agent.name,
|
|
2235
|
+
session: ctx.session.id,
|
|
2236
|
+
channel: ctx.channel.id,
|
|
2237
|
+
message: event.data.message,
|
|
2238
|
+
}),
|
|
2239
|
+
signal: AbortSignal.timeout(5_000),
|
|
2240
|
+
});
|
|
2241
|
+
},
|
|
2242
|
+
},
|
|
2243
|
+
});
|
|
2244
|
+
```
|
|
2245
|
+
|
|
2246
|
+
## Events / when hooks run
|
|
2247
|
+
|
|
2248
|
+
Use event names from the
|
|
2249
|
+
[session event vocabulary](/docs/reference/sessions.md#stream-events). A hook
|
|
2250
|
+
receives each matching event after it is recorded, and the model does not wait
|
|
2251
|
+
for the handler.
|
|
2252
|
+
|
|
2253
|
+
Within one session, handlers run one at a time. A slow handler delays later
|
|
2254
|
+
handlers for that session, but it does not delay the model or handlers for
|
|
2255
|
+
other sessions. Hooks also fire for evals, so check
|
|
2256
|
+
`ctx.session.purpose === "eval"` before metering or paging. A restart does not
|
|
2257
|
+
replay recorded events into hooks.
|
|
2258
|
+
|
|
2259
|
+
## When not to use a hook
|
|
2260
|
+
|
|
2261
|
+
| Want | Use instead |
|
|
2262
|
+
| --- | --- |
|
|
2263
|
+
| Add context before the model | `instructions.md`, skills, or `workspaceFiles` |
|
|
2264
|
+
| Deliver to Slack or a PR | Channel [`events`](/docs/reference/channels.md#events) or packs |
|
|
2265
|
+
| Block or approve a tool | [`needsApproval`](/docs/reference/tools.md#gate-a-tool-on-human-approval) |
|
|
2266
|
+
| Gate final assistant text | `defineResult` |
|
|
2267
|
+
| Gate behavior | [Evals](/docs/evals.md) |
|
|
2268
|
+
|
|
2269
|
+
[Cursor Agent hooks](https://cursor.com/docs/agent/hooks) in
|
|
2270
|
+
`.cursor/hooks.json` are a different product. They can observe, block, or
|
|
2271
|
+
modify the local agent loop.
|
|
2272
|
+
|
|
2273
|
+
## Related
|
|
2274
|
+
|
|
2275
|
+
- [Hooks reference](/docs/reference/hooks.md): payloads, context, and discovery
|
|
2276
|
+
- [Sessions: stream events](/docs/reference/sessions.md#stream-events): event
|
|
2277
|
+
vocabulary and payload sequence
|
|
2278
|
+
- [OpenTelemetry](/docs/guides/opentelemetry.md): export traces and custom metrics
|
|
2279
|
+
- [Channels: events](/docs/reference/channels.md#events): deliver replies back to
|
|
2280
|
+
Slack, source control, or another surface
|
|
2281
|
+
|
|
2282
|
+
---
|
|
2283
|
+
|
|
2169
2284
|
Source: /docs/guides/improve.md
|
|
2170
2285
|
|
|
2171
2286
|
# Self-improvement
|
|
@@ -2319,15 +2434,11 @@ Source: /docs/guides/jev.md
|
|
|
2319
2434
|
|
|
2320
2435
|
# Use Jev in review tools
|
|
2321
2436
|
|
|
2322
|
-
Use Jev
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
Ask one question per judgment. If an approval depends on risk, test
|
|
2329
|
-
coverage, and the size of the change, ask three questions in one call
|
|
2330
|
-
and combine the answers in code.
|
|
2437
|
+
Use Jev when a review workflow needs a typed decision instead of prose.
|
|
2438
|
+
A review agent can filter speculative findings, classify pull request
|
|
2439
|
+
risk, choose a reviewer, or decide whether a merge needs a documentation
|
|
2440
|
+
follow-up. Jev returns a choice, score, or probability; your TypeScript
|
|
2441
|
+
decides what happens next.
|
|
2331
2442
|
|
|
2332
2443
|
Set `TYPESAFE_API_KEY`. The default model is `jev-latest`.
|
|
2333
2444
|
|
|
@@ -2340,11 +2451,12 @@ export default jev();
|
|
|
2340
2451
|
|
|
2341
2452
|
## Start only the review turns you need
|
|
2342
2453
|
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2454
|
+
Call Jev from a channel hook before a model turn starts. When a pull
|
|
2455
|
+
request opens or becomes ready for review, this hook sends its title,
|
|
2456
|
+
body, labels, and filenames to Jev to decide whether the change needs
|
|
2457
|
+
security review. A result that clears the threshold starts the review
|
|
2458
|
+
turn; otherwise, the hook returns `null`, so the agent doesn't run or
|
|
2459
|
+
post to GitHub.
|
|
2348
2460
|
|
|
2349
2461
|
```ts
|
|
2350
2462
|
// agent/channels/github.ts
|
|
@@ -2400,8 +2512,7 @@ export default githubChannel({
|
|
|
2400
2512
|
});
|
|
2401
2513
|
```
|
|
2402
2514
|
|
|
2403
|
-
|
|
2404
|
-
the diff itself.
|
|
2515
|
+
Jev receives only the pull request metadata shown here, not the diff.
|
|
2405
2516
|
|
|
2406
2517
|
## Filter findings before you post them
|
|
2407
2518
|
|
|
@@ -2506,8 +2617,8 @@ approval event.
|
|
|
2506
2617
|
|
|
2507
2618
|
After a pull request merges, a code-wiki agent can ask whether the
|
|
2508
2619
|
change introduced a durable fact that belongs in the docs. A low
|
|
2509
|
-
probability
|
|
2510
|
-
pull request
|
|
2620
|
+
probability skips the follow-up, while a high probability opens a
|
|
2621
|
+
documentation pull request.
|
|
2511
2622
|
|
|
2512
2623
|
```ts
|
|
2513
2624
|
import { above, decide } from "@cursor/july/extensions/jev";
|
|
@@ -2532,14 +2643,14 @@ return openDocsPullRequest({ title, summary });
|
|
|
2532
2643
|
|
|
2533
2644
|
## Write tools with Jev
|
|
2534
2645
|
|
|
2535
|
-
`decide`
|
|
2536
|
-
|
|
2537
|
-
makes the same request and returns `{ answers }`.
|
|
2646
|
+
Call `decide` from a channel hook, server tool, or router when you want
|
|
2647
|
+
the answer map directly. Use `evaluate` when you want `{ answers }`.
|
|
2538
2648
|
|
|
2539
2649
|
Use a boolean for a yes-or-no gate, a choice for a closed set such as
|
|
2540
|
-
risk tiers or owners, and a score for an ordered rubric. `above`
|
|
2541
|
-
a boolean probability or score
|
|
2542
|
-
|
|
2650
|
+
risk tiers or owners, and a score for an ordered rubric. `above` returns
|
|
2651
|
+
`true` when a boolean probability or score meets the threshold.
|
|
2652
|
+
`needsHuman` returns `true` when a boolean probability or the selected
|
|
2653
|
+
choice's probability falls below the confidence threshold.
|
|
2543
2654
|
|
|
2544
2655
|
Keep the questions atomic and combine them in TypeScript. For example,
|
|
2545
2656
|
ask separately whether a finding is real, whether its impact is
|
|
@@ -2549,8 +2660,8 @@ rule that decides whether all three are enough to post.
|
|
|
2549
2660
|
## Let the agent ask Jev
|
|
2550
2661
|
|
|
2551
2662
|
Mounting the extension adds a read-only harness tool named
|
|
2552
|
-
`<namespace>__evaluate`. With the
|
|
2553
|
-
`jev__evaluate`.
|
|
2663
|
+
`<namespace>__evaluate`. With the `agent/extensions/jev.ts` mount shown
|
|
2664
|
+
earlier, the model sees `jev__evaluate`.
|
|
2554
2665
|
|
|
2555
2666
|
The tool accepts one state and a list of boolean, choice, or score
|
|
2556
2667
|
questions. It returns `{ answers }` and never posts, approves, or opens
|
|
@@ -2592,59 +2703,6 @@ export default jev({
|
|
|
2592
2703
|
the exported helpers, so project tools can still import `decide`,
|
|
2593
2704
|
`above`, and `needsHuman`.
|
|
2594
2705
|
|
|
2595
|
-
## Jev and trajectory evals
|
|
2596
|
-
|
|
2597
|
-
An eval checks a whole turn: the agent called the read, and it stayed
|
|
2598
|
-
off approve. `decide` is the one call inside the tool, before GitHub.
|
|
2599
|
-
Use the [Evals guide](/docs/evals.md) when you want the turn to keep
|
|
2600
|
-
behaving. Use `decide` when the tool itself needs a tier or a yes.
|
|
2601
|
-
|
|
2602
|
-
## Test without the live API
|
|
2603
|
-
|
|
2604
|
-
Pass `fetch` and `apiKey` and the same `decide` path runs in a test.
|
|
2605
|
-
|
|
2606
|
-
```ts
|
|
2607
|
-
import { decide } from "@cursor/july/extensions/jev";
|
|
2608
|
-
|
|
2609
|
-
const answers = await decide({
|
|
2610
|
-
state: {
|
|
2611
|
-
title: "Skip the refund auth check",
|
|
2612
|
-
summary: "acme/checkout#42 drops the session check on POST /refunds.",
|
|
2613
|
-
},
|
|
2614
|
-
questions: {
|
|
2615
|
-
risk: {
|
|
2616
|
-
type: "choice",
|
|
2617
|
-
instructions: "What risk tier is this pull request?",
|
|
2618
|
-
criteria: {
|
|
2619
|
-
"very-low": "docs, formatting, or a mechanical rename",
|
|
2620
|
-
low: "a local change with tests and no new trust boundary",
|
|
2621
|
-
medium: "auth, billing, or a behavior change callers depend on",
|
|
2622
|
-
high: "a likely exploit, data loss, or a broken public contract",
|
|
2623
|
-
},
|
|
2624
|
-
},
|
|
2625
|
-
},
|
|
2626
|
-
apiKey: "sk-test",
|
|
2627
|
-
fetch: async () =>
|
|
2628
|
-
new Response(
|
|
2629
|
-
JSON.stringify({
|
|
2630
|
-
answers: {
|
|
2631
|
-
risk: {
|
|
2632
|
-
type: "choice",
|
|
2633
|
-
choice: "high",
|
|
2634
|
-
probabilities: {
|
|
2635
|
-
"very-low": 0.02,
|
|
2636
|
-
low: 0.05,
|
|
2637
|
-
medium: 0.18,
|
|
2638
|
-
high: 0.75,
|
|
2639
|
-
},
|
|
2640
|
-
},
|
|
2641
|
-
},
|
|
2642
|
-
}),
|
|
2643
|
-
{ status: 200 }
|
|
2644
|
-
),
|
|
2645
|
-
});
|
|
2646
|
-
```
|
|
2647
|
-
|
|
2648
2706
|
## Practices
|
|
2649
2707
|
|
|
2650
2708
|
- Pass the pull request title, a short summary, and the draft finding.
|
|
@@ -4032,11 +4090,11 @@ coding agent extend the project for you
|
|
|
4032
4090
|
|
|
4033
4091
|
Source: /docs/reference/agent-config.md
|
|
4034
4092
|
|
|
4035
|
-
# Agent config
|
|
4093
|
+
# Agent config
|
|
4036
4094
|
|
|
4037
|
-
`agent/agent.ts` default-exports `defineAgent(config)
|
|
4038
|
-
|
|
4039
|
-
|
|
4095
|
+
`agent/agent.ts` default-exports `defineAgent(config)`, which sets the
|
|
4096
|
+
model, execution runtime, and runtime-specific defaults. Every root
|
|
4097
|
+
config field is optional.
|
|
4040
4098
|
|
|
4041
4099
|
```ts
|
|
4042
4100
|
import { defineAgent } from "@cursor/july";
|
|
@@ -4056,9 +4114,7 @@ export default defineAgent({
|
|
|
4056
4114
|
});
|
|
4057
4115
|
```
|
|
4058
4116
|
|
|
4059
|
-
##
|
|
4060
|
-
|
|
4061
|
-
`defineAgent` accepts these fields.
|
|
4117
|
+
## Agent fields
|
|
4062
4118
|
|
|
4063
4119
|
| Field | Type | Meaning |
|
|
4064
4120
|
| --- | --- | --- |
|
|
@@ -4067,14 +4123,14 @@ export default defineAgent({
|
|
|
4067
4123
|
| `description` | string | What the agent is for. Required on subagents; the parent model reads it to decide when to delegate. Documentation-only on the root. |
|
|
4068
4124
|
| `instructions` | string | Inline instructions. Prefer `instructions.md`; this exists for subagents and generated configs. |
|
|
4069
4125
|
| `runtime` | `"local"` or `"cloud"` | Where turns execute. Default `"local"`. |
|
|
4070
|
-
| `cloud` | object | Cloud agent defaults: repos, env, envVars
|
|
4126
|
+
| `cloud` | object | Cloud agent defaults: repos, env, envVars. Used when `runtime` is `"cloud"`, and as the base merged under per-session `cloud` send options. |
|
|
4071
4127
|
| `local` | `{ cwd?, workspaceDir?, sandbox? }` | Local harness defaults; ignored for cloud turns. See [Local options](#local-options). |
|
|
4072
|
-
| `hosting` | `{ egressDomains?, secretNames? }` |
|
|
4073
|
-
| `concurrency` | `{ maxRunningTurns? }` |
|
|
4128
|
+
| `hosting` | `{ egressDomains?, secretNames? }` | `agent-sdk deploy` declarations for allowed egress domains and expected secret names. Ignored by local serving. |
|
|
4129
|
+
| `concurrency` | `{ maxRunningTurns? }` | Agent-wide turn admission limit. See [Concurrency](#concurrency). |
|
|
4074
4130
|
| `builtinTools` | `{ reminders? }` | Framework-provided model-facing tools, opted in per capability. See [Built-in tools](#built-in-tools). |
|
|
4075
|
-
| `tools` | `ToolName[]` | Allowlist of built-in harness tools offered to the model. Unset = the model's full standard toolset. See [
|
|
4131
|
+
| `tools` | `ToolName[]` | Allowlist of built-in harness tools offered to the model. Unset = the model's full standard toolset. See [Harness tools](#harness-tools). |
|
|
4076
4132
|
|
|
4077
|
-
##
|
|
4133
|
+
## Model
|
|
4078
4134
|
|
|
4079
4135
|
`model` is a Cursor model id string, or `{ id, params }`. Effort and
|
|
4080
4136
|
speed are params, not id suffixes. The SDK rejects suffix-style ids
|
|
@@ -4096,24 +4152,17 @@ A plain string works when you don't need params:
|
|
|
4096
4152
|
model: "composer-2.5",
|
|
4097
4153
|
```
|
|
4098
4154
|
|
|
4099
|
-
##
|
|
4155
|
+
## Runtime
|
|
4100
4156
|
|
|
4101
|
-
`runtime: "local"` (the default) runs turns on
|
|
4102
|
-
|
|
4103
|
-
all apply.
|
|
4157
|
+
`runtime: "local"` (the default) runs turns on this machine. Server
|
|
4158
|
+
tools, skills, sandbox seeds, and tool approvals all apply.
|
|
4104
4159
|
|
|
4105
|
-
`runtime: "cloud"` runs turns on Cursor cloud agents
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
`--public-url` or `--cloud-tools-url` is set (omitted with a warning
|
|
4109
|
-
otherwise), and instructions and agent-tool catalogs are prepended to
|
|
4110
|
-
the first prompt, because the local session workspace is not the cloud
|
|
4111
|
-
VM.
|
|
4160
|
+
`runtime: "cloud"` runs turns on Cursor cloud agents. Pass a `cloud`
|
|
4161
|
+
block with the repositories the VM needs. See [Tools](/docs/reference/tools.md) for
|
|
4162
|
+
server- and agent-tool behavior on cloud turns.
|
|
4112
4163
|
|
|
4113
|
-
`validate` warns when `runtime: "cloud"` is combined with agent tools
|
|
4114
|
-
|
|
4115
|
-
when skills or sandbox seeds are present (they sync onto an Agent Store
|
|
4116
|
-
rather than the session workspace), and when the `cloud` block is
|
|
4164
|
+
`validate` warns when `runtime: "cloud"` is combined with agent tools,
|
|
4165
|
+
when skills or sandbox seeds are present, and when the `cloud` block is
|
|
4117
4166
|
missing.
|
|
4118
4167
|
|
|
4119
4168
|
## Local options
|
|
@@ -4122,18 +4171,15 @@ missing.
|
|
|
4122
4171
|
|
|
4123
4172
|
`local.workspaceDir` points every session at one shared harness cwd,
|
|
4124
4173
|
for agents that work inside an existing checkout. It takes precedence
|
|
4125
|
-
over `cwd`, and a per-send `workspaceDir` still wins over both.
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
serve process instead of once per session. The trade: sessions share a
|
|
4129
|
-
working tree, so a file one turn writes is visible to the next.
|
|
4174
|
+
over `cwd`, and a per-send `workspaceDir` still wins over both.
|
|
4175
|
+
Sessions share a working tree, so a file one turn writes is visible to
|
|
4176
|
+
the next.
|
|
4130
4177
|
|
|
4131
4178
|
`local.sandbox` runs the harness inside Cursor's local sandbox. It's
|
|
4132
|
-
off by default
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
than a prompt-level one.
|
|
4179
|
+
off by default: shell then auto-approves and inherits the serve process
|
|
4180
|
+
environment, including any credentials the host holds. Turn it on for
|
|
4181
|
+
agents whose turns read untrusted input (webhook payloads, PR diffs,
|
|
4182
|
+
inbound chat); it's a tool boundary, not a prompt-level one.
|
|
4137
4183
|
|
|
4138
4184
|
### Local cwd
|
|
4139
4185
|
|
|
@@ -4149,13 +4195,12 @@ does not leak rules, skills, or MCP servers into the turn. A standalone git
|
|
|
4149
4195
|
root keeps the in-project session workspace. Point `cwd` at a checkout only
|
|
4150
4196
|
when the agent should inherit that tree.
|
|
4151
4197
|
|
|
4152
|
-
##
|
|
4198
|
+
## Harness tools
|
|
4153
4199
|
|
|
4154
4200
|
Use `tools` to limit which built-in Cursor harness tools the model can
|
|
4155
4201
|
call. Omit it to keep the standard toolset. When you set it, the model
|
|
4156
4202
|
gets only the tools you list. An empty list disables all native
|
|
4157
|
-
built-in tools.
|
|
4158
|
-
stay disabled until you add them.
|
|
4203
|
+
built-in tools. New platform tools stay disabled until you add them.
|
|
4159
4204
|
|
|
4160
4205
|
```ts
|
|
4161
4206
|
export default defineAgent({
|
|
@@ -4166,12 +4211,13 @@ export default defineAgent({
|
|
|
4166
4211
|
});
|
|
4167
4212
|
```
|
|
4168
4213
|
|
|
4169
|
-
The Agent SDK always adds `"mcp"` to a configured allowlist
|
|
4170
|
-
server tools in `agent/tools/`
|
|
4171
|
-
expose declared connections and servers from the harness
|
|
4172
|
-
ambient `.cursor` config. To exclude a checkout's MCP
|
|
4173
|
-
`local.cwd` outside the checkout. See
|
|
4174
|
-
`local.sandbox` makes MCP tool calls fail
|
|
4214
|
+
The Agent SDK always adds `"mcp"` to a configured allowlist, because
|
|
4215
|
+
authored server tools in `agent/tools/` reach the model over MCP. MCP
|
|
4216
|
+
can also expose declared connections and servers from the harness
|
|
4217
|
+
directory's ambient `.cursor` config. To exclude a checkout's MCP
|
|
4218
|
+
servers, point `local.cwd` outside the checkout. See
|
|
4219
|
+
[Local cwd](#local-cwd). `local.sandbox` makes MCP tool calls fail
|
|
4220
|
+
closed.
|
|
4175
4221
|
|
|
4176
4222
|
Use the SDK's public tool names, including `"shell"`, `"read"`,
|
|
4177
4223
|
`"edit"`, `"grep"`, `"glob"`, `"ls"`, and `"task"`. Unknown names
|
|
@@ -4188,8 +4234,7 @@ Two names have broader effects:
|
|
|
4188
4234
|
Tool allowlists work only with the local runtime. A
|
|
4189
4235
|
`runtime: "cloud"` agent that sets `tools` fails at serve startup.
|
|
4190
4236
|
The Agent SDK also refuses per-send cloud sessions from a hybrid agent
|
|
4191
|
-
with an allowlist.
|
|
4192
|
-
access.
|
|
4237
|
+
with an allowlist.
|
|
4193
4238
|
|
|
4194
4239
|
The allowlist controls which tools the model can call. It does not
|
|
4195
4240
|
isolate the serve host. For agents that process untrusted input, also
|
|
@@ -4197,10 +4242,10 @@ set `local: { sandbox: true }`.
|
|
|
4197
4242
|
|
|
4198
4243
|
## Cloud options
|
|
4199
4244
|
|
|
4200
|
-
|
|
4201
|
-
`{ url, startingRef? }`), environment selection, `envVars
|
|
4202
|
-
|
|
4203
|
-
|
|
4245
|
+
The `cloud` block sets default repositories (each
|
|
4246
|
+
`{ url, startingRef? }`), environment selection, and `envVars`. A local
|
|
4247
|
+
agent uses the same block as the base config when a channel opens a
|
|
4248
|
+
cloud-attached session per send (the `cloud` option on
|
|
4204
4249
|
[`send`](/docs/reference/channels.md#handler-arguments)).
|
|
4205
4250
|
|
|
4206
4251
|
## Concurrency
|
|
@@ -4223,9 +4268,8 @@ export default defineAgent({
|
|
|
4223
4268
|
## Built-in tools
|
|
4224
4269
|
|
|
4225
4270
|
`builtinTools` opts into framework-provided model-facing tools. Each
|
|
4226
|
-
enabled capability
|
|
4227
|
-
|
|
4228
|
-
like authored tools. Authored tools with the same name win, with a
|
|
4271
|
+
enabled capability shows up as ordinary server tools, so turns, direct
|
|
4272
|
+
calls, `info`, and the playground treat them like authored tools. Authored tools with the same name win, with a
|
|
4229
4273
|
warning, and like all server tools they run on the local runtime.
|
|
4230
4274
|
|
|
4231
4275
|
`builtinTools: { reminders: true }` adds three tools bound to the
|
|
@@ -4234,22 +4278,6 @@ current conversation over `host.reminders`: `reminders_create`,
|
|
|
4234
4278
|
continuation key can't arm reminders. See
|
|
4235
4279
|
[Schedules and reminders](/docs/reference/schedules.md#reminders).
|
|
4236
4280
|
|
|
4237
|
-
## Generate instructions
|
|
4238
|
-
|
|
4239
|
-
When the system prompt must be computed, author `agent/instructions.ts`
|
|
4240
|
-
instead of markdown:
|
|
4241
|
-
|
|
4242
|
-
```ts
|
|
4243
|
-
import { defineInstructions } from "@cursor/july";
|
|
4244
|
-
|
|
4245
|
-
export default defineInstructions({
|
|
4246
|
-
markdown: `You are the on-call assistant for ${process.env.TEAM_NAME}.`,
|
|
4247
|
-
});
|
|
4248
|
-
```
|
|
4249
|
-
|
|
4250
|
-
The directory form and the runtime mapping are in
|
|
4251
|
-
[Instructions](/docs/reference/instructions.md).
|
|
4252
|
-
|
|
4253
4281
|
## Serve programmatically
|
|
4254
4282
|
|
|
4255
4283
|
`serve(dirOrProject, options)` embeds the server in your own process:
|
|
@@ -4259,7 +4287,7 @@ import { serve } from "@cursor/july";
|
|
|
4259
4287
|
|
|
4260
4288
|
const handle = await serve("./my-agent", {
|
|
4261
4289
|
port: 3000,
|
|
4262
|
-
apiKey: process.env.CURSOR_API_KEY,
|
|
4290
|
+
apiKey: process.env.CURSOR_API_KEY,
|
|
4263
4291
|
});
|
|
4264
4292
|
console.log(`listening on ${handle.url}`);
|
|
4265
4293
|
// handle.callTool(...), handle.dispatchSchedule("heartbeat"),
|
|
@@ -4268,20 +4296,17 @@ console.log(`listening on ${handle.url}`);
|
|
|
4268
4296
|
|
|
4269
4297
|
Host settings match the documented [CLI](/docs/reference/cli.md) `serve` flags.
|
|
4270
4298
|
`serve()` also accepts `discovery` (project-loading options) and
|
|
4271
|
-
`mode: "single" | "multi"`.
|
|
4272
|
-
|
|
4273
|
-
`
|
|
4274
|
-
when unset), then `CURSOR_SERVICE_ACCOUNT_KEY`, then the key stored by
|
|
4275
|
-
`agent-sdk login`. On a host that has both the service-account key and a
|
|
4276
|
-
bind file, the file principal wins.
|
|
4299
|
+
`mode: "single" | "multi"`. Pass `apiKey` or use the same Cursor
|
|
4300
|
+
credential as the CLI: `CURSOR_API_KEY`, `CURSOR_API_KEY_FILE`,
|
|
4301
|
+
`CURSOR_SERVICE_ACCOUNT_KEY`, or `agent-sdk login`.
|
|
4277
4302
|
|
|
4278
|
-
##
|
|
4279
|
-
|
|
4280
|
-
Continue with these pages:
|
|
4303
|
+
## Related
|
|
4281
4304
|
|
|
4282
4305
|
- [Instructions](/docs/reference/instructions.md): the required half of a minimal
|
|
4283
4306
|
agent
|
|
4284
4307
|
- [CLI](/docs/reference/cli.md): the `serve` flags `serve()` accepts
|
|
4308
|
+
- [Sessions](/docs/reference/sessions.md): workspaces, identifiers, and turn admission
|
|
4309
|
+
- [Schedules](/docs/reference/schedules.md): reminder tools opted in here
|
|
4285
4310
|
|
|
4286
4311
|
---
|
|
4287
4312
|
|
|
@@ -4289,13 +4314,12 @@ Source: /docs/reference/artifacts.md
|
|
|
4289
4314
|
|
|
4290
4315
|
# Artifacts
|
|
4291
4316
|
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
artifacts
|
|
4295
|
-
|
|
4296
|
-
streams.
|
|
4317
|
+
Artifacts are durable outputs such as reviewed pull requests, reports,
|
|
4318
|
+
or decision records. An artifact kind defines the data it accepts, and
|
|
4319
|
+
the artifacts API tags or updates records by key. Records persist across
|
|
4320
|
+
sessions and can be listed, streamed, or downloaded.
|
|
4297
4321
|
|
|
4298
|
-
##
|
|
4322
|
+
## Artifact kinds
|
|
4299
4323
|
|
|
4300
4324
|
Author `agent/artifacts.ts` with `defineArtifacts` from
|
|
4301
4325
|
`@cursor/july/artifacts`:
|
|
@@ -4316,26 +4340,21 @@ export default defineArtifacts({
|
|
|
4316
4340
|
});
|
|
4317
4341
|
```
|
|
4318
4342
|
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4343
|
+
| Option | Contract |
|
|
4344
|
+
| --- | --- |
|
|
4345
|
+
| `kinds` | Map of accepted kind names to a non-empty `description` and optional Zod `schema` |
|
|
4346
|
+
| `agentTool` | Expose `tag_artifact` to the model; requires at least one declared kind |
|
|
4347
|
+
| `max` | Positive retention cap; defaults to `1000` and evicts the oldest-updated record |
|
|
4348
|
+
|
|
4349
|
+
With declared kinds, `tag` rejects any other kind. With no registry, it
|
|
4350
|
+
accepts free-form kind names and defaults an omitted kind to
|
|
4351
|
+
`"artifact"`. A kind's schema validates `data`, and the parsed value is
|
|
4352
|
+
stored, including schema defaults and coercions.
|
|
4329
4353
|
|
|
4330
|
-
## Tag from host code
|
|
4354
|
+
## Tag artifacts from host code
|
|
4331
4355
|
|
|
4332
|
-
|
|
4333
|
-
an `ArtifactsApi` with `tag` and `list
|
|
4334
|
-
handlers and `onStart`, schedule `run` handlers, and reminder `run`
|
|
4335
|
-
handlers. Tool and hook facades are session-bound, so `tag` auto-fills
|
|
4336
|
-
the `sessionId` (and `turnId` when known). Channel, schedule, and
|
|
4337
|
-
reminder facades are unbound; pass `sessionId` in the tag input to
|
|
4338
|
-
attribute one.
|
|
4356
|
+
Tools, hooks, channel handlers, channel `onStart`, schedules, and
|
|
4357
|
+
reminders receive an `ArtifactsApi` with `tag` and `list`.
|
|
4339
4358
|
|
|
4340
4359
|
```ts
|
|
4341
4360
|
await ctx.artifacts.tag({
|
|
@@ -4346,59 +4365,66 @@ await ctx.artifacts.tag({
|
|
|
4346
4365
|
});
|
|
4347
4366
|
```
|
|
4348
4367
|
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
`
|
|
4353
|
-
`
|
|
4354
|
-
`
|
|
4368
|
+
| Tag field | Contract |
|
|
4369
|
+
| --- | --- |
|
|
4370
|
+
| `data` | Required JSON data, validated when the kind has a schema |
|
|
4371
|
+
| `kind` | Declared or free-form kind |
|
|
4372
|
+
| `key` | Agent-wide upsert key; the same key updates one record across kinds |
|
|
4373
|
+
| `title` | Optional display title |
|
|
4374
|
+
| `contents` | String or bytes served by the content route |
|
|
4375
|
+
| `contentType` | MIME type for `contents` |
|
|
4376
|
+
| `sessionId`, `turnId` | Attribute the artifact to a session or turn |
|
|
4377
|
+
| `source` | `"host"` or `"model"`; defaults to `"host"` |
|
|
4378
|
+
|
|
4379
|
+
Tool, hook, result, and channel-event contexts are session-bound, so
|
|
4380
|
+
they fill `sessionId` and the current `turnId`. Channel routes,
|
|
4381
|
+
`onStart`, schedules, and reminders receive an unbound facade; pass
|
|
4382
|
+
`sessionId` to attribute an artifact.
|
|
4383
|
+
|
|
4384
|
+
Re-tagging a key without `contents` keeps its file or blob when the
|
|
4385
|
+
`sessionId` stays the same. Rebinding the key to another session without
|
|
4386
|
+
new contents removes the previous payload. `tag` returns the stored
|
|
4387
|
+
`ArtifactRecord`.
|
|
4388
|
+
|
|
4389
|
+
| Record field | Contract |
|
|
4390
|
+
| --- | --- |
|
|
4391
|
+
| `id` | Stable ID derived from `key`, or a generated ID when no key is set |
|
|
4392
|
+
| `kind`, `data` | Validated kind and JSON payload |
|
|
4393
|
+
| `key`, `title` | Optional upsert key and display title |
|
|
4394
|
+
| `content` | Optional `{ size, contentType? }` metadata |
|
|
4395
|
+
| `sessionId`, `turnId` | Optional session attribution |
|
|
4396
|
+
| `source` | `"host"` or `"model"` |
|
|
4397
|
+
| `createdAt`, `updatedAt` | ISO-8601 timestamps |
|
|
4355
4398
|
|
|
4356
|
-
##
|
|
4399
|
+
## Expose `tag_artifact` to the model
|
|
4357
4400
|
|
|
4358
4401
|
With `agentTool: true`, the `tag_artifact` server tool materializes from
|
|
4359
|
-
the kinds registry. Its
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
validated exactly like a host-side tag. An authored tool named
|
|
4363
|
-
`tag_artifact` shadows the built-in, with a warning.
|
|
4364
|
-
|
|
4365
|
-
## Observe and list
|
|
4402
|
+
the kinds registry. Its input accepts the declared kinds and validates
|
|
4403
|
+
their data with the same schemas as host-side tagging. The kind
|
|
4404
|
+
descriptions tell the model which output each one represents.
|
|
4366
4405
|
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
`source` (`"host"` for host code, `"model"` for `tag_artifact`). Hooks,
|
|
4370
|
-
channel `events`, and evals see it like any other
|
|
4371
|
-
[stream event](/docs/reference/sessions.md#which-events-can-i-stream).
|
|
4406
|
+
An authored tool named `tag_artifact` takes precedence over the generated
|
|
4407
|
+
tool.
|
|
4372
4408
|
|
|
4373
|
-
|
|
4409
|
+
## List artifacts
|
|
4374
4410
|
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
```
|
|
4379
|
-
|
|
4380
|
-
`GET /v1/artifacts` returns records newest-updated first, filterable by
|
|
4381
|
-
`kind` and `sessionId`. Session ownership applies, same as
|
|
4382
|
-
`/v1/sessions`. The playground renders tagged artifacts too.
|
|
4411
|
+
`list({ kind?, sessionId? })` returns matching records newest-updated
|
|
4412
|
+
first. HTTP callers can list records and download content through the
|
|
4413
|
+
[artifact routes](/docs/reference/http-api.md#list-and-download-artifacts).
|
|
4383
4414
|
|
|
4384
|
-
##
|
|
4415
|
+
## Stream artifact tags
|
|
4385
4416
|
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
```ts
|
|
4391
|
-
t.taggedArtifact("reviewed-pr", (record) => record.source === "model");
|
|
4392
|
-
```
|
|
4417
|
+
Tagging an artifact with a `sessionId` emits `artifact.tagged` on that
|
|
4418
|
+
session. Its event data contains `id`, `kind`, `key`, `title`, `data`,
|
|
4419
|
+
and `source`. See [Stream events](/docs/reference/sessions.md#stream-events) for the
|
|
4420
|
+
event envelope.
|
|
4393
4421
|
|
|
4394
|
-
##
|
|
4395
|
-
|
|
4396
|
-
Continue with these pages:
|
|
4422
|
+
## Related
|
|
4397
4423
|
|
|
4398
|
-
- [Sessions
|
|
4399
|
-
|
|
4400
|
-
- [
|
|
4401
|
-
- [
|
|
4424
|
+
- [Sessions](/docs/reference/sessions.md)
|
|
4425
|
+
- [Tools](/docs/reference/tools.md)
|
|
4426
|
+
- [Evals](/docs/reference/evals.md)
|
|
4427
|
+
- [HTTP API](/docs/reference/http-api.md)
|
|
4402
4428
|
|
|
4403
4429
|
---
|
|
4404
4430
|
|
|
@@ -4406,24 +4432,21 @@ Source: /docs/reference/channels.md
|
|
|
4406
4432
|
|
|
4407
4433
|
# Channels
|
|
4408
4434
|
|
|
4409
|
-
A channel
|
|
4410
|
-
|
|
4411
|
-
under `/v1/channels/<id>`. The
|
|
4412
|
-
|
|
4413
|
-
hosted and self-managed products. This page is the authoring reference;
|
|
4414
|
-
for the walkthrough, see the [Webhooks guide](/docs/guides/webhooks.md).
|
|
4435
|
+
A channel connects an external surface to agent sessions. A file at
|
|
4436
|
+
`agent/channels/<id>.ts` defines channel `<id>` and mounts its routes
|
|
4437
|
+
under `/v1/channels/<id>`. The built-in HTTP session channel is always
|
|
4438
|
+
available alongside any custom or prebuilt channels.
|
|
4415
4439
|
|
|
4416
4440
|
## Built-in HTTP channel
|
|
4417
4441
|
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4442
|
+
The built-in channel serves the session, approval, tool, discovery, and
|
|
4443
|
+
health routes. In a multi-agent host, each agent's routes sit under its
|
|
4444
|
+
slug. See the [HTTP API](/docs/reference/http-api.md) for request and response
|
|
4445
|
+
contracts.
|
|
4422
4446
|
|
|
4423
4447
|
## Define a custom channel
|
|
4424
4448
|
|
|
4425
|
-
|
|
4426
|
-
route prefix:
|
|
4449
|
+
Use `defineChannel` with one or more typed routes:
|
|
4427
4450
|
|
|
4428
4451
|
```ts
|
|
4429
4452
|
import { defineChannel, POST } from "@cursor/july/channels";
|
|
@@ -4436,237 +4459,173 @@ export default defineChannel({
|
|
|
4436
4459
|
bodySchema: z.object({
|
|
4437
4460
|
message: z.string(),
|
|
4438
4461
|
prUrl: z.string().url(),
|
|
4439
|
-
thread: z.string().optional(),
|
|
4440
4462
|
}),
|
|
4441
|
-
handler: async (
|
|
4442
|
-
const prepared = await callTool("inspect_pr", {
|
|
4443
|
-
prUrl: body.prUrl,
|
|
4444
|
-
});
|
|
4445
|
-
if (prepared.isError) {
|
|
4446
|
-
return Response.json(
|
|
4447
|
-
{ error: prepared.errorMessage ?? "Could not inspect pull request" },
|
|
4448
|
-
{ status: 502 }
|
|
4449
|
-
);
|
|
4450
|
-
}
|
|
4451
|
-
|
|
4463
|
+
handler: async (_request, { send, body }) => {
|
|
4452
4464
|
const session = await send(
|
|
4453
|
-
`${body.message}\n\
|
|
4465
|
+
`${body.message}\n\nPull request: ${body.prUrl}`,
|
|
4454
4466
|
{
|
|
4455
|
-
continuationToken:
|
|
4456
|
-
workspaceFiles: {
|
|
4457
|
-
"pr.json": JSON.stringify(prepared.result, null, 2) ?? "null",
|
|
4458
|
-
},
|
|
4467
|
+
continuationToken: `pr:${body.prUrl}`,
|
|
4459
4468
|
}
|
|
4460
4469
|
);
|
|
4461
4470
|
return Response.json({ sessionId: session.id });
|
|
4462
4471
|
},
|
|
4463
4472
|
}),
|
|
4464
4473
|
],
|
|
4465
|
-
events: {
|
|
4466
|
-
"message.completed"(event, channel, ctx) {
|
|
4467
|
-
// deliver the reply to the surface that owns this channel
|
|
4468
|
-
},
|
|
4469
|
-
},
|
|
4470
|
-
// auth: [...], state: {...}, onStart(...), onStop(...)
|
|
4471
4474
|
});
|
|
4472
4475
|
```
|
|
4473
4476
|
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
writes the tool result to `pr.json`. Instructions can ask the model to
|
|
4478
|
-
inspect a PR, but host code guarantees it.
|
|
4477
|
+
The route above is
|
|
4478
|
+
`POST /v1/channels/<id>/review`. Calls for the same pull request reuse
|
|
4479
|
+
one conversation because they pass the same continuation token.
|
|
4479
4480
|
|
|
4480
4481
|
## Route verbs and schemas
|
|
4481
4482
|
|
|
4482
|
-
|
|
4483
|
-
schemas
|
|
4483
|
+
Route paths must begin with `/`. The method helper determines which Zod
|
|
4484
|
+
schemas the route accepts:
|
|
4484
4485
|
|
|
4485
|
-
|
|
|
4486
|
-
|
|
|
4487
|
-
| `GET`
|
|
4488
|
-
| `POST
|
|
4489
|
-
| `DELETE`
|
|
4486
|
+
| Helper | Schema contract |
|
|
4487
|
+
| --- | --- |
|
|
4488
|
+
| `GET` | `querySchema` is required |
|
|
4489
|
+
| `POST`, `PUT`, `PATCH` | `bodySchema` is required; `querySchema` is optional |
|
|
4490
|
+
| `DELETE` | Both schemas are optional |
|
|
4490
4491
|
|
|
4491
|
-
Plain JSON Schema objects
|
|
4492
|
-
`z.unknown()` for
|
|
4493
|
-
the handler
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
buttons and composer **slash commands**.
|
|
4492
|
+
Plain JSON Schema objects don't type-check. Use `z.object({})` or
|
|
4493
|
+
`z.unknown()` for an open surface. The host validates the body and query
|
|
4494
|
+
before calling the handler, returning `400` on failure; an empty body is
|
|
4495
|
+
read as `{}`. Declared schemas also appear in `GET /v1/info` for
|
|
4496
|
+
playground requests and slash commands.
|
|
4497
4497
|
|
|
4498
4498
|
## Handler arguments
|
|
4499
4499
|
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
| Member
|
|
4503
|
-
|
|
|
4504
|
-
| `send(message, options?)`
|
|
4505
|
-
| `getSession(sessionId)`
|
|
4506
|
-
| `receive(
|
|
4507
|
-
| `callTool(name, input, options?)`
|
|
4508
|
-
| `body`, `query`, `params`
|
|
4509
|
-
| `auth`
|
|
4510
|
-
| `requestIp`
|
|
4511
|
-
| `host`
|
|
4512
|
-
| `waitUntil(promise)`
|
|
4513
|
-
| `sessionUrls(request, sessionId)`
|
|
4514
|
-
| `artifacts`
|
|
4515
|
-
|
|
4516
|
-
`send` options
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4500
|
+
Each handler receives the Fetch `Request` and a typed arguments object.
|
|
4501
|
+
|
|
4502
|
+
| Member | Contract |
|
|
4503
|
+
| --- | --- |
|
|
4504
|
+
| `send(message, options?)` | Start or resume a session on this channel |
|
|
4505
|
+
| `getSession(sessionId)` | Return this channel's session, or `null` |
|
|
4506
|
+
| `receive(channel, input)` | Hand work to another channel |
|
|
4507
|
+
| `callTool(name, input, options?)` | [Call a server tool](/docs/reference/tools.md#call-a-tool-without-a-model-turn) without a model turn |
|
|
4508
|
+
| `body`, `query`, `params` | Validated inputs and `:param` path segments |
|
|
4509
|
+
| `auth` | The `AuthContext` returned by the route's auth chain |
|
|
4510
|
+
| `requestIp` | The TCP peer address, or `null` |
|
|
4511
|
+
| `host` | Shared MCP, provider, storage, telemetry, and reminder services |
|
|
4512
|
+
| `waitUntil(promise)` | Track work after the response returns |
|
|
4513
|
+
| `sessionUrls(request, sessionId)` | Build absolute playground and trace URLs for this mount |
|
|
4514
|
+
| `artifacts` | List or tag [artifacts](/docs/reference/artifacts.md); pass `sessionId` when attributing one |
|
|
4515
|
+
|
|
4516
|
+
### `send` options
|
|
4517
|
+
|
|
4518
|
+
| Option | Contract |
|
|
4519
|
+
| --- | --- |
|
|
4520
|
+
| `continuationToken` | Resume the session with this channel-local key, or create one when the key is new |
|
|
4521
|
+
| `admission` | `"preempt"` interrupts a busy turn; `"coalesce"` queues behind it. The default is `"preempt"` |
|
|
4522
|
+
| `workspaceFiles` | Add relative files for the next turn |
|
|
4523
|
+
| `workspaceDir` | Use an absolute local working directory |
|
|
4524
|
+
| `cloud` | Override cloud session options when creating a session |
|
|
4525
|
+
| `auth` | Set the session principal; defaults to the request principal |
|
|
4526
|
+
| `state` | Set starting channel state for a new session |
|
|
4527
|
+
| `title` | Set the display title for a new session |
|
|
4528
|
+
| `purpose` | Use `"eval"` to mark a new session as regression traffic |
|
|
4529
|
+
| `dryRun` | Run read tools and stub write tools for a new session |
|
|
4530
|
+
| `asOf` | Freeze a new session at an ISO-8601 instant with a timezone |
|
|
4531
|
+
|
|
4532
|
+
`send` returns a `ChannelSession`. Its `id` identifies the session,
|
|
4533
|
+
`continuationToken` contains its current channel key, and `isNew` says
|
|
4534
|
+
whether this call created it. A coalesced call also returns
|
|
4535
|
+
`coalesced: true`.
|
|
4524
4536
|
|
|
4525
4537
|
## Events
|
|
4526
4538
|
|
|
4527
4539
|
The `events` map subscribes the channel to stream events for the
|
|
4528
4540
|
sessions it owns. Keys are event types from the
|
|
4529
|
-
[event vocabulary](/docs/reference/sessions.md#
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
replies back to its surface.
|
|
4535
|
-
|
|
4536
|
-
## State and lifecycle
|
|
4537
|
-
|
|
4538
|
-
`state` declares the starting per-session adapter state (JSON), persisted
|
|
4539
|
-
on the session record. Routes and event handlers read and mutate it
|
|
4540
|
-
through `channel.state`. `onStart(args)` runs when the channel mounts.
|
|
4541
|
-
`onStop()` runs when the server stops.
|
|
4542
|
-
|
|
4543
|
-
`onStart` receives the route helpers (`send`, `getSession`, `receive`,
|
|
4544
|
-
`callTool`, `host`, `waitUntil`, `artifacts`, `logger`) plus helpers
|
|
4545
|
-
for long-lived transports:
|
|
4546
|
-
|
|
4547
|
-
- `emitAssistantMessage(sessionId, text)` appends an assistant message
|
|
4548
|
-
without a model turn, for host tasks that already produced the final
|
|
4549
|
-
text.
|
|
4550
|
-
- `hasContinuationSession(token)` and `isContinuationBusy(token)`
|
|
4551
|
-
report whether a continuation token has a live session and whether a
|
|
4552
|
-
turn is in flight on it.
|
|
4553
|
-
- `interruptContinuation(token)` stops the in-flight turn and clears
|
|
4554
|
-
coalesced follow-ups queued behind it.
|
|
4555
|
-
- `resolveApproval(sessionId, callId, decision, auth, options?)`
|
|
4556
|
-
approves or denies a parked tool call, how Slack Block Kit buttons
|
|
4557
|
-
unblock a turn without the HTTP approvals route.
|
|
4541
|
+
[event vocabulary](/docs/reference/sessions.md#stream-events), or `"*"`. Each handler
|
|
4542
|
+
receives `(event, channel, ctx)`, including the session's
|
|
4543
|
+
`channel.state`, session info, and shared host services. Use these
|
|
4544
|
+
handlers to deliver progress and replies to the surface that owns the
|
|
4545
|
+
channel.
|
|
4558
4546
|
|
|
4559
|
-
##
|
|
4547
|
+
## Session state
|
|
4548
|
+
|
|
4549
|
+
`state` on the channel definition supplies starting JSON for each new
|
|
4550
|
+
session. A route can instead pass `state` to `send`; event handlers read
|
|
4551
|
+
and update the active value through `channel.state`.
|
|
4560
4552
|
|
|
4561
|
-
|
|
4562
|
-
`[localDevStrict()]` when unset. A policy is a function
|
|
4563
|
-
`(request, info) => AuthContext | null` (async allowed); the first
|
|
4564
|
-
non-null wins, and a request no policy admits gets `401`.
|
|
4553
|
+
## Start and stop a channel
|
|
4565
4554
|
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
| `localDev()` | Like `localDevStrict()` but without the `Host` check. An explicit, weaker opt-in. |
|
|
4570
|
-
| `loopbackOnly()` | A loopback TCP peer, ignoring forwarding headers; for dev relays that legitimately carry them, like `gh webhook forward`. |
|
|
4571
|
-
| `bearerAuth(token)` | `Authorization: Bearer <token>`, compared in constant time. Also accepts a verifier function mapping a presented token to an `AuthContext`. |
|
|
4572
|
-
| `allowAll()` | Everyone, as an `anonymous` principal. Only for surfaces protected upstream (an HMAC-verified webhook) or intentionally public. |
|
|
4573
|
-
| `publicEndpoint()` | Everyone on this custom channel. Managed hosting also serves the channel without an alias token. Use it only when the handler verifies the provider signature. |
|
|
4555
|
+
`onStart(args)` runs when the channel mounts, and `onStop()` runs when
|
|
4556
|
+
the host stops. `onStart` receives the route helpers plus these
|
|
4557
|
+
transport controls:
|
|
4574
4558
|
|
|
4575
|
-
|
|
4576
|
-
|
|
4559
|
+
| Helper | Contract |
|
|
4560
|
+
| --- | --- |
|
|
4561
|
+
| `emitAssistantMessage(sessionId, text)` | Append final assistant text without starting a model turn |
|
|
4562
|
+
| `hasContinuationSession(token)` | Check whether a token maps to a session |
|
|
4563
|
+
| `isContinuationBusy(token)` | Check whether a turn is active for a token |
|
|
4564
|
+
| `interruptContinuation(token)` | Stop the active turn and clear queued coalesced follow-ups |
|
|
4565
|
+
| `resolveApproval(...)` | Approve or deny a parked tool call |
|
|
4566
|
+
|
|
4567
|
+
## Auth policies
|
|
4568
|
+
|
|
4569
|
+
Every route runs the channel's `auth` array. The default is
|
|
4570
|
+
`[localDevStrict()]`. Policies may be asynchronous; the first one to
|
|
4571
|
+
return an `AuthContext` admits the request, and an all-null result
|
|
4572
|
+
returns `401`.
|
|
4573
|
+
|
|
4574
|
+
| Policy | Admits |
|
|
4575
|
+
| --- | --- |
|
|
4576
|
+
| `localDevStrict()` | Direct loopback requests with a loopback hostname and no proxy-forwarding headers |
|
|
4577
|
+
| `localDev()` | Direct loopback requests with no proxy-forwarding headers, without checking the hostname |
|
|
4578
|
+
| `loopbackOnly()` | Any loopback TCP peer, including local relays that carry forwarding headers |
|
|
4579
|
+
| `bearerAuth(tokenOrVerify)` | A matching bearer token, or a token accepted by the verifier |
|
|
4580
|
+
| `sharedSecretAuth({ header, secret })` | A header matching the named environment or deployment secret |
|
|
4581
|
+
| `hmacSignatureAuth({ header, secret, prefix? })` | A hex HMAC-SHA256 signature over the raw body using the named secret |
|
|
4582
|
+
| `allowAll()` | Every caller as an anonymous principal |
|
|
4583
|
+
| `publicEndpoint()` | Every caller on this custom channel; managed hosting also exposes the route without an alias token |
|
|
4584
|
+
|
|
4585
|
+
Use `allowAll()` only for an intentionally public surface or one
|
|
4586
|
+
protected upstream. With `publicEndpoint()`, the handler must verify the
|
|
4587
|
+
provider's signature. The policy applies only to custom channel routes;
|
|
4588
|
+
it doesn't open the built-in session or tool API.
|
|
4577
4589
|
|
|
4578
4590
|
The resolved `AuthContext` (`{ authenticator, principalId,
|
|
4579
4591
|
principalType, attributes? }`) becomes the request principal. Sessions
|
|
4580
|
-
|
|
4581
|
-
|
|
4592
|
+
belong to the principal that created them, and other principals receive
|
|
4593
|
+
`403` on owned routes.
|
|
4582
4594
|
|
|
4583
4595
|
Server flags interact with authored auth: `--bearer-token` swaps the
|
|
4584
4596
|
default `localDevStrict()` for `bearerAuth(...)` on channels that don't
|
|
4585
4597
|
author their own chain, and `--allow-anonymous` swaps it for
|
|
4586
|
-
`allowAll()`.
|
|
4587
|
-
declares `[localDevStrict()]` stays loopback-only even on an
|
|
4588
|
-
`--allow-anonymous` host.
|
|
4589
|
-
|
|
4590
|
-
## First class channels
|
|
4591
|
-
|
|
4592
|
-
**Slack** (`@cursor/july/channels/slack`): Socket Mode
|
|
4593
|
-
transport, streaming replies, engagement rules, approval cards, and a
|
|
4594
|
-
default block on Slack Connect / guest / other-workspace senders. Author
|
|
4595
|
-
`agent/channels/slack.ts` with `slackChannel()`. Guide:
|
|
4596
|
-
[Slack](/docs/guides/slack.md).
|
|
4597
|
-
|
|
4598
|
-
**GitHub** (`@cursor/july/channels/github`): webhook dispatch
|
|
4599
|
-
with signature verification, per-event hooks returning `{ auth }` (a
|
|
4600
|
-
model turn), `{ task }` (host work), or `null`, and CLI tooling for
|
|
4601
|
-
replay and live forwarding. Author `agent/channels/github.ts` with
|
|
4602
|
-
`githubChannel()`. Opt-in `progress.commitStatus` and `progress.banner`
|
|
4603
|
-
converge a merge-box check and sticky PR comment from default stream
|
|
4604
|
-
events. Supports GitHub.com and GitHub Enterprise Server. Guide:
|
|
4605
|
-
[GitHub](/docs/guides/github.md).
|
|
4606
|
-
|
|
4607
|
-
**GitLab** (`@cursor/july/channels/gitlab`): verified project hooks for
|
|
4608
|
-
merge requests, notes, pipelines, pushes, and custom event types. Supports
|
|
4609
|
-
GitLab.com and self-managed GitLab. Author `agent/channels/gitlab.ts` with
|
|
4610
|
-
`gitlabChannel()`. Guide: [GitLab](/docs/guides/gitlab.md).
|
|
4611
|
-
|
|
4612
|
-
**Bitbucket** (`@cursor/july/channels/bitbucket`): verified repository hooks
|
|
4613
|
-
for pull requests, comments, pushes, and custom event types. Supports
|
|
4614
|
-
Bitbucket Cloud and Bitbucket Data Center through one normalized hook API.
|
|
4615
|
-
Author `agent/channels/bitbucket.ts` with `bitbucketChannel()`. Guide:
|
|
4616
|
-
[Bitbucket](/docs/guides/bitbucket.md).
|
|
4617
|
-
|
|
4618
|
-
**Deployments** (`@cursor/july/channels/deployments`): pull deploy
|
|
4619
|
-
events. Declare `events` and handle each one in `onEvent`. Each event
|
|
4620
|
-
carries `deploySourceUri` and `deployVersion`. Author
|
|
4621
|
-
`agent/channels/deployments.ts` with `deploymentsChannel()`.
|
|
4622
|
-
|
|
4623
|
-
On Cursor-managed hosting, omit `deploySourceUris`. The deployment's
|
|
4624
|
-
watched repositories bind the event scope automatically. Name sources
|
|
4625
|
-
to narrow the scope or to drive the self-hosted pull relay. Subscribe
|
|
4626
|
-
per deploy source with `deploySourceUris` and narrow with `environments`
|
|
4627
|
-
or `events`. Each entry must match `Deployment.deploy_source_uri` as
|
|
4628
|
-
your deployment writer records it. Matching is case-insensitive but
|
|
4629
|
-
otherwise literal. It uses the host credential. A restart resumes
|
|
4630
|
-
rather than dropping events. An empty `deploySourceUris` list mounts the
|
|
4631
|
-
channel but starts no pull, so an env-configured agent stays inert until
|
|
4632
|
-
its deploy sources are set.
|
|
4633
|
-
|
|
4634
|
-
**Change Monitors** (`@cursor/july/channels/change-monitors`): Change
|
|
4635
|
-
Monitor Checkpoint events. The channel publishes Factory
|
|
4636
|
-
`checkpoint.created` for every Checkpoint create. The agent filters the
|
|
4637
|
-
result (for example to the `issues` arm). The payload contains the
|
|
4638
|
-
full Checkpoint resource. This channel is scoped to Change Monitors,
|
|
4639
|
-
not generic Factory Checkpoints. There is no repository filter or
|
|
4640
|
-
resource filter. Author `agent/channels/change-monitors.ts` with
|
|
4641
|
-
`changeMonitorsChannel()`. It uses the host credential.
|
|
4642
|
-
|
|
4643
|
-
**Issues** (`@cursor/july/channels/issues`): Factory issue events.
|
|
4644
|
-
The channel publishes `issue.created` for every Issue create. The
|
|
4645
|
-
agent filters if it needs a subset. The payload contains the full
|
|
4646
|
-
Issue resource. There is no repository filter or resource filter.
|
|
4647
|
-
Author `agent/channels/issues.ts` with `issuesChannel()`. It uses the
|
|
4648
|
-
host credential.
|
|
4598
|
+
`allowAll()`. An authored `auth` array always takes precedence.
|
|
4649
4599
|
|
|
4650
|
-
|
|
4651
|
-
`defineChannel` webhook form.
|
|
4600
|
+
## Prebuilt channels
|
|
4652
4601
|
|
|
4653
|
-
|
|
4602
|
+
| Import | Factory | Surface |
|
|
4603
|
+
| --- | --- | --- |
|
|
4604
|
+
| `@cursor/july/channels/slack` | `slackChannel()` | Slack messages, threads, streaming replies, and approvals. See [Slack](/docs/guides/slack.md) |
|
|
4605
|
+
| `@cursor/july/channels/github` | `githubChannel()` | GitHub and GitHub Enterprise webhooks. See [GitHub](/docs/guides/github.md) |
|
|
4606
|
+
| `@cursor/july/channels/gitlab` | `gitlabChannel()` | GitLab.com and self-managed GitLab hooks. See [GitLab](/docs/guides/gitlab.md) |
|
|
4607
|
+
| `@cursor/july/channels/bitbucket` | `bitbucketChannel()` | Bitbucket Cloud and Data Center hooks. See [Bitbucket](/docs/guides/bitbucket.md) |
|
|
4608
|
+
| `@cursor/july/channels/deployments` | `deploymentsChannel()` | Deployment events filtered by source, environment, or event name |
|
|
4609
|
+
| `@cursor/july/channels/change-monitors` | `changeMonitorsChannel()` | Change Monitor `checkpoint.created` events |
|
|
4610
|
+
| `@cursor/july/channels/issues` | `issuesChannel()` | Factory `issue.created` events |
|
|
4654
4611
|
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
automations use keys like `pr:owner/repo#N`. Same token, same durable
|
|
4658
|
-
session; one active continuation per session; the HTTP channel returns
|
|
4659
|
-
`409` for stale tokens. For the full session model, see
|
|
4660
|
-
[Sessions](/docs/reference/sessions.md).
|
|
4612
|
+
For other platforms like Discord or Teams, use the authored
|
|
4613
|
+
`defineChannel` route form.
|
|
4661
4614
|
|
|
4662
|
-
##
|
|
4615
|
+
## Continuation tokens
|
|
4663
4616
|
|
|
4664
|
-
|
|
4617
|
+
Each channel defines its continuation-token format. The same token
|
|
4618
|
+
resumes the same conversation; the built-in HTTP channel rotates its
|
|
4619
|
+
opaque token after every accepted follow-up and returns `409` for a
|
|
4620
|
+
stale token. See [Session identifiers](/docs/reference/sessions.md#session-identifiers)
|
|
4621
|
+
for the full contract.
|
|
4665
4622
|
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
- [
|
|
4669
|
-
|
|
4623
|
+
## Related
|
|
4624
|
+
|
|
4625
|
+
- [Webhooks](/docs/guides/webhooks.md)
|
|
4626
|
+
- [HTTP API](/docs/reference/http-api.md)
|
|
4627
|
+
- [Sessions](/docs/reference/sessions.md)
|
|
4628
|
+
- [Hooks](/docs/reference/hooks.md)
|
|
4670
4629
|
|
|
4671
4630
|
---
|
|
4672
4631
|
|
|
@@ -5642,19 +5601,18 @@ These environment variables affect the CLI and its channel packs.
|
|
|
5642
5601
|
|
|
5643
5602
|
Source: /docs/reference/connections.md
|
|
5644
5603
|
|
|
5645
|
-
# MCP
|
|
5604
|
+
# MCP connections
|
|
5646
5605
|
|
|
5647
|
-
An MCP connection gives the agent tools from an MCP server.
|
|
5648
|
-
server under `agent/mcp-connections
|
|
5649
|
-
name
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5606
|
+
An MCP connection gives the agent tools from an MCP server. Define one
|
|
5607
|
+
file per server under `agent/mcp-connections/`; the filename becomes the
|
|
5608
|
+
server name. Default-export `defineConnection` from
|
|
5609
|
+
`@cursor/july/connections`. The transport is remote HTTP, local stdio,
|
|
5610
|
+
the signed-in Cursor account's connectors, or a peer agent on the same
|
|
5611
|
+
host.
|
|
5653
5612
|
|
|
5654
|
-
Put a server in `agent/host-connections/` when host tools should
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
those files.
|
|
5613
|
+
Put a server in `agent/host-connections/` when only host tools should
|
|
5614
|
+
call it. Host connections use the same `defineConnection` shape and
|
|
5615
|
+
support `agent-sdk mcp oauth`; the model and playground don't see them.
|
|
5658
5616
|
|
|
5659
5617
|
## Remote MCP server
|
|
5660
5618
|
|
|
@@ -5676,8 +5634,7 @@ Tokens come from env vars. Never hardcode them in the file.
|
|
|
5676
5634
|
For servers that speak OAuth, set `oauth: true` and authorize with the
|
|
5677
5635
|
CLI or mid-run Connect. Tokens live in `mcp-auth.json` under the CLI
|
|
5678
5636
|
config directory. `--store` copies them onto the deployment as
|
|
5679
|
-
`MCP_OAUTH_<NAME>_*` secrets.
|
|
5680
|
-
process retry.
|
|
5637
|
+
`MCP_OAUTH_<NAME>_*` secrets.
|
|
5681
5638
|
|
|
5682
5639
|
```ts
|
|
5683
5640
|
export default defineConnection({
|
|
@@ -5689,24 +5646,17 @@ export default defineConnection({
|
|
|
5689
5646
|
```bash
|
|
5690
5647
|
agent-sdk mcp oauth inventory # browser PKCE → local mcp-auth.json
|
|
5691
5648
|
agent-sdk mcp oauth inventory --store # also upsert deployment secrets
|
|
5692
|
-
# Hosted Connect retries this process. Self-hosted stays file-only.
|
|
5693
5649
|
```
|
|
5694
5650
|
|
|
5695
5651
|
Full walkthrough: [Host MCP OAuth](/docs/guides/mcp-oauth.md). Companion
|
|
5696
5652
|
skill: [`skills/mcp-auth/SKILL.md`](https://github.com/cursor/cursor/blob/main/packages/agent-serve/skills/mcp-auth/SKILL.md).
|
|
5697
5653
|
|
|
5698
|
-
|
|
5699
|
-
already linked in the Cursor dashboard. Omit `servers` (or pass `"*"`)
|
|
5700
|
-
to forward every connected connector. If the model should call those
|
|
5701
|
-
tools by name on local turns, set `advertiseTools: true`.
|
|
5702
|
-
|
|
5703
|
-
## Per-session auth (`auth`)
|
|
5654
|
+
## Per-session auth
|
|
5704
5655
|
|
|
5705
|
-
For http/sse connections whose credential depends on
|
|
5706
|
-
for
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
merged over the static ones:
|
|
5656
|
+
For http/sse connections whose credential depends on who the session is
|
|
5657
|
+
for, declare an `auth` callback instead of static headers. It runs
|
|
5658
|
+
host-side with the session's `SessionInfo` and returns headers merged
|
|
5659
|
+
over the static ones:
|
|
5710
5660
|
|
|
5711
5661
|
```ts
|
|
5712
5662
|
export default defineConnection({
|
|
@@ -5714,39 +5664,31 @@ export default defineConnection({
|
|
|
5714
5664
|
auth: async (session) => ({
|
|
5715
5665
|
headers: { Authorization: `Bearer ${await grantFor(session)}` },
|
|
5716
5666
|
}),
|
|
5717
|
-
advertiseTools: true,
|
|
5667
|
+
advertiseTools: true,
|
|
5718
5668
|
});
|
|
5719
5669
|
```
|
|
5720
5670
|
|
|
5721
|
-
The
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
identity. Local runtime only; cloud turns are refused. `host.mcp` calls
|
|
5727
|
-
from server tools keep the static headers only. Not combinable with
|
|
5728
|
-
`oauth: true`; the host OAuth provider owns the Authorization header.
|
|
5671
|
+
The identity always comes from the session itself, never from a tenant
|
|
5672
|
+
parameter the model could invent. A callback that throws fails the
|
|
5673
|
+
turn; a cloud turn with `auth` is refused instead of running without
|
|
5674
|
+
that identity. `host.mcp` calls from server tools keep the static
|
|
5675
|
+
headers only. You can't combine `auth` with `oauth: true`.
|
|
5729
5676
|
|
|
5730
5677
|
Derive the identity from durable session facts: `session.auth`,
|
|
5731
|
-
`session.id`, or your channel's own session state. Do
|
|
5732
|
-
`session.continuationKey
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
## Advertise a connection's tools by name (`advertiseTools`) {#advertise-tools}
|
|
5746
|
-
|
|
5747
|
-
Set `advertiseTools: true` when the model should call an MCP server's tools
|
|
5748
|
-
by name. The Agent SDK preserves each tool's name, description, input and
|
|
5749
|
-
output schemas, and MCP annotations.
|
|
5678
|
+
`session.id`, or your channel's own session state. Do not key it off
|
|
5679
|
+
`session.continuationKey`. The HTTP channel rotates that key after every
|
|
5680
|
+
accepted follow-up, so a tenant mapping keyed on it breaks
|
|
5681
|
+
mid-conversation.
|
|
5682
|
+
|
|
5683
|
+
`auth` works attached or advertised. Advertise the auth connection
|
|
5684
|
+
instead of attaching it next to a stateful stdio server.
|
|
5685
|
+
|
|
5686
|
+
## Advertise tools {#advertise-tools}
|
|
5687
|
+
|
|
5688
|
+
Set `advertiseTools: true` when the model should call an MCP server's
|
|
5689
|
+
tools by name. The Agent SDK preserves each tool's description, input
|
|
5690
|
+
and output schemas, and MCP annotations. Exposed names normalize invalid
|
|
5691
|
+
characters and add numeric suffixes to avoid collisions.
|
|
5750
5692
|
|
|
5751
5693
|
```ts
|
|
5752
5694
|
export default defineConnection({
|
|
@@ -5756,20 +5698,22 @@ export default defineConnection({
|
|
|
5756
5698
|
});
|
|
5757
5699
|
```
|
|
5758
5700
|
|
|
5759
|
-
A listing
|
|
5760
|
-
|
|
5761
|
-
|
|
5701
|
+
A listing or authentication failure fails the turn by default. Set
|
|
5702
|
+
`optional: true` to omit an unavailable connection instead. Advertised
|
|
5703
|
+
tools follow the same runtime support as server tools, and [direct tool
|
|
5704
|
+
calls](/docs/reference/tools.md#call-a-tool-without-a-model-turn) use the same names.
|
|
5762
5705
|
|
|
5763
|
-
In a dry-run session, MCP tools marked read-only run normally. Tools
|
|
5764
|
-
as writes are stubbed. Tools without effect annotations are
|
|
5706
|
+
In a dry-run session, MCP tools marked read-only run normally. Tools
|
|
5707
|
+
marked as writes are stubbed. Tools without effect annotations are
|
|
5708
|
+
unavailable.
|
|
5765
5709
|
|
|
5766
|
-
##
|
|
5710
|
+
## Filter connection tools
|
|
5767
5711
|
|
|
5768
5712
|
Use `tools` the same way you allowlist harness tools on the agent. When
|
|
5769
5713
|
set, the connection serves only those names. Use `disallowedTools` to
|
|
5770
|
-
drop names instead. The two combine as deny-wins
|
|
5771
|
-
|
|
5772
|
-
|
|
5714
|
+
drop names instead. The two combine as deny-wins. The model and
|
|
5715
|
+
`host.mcp` only see what remains. A model-visible filter requires
|
|
5716
|
+
`advertiseTools: true`.
|
|
5773
5717
|
|
|
5774
5718
|
```ts
|
|
5775
5719
|
export default defineConnection({
|
|
@@ -5777,7 +5721,9 @@ export default defineConnection({
|
|
|
5777
5721
|
advertiseTools: true,
|
|
5778
5722
|
tools: ["search_skus", "get_stock"],
|
|
5779
5723
|
});
|
|
5724
|
+
```
|
|
5780
5725
|
|
|
5726
|
+
```ts
|
|
5781
5727
|
export default defineConnection({
|
|
5782
5728
|
url: "https://mcp.example.com/inventory",
|
|
5783
5729
|
advertiseTools: true,
|
|
@@ -5786,9 +5732,9 @@ export default defineConnection({
|
|
|
5786
5732
|
```
|
|
5787
5733
|
|
|
5788
5734
|
Names are the server's `tools/list` names. Unknown names are omitted. A
|
|
5789
|
-
filter that matches nothing on the server fails the turn
|
|
5790
|
-
`effects: "read"` to keep only the listed
|
|
5791
|
-
reads.
|
|
5735
|
+
filter that matches nothing on the server fails the turn unless
|
|
5736
|
+
`optional: true`. Combine with `effects: "read"` to keep only the listed
|
|
5737
|
+
tools the server classifies as reads.
|
|
5792
5738
|
|
|
5793
5739
|
A list of names is an allowlist. An object of handlers authors TypeScript
|
|
5794
5740
|
tools. On `host-connections/`, a name list restricts `host.mcp` without
|
|
@@ -5806,12 +5752,8 @@ export default defineConnection({
|
|
|
5806
5752
|
});
|
|
5807
5753
|
```
|
|
5808
5754
|
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
To run TypeScript in the agent environment (including a repo-less cloud
|
|
5813
|
-
VM), author the tools on the connection instead. The Agent SDK packages
|
|
5814
|
-
them as stdio MCP. You write `execute`. The Agent SDK speaks the protocol.
|
|
5755
|
+
To run TypeScript in the agent environment, including a repo-less cloud
|
|
5756
|
+
VM, author the tools on the connection instead. You write `execute`:
|
|
5815
5757
|
|
|
5816
5758
|
```ts
|
|
5817
5759
|
export default defineConnection({
|
|
@@ -5829,12 +5771,12 @@ export default defineConnection({
|
|
|
5829
5771
|
## Cursor account MCP connection
|
|
5830
5772
|
|
|
5831
5773
|
`{ cursorAccount: true }` forwards the MCP connectors the signed-in
|
|
5832
|
-
Cursor account already authorized (dashboard → MCP)
|
|
5833
|
-
|
|
5774
|
+
Cursor account already authorized (dashboard → MCP), such as Linear,
|
|
5775
|
+
Notion, and Slack. You don't configure tokens. Every tool runs on the
|
|
5834
5776
|
Cursor backend with the account's stored OAuth credentials, so raw
|
|
5835
|
-
tokens never reach the
|
|
5777
|
+
tokens never reach the serving host, session workspaces, or traces.
|
|
5836
5778
|
|
|
5837
|
-
By default the agent gets
|
|
5779
|
+
By default the agent gets every connected HTTP/SSE connector on the
|
|
5838
5780
|
account. Pass `servers: "*"` (or `["*"]`) for the same all-connectors
|
|
5839
5781
|
behavior in an explicit form. Pass a name list when you want a smaller
|
|
5840
5782
|
set.
|
|
@@ -5845,12 +5787,9 @@ export default defineConnection({
|
|
|
5845
5787
|
cursorAccount: true,
|
|
5846
5788
|
advertiseTools: true,
|
|
5847
5789
|
});
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
servers: "*",
|
|
5852
|
-
advertiseTools: true,
|
|
5853
|
-
});
|
|
5790
|
+
```
|
|
5791
|
+
|
|
5792
|
+
```ts
|
|
5854
5793
|
// only Linear:
|
|
5855
5794
|
export default defineConnection({
|
|
5856
5795
|
cursorAccount: true,
|
|
@@ -5861,17 +5800,15 @@ export default defineConnection({
|
|
|
5861
5800
|
|
|
5862
5801
|
Name the file `account.ts`. `cursor.ts` collides with the IDE `cursor`
|
|
5863
5802
|
MCP namespace. `advertiseTools: true` puts connector tools on local
|
|
5864
|
-
turns by name.
|
|
5803
|
+
turns by name.
|
|
5865
5804
|
|
|
5866
5805
|
The host must be signed in (`agent-sdk login`, `CURSOR_API_KEY`, or
|
|
5867
|
-
`CURSOR_SERVICE_ACCOUNT_KEY`).
|
|
5868
|
-
`serve` fails fast at startup otherwise, and logs each connector's live
|
|
5869
|
-
status (`connected`, `needsAuth`, `error`) as it starts.
|
|
5806
|
+
`CURSOR_SERVICE_ACCOUNT_KEY`). `serve` fails at startup otherwise.
|
|
5870
5807
|
|
|
5871
5808
|
Filtered account connections work on managed cloud deployments. A
|
|
5872
|
-
self-hosted cloud agent with a concrete `servers` list needs
|
|
5873
|
-
Serve fails instead of ignoring the filter. Use a
|
|
5874
|
-
for stdio servers.
|
|
5809
|
+
self-hosted cloud agent with a concrete `servers` list needs
|
|
5810
|
+
`--public-url`. Serve fails instead of ignoring the filter. Use a
|
|
5811
|
+
`{ command }` connection for stdio servers.
|
|
5875
5812
|
|
|
5876
5813
|
> [!CAUTION]
|
|
5877
5814
|
> Whoever can talk to the agent can drive these connectors, because they
|
|
@@ -5881,11 +5818,11 @@ for stdio servers.
|
|
|
5881
5818
|
> for example an SSO proxy or the hosted alias token). Prefer
|
|
5882
5819
|
> `--bearer-token` on shared hosts.
|
|
5883
5820
|
|
|
5884
|
-
## Peer MCP connection
|
|
5821
|
+
## Peer MCP connection {#peer-mcp-connection}
|
|
5885
5822
|
|
|
5886
5823
|
`{ agent: "<slug>" }` addresses another agent mounted on the same serve
|
|
5887
|
-
host. The model gets the peer's `ask` and `check`
|
|
5888
|
-
tools and can delegate work to it:
|
|
5824
|
+
host. The model gets the peer's `ask` and `check` tools, plus
|
|
5825
|
+
`call_tool` when the peer has server tools, and can delegate work to it:
|
|
5889
5826
|
|
|
5890
5827
|
```ts
|
|
5891
5828
|
export default defineConnection({
|
|
@@ -5897,63 +5834,51 @@ export default defineConnection({
|
|
|
5897
5834
|
Unknown slugs and self-references fail `serve` at startup. Walkthrough:
|
|
5898
5835
|
[Peer agents](/docs/guides/agent-to-agent.md#delegate-a-question-to-a-specialist).
|
|
5899
5836
|
|
|
5900
|
-
##
|
|
5901
|
-
|
|
5902
|
-
A file under `agent/mcp-connections/` serves three consumers. Host
|
|
5903
|
-
connections skip the first one.
|
|
5904
|
-
|
|
5905
|
-
1. **Cursor agent:** Attached connections ride SDK `mcpServers` behind
|
|
5906
|
-
harness MCP meta-tools. Set `advertiseTools: true` so local turns see
|
|
5907
|
-
named tools.
|
|
5908
|
-
2. **Server tools:** Deterministic host code composes MCP calls
|
|
5909
|
-
through `ctx.host.mcp`:
|
|
5910
|
-
|
|
5911
|
-
```ts
|
|
5912
|
-
export default defineTool({
|
|
5913
|
-
description: "Search Linear issues.",
|
|
5914
|
-
inputSchema: z.object({ query: z.string() }),
|
|
5915
|
-
async execute({ query }, ctx) {
|
|
5916
|
-
return ctx.host.mcp.callTool("linear", "list_issues", { query });
|
|
5917
|
-
},
|
|
5918
|
-
});
|
|
5919
|
-
```
|
|
5920
|
-
|
|
5921
|
-
3. **Channel and schedule handlers:** Webhooks hit MCP servers with no
|
|
5922
|
-
model turn at all, through `args.host.mcp`:
|
|
5923
|
-
|
|
5924
|
-
```ts
|
|
5925
|
-
POST("/sync", {
|
|
5926
|
-
bodySchema: z.object({}),
|
|
5927
|
-
handler: async (_req, { host }) => {
|
|
5928
|
-
const result = await host.mcp.callTool("linear", "list_issues", {});
|
|
5929
|
-
return Response.json(result);
|
|
5930
|
-
},
|
|
5931
|
-
});
|
|
5932
|
-
```
|
|
5933
|
-
|
|
5934
|
-
The host registry is small: `host.mcp.names()` lists MCP connection names,
|
|
5935
|
-
and `listTools(name)` / `callTool(name, tool, args)` open the client
|
|
5936
|
-
lazily on first use.
|
|
5837
|
+
## Call MCP from host code
|
|
5937
5838
|
|
|
5938
|
-
|
|
5839
|
+
A file under `agent/mcp-connections/` is available to the Cursor agent,
|
|
5840
|
+
to server tools through `ctx.host.mcp`, and to channel and schedule
|
|
5841
|
+
handlers through `args.host.mcp`. Host connections skip the model.
|
|
5842
|
+
|
|
5843
|
+
```ts
|
|
5844
|
+
// agent/tools/search_linear.ts
|
|
5845
|
+
import { defineTool } from "@cursor/july/tools";
|
|
5846
|
+
import { z } from "zod";
|
|
5939
5847
|
|
|
5940
|
-
|
|
5848
|
+
export default defineTool({
|
|
5849
|
+
description: "Search Linear issues.",
|
|
5850
|
+
inputSchema: z.object({ query: z.string() }),
|
|
5851
|
+
async execute({ query }, ctx) {
|
|
5852
|
+
return ctx.host.mcp.callTool("linear", "list_issues", { query });
|
|
5853
|
+
},
|
|
5854
|
+
});
|
|
5855
|
+
```
|
|
5856
|
+
|
|
5857
|
+
`host.mcp.names()` lists connection names.
|
|
5858
|
+
`listTools(name)` / `callTool(name, tool, args)` call into a named
|
|
5859
|
+
connection.
|
|
5860
|
+
|
|
5861
|
+
## Related
|
|
5941
5862
|
|
|
5942
5863
|
- [Host MCP OAuth](/docs/guides/mcp-oauth.md): `mcp oauth`, Connect, `--store`
|
|
5943
5864
|
- [Tools](/docs/reference/tools.md): authored tools that wrap MCP connections
|
|
5944
5865
|
- [Webhooks](/docs/guides/webhooks.md): calling MCP connections from handlers
|
|
5866
|
+
- [Peer agents](/docs/guides/agent-to-agent.md): when a specialist is its
|
|
5867
|
+
own agent
|
|
5945
5868
|
|
|
5946
5869
|
---
|
|
5947
5870
|
|
|
5948
5871
|
Source: /docs/reference/evals.md
|
|
5949
5872
|
|
|
5950
|
-
# Evals
|
|
5873
|
+
# Evals
|
|
5951
5874
|
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5875
|
+
Evals run fixed cases against an agent and record whether its turns,
|
|
5876
|
+
tools, events, and output meet a contract. Files under the project-root
|
|
5877
|
+
`evals/` directory define cases with `@cursor/july/evals`; the runner
|
|
5878
|
+
discovers their IDs, executes them, and reports every assertion. See the
|
|
5879
|
+
[Evals guide](/docs/evals.md) for the regression workflow.
|
|
5955
5880
|
|
|
5956
|
-
##
|
|
5881
|
+
## Eval discovery and case IDs
|
|
5957
5882
|
|
|
5958
5883
|
Eval files live under the project-root `evals/` directory and end in
|
|
5959
5884
|
`.eval.ts` or `.eval.js`. The path under that directory becomes the
|
|
@@ -5992,15 +5917,15 @@ Those cases are `prs/checkout` and `prs/search` when the file is
|
|
|
5992
5917
|
`evals/prs.eval.ts`. Case IDs must be unique single path segments.
|
|
5993
5918
|
|
|
5994
5919
|
A file can also export an array of `defineEval` calls. The runner names
|
|
5995
|
-
them with zero-padded indexes such as `sql/0000`.
|
|
5996
|
-
handwritten scenarios
|
|
5920
|
+
them with zero-padded indexes such as `sql/0000`. Named `cases` give
|
|
5921
|
+
handwritten scenarios stable IDs; arrays fit loaded datasets.
|
|
5997
5922
|
|
|
5998
5923
|
`iterations` repeats one datapoint from 1 to 100 times. For
|
|
5999
5924
|
`iterations: 3`, `weather/nyc` expands to `weather/nyc/1`,
|
|
6000
5925
|
`weather/nyc/2`, and `weather/nyc/3`; selecting `weather/nyc` runs all
|
|
6001
5926
|
three.
|
|
6002
5927
|
|
|
6003
|
-
##
|
|
5928
|
+
## Eval configuration
|
|
6004
5929
|
|
|
6005
5930
|
Every running suite needs `evals/evals.config.ts` with
|
|
6006
5931
|
`maxConcurrency`:
|
|
@@ -6021,38 +5946,39 @@ export default defineEvalConfig({
|
|
|
6021
5946
|
| `timeoutMs` | Per-case timeout; case/file, CLI, then config precedence |
|
|
6022
5947
|
| `judge` | Default model for `t.judge` |
|
|
6023
5948
|
| `reporters` | Objects notified as cases and runs complete |
|
|
6024
|
-
| `maxPlaygroundRuns` | Number of server-side batches kept in playground history |
|
|
5949
|
+
| `maxPlaygroundRuns` | Number of server-side batches kept in playground history; defaults to 20 |
|
|
6025
5950
|
|
|
6026
5951
|
A case can override `description`, `tags`, `timeoutMs`, `iterations`,
|
|
6027
5952
|
`judge`, `reporters`, and `metadata`. Case metadata merges over
|
|
6028
5953
|
file-level metadata; case reporters add to the file's reporters.
|
|
6029
5954
|
|
|
6030
|
-
##
|
|
5955
|
+
## Send turns in a case
|
|
6031
5956
|
|
|
6032
5957
|
`await t.send(message, options?)` runs one turn and waits until it
|
|
6033
5958
|
finishes, fails, or parks for approval. Several sends in one test share
|
|
6034
5959
|
the session.
|
|
6035
5960
|
|
|
6036
5961
|
The returned turn exposes its assistant `message`, `sessionId`,
|
|
6037
|
-
`events`, ordered `toolCalls`, `ok`, and
|
|
6038
|
-
turn inspect only that turn; assertions on `t` inspect the whole
|
|
6039
|
-
|
|
6040
|
-
`t.sessionId`, and the timeout
|
|
5962
|
+
`events`, ordered `toolCalls`, `ok`, and one-based `index`. Assertions
|
|
5963
|
+
on the turn inspect only that turn; assertions on `t` inspect the whole
|
|
5964
|
+
case. Run values include `t.reply`, `t.events`, `t.turns`,
|
|
5965
|
+
`t.sessionId`, `t.iteration`, `t.iterations`, and the timeout
|
|
5966
|
+
`t.signal`.
|
|
6041
5967
|
|
|
6042
5968
|
These options apply on the first send because they shape the session:
|
|
6043
5969
|
|
|
6044
5970
|
| Option | Contract |
|
|
6045
5971
|
| --- | --- |
|
|
6046
5972
|
| `workspaceFiles` | Relative path-to-content map seeded into the session workspace |
|
|
6047
|
-
| `workspaceDir` | Absolute
|
|
5973
|
+
| `workspaceDir` | Absolute working directory for a new local session |
|
|
6048
5974
|
| `cloud` | Cloud session options merged over the agent's static cloud config |
|
|
6049
5975
|
|
|
6050
|
-
Use `turn.expectOk()` when later test steps depend on
|
|
6051
|
-
succeeding.
|
|
5976
|
+
Use `turn.expectOk()` when later test steps depend on the turn
|
|
5977
|
+
succeeding. It throws when the turn failed.
|
|
6052
5978
|
|
|
6053
5979
|
## Trajectory assertions
|
|
6054
5980
|
|
|
6055
|
-
Assertions record failures
|
|
5981
|
+
Assertions record failures without stopping the test, so one case
|
|
6056
5982
|
reports every violated contract.
|
|
6057
5983
|
|
|
6058
5984
|
| Assertion | Checks |
|
|
@@ -6175,53 +6101,43 @@ export default rows.map(row =>
|
|
|
6175
6101
|
);
|
|
6176
6102
|
```
|
|
6177
6103
|
|
|
6178
|
-
Materialize API-backed evidence before running a large suite. Commit
|
|
6179
|
-
the exact payload, diff, or metadata revision and seed it with
|
|
6180
|
-
`workspaceFiles`.
|
|
6181
|
-
|
|
6182
6104
|
## Reporters and results
|
|
6183
6105
|
|
|
6184
6106
|
Built-in reporters include `JUnit({ filePath, suiteName? })` and
|
|
6185
6107
|
`Artifacts({ dir })`. Custom reporters can expose `onRunStart`,
|
|
6186
|
-
`onEvalComplete`, and `onRunComplete`.
|
|
6187
|
-
do not change the eval verdict.
|
|
6108
|
+
`onEvalComplete`, and `onRunComplete`.
|
|
6188
6109
|
|
|
6189
|
-
JSON output contains run totals
|
|
6190
|
-
|
|
6191
|
-
calls, metrics, logs, duration, metadata, tags,
|
|
6192
|
-
skip
|
|
6110
|
+
JSON output contains run totals and one result per case. Results include
|
|
6111
|
+
the case ID, verdict, assertions, session ID, inputs, final text, tools,
|
|
6112
|
+
tool calls, metrics, logs, duration, metadata, tags, and any error or
|
|
6113
|
+
skip reason.
|
|
6193
6114
|
|
|
6194
|
-
##
|
|
6115
|
+
## Select cases
|
|
6195
6116
|
|
|
6196
6117
|
```bash
|
|
6197
6118
|
agent-sdk eval --dir . --list
|
|
6198
6119
|
agent-sdk eval --dir .
|
|
6199
6120
|
agent-sdk eval --dir . builds/checkout
|
|
6200
6121
|
agent-sdk eval --dir . --tag smoke
|
|
6201
|
-
agent-sdk eval --dir . --verbose
|
|
6202
6122
|
```
|
|
6203
6123
|
|
|
6204
6124
|
ID filters match an exact ID and its descendants. Repeated IDs use OR;
|
|
6205
6125
|
repeated tags use OR. When both are present, a case must match both
|
|
6206
6126
|
groups.
|
|
6207
6127
|
|
|
6208
|
-
|
|
6209
|
-
|
|
6128
|
+
## Inspect run artifacts
|
|
6129
|
+
|
|
6130
|
+
Default run artifacts go under `evals/<stamp>/` in the project state
|
|
6131
|
+
directory and include
|
|
6210
6132
|
`summary.json`, `results.jsonl`, and `evals/<case-id>.json`.
|
|
6211
6133
|
`--artifacts <dir>` chooses another destination; `--no-artifacts`
|
|
6212
6134
|
disables them. This location is independent of `--state-root`.
|
|
6213
6135
|
|
|
6214
|
-
|
|
6215
|
-
`CURSOR_API_KEY`, `CURSOR_API_KEY_FILE`,
|
|
6216
|
-
`CURSOR_SERVICE_ACCOUNT_KEY`, then `agent-sdk login`. Listing cases
|
|
6217
|
-
needs no credential.
|
|
6218
|
-
|
|
6219
|
-
## Playground and hosted runs
|
|
6136
|
+
## Run evals against a server
|
|
6220
6137
|
|
|
6221
|
-
The playground **Evals** view starts batches on its running server
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
deployment.
|
|
6138
|
+
The playground **Evals** view starts batches on its running server.
|
|
6139
|
+
`--url` targets a named running server, and `--prod --slug <slug>`
|
|
6140
|
+
targets a hosted deployment.
|
|
6225
6141
|
|
|
6226
6142
|
```bash
|
|
6227
6143
|
agent-sdk eval --prod --slug vulnerability-scanner --tag smoke
|
|
@@ -6229,17 +6145,16 @@ agent-sdk eval status <eval-id> --prod --slug vulnerability-scanner
|
|
|
6229
6145
|
agent-sdk eval cancel <eval-id> --prod --slug vulnerability-scanner
|
|
6230
6146
|
```
|
|
6231
6147
|
|
|
6232
|
-
Server-side batches use the target
|
|
6233
|
-
|
|
6234
|
-
|
|
6148
|
+
Server-side batches use the target's discovered cases and return an eval
|
|
6149
|
+
ID for `status` or `cancel`. Local reporter and concurrency flags don't
|
|
6150
|
+
apply to `--url` or `--prod` runs.
|
|
6235
6151
|
|
|
6236
6152
|
## Related
|
|
6237
6153
|
|
|
6238
|
-
- [Evals guide](/docs/evals.md)
|
|
6239
|
-
- [CLI reference](/docs/reference/cli.md#eval)
|
|
6240
|
-
- [Sessions](/docs/reference/sessions.md)
|
|
6241
|
-
- [Artifacts](/docs/reference/artifacts.md)
|
|
6242
|
-
`taggedArtifact`
|
|
6154
|
+
- [Evals guide](/docs/evals.md)
|
|
6155
|
+
- [CLI reference](/docs/reference/cli.md#eval)
|
|
6156
|
+
- [Sessions](/docs/reference/sessions.md)
|
|
6157
|
+
- [Artifacts](/docs/reference/artifacts.md)
|
|
6243
6158
|
|
|
6244
6159
|
---
|
|
6245
6160
|
|
|
@@ -6277,10 +6192,10 @@ The extension validates its configuration while the project loads.
|
|
|
6277
6192
|
Missing or mistyped settings fail `agent-sdk validate` before a turn
|
|
6278
6193
|
can call the contributed code.
|
|
6279
6194
|
|
|
6280
|
-
Extension instructions are appended to the agent's
|
|
6281
|
-
agent still needs its own `agent/instructions.md`.
|
|
6195
|
+
Extension instructions are appended to the root agent's instructions.
|
|
6196
|
+
The root agent still needs its own `agent/instructions.md`.
|
|
6282
6197
|
|
|
6283
|
-
##
|
|
6198
|
+
## Inspect a mount
|
|
6284
6199
|
|
|
6285
6200
|
Run discovery after mounting or upgrading an extension:
|
|
6286
6201
|
|
|
@@ -6368,18 +6283,14 @@ server. OAuth-backed plugin servers use
|
|
|
6368
6283
|
[Host MCP OAuth](/docs/guides/mcp-oauth.md); transport and tool-filter
|
|
6369
6284
|
details live in [MCP connections](/docs/reference/connections.md).
|
|
6370
6285
|
|
|
6371
|
-
##
|
|
6372
|
-
|
|
6373
|
-
Share capabilities that can safely join another agent under a
|
|
6374
|
-
namespace:
|
|
6286
|
+
## Extension contents
|
|
6375
6287
|
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6288
|
+
| Ships under the namespace | Ignored |
|
|
6289
|
+
| --- | --- |
|
|
6290
|
+
| Instructions, tools, skills, MCP and host connections | `agent.ts`, storage, OpenTelemetry |
|
|
6291
|
+
| Hooks, channels, schedules, and subagents | Playground code, custom sandbox backends |
|
|
6292
|
+
| Artifact kinds and workspace seed files | Nested extensions |
|
|
6379
6293
|
|
|
6380
|
-
Agent-wide configuration does not compose through a mount.
|
|
6381
|
-
`agent.ts`, storage, OpenTelemetry, playground code, custom sandbox
|
|
6382
|
-
backends, and nested extensions are ignored in an extension package;
|
|
6383
6294
|
`agent-sdk validate` reports unsupported paths.
|
|
6384
6295
|
|
|
6385
6296
|
## Build an extension
|
|
@@ -6446,18 +6357,16 @@ Source: /docs/reference/hooks.md
|
|
|
6446
6357
|
|
|
6447
6358
|
# Hooks
|
|
6448
6359
|
|
|
6449
|
-
A hook subscribes to
|
|
6450
|
-
after each event is recorded: an audit line, a metric, a
|
|
6451
|
-
transcript
|
|
6452
|
-
|
|
6453
|
-
|
|
6360
|
+
A hook subscribes to selected session events and can run a side effect
|
|
6361
|
+
after each matching event is recorded: an audit line, a metric, a
|
|
6362
|
+
transcript copy, or derived state. Hooks run for every session of the
|
|
6363
|
+
agent, on local and cloud turns alike. They cannot change the turn, the
|
|
6364
|
+
prompt, or the reply; a handler that throws is logged and skipped.
|
|
6454
6365
|
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
happen before the model runs or must fail a turn; see
|
|
6460
|
-
[When not to use a hook](#when-not-to-use-a-hook).
|
|
6366
|
+
Treat the event as read-only. Later subscribers see the same object.
|
|
6367
|
+
That makes hooks safe to add to a production agent, and the wrong
|
|
6368
|
+
surface for anything that must run before the model or must fail a
|
|
6369
|
+
turn; see [Hook boundaries](#hook-boundaries).
|
|
6461
6370
|
|
|
6462
6371
|
`defineHook` is unrelated to
|
|
6463
6372
|
[Cursor Agent hooks](https://cursor.com/docs/agent/hooks), the
|
|
@@ -6506,95 +6415,54 @@ later sessions to read. Delete the file to opt out.
|
|
|
6506
6415
|
## Events and payloads
|
|
6507
6416
|
|
|
6508
6417
|
Keys are event types from the
|
|
6509
|
-
[event vocabulary](/docs/reference/sessions.md#
|
|
6418
|
+
[event vocabulary](/docs/reference/sessions.md#stream-events), or `"*"`
|
|
6510
6419
|
for every event. A typed key narrows `event.data`; a `"*"` handler
|
|
6511
6420
|
receives the union, so switch on `event.type`. Every event carries the
|
|
6512
6421
|
stream envelope `{ type, index, sessionId, turnId?, at, data }`, with
|
|
6513
|
-
`turnId` set on turn-scoped events.
|
|
6514
|
-
|
|
6515
|
-
The payloads hooks read most often:
|
|
6422
|
+
`turnId` set on turn-scoped events. Skip `*.appended` deltas when you
|
|
6423
|
+
want the final text; `message.completed` already has it.
|
|
6516
6424
|
|
|
6517
6425
|
| Event | `event.data` |
|
|
6518
6426
|
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
6519
6427
|
| `message.received` | `{ text }` |
|
|
6520
6428
|
| `turn.completed` | `{ result?, usage?, cost? }`. `usage` has `inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, and optional `reasoningTokens`. `cost` has `totalUsd` and the `model` it was priced against |
|
|
6521
|
-
| `turn.failed` | `{ message }`
|
|
6522
|
-
| `actions.requested` | `{ calls: [{ callId, toolName, args? }] }`.
|
|
6523
|
-
| `action.result` | `{ callId, toolName, output?, isError, stubbed? }`. `stubbed` means a dry-run session answered a write without running it
|
|
6429
|
+
| `turn.failed` | `{ message, status? }`. `status` is `"error"` or `"cancelled"` when present |
|
|
6430
|
+
| `actions.requested` | `{ calls: [{ callId, toolName, args?, parentCallId? }], parentCallId? }`. `parentCallId` marks subagent work |
|
|
6431
|
+
| `action.result` | `{ callId, toolName, output?, isError, stubbed?, parentCallId? }`. `stubbed` means a dry-run session answered a write without running it |
|
|
6524
6432
|
|
|
6525
6433
|
The types are `SessionEvent`, `SessionEventType`, and `HookContext`,
|
|
6526
6434
|
exported from `@cursor/july`.
|
|
6527
6435
|
|
|
6528
6436
|
## Handler context
|
|
6529
6437
|
|
|
6530
|
-
| Member | What it is
|
|
6531
|
-
| --------------------------------------------------- |
|
|
6532
|
-
| `ctx.session` | Read-only session info: `id`, `channelId`, `mode` (`chat` or `task`), `purpose` (`live` or `eval`), `auth`, plus `title` and `sdkAgentId` when set
|
|
6533
|
-
| `ctx.agent` | `{ name }` of the agent the event belongs to
|
|
6534
|
-
| `ctx.channel` | `{ id, continuationToken }`. The token is `null` when the session can't take follow-ups
|
|
6535
|
-
| `ctx.host.kv` | Durable JSON, shared by every session of the agent
|
|
6536
|
-
| `ctx.host.files` | Durable files, bound to this session. Pass `{ scope: "deployment" }` for agent-wide files
|
|
6537
|
-
| `ctx.host.otel` | Counters, histograms, and tags, attributed to this session
|
|
6538
|
-
| `ctx.host.mcp`, `ctx.host.github`, `ctx.host.slack` | The same shared clients tools get
|
|
6539
|
-
| `ctx.host.reminders` | Per-session [reminders](/docs/reference/schedules.md), the same API tools get
|
|
6540
|
-
| `ctx.artifacts` | Session-bound [artifacts](/docs/reference/artifacts.md) facade: `tag` fills in `sessionId` and `turnId`
|
|
6541
|
-
| `ctx.stateRoot` | Absolute path of the local state root. It resets when a hosted deployment is replaced; keep derived state in `kv` or `files`
|
|
6542
|
-
|
|
6543
|
-
##
|
|
6544
|
-
|
|
6545
|
-
A hook runs after the event is
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
- A slow handler holds up the next event's handlers for that session,
|
|
6555
|
-
not the model. Keep handlers short and queue anything slow.
|
|
6556
|
-
- Hooks fire for eval sessions too. Check
|
|
6557
|
-
`ctx.session.purpose === "eval"` before metering or paging.
|
|
6558
|
-
|
|
6559
|
-
Each event reaches a hook at most once. A restart doesn't replay the log
|
|
6560
|
-
into hooks, so a mirror needs no dedupe, and the event log rather than
|
|
6561
|
-
the hook's copy is the source of truth.
|
|
6562
|
-
|
|
6563
|
-
## Hooks, channel events, or evals?
|
|
6564
|
-
|
|
6565
|
-
All of them consume the same stream, for different jobs:
|
|
6566
|
-
|
|
6567
|
-
| | Hooks | Channel `events` | Evals |
|
|
6568
|
-
| ------------------ | ----------------------------------------------- | ----------------------------------------------------------------- | --------------------------------- |
|
|
6569
|
-
| Scope | every session of the agent | sessions the channel owns | one test turn |
|
|
6570
|
-
| Job | observe: audit, metrics, mirrors, derived state | deliver: replies back to the channel's surface | assert: gates over the trajectory |
|
|
6571
|
-
| Context | `ctx.host`, `ctx.artifacts`, session info | `channel.state`, `setContinuationToken`, `ctx.host`, session info | the `t` assertion helpers |
|
|
6572
|
-
| Can affect the run | no | yes, it owns the surface | n/a |
|
|
6573
|
-
| Authored at | `agent/hooks/*.ts` | channel config | `evals/**/*.eval.ts` |
|
|
6574
|
-
|
|
6575
|
-
## When not to use a hook
|
|
6576
|
-
|
|
6577
|
-
| You want to | Use instead |
|
|
6578
|
-
| ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
6579
|
-
| Add context before the model runs | The channel's `send` message and `workspaceFiles`, `instructions.md`, skills, or `sandbox/workspace/` seed files |
|
|
6580
|
-
| Reply on Slack, comment on a PR, or post any other delivery | The channel's `events` map, or the Slack and GitHub packs |
|
|
6581
|
-
| Show PR progress (merge-box check, sticky banner) | `githubChannel({ progress: { commitStatus, banner } })`; see the [PR autofixer](/docs/templates/pr-autofixer.md) |
|
|
6582
|
-
| Block, approve, or rewrite a tool call | [`needsApproval`](/docs/reference/tools.md#gate-a-tool-on-human-approval) on the tool |
|
|
6583
|
-
| Act on the final assistant text, reject it for a same-turn repair, or fail a bad turn | `defineResult` |
|
|
6584
|
-
| Gate a change on behavior | [Evals](/docs/evals.md) |
|
|
6585
|
-
|
|
6586
|
-
## Patterns
|
|
6587
|
-
|
|
6588
|
-
Usage metering is the [authoring example](#author-a-hook). Three more:
|
|
6589
|
-
|
|
6590
|
-
### Alert on failure
|
|
6438
|
+
| Member | What it is |
|
|
6439
|
+
| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
6440
|
+
| `ctx.session` | Read-only session info: `id`, `channelId`, `mode` (`chat` or `task`), `purpose` (`live` or `eval`), `auth`, plus `title` and `sdkAgentId` when set |
|
|
6441
|
+
| `ctx.agent` | `{ name }` of the agent the event belongs to |
|
|
6442
|
+
| `ctx.channel` | `{ id, continuationToken }`. The token is `null` when the session can't take follow-ups |
|
|
6443
|
+
| `ctx.host.kv` | Durable JSON, shared by every session of the agent. Prefix keys with `ctx.session.id` for per-session state |
|
|
6444
|
+
| `ctx.host.files` | Durable files, bound to this session. Pass `{ scope: "deployment" }` for agent-wide files |
|
|
6445
|
+
| `ctx.host.otel` | Counters, histograms, and tags, attributed to this session |
|
|
6446
|
+
| `ctx.host.mcp`, `ctx.host.github`, `ctx.host.slack` | The same shared clients tools get |
|
|
6447
|
+
| `ctx.host.reminders` | Per-session [reminders](/docs/reference/schedules.md#reminders), the same API tools get |
|
|
6448
|
+
| `ctx.artifacts` | Session-bound [artifacts](/docs/reference/artifacts.md) facade: `tag` fills in `sessionId` and `turnId` |
|
|
6449
|
+
| `ctx.stateRoot` | Absolute path of the local state root. It resets when a hosted deployment is replaced; keep derived state in `kv` or `files` |
|
|
6450
|
+
|
|
6451
|
+
## Hook dispatch
|
|
6452
|
+
|
|
6453
|
+
A hook runs after the event is recorded. It never delays the model and
|
|
6454
|
+
never sees an event that wasn't recorded.
|
|
6455
|
+
|
|
6456
|
+
| Rule | What happens |
|
|
6457
|
+
| --- | --- |
|
|
6458
|
+
| Same session | Events dispatch one at a time |
|
|
6459
|
+
| Eval sessions | The same stream fires; skip metering or paging when `ctx.session.purpose === "eval"` |
|
|
6460
|
+
| Host restart | Recorded events are not replayed into hooks, so a mirror needs no dedupe |
|
|
6461
|
+
| Slow handler | Holds the next event's handlers on that session, not the model. Keep handlers short and queue anything slow |
|
|
6591
6462
|
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
process starts, so a module-scope read stays empty. Give the call a
|
|
6596
|
-
timeout, since a stalled request holds up later handlers on that
|
|
6597
|
-
session.
|
|
6463
|
+
Read hosted secrets inside the handler, not at module scope. Give
|
|
6464
|
+
outbound calls a timeout; a stalled request holds later handlers on that
|
|
6465
|
+
session. Skip cancelled turns when paging; they record interrupted work.
|
|
6598
6466
|
|
|
6599
6467
|
```ts
|
|
6600
6468
|
// agent/hooks/page-on-failure.ts
|
|
@@ -6607,7 +6475,7 @@ export default defineHook({
|
|
|
6607
6475
|
if (
|
|
6608
6476
|
pagerUrl === undefined ||
|
|
6609
6477
|
ctx.session.purpose === "eval" ||
|
|
6610
|
-
event.data.
|
|
6478
|
+
event.data.status === "cancelled"
|
|
6611
6479
|
) {
|
|
6612
6480
|
return;
|
|
6613
6481
|
}
|
|
@@ -6627,78 +6495,47 @@ export default defineHook({
|
|
|
6627
6495
|
});
|
|
6628
6496
|
```
|
|
6629
6497
|
|
|
6630
|
-
|
|
6498
|
+
## Hooks vs channels vs evals
|
|
6631
6499
|
|
|
6632
|
-
|
|
6633
|
-
`*.appended` deltas: they arrive per token, and `message.completed`
|
|
6634
|
-
carries the final text. Session scope keeps transcripts apart without a
|
|
6635
|
-
session id in the path. The mirror holds reasoning text and raw tool
|
|
6636
|
-
arguments and outputs, so pick the store accordingly, and write to your
|
|
6637
|
-
own store instead when you need cross-session queries.
|
|
6500
|
+
All three consume the same stream, for different jobs:
|
|
6638
6501
|
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
if (event.type.endsWith(".appended")) {
|
|
6647
|
-
return;
|
|
6648
|
-
}
|
|
6649
|
-
const name = String(event.index).padStart(6, "0");
|
|
6650
|
-
await ctx.host.files.write(
|
|
6651
|
-
`transcript/${name}.json`,
|
|
6652
|
-
JSON.stringify(event)
|
|
6653
|
-
);
|
|
6654
|
-
},
|
|
6655
|
-
},
|
|
6656
|
-
});
|
|
6657
|
-
```
|
|
6658
|
-
|
|
6659
|
-
### Keep derived state across a replace
|
|
6660
|
-
|
|
6661
|
-
Write it to `ctx.host.kv` under a session-prefixed key; a tool reads it
|
|
6662
|
-
back with `ctx.host.kv.get`.
|
|
6502
|
+
| | Hooks | Channel `events` | Evals |
|
|
6503
|
+
| ------------------ | ----------------------------------------------- | ----------------------------------------------------------------- | --------------------------------- |
|
|
6504
|
+
| Scope | every session of the agent | sessions the channel owns | one test turn |
|
|
6505
|
+
| Job | observe: audit, metrics, mirrors, derived state | deliver: replies back to the channel's surface | assert: gates over the trajectory |
|
|
6506
|
+
| Context | `ctx.host`, `ctx.artifacts`, session info | `channel.state`, `setContinuationToken`, `ctx.host`, session info | the `t` assertion helpers |
|
|
6507
|
+
| Can affect the run | no | yes, it owns the surface | n/a |
|
|
6508
|
+
| Authored at | `agent/hooks/*.ts` | channel config | `evals/**/*.eval.ts` |
|
|
6663
6509
|
|
|
6664
|
-
|
|
6665
|
-
// agent/hooks/last-result.ts
|
|
6666
|
-
import { defineHook } from "@cursor/july/hooks";
|
|
6510
|
+
## Hook boundaries
|
|
6667
6511
|
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
},
|
|
6677
|
-
});
|
|
6678
|
-
```
|
|
6512
|
+
| You want to | Use instead |
|
|
6513
|
+
| ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
6514
|
+
| Add context before the model runs | The channel's `send` message and `workspaceFiles`, `instructions.md`, skills, or `sandbox/workspace/` seed files |
|
|
6515
|
+
| Reply on Slack, comment on a PR, or post any other delivery | The channel's `events` map, or the Slack and GitHub packs |
|
|
6516
|
+
| Show PR progress (merge-box check, sticky banner) | `githubChannel({ progress: { commitStatus, banner } })`; see the [PR autofixer](/docs/templates/pr-autofixer.md) |
|
|
6517
|
+
| Block, approve, or rewrite a tool call | [`needsApproval`](/docs/reference/tools.md#gate-a-tool-on-human-approval) on the tool |
|
|
6518
|
+
| Act on the final assistant text, reject it for a same-turn repair, or fail a bad turn | `defineResult` |
|
|
6519
|
+
| Gate a change on behavior | [Evals](/docs/evals.md) |
|
|
6679
6520
|
|
|
6680
|
-
## Test
|
|
6521
|
+
## Test a hook
|
|
6681
6522
|
|
|
6682
6523
|
A hook definition is a plain object, so a unit test calls
|
|
6683
6524
|
`hook.events["turn.completed"]` directly with an event and a stub
|
|
6684
6525
|
`HookContext`. Discovery skips `*.test.ts`, so the test can live next to
|
|
6685
6526
|
the hook.
|
|
6686
6527
|
|
|
6687
|
-
|
|
6528
|
+
| Command | What it reports |
|
|
6529
|
+
| --- | --- |
|
|
6530
|
+
| `agent-sdk validate --dir .` | Discovery errors and the empty-handlers warning |
|
|
6531
|
+
| `agent-sdk info --dir . --json` | Loaded hooks under `agents[].hooks` |
|
|
6532
|
+
| `agent-sdk run --dir . --message "…"` | Serve log on stderr, including `hook "<name>" handler for <event> threw: …` |
|
|
6688
6533
|
|
|
6689
|
-
|
|
6690
|
-
empty-handlers warning.
|
|
6691
|
-
- `agent-sdk info --dir . --json` lists the loaded hooks under
|
|
6692
|
-
`agents[].hooks`.
|
|
6693
|
-
- Send a turn with `agent-sdk dev` or `agent-sdk run --dir . --message "…"`
|
|
6694
|
-
and watch the serve log for
|
|
6695
|
-
`hook "<name>" handler for <event> threw: …`. `run` prints that log on
|
|
6696
|
-
stderr. On hosting, read it with [`agent-sdk logs`](/docs/reference/cli.md#logs).
|
|
6534
|
+
On hosting, read the same log with [`agent-sdk logs`](/docs/reference/cli.md#logs).
|
|
6697
6535
|
|
|
6698
|
-
##
|
|
6699
|
-
|
|
6700
|
-
Continue with these pages:
|
|
6536
|
+
## Related
|
|
6701
6537
|
|
|
6538
|
+
- [Hooks guide](/docs/guides/hooks.md): meter usage and page on failure
|
|
6702
6539
|
- [Sessions and streaming](/docs/reference/sessions.md): the event vocabulary hooks observe
|
|
6703
6540
|
- [OpenTelemetry](/docs/guides/opentelemetry.md): OTLP traces and metrics
|
|
6704
6541
|
from the same event stream
|
|
@@ -6710,34 +6547,33 @@ Continue with these pages:
|
|
|
6710
6547
|
|
|
6711
6548
|
Source: /docs/reference/http-api.md
|
|
6712
6549
|
|
|
6713
|
-
# HTTP API
|
|
6550
|
+
# HTTP API
|
|
6551
|
+
|
|
6552
|
+
Agent SDK hosts expose one public HTTP surface. In the default
|
|
6553
|
+
multi-agent layout, each agent uses `/<slug>/v1/*`; `--mode single`
|
|
6554
|
+
serves the same routes at `/v1/*`. Routes use the agent's HTTP auth
|
|
6555
|
+
chain, and session-owned resources return `403` to another principal.
|
|
6714
6556
|
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6557
|
+
Unless a section says otherwise, the default auth policy is
|
|
6558
|
+
`localDevStrict()`. `--bearer-token` replaces it with bearer auth, and
|
|
6559
|
+
`--allow-anonymous` replaces it with anonymous access. Built-in JSON
|
|
6560
|
+
routes use `{ ok: false, error: "<code>", message? }` for errors; MCP
|
|
6561
|
+
uses JSON-RPC, and custom channel handlers define their own responses.
|
|
6720
6562
|
|
|
6721
|
-
|
|
6722
|
-
default is `localDevStrict()` (loopback only), replaced by `bearerAuth` under
|
|
6723
|
-
`--bearer-token` or `allowAll()` under `--allow-anonymous`. Session
|
|
6724
|
-
routes also require the caller to be the session's owner (`403`
|
|
6725
|
-
otherwise). Errors return JSON
|
|
6726
|
-
`{ ok: false, error: "<code>", message? }` with a matching HTTP status.
|
|
6563
|
+
## Host routes
|
|
6727
6564
|
|
|
6728
|
-
|
|
6565
|
+
These routes live at the host root in multi-agent mode. The index routes
|
|
6566
|
+
exist only when the playground is enabled.
|
|
6729
6567
|
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6568
|
+
| Route | Contract |
|
|
6569
|
+
| --- | --- |
|
|
6570
|
+
| `GET /` | HTML index of mounted agents; no auth |
|
|
6571
|
+
| `GET /v1/agents` | JSON index of mounted agents; no auth |
|
|
6572
|
+
| `GET /docs`, `GET /docs/*` | Documentation site in either layout; no auth |
|
|
6573
|
+
| `GET /v1/health` | Host liveness; no auth |
|
|
6734
6574
|
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
| `GET /` | A web index of every mounted agent, linking to playgrounds (playground only) |
|
|
6738
|
-
| `GET /v1/agents` | The JSON index of mounted agents (playground only, no auth) |
|
|
6739
|
-
| `GET /docs`, `GET /docs/*` | This documentation, served as a static site (both layouts, no auth) |
|
|
6740
|
-
| `GET /v1/health` | Host-level liveness, no auth |
|
|
6575
|
+
`--no-playground` removes the two index routes. `--no-docs` removes the
|
|
6576
|
+
documentation site.
|
|
6741
6577
|
|
|
6742
6578
|
## Start a session
|
|
6743
6579
|
|
|
@@ -6751,18 +6587,18 @@ curl -X POST http://127.0.0.1:3000/<slug>/v1/session \
|
|
|
6751
6587
|
# "playgroundUrl":"…?sessionId=ses_…","traceUrl":"…/v1/session/ses_…/events"}
|
|
6752
6588
|
```
|
|
6753
6589
|
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
and `playgroundUrl` deep-links the session in the playground.
|
|
6590
|
+
Once accepted, the response returns `sessionId` for inspection and
|
|
6591
|
+
`continuationToken` for follow-ups; follow the stream for progress.
|
|
6757
6592
|
|
|
6758
|
-
| Body field |
|
|
6593
|
+
| Body field | Contract |
|
|
6759
6594
|
| --- | --- |
|
|
6760
6595
|
| `message` | Required user message |
|
|
6761
|
-
| `title` |
|
|
6596
|
+
| `title` | Display title |
|
|
6762
6597
|
| `dryRun` | Run read tools and stub write tools |
|
|
6763
|
-
| `asOf` | ISO-8601 instant with a timezone
|
|
6764
|
-
| `workspaceFiles` |
|
|
6598
|
+
| `asOf` | ISO-8601 instant with a timezone; sets `ctx.now()` and rejects omitted, relative, or later declared tool time arguments. Invalid values return `400` |
|
|
6599
|
+
| `workspaceFiles` | Relative files added to the session workspace |
|
|
6765
6600
|
| `cloud` | Per-session cloud options merged over the agent defaults |
|
|
6601
|
+
| `purpose` | Use `"eval"` to mark regression traffic |
|
|
6766
6602
|
|
|
6767
6603
|
## Send a follow-up
|
|
6768
6604
|
|
|
@@ -6774,15 +6610,15 @@ curl -X POST http://127.0.0.1:3000/<slug>/v1/session/ses_… \
|
|
|
6774
6610
|
-d '{"continuationToken":"http:…","message":"Make it shorter."}'
|
|
6775
6611
|
```
|
|
6776
6612
|
|
|
6777
|
-
|
|
6778
|
-
Each accepted follow-up rotates the token
|
|
6779
|
-
|
|
6780
|
-
|
|
6613
|
+
The route accepts any chat session, including one created by a custom
|
|
6614
|
+
channel. Each accepted follow-up rotates the continuation token and
|
|
6615
|
+
returns the replacement. A message sent to a busy session interrupts
|
|
6616
|
+
the active turn before starting.
|
|
6781
6617
|
|
|
6782
|
-
|
|
6783
|
-
|
|
6618
|
+
The route returns `409` for a stale token or task session, and `403`
|
|
6619
|
+
when the caller doesn't own the session.
|
|
6784
6620
|
|
|
6785
|
-
## Stream
|
|
6621
|
+
## Stream or replay session events
|
|
6786
6622
|
|
|
6787
6623
|
`GET /v1/session/:sessionId/stream` is the live NDJSON feed.
|
|
6788
6624
|
|
|
@@ -6790,44 +6626,36 @@ follow-ups. Expect `403` when the caller is not the session owner.
|
|
|
6790
6626
|
curl -N 'http://127.0.0.1:3000/<slug>/v1/session/ses_…/stream?startIndex=0'
|
|
6791
6627
|
```
|
|
6792
6628
|
|
|
6793
|
-
|
|
6794
|
-
default
|
|
6795
|
-
|
|
6796
|
-
resume without duplicates. The stream is durable and reconnectable. For
|
|
6797
|
-
the vocabulary, see
|
|
6798
|
-
[Sessions](/docs/reference/sessions.md#which-events-can-i-stream).
|
|
6629
|
+
The route replays one event per line from `startIndex`, then follows new
|
|
6630
|
+
events. The default `0` replays the full stream. To reconnect without
|
|
6631
|
+
duplicates, pass the last index you received plus one.
|
|
6799
6632
|
|
|
6800
6633
|
`GET /v1/session/:sessionId/events` returns a one-shot NDJSON dump.
|
|
6801
|
-
Pass `?format=json` for `{ sessionId, events, playgroundUrl }`.
|
|
6802
|
-
|
|
6803
|
-
## Stop and list
|
|
6634
|
+
Pass `?format=json` for `{ sessionId, events, playgroundUrl }`. See
|
|
6635
|
+
[Stream events](/docs/reference/sessions.md#stream-events) for the event vocabulary.
|
|
6804
6636
|
|
|
6805
|
-
|
|
6806
|
-
sending a new message. `GET /v1/sessions` lists sessions owned by the
|
|
6807
|
-
calling principal. Under `serve --dev` on loopback it includes all
|
|
6808
|
-
sessions, which is how webhook and schedule sessions show up in the
|
|
6809
|
-
playground.
|
|
6637
|
+
## Manage sessions
|
|
6810
6638
|
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
`
|
|
6814
|
-
|
|
6815
|
-
`
|
|
6816
|
-
session routes and returns `404` for an unknown session. The
|
|
6817
|
-
[`agent-sdk cost`](/docs/reference/cli.md#cost) command reports the same data.
|
|
6639
|
+
| Route | Contract |
|
|
6640
|
+
| --- | --- |
|
|
6641
|
+
| `POST /v1/session/:sessionId/stop` | Interrupt the active turn without sending another message |
|
|
6642
|
+
| `GET /v1/sessions` | List sessions owned by the caller |
|
|
6643
|
+
| `GET /v1/session/:sessionId/cost` | Return per-turn token usage and estimated cost |
|
|
6818
6644
|
|
|
6819
|
-
|
|
6645
|
+
On loopback under `serve --dev`, the session list includes every
|
|
6646
|
+
principal so webhook and schedule sessions appear in the playground.
|
|
6647
|
+
The cost route returns `404` for an unknown session.
|
|
6820
6648
|
|
|
6821
|
-
|
|
6649
|
+
## Resolve tool approvals
|
|
6822
6650
|
|
|
6823
|
-
| Route
|
|
6824
|
-
|
|
|
6825
|
-
| `GET /v1/session/:sessionId/approvals`
|
|
6826
|
-
| `POST /v1/session/:sessionId/approvals/:callId` | Resolve one
|
|
6651
|
+
| Route | Contract |
|
|
6652
|
+
| --- | --- |
|
|
6653
|
+
| `GET /v1/session/:sessionId/approvals` | List pending tool approvals |
|
|
6654
|
+
| `POST /v1/session/:sessionId/approvals/:callId` | Resolve one with `{"decision":"approve"}` or `{"decision":"deny"}` |
|
|
6827
6655
|
|
|
6828
6656
|
For the lifecycle, see [Gate a tool on human approval](/docs/reference/tools.md#gate-a-tool-on-human-approval).
|
|
6829
6657
|
|
|
6830
|
-
## Call a tool
|
|
6658
|
+
## Call a tool without a model turn
|
|
6831
6659
|
|
|
6832
6660
|
`POST /v1/tools/:toolName` runs a server tool with no model turn.
|
|
6833
6661
|
|
|
@@ -6839,133 +6667,118 @@ curl -X POST http://127.0.0.1:3000/<slug>/v1/tools/inspect_pr \
|
|
|
6839
6667
|
# "isError":false,"result":{…},"durationMs":12}
|
|
6840
6668
|
```
|
|
6841
6669
|
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
unknown tools with `404` and the list of available names. For the
|
|
6848
|
-
semantics, see [Tools](/docs/reference/tools.md#call-a-tool-without-a-model-turn).
|
|
6670
|
+
| Body field | Contract |
|
|
6671
|
+
| --- | --- |
|
|
6672
|
+
| `input` | Tool input; defaults to `{}` |
|
|
6673
|
+
| `sessionId` | Bind the call to an existing session |
|
|
6674
|
+
| `continuationToken` | Bind the call by its wire continuation token; mutually exclusive with `sessionId` |
|
|
6849
6675
|
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
[Tools](/docs/reference/tools.md#call-a-tool-without-a-model-turn).
|
|
6676
|
+
Omit both identifiers for an unbound call. Agent-execution tools return
|
|
6677
|
+
`400`, and an unknown name returns `404` with the available names. See
|
|
6678
|
+
[Tools](/docs/reference/tools.md#call-a-tool-without-a-model-turn) for session
|
|
6679
|
+
binding, busy-session rules, and error codes.
|
|
6855
6680
|
|
|
6856
|
-
## Discovery
|
|
6681
|
+
## Discovery routes
|
|
6857
6682
|
|
|
6858
6683
|
These read-only routes describe the running agent.
|
|
6859
6684
|
|
|
6860
|
-
| Route
|
|
6861
|
-
|
|
|
6862
|
-
| `GET /v1/info`
|
|
6863
|
-
| `GET /v1/tools`
|
|
6864
|
-
| `GET /v1/tools/:name`
|
|
6865
|
-
| `GET /v1/health`
|
|
6866
|
-
| `GET /v1/logs?after=N` |
|
|
6685
|
+
| Route | Contract |
|
|
6686
|
+
| --- | --- |
|
|
6687
|
+
| `GET /v1/info` | Return the discovered model, tools, skills, connections, subagents, channels, schedules, hooks, and diagnostics |
|
|
6688
|
+
| `GET /v1/tools` | Return live server tools and advertised MCP tools as `{ name, title?, source? }`; bind tenant-scoped listings with `session` or `continuationToken` |
|
|
6689
|
+
| `GET /v1/tools/:name` | Return one tool's description, execution mode, approval and effect rules, schemas, and source |
|
|
6690
|
+
| `GET /v1/health` | Return per-agent liveness; no auth |
|
|
6691
|
+
| `GET /v1/logs?after=N` | Return recent server logs and the next polling cursor |
|
|
6867
6692
|
|
|
6868
|
-
|
|
6693
|
+
An unknown tool name returns `404` with available names. If an MCP
|
|
6694
|
+
connection can't list its tools, the catalog skips that connection and
|
|
6695
|
+
includes it in `connectionErrors`.
|
|
6869
6696
|
|
|
6870
|
-
|
|
6871
|
-
`tag_artifact`. See [Artifacts](/docs/reference/artifacts.md).
|
|
6697
|
+
## List and download artifacts
|
|
6872
6698
|
|
|
6873
|
-
| Route
|
|
6874
|
-
|
|
|
6875
|
-
| `GET /v1/artifacts`
|
|
6876
|
-
| `GET /v1/artifacts/:id/content`
|
|
6699
|
+
| Route | Contract |
|
|
6700
|
+
| --- | --- |
|
|
6701
|
+
| `GET /v1/artifacts` | Return `{ artifacts }`, newest-updated first; filter with `kind`, `sessionId`, and a positive `limit` |
|
|
6702
|
+
| `GET /v1/artifacts/:id/content` | Download an artifact's file or blob as an attachment; return `404` when no content exists |
|
|
6877
6703
|
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
principals, while bearer or custom channel auth keeps strict
|
|
6881
|
-
per-principal isolation.
|
|
6704
|
+
The list follows the same ownership rules as `GET /v1/sessions`. See
|
|
6705
|
+
[Artifacts](/docs/reference/artifacts.md) for tagging and record fields.
|
|
6882
6706
|
|
|
6883
|
-
##
|
|
6707
|
+
## Call custom channel routes
|
|
6884
6708
|
|
|
6885
|
-
Authored routes mount under `/v1/channels/<id>` with
|
|
6886
|
-
and Zod
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
applies. The GitHub channel verifies `X-Hub-Signature-256` when a
|
|
6890
|
-
secret is configured. See [Channels](/docs/reference/channels.md).
|
|
6709
|
+
Authored routes mount under `/v1/channels/<id>` with their declared
|
|
6710
|
+
methods and paths. The host validates their Zod body and query schemas
|
|
6711
|
+
before calling the handler, returning `400` on failure. Each channel's
|
|
6712
|
+
auth chain applies. See [Channels](/docs/reference/channels.md).
|
|
6891
6713
|
|
|
6892
6714
|
## MCP endpoint
|
|
6893
6715
|
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
spec-compliant 405s). The tools are `ask` (delegate a message, bounded
|
|
6897
|
-
waits), `check` (poll a running session), and `call_tool` (deterministic
|
|
6898
|
-
server-tool passthrough, present when the agent has server tools). The
|
|
6899
|
-
route runs the same auth chain as the session API. Peer wiring:
|
|
6900
|
-
[MCP connections](/docs/reference/connections.md#peer-mcp-connection).
|
|
6716
|
+
Both MCP routes use stateless streamable HTTP. Send protocol requests
|
|
6717
|
+
with `POST`; `GET` and `DELETE` return `405`.
|
|
6901
6718
|
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
`/v1/mcp
|
|
6906
|
-
|
|
6719
|
+
| Route | Tools and auth |
|
|
6720
|
+
| --- | --- |
|
|
6721
|
+
| `/v1/mcp` | `ask`, `check`, and `call_tool` when server tools exist; uses the session API auth chain |
|
|
6722
|
+
| `/v1/mcp/tools` | Deterministic server tools only; uses the CLI-level loopback, bearer, or anonymous auth chain |
|
|
6723
|
+
|
|
6724
|
+
See [MCP connections](/docs/reference/connections.md#peer-mcp-connection) to connect
|
|
6725
|
+
one agent to another.
|
|
6907
6726
|
|
|
6908
6727
|
## Playground eval routes
|
|
6909
6728
|
|
|
6910
|
-
The playground Evals tab and
|
|
6729
|
+
The playground Evals tab and remote eval commands use these routes:
|
|
6911
6730
|
|
|
6912
|
-
| Route
|
|
6913
|
-
|
|
|
6914
|
-
| `GET /v1/dev/evals`
|
|
6915
|
-
| `GET /v1/dev/evals/runs`
|
|
6916
|
-
| `POST /v1/dev/evals/runs`
|
|
6917
|
-
| `GET /v1/dev/evals/runs/:runId` |
|
|
6918
|
-
| `POST /v1/dev/evals/runs/:runId/cancel` | Cancel
|
|
6731
|
+
| Route | Contract |
|
|
6732
|
+
| --- | --- |
|
|
6733
|
+
| `GET /v1/dev/evals` | List discovered cases and eval config |
|
|
6734
|
+
| `GET /v1/dev/evals/runs` | List recent run snapshots, newest first |
|
|
6735
|
+
| `POST /v1/dev/evals/runs` | Start `{ filterIds?, tags?, timeoutMs?, verbose? }`; return `202`, `404` for no match, or `409` while another run is active |
|
|
6736
|
+
| `GET /v1/dev/evals/runs/:runId` | Return progress and the final snapshot |
|
|
6737
|
+
| `POST /v1/dev/evals/runs/:runId/cancel` | Cancel an active run; return `404` when unknown or `409` when no longer running |
|
|
6919
6738
|
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
use OR semantics. When both fields are present, a case must match one
|
|
6924
|
-
entry from each field. Listed runs persist across restarts when
|
|
6925
|
-
durable storage is configured. Otherwise they are
|
|
6926
|
-
process-memory only.
|
|
6739
|
+
Poll the run route until its status is `completed`, `failed`, or
|
|
6740
|
+
`cancelled`. Entries within `filterIds` and `tags` use OR semantics;
|
|
6741
|
+
when both fields are present, a case must match each group.
|
|
6927
6742
|
|
|
6928
6743
|
## Dev-mode routes
|
|
6929
6744
|
|
|
6930
6745
|
These routes exist only under `serve --dev`.
|
|
6931
6746
|
|
|
6932
|
-
| Route
|
|
6933
|
-
|
|
|
6747
|
+
| Route | Contract |
|
|
6748
|
+
| --- | --- |
|
|
6934
6749
|
| `POST /v1/dev/schedules/:scheduleId` | Dispatch a schedule by hand, exactly once. Returns `{scheduleId, sessionIds}` |
|
|
6935
|
-
| `GET /v1/dev/reminders`
|
|
6936
|
-
| `POST /v1/dev/reminders/:reminderId` | Fire a reminder by hand
|
|
6750
|
+
| `GET /v1/dev/reminders` | List reminders |
|
|
6751
|
+
| `POST /v1/dev/reminders/:reminderId` | Fire a reminder by hand |
|
|
6937
6752
|
|
|
6938
6753
|
Schedules and reminders never fire automatically in dev mode. These
|
|
6939
|
-
routes
|
|
6754
|
+
routes run them manually.
|
|
6940
6755
|
|
|
6941
6756
|
## Playground assets
|
|
6942
6757
|
|
|
6943
6758
|
`GET /playground` and `GET /playground/assets/:file` serve the
|
|
6944
|
-
playground
|
|
6945
|
-
above and has no privileged surface.
|
|
6759
|
+
playground. `--no-playground` removes both routes.
|
|
6946
6760
|
|
|
6947
6761
|
## Status codes
|
|
6948
6762
|
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
| Code | Meaning here |
|
|
6952
|
-
| ----- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
6953
|
-
| `400` | Schema-invalid body or query, agent-execution tool called on the host, malformed request |
|
|
6954
|
-
| `401` | No auth policy admitted the request |
|
|
6955
|
-
| `403` | Authenticated, but not the session owner |
|
|
6956
|
-
| `404` | Unknown session, tool, schedule, reminder, or eval run; no eval datapoints match a run request |
|
|
6957
|
-
| `405` | Wrong method (GET on the MCP endpoint, say) |
|
|
6958
|
-
| `409` | Stale continuation token, a busy session-bound tool call, a non-followable task session, or an eval run already in progress |
|
|
6959
|
-
| `202` | Accepted for background work (GitHub `{ task }` hooks, eval runs) |
|
|
6763
|
+
Built-in routes use these common status codes.
|
|
6960
6764
|
|
|
6961
|
-
|
|
6765
|
+
| Code | Meaning |
|
|
6766
|
+
| --- | --- |
|
|
6767
|
+
| `400` | Invalid body, query, tool input, or request shape |
|
|
6768
|
+
| `401` | No auth policy admitted the request |
|
|
6769
|
+
| `403` | The caller is authenticated but doesn't own the resource |
|
|
6770
|
+
| `404` | A named resource doesn't exist, or an eval selection matches no cases |
|
|
6771
|
+
| `405` | The route doesn't accept this method |
|
|
6772
|
+
| `409` | The resource state rejects the request, such as a stale token or busy write |
|
|
6773
|
+
| `202` | The request was accepted for asynchronous work |
|
|
6774
|
+
| `500` | A write-effect tool can't create its session workspace (`workspace_unavailable`) |
|
|
6962
6775
|
|
|
6963
|
-
|
|
6776
|
+
## Related
|
|
6964
6777
|
|
|
6965
|
-
- [Sessions
|
|
6966
|
-
|
|
6967
|
-
- [
|
|
6968
|
-
- [Deployment](/docs/deployment.md)
|
|
6778
|
+
- [Sessions](/docs/reference/sessions.md)
|
|
6779
|
+
- [Channels](/docs/reference/channels.md)
|
|
6780
|
+
- [Tools](/docs/reference/tools.md)
|
|
6781
|
+
- [Deployment](/docs/deployment.md)
|
|
6969
6782
|
|
|
6970
6783
|
---
|
|
6971
6784
|
|
|
@@ -6973,19 +6786,17 @@ Source: /docs/reference/instructions.md
|
|
|
6973
6786
|
|
|
6974
6787
|
# Instructions
|
|
6975
6788
|
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6789
|
+
Agent instructions form the always-on system prompt and reach the model
|
|
6790
|
+
on every turn. A root agent requires them; a subagent may inline
|
|
6791
|
+
`instructions` in `agent.ts` instead.
|
|
6979
6792
|
|
|
6980
6793
|
## Authoring forms
|
|
6981
6794
|
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
| Form | Reach for it when |
|
|
6795
|
+
| Form | Use it when |
|
|
6985
6796
|
| --- | --- |
|
|
6986
|
-
| `agent/instructions.md` | Plain Markdown for most agents
|
|
6987
|
-
| `agent/instructions.ts` | Generated prompts. Default-export `defineInstructions({ markdown })` or a plain string
|
|
6988
|
-
| `agent/instructions/` directory | A long prompt split across files, composed in filename order
|
|
6797
|
+
| `agent/instructions.md` | Plain Markdown for most agents |
|
|
6798
|
+
| `agent/instructions.ts` | Generated prompts. Default-export `defineInstructions({ markdown })` or a plain string |
|
|
6799
|
+
| `agent/instructions/` directory | A long prompt split across files, composed in filename order |
|
|
6989
6800
|
|
|
6990
6801
|
```ts
|
|
6991
6802
|
// agent/instructions.ts
|
|
@@ -6996,22 +6807,17 @@ export default defineInstructions({
|
|
|
6996
6807
|
});
|
|
6997
6808
|
```
|
|
6998
6809
|
|
|
6999
|
-
##
|
|
7000
|
-
|
|
7001
|
-
On the local runtime, instructions land in the session workspace as
|
|
7002
|
-
`AGENTS.md`, and the harness loads them natively. On the cloud runtime,
|
|
7003
|
-
they're prepended to the first prompt, because the cloud VM doesn't
|
|
7004
|
-
share the local session workspace.
|
|
6810
|
+
## Delivery
|
|
7005
6811
|
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
covers
|
|
6812
|
+
Local and cloud turns receive the composed instructions. They aren't
|
|
6813
|
+
written into the session workspace. Parent directories can still
|
|
6814
|
+
contribute ambient `AGENTS.md` and `.cursor` settings; [Agent config:
|
|
6815
|
+
local cwd](/docs/reference/agent-config.md#local-cwd) covers how to control that.
|
|
7010
6816
|
|
|
7011
|
-
##
|
|
6817
|
+
## Contents
|
|
7012
6818
|
|
|
7013
|
-
Keep them a few lines: identity, when to use which tool, output
|
|
7014
|
-
The [quickstart PR approver](/docs/quickstart.md) is the pattern:
|
|
6819
|
+
Keep them a few lines: identity, when to use which tool, and the output
|
|
6820
|
+
shape. The [quickstart PR approver](/docs/quickstart.md) is the pattern:
|
|
7015
6821
|
|
|
7016
6822
|
```md
|
|
7017
6823
|
# PR approver
|
|
@@ -7025,21 +6831,13 @@ You review GitHub pull requests. Be specific and brief.
|
|
|
7025
6831
|
End with one sentence: the verdict and why.
|
|
7026
6832
|
```
|
|
7027
6833
|
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
model only sometimes needs belongs in `agent/skills/`, where it loads
|
|
7034
|
-
on demand and keeps the always-on prompt small.
|
|
7035
|
-
|
|
7036
|
-
Instructions are the third lever in the
|
|
7037
|
-
[hillclimbing loop](/docs/hillclimbing.md), after host preparation and evidence
|
|
7038
|
-
shape. If a fixture keeps failing, look there before rewriting prose.
|
|
6834
|
+
Name the tools and the decision rule ("use X before answering about
|
|
6835
|
+
Y"), not general encouragement. State the output contract, including
|
|
6836
|
+
length, format, and fences, so your [evals](/docs/evals.md) can gate it.
|
|
6837
|
+
Put multi-step workflows the model only sometimes needs in
|
|
6838
|
+
`agent/skills/`; they load on demand and keep the always-on prompt small.
|
|
7039
6839
|
|
|
7040
|
-
##
|
|
7041
|
-
|
|
7042
|
-
Continue with these pages:
|
|
6840
|
+
## Related
|
|
7043
6841
|
|
|
7044
6842
|
- [Skills](/docs/reference/skills.md): procedures the model loads only when relevant
|
|
7045
6843
|
- [Agent config](/docs/reference/agent-config.md): the file next to this one
|
|
@@ -7052,55 +6850,38 @@ Source: /docs/reference/playground.md
|
|
|
7052
6850
|
|
|
7053
6851
|
# Playground
|
|
7054
6852
|
|
|
7055
|
-
|
|
6853
|
+
`agent-sdk serve` enables a web playground at
|
|
7056
6854
|
`http://127.0.0.1:3000/<slug>/playground` (or `/playground` in single
|
|
7057
|
-
mode).
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
- **Evals**: list and run filesystem evals from the browser (backed by
|
|
7079
|
-
`/v1/dev/evals`). Schedule hand-dispatch still requires `--dev`.
|
|
7080
|
-
- **The surface**: inspect the discovered tools, skills, subagents, MCP
|
|
7081
|
-
connections, channels, and hooks.
|
|
7082
|
-
- **Custom tool chips**: drop `agent/playground/tools/<toolName>.tsx` to
|
|
7083
|
-
change how that tool renders. Chips compile from the agent tree;
|
|
7084
|
-
an [extension](/docs/reference/extensions.md) cannot contribute them.
|
|
7085
|
-
- **Raw events pane**: flip it on to inspect the event stream.
|
|
7086
|
-
- **Logs tab**: recent server log lines, polled from `GET /v1/logs`.
|
|
7087
|
-
|
|
7088
|
-
In multi-agent mode each agent has its own playground at
|
|
7089
|
-
`/<slug>/playground`, and `/` is an index of them all.
|
|
7090
|
-
|
|
7091
|
-
## Share it beyond localhost
|
|
6855
|
+
mode). In multi-agent mode, each agent has its own playground, and `/`
|
|
6856
|
+
lists them all.
|
|
6857
|
+
|
|
6858
|
+
## Playground surfaces
|
|
6859
|
+
|
|
6860
|
+
| Surface | What you can do |
|
|
6861
|
+
| --- | --- |
|
|
6862
|
+
| Chat | Talk to the agent. Text and reasoning stream live, and tool calls appear inline with their arguments, output, and error state |
|
|
6863
|
+
| Slash commands | Custom channel routes without path parameters become composer commands; GitHub and Slack ingress routes are excluded. A `drive` route becomes `/drive <pr-url>`, with `/help` and autocomplete |
|
|
6864
|
+
| Try | Invoke a custom channel route from the Agent tab. The modal remembers your last body per endpoint, copies curl, and opens a session when the route creates one |
|
|
6865
|
+
| Runs | Browse the sessions you own and eval runs. Search by title or identifier; open sessions in Chat, Trace, or Raw and eval runs in Evals |
|
|
6866
|
+
| Approvals | Parked `needsApproval` tool calls render Approve / Deny buttons |
|
|
6867
|
+
| Evals | List and run filesystem evals from the browser |
|
|
6868
|
+
| Agent | Inspect the discovered tools, skills, subagents, MCP connections, channels, and hooks |
|
|
6869
|
+
| Raw | Inspect the selected session's event stream |
|
|
6870
|
+
| Logs | Recent server log lines, polled from `GET /v1/logs` |
|
|
6871
|
+
|
|
6872
|
+
In `--dev` on loopback, or with `--allow-anonymous`, the session list
|
|
6873
|
+
includes every principal.
|
|
6874
|
+
|
|
6875
|
+
## Remote access
|
|
7092
6876
|
|
|
7093
6877
|
The default `localDevStrict()` auth admits direct loopback calls only
|
|
7094
6878
|
and rejects proxy-forwarding headers, so a tunnel or LAN address won't
|
|
7095
|
-
work
|
|
7096
|
-
until you pass `--bearer-token <secret>` (or
|
|
6879
|
+
work until you pass `--bearer-token <secret>` (or
|
|
7097
6880
|
`serve(dir, { authToken })`). Open the playground on the remote device
|
|
7098
|
-
and paste the token into the token field in the navbar.
|
|
7099
|
-
demo-only alternative for trusted networks.
|
|
6881
|
+
and paste the token into the token field in the navbar.
|
|
6882
|
+
`--allow-anonymous` is the demo-only alternative for trusted networks.
|
|
7100
6883
|
|
|
7101
|
-
##
|
|
7102
|
-
|
|
7103
|
-
Continue with these pages:
|
|
6884
|
+
## Related
|
|
7104
6885
|
|
|
7105
6886
|
- [HTTP API](/docs/reference/http-api.md): the HTTP surface the playground uses
|
|
7106
6887
|
- [Sessions and streaming](/docs/reference/sessions.md): the streams it renders
|
|
@@ -7137,7 +6918,7 @@ to the directory name. When serving multiple agents, the slug is the
|
|
|
7137
6918
|
directory name and must match `[A-Za-z0-9][A-Za-z0-9_-]*` (and not the
|
|
7138
6919
|
reserved `v1`, `playground`, or `docs` segments).
|
|
7139
6920
|
|
|
7140
|
-
## Project
|
|
6921
|
+
## Project tree
|
|
7141
6922
|
|
|
7142
6923
|
Most projects start with this shape.
|
|
7143
6924
|
|
|
@@ -7162,8 +6943,8 @@ my-agent/
|
|
|
7162
6943
|
```
|
|
7163
6944
|
|
|
7164
6945
|
Evals live in `evals/` at the project root, a sibling of `agent/`, never
|
|
7165
|
-
inside it. `agent/evals/` is
|
|
7166
|
-
[Evals](/docs/evals.md).
|
|
6946
|
+
inside it. `agent/evals/` is ignored, and `validate` warns about it.
|
|
6947
|
+
See [Evals](/docs/evals.md).
|
|
7167
6948
|
|
|
7168
6949
|
## Folder reference
|
|
7169
6950
|
|
|
@@ -7181,30 +6962,26 @@ Each path maps to a capability and a reference page.
|
|
|
7181
6962
|
| `agent/extensions/<ns>.ts` or `agent/extensions/<ns>/` | A mounted extension or Cursor plugin; its contributions become `<ns>__<name>` | [Extensions](/docs/reference/extensions.md) |
|
|
7182
6963
|
| `agent/channels/*.ts` | HTTP surfaces beyond the built-in session API; `slack.ts` and `github.ts` use the platform packs | [Channels](/docs/reference/channels.md) |
|
|
7183
6964
|
| `agent/hooks/*.ts` | Observe-only event subscribers, never fatal | [Hooks](/docs/reference/hooks.md) |
|
|
7184
|
-
| `agent/otel.ts` | Factory-only OTLP authoring (`defineOtel`). Public path is env / `serve({ otel })`. | [OpenTelemetry](/docs/guides/opentelemetry.md) |
|
|
7185
|
-
| `agent/storage.ts` | `defineStorage` backend for the durable `host.kv` / `host.files` APIs | None |
|
|
7186
6965
|
| `agent/artifacts.ts` | `defineArtifacts` kinds, the `tag_artifact` opt-in, and retention | [Artifacts](/docs/reference/artifacts.md) |
|
|
7187
6966
|
| `agent/result.ts` | `defineResult` host `commit` on the final assistant text (`throw` or `ctx.reject`) | None |
|
|
7188
6967
|
| `agent/schedules/*` | Cron-driven runs (UTC, 5-field; never auto-fire under `--dev`) | [Schedules](/docs/reference/schedules.md) |
|
|
7189
|
-
| `agent/
|
|
7190
|
-
| `agent/
|
|
6968
|
+
| `agent/reminders/*.ts` | Named reminder handlers that stay armed across restarts | [Schedules](/docs/reference/schedules.md#reminders) |
|
|
6969
|
+
| `agent/sandbox/workspace/**` | Seed files copied into each local session workspace | [Sessions](/docs/reference/sessions.md#local-session-workspace) |
|
|
7191
6970
|
| `agent/lib/` | Import-only shared code, never discovered | None |
|
|
7192
6971
|
| `evals/evals.config.ts` | Shared eval settings (e.g. `maxConcurrency`); required when evals exist | [Evals](/docs/evals.md) |
|
|
7193
6972
|
| `evals/**/*.eval.ts` | Filesystem evals; case id = path under `evals/` | [Evals](/docs/evals.md) |
|
|
7194
6973
|
|
|
7195
|
-
`agent/lib/`
|
|
7196
|
-
|
|
7197
|
-
|
|
6974
|
+
Use `agent/lib/` for shared imports. A `.ts` file in one of the listed
|
|
6975
|
+
discovery folders loads as a definition; unrecognized directories
|
|
6976
|
+
produce a validation warning.
|
|
7198
6977
|
|
|
7199
|
-
##
|
|
6978
|
+
## Inspect discovery
|
|
7200
6979
|
|
|
7201
6980
|
Run `agent-sdk validate --dir .` and `agent-sdk info --dir .`.
|
|
7202
6981
|
`validate` prints diagnostics, and `serve` refuses to start on
|
|
7203
6982
|
error-severity ones. Warnings, such as cloud runtime combined with
|
|
7204
6983
|
local-only capabilities, print but don't block. `info` lists the discovered
|
|
7205
|
-
surface, so a missing tool or channel shows up immediately.
|
|
7206
|
-
there, check the folder reference: the file is usually in the wrong directory
|
|
7207
|
-
or has the wrong extension.
|
|
6984
|
+
surface, so a missing tool or channel shows up immediately.
|
|
7208
6985
|
|
|
7209
6986
|
```bash
|
|
7210
6987
|
agent-sdk validate --dir . # diagnostics; non-zero exit on errors
|
|
@@ -7212,51 +6989,50 @@ agent-sdk info --dir . # human-readable surface
|
|
|
7212
6989
|
agent-sdk info --dir . --json # machine-readable project info (same shape as GET /v1/info)
|
|
7213
6990
|
```
|
|
7214
6991
|
|
|
7215
|
-
##
|
|
7216
|
-
|
|
7217
|
-
Continue with these pages:
|
|
6992
|
+
## Related
|
|
7218
6993
|
|
|
7219
6994
|
- [Agent config](/docs/reference/agent-config.md): the runtime config at the root
|
|
7220
6995
|
- [Tools](/docs/reference/tools.md): add typed actions under `agent/tools/`
|
|
6996
|
+
- [CLI](/docs/reference/cli.md): commands that discover this tree
|
|
7221
6997
|
|
|
7222
6998
|
---
|
|
7223
6999
|
|
|
7224
7000
|
Source: /docs/reference/prompt.md
|
|
7225
7001
|
|
|
7226
|
-
#
|
|
7002
|
+
# Prompt strings
|
|
7227
7003
|
|
|
7228
|
-
|
|
7229
|
-
|
|
7230
|
-
and
|
|
7004
|
+
The `prompt` template tag keeps multi-line strings aligned with the
|
|
7005
|
+
surrounding TypeScript while returning dedented text. Use it for tool
|
|
7006
|
+
descriptions, reminder prompts, channel context, and errors. Import it
|
|
7007
|
+
from the package root or the dedicated entrypoint:
|
|
7231
7008
|
|
|
7232
7009
|
```ts
|
|
7233
7010
|
import { prompt } from "@cursor/july";
|
|
7234
7011
|
// or: import { prompt } from "@cursor/july/prompt";
|
|
7235
7012
|
```
|
|
7236
7013
|
|
|
7237
|
-
##
|
|
7014
|
+
## Dedented strings
|
|
7238
7015
|
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
multiline form stays readable in source.
|
|
7016
|
+
`prompt` returns one string. It removes the common leading whitespace
|
|
7017
|
+
and one newline immediately after the opening backtick.
|
|
7242
7018
|
|
|
7243
7019
|
```ts
|
|
7244
7020
|
throw new Error(prompt`
|
|
7245
|
-
It is outside business hours (Mon
|
|
7021
|
+
It is outside business hours (Mon-Fri 9am-5pm ET).
|
|
7246
7022
|
Use request_author_approval, or pass approval=human_request.
|
|
7247
7023
|
`);
|
|
7248
7024
|
```
|
|
7249
7025
|
|
|
7250
7026
|
Blank lines inside the body are preserved. Relative indentation after the
|
|
7251
|
-
common prefix is
|
|
7027
|
+
common prefix is preserved, so nested lists keep their shape.
|
|
7252
7028
|
|
|
7253
7029
|
When interpolating multi-line values (for example a list of services), give
|
|
7254
7030
|
those lines the same indent as the `prompt` body so dedent stays consistent.
|
|
7255
7031
|
|
|
7256
|
-
##
|
|
7032
|
+
## Line arrays
|
|
7257
7033
|
|
|
7258
|
-
|
|
7259
|
-
|
|
7034
|
+
`prompt.lines` applies the same rules and returns `string[]`, with one
|
|
7035
|
+
entry per line. Use it when an API accepts separate context lines:
|
|
7260
7036
|
|
|
7261
7037
|
```ts
|
|
7262
7038
|
context: prompt.lines`
|
|
@@ -7266,13 +7042,18 @@ context: prompt.lines`
|
|
|
7266
7042
|
`
|
|
7267
7043
|
```
|
|
7268
7044
|
|
|
7045
|
+
## Related
|
|
7046
|
+
|
|
7047
|
+
- [Tools](/docs/reference/tools.md)
|
|
7048
|
+
- [Channels](/docs/reference/channels.md)
|
|
7049
|
+
|
|
7269
7050
|
---
|
|
7270
7051
|
|
|
7271
7052
|
Source: /docs/reference/schedules.md
|
|
7272
7053
|
|
|
7273
7054
|
# Schedules and reminders
|
|
7274
7055
|
|
|
7275
|
-
|
|
7056
|
+
An agent can act without an inbound message in two ways. A schedule is
|
|
7276
7057
|
deploy-time cron: "every weekday at 09:00, summarize open incidents." A
|
|
7277
7058
|
reminder is a runtime wake bound to one conversation: "re-check this
|
|
7278
7059
|
PR's CI in two hours." Schedules live in the filesystem; reminders are
|
|
@@ -7283,10 +7064,9 @@ created by running code.
|
|
|
7283
7064
|
Cron expressions are standard 5-field, evaluated in UTC with minute
|
|
7284
7065
|
granularity.
|
|
7285
7066
|
|
|
7286
|
-
###
|
|
7067
|
+
### Markdown schedules
|
|
7287
7068
|
|
|
7288
|
-
A
|
|
7289
|
-
task:
|
|
7069
|
+
A markdown file with `cron:` frontmatter is a fire-and-forget task:
|
|
7290
7070
|
|
|
7291
7071
|
```md
|
|
7292
7072
|
---
|
|
@@ -7300,10 +7080,10 @@ Each firing starts a task-mode session: the body is the prompt, the
|
|
|
7300
7080
|
session runs to `session.completed` or `session.failed`, and it isn't
|
|
7301
7081
|
followable.
|
|
7302
7082
|
|
|
7303
|
-
###
|
|
7083
|
+
### Schedule handlers
|
|
7304
7084
|
|
|
7305
|
-
`defineSchedule` with a `run` handler
|
|
7306
|
-
|
|
7085
|
+
Use `defineSchedule` with a `run` handler to call tools or hand work into
|
|
7086
|
+
a channel so its delivery events fire:
|
|
7307
7087
|
|
|
7308
7088
|
```ts
|
|
7309
7089
|
import { defineSchedule } from "@cursor/july/schedules";
|
|
@@ -7312,7 +7092,6 @@ import webhook from "../channels/webhook.js";
|
|
|
7312
7092
|
export default defineSchedule({
|
|
7313
7093
|
cron: "*/30 * * * *",
|
|
7314
7094
|
async run({ receive, waitUntil, appAuth, host }) {
|
|
7315
|
-
// optional: await host.mcp.callTool("units", "celsius_to_fahrenheit", { value: 0 });
|
|
7316
7095
|
waitUntil(
|
|
7317
7096
|
receive(webhook, {
|
|
7318
7097
|
message:
|
|
@@ -7331,14 +7110,12 @@ schedule-scoped principal for work the agent does on its own behalf),
|
|
|
7331
7110
|
and `host` (shared services: `host.mcp`, `host.github`, `host.slack`,
|
|
7332
7111
|
`host.reminders`).
|
|
7333
7112
|
|
|
7334
|
-
### Dispatch
|
|
7113
|
+
### Dispatch a schedule
|
|
7335
7114
|
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
In dev (`serve --dev`), schedules never fire automatically. Dispatch one
|
|
7341
|
-
by hand, exactly once, through the same path production uses:
|
|
7115
|
+
| Mode | What fires |
|
|
7116
|
+
| --- | --- |
|
|
7117
|
+
| Production `agent-sdk serve` | Cron cadence. `--no-schedules` disables them. Run them in exactly one process per project |
|
|
7118
|
+
| `serve --dev` | Nothing automatic. Dispatch by hand through the same path production uses |
|
|
7342
7119
|
|
|
7343
7120
|
```bash
|
|
7344
7121
|
curl -X POST http://127.0.0.1:3000/<slug>/v1/dev/schedules/heartbeat
|
|
@@ -7350,104 +7127,67 @@ The playground can dispatch schedules in dev mode too, and
|
|
|
7350
7127
|
|
|
7351
7128
|
## Reminders
|
|
7352
7129
|
|
|
7353
|
-
A reminder is created at runtime and bound to a channel continuation.
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7130
|
+
A reminder is created at runtime and bound to a channel continuation. A
|
|
7131
|
+
prompt reminder wakes that conversation when it fires; a handler reminder
|
|
7132
|
+
runs host code, which can call `followup` to wake it. Recurring reminders
|
|
7133
|
+
behave like `setInterval`, and one-shots behave like `setTimeout`. Prompt
|
|
7134
|
+
and named-handler reminders stay armed across restarts.
|
|
7357
7135
|
|
|
7358
7136
|
```ts
|
|
7359
7137
|
await handle.createReminder({
|
|
7360
7138
|
purpose: "ci_recheck",
|
|
7361
7139
|
channelId: "drive",
|
|
7362
|
-
continuationToken: "pr:
|
|
7363
|
-
delay: "2h",
|
|
7140
|
+
continuationToken: "pr:acme/checkout#42",
|
|
7141
|
+
delay: "2h",
|
|
7364
7142
|
prompt: "Re-check CI. Only act if still failing.",
|
|
7365
7143
|
until: "Cancel once CI is green or the PR is merged.",
|
|
7366
7144
|
});
|
|
7367
7145
|
```
|
|
7368
7146
|
|
|
7369
|
-
|
|
7147
|
+
When host code must decide what happens on each tick, author a named
|
|
7148
|
+
handler and pass its default export with serializable `args`:
|
|
7370
7149
|
|
|
7371
7150
|
```ts
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
channelId: "drive",
|
|
7375
|
-
continuationToken: "pr:owner/repo#1",
|
|
7376
|
-
every: "30m",
|
|
7377
|
-
async run({ fireCount, followup }) {
|
|
7378
|
-
if (fireCount >= 3) {
|
|
7379
|
-
return { action: "stop" };
|
|
7380
|
-
}
|
|
7151
|
+
// agent/reminders/ci_recheck.ts
|
|
7152
|
+
import { defineReminder } from "@cursor/july/reminders";
|
|
7381
7153
|
|
|
7154
|
+
export default defineReminder({
|
|
7155
|
+
async run({ args, followup }) {
|
|
7382
7156
|
await followup({
|
|
7383
|
-
message:
|
|
7157
|
+
message: `Re-check CI for ${String(args.prUrl)}. Report only if the status changed.`,
|
|
7384
7158
|
});
|
|
7385
7159
|
return { action: "delivered" };
|
|
7386
7160
|
},
|
|
7387
7161
|
});
|
|
7388
7162
|
```
|
|
7389
7163
|
|
|
7390
|
-
This reminder wakes the conversation three times, then stops itself.
|
|
7391
|
-
|
|
7392
|
-
The same API is `host.reminders` on channel handlers, tools, and
|
|
7393
|
-
schedule runs. An agent can even be given a tool that creates its own
|
|
7394
|
-
reminders.
|
|
7395
|
-
|
|
7396
|
-
For example, create `agent/tools/remind_me.ts`:
|
|
7397
|
-
|
|
7398
7164
|
```ts
|
|
7399
|
-
import
|
|
7400
|
-
import { z } from "zod";
|
|
7401
|
-
|
|
7402
|
-
export default defineTool({
|
|
7403
|
-
description: "Schedule a one-time reminder in this conversation.",
|
|
7404
|
-
inputSchema: z.object({
|
|
7405
|
-
delay: z
|
|
7406
|
-
.string()
|
|
7407
|
-
.describe("When to wake the conversation, such as 20m or 2h"),
|
|
7408
|
-
prompt: z
|
|
7409
|
-
.string()
|
|
7410
|
-
.min(1)
|
|
7411
|
-
.describe("What the agent should do when it wakes"),
|
|
7412
|
-
}),
|
|
7413
|
-
async execute({ delay, prompt }, ctx) {
|
|
7414
|
-
const reminders = ctx.host.reminders;
|
|
7415
|
-
if (reminders === undefined) {
|
|
7416
|
-
throw new Error("Reminders are disabled on this host.");
|
|
7417
|
-
}
|
|
7165
|
+
import ciRecheck from "./agent/reminders/ci_recheck.js";
|
|
7418
7166
|
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
channelId: ctx.session.channelId,
|
|
7427
|
-
continuationToken,
|
|
7428
|
-
delay,
|
|
7429
|
-
prompt,
|
|
7430
|
-
});
|
|
7431
|
-
|
|
7432
|
-
return {
|
|
7433
|
-
reminderId: reminder.id,
|
|
7434
|
-
nextFireAt: reminder.nextFireAt,
|
|
7435
|
-
};
|
|
7436
|
-
},
|
|
7167
|
+
await handle.createReminder({
|
|
7168
|
+
purpose: "ci_recheck",
|
|
7169
|
+
channelId: "drive",
|
|
7170
|
+
continuationToken: "pr:acme/checkout#42",
|
|
7171
|
+
every: "30m",
|
|
7172
|
+
handler: ciRecheck,
|
|
7173
|
+
args: { prUrl: "https://github.com/acme/checkout/pull/42" },
|
|
7437
7174
|
});
|
|
7438
7175
|
```
|
|
7439
7176
|
|
|
7440
|
-
|
|
7441
|
-
|
|
7177
|
+
Use an anonymous `run` handler only for legacy projects that can re-arm
|
|
7178
|
+
it after a restart. New projects should use a named handler.
|
|
7442
7179
|
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
cancellation condition for the model
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7180
|
+
| Form | What it does | After a restart |
|
|
7181
|
+
| --- | --- | --- |
|
|
7182
|
+
| Prompt | Sends `prompt` into the session. `until` is the standing cancellation condition for the model | Stays armed |
|
|
7183
|
+
| Named handler | Runs a discovered handler with serializable `args`; it starts a model turn only if the handler calls `followup` | Stays armed |
|
|
7184
|
+
| Anonymous `run` | Host handler returns `stop`, `skip`, or `delivered` per tick; it starts a model turn only if it calls `followup` | Must be re-armed |
|
|
7185
|
+
|
|
7186
|
+
The same API is `host.reminders` on channel handlers, tools, and
|
|
7187
|
+
schedule runs. `builtinTools: { reminders: true }` adds
|
|
7188
|
+
`reminders_create`, `reminders_list`, and `reminders_cancel` on the
|
|
7189
|
+
current conversation; see
|
|
7190
|
+
[Agent config: built-in tools](/docs/reference/agent-config.md#built-in-tools).
|
|
7451
7191
|
|
|
7452
7192
|
`--dev` does not auto-fire reminders. Dispatch one by hand:
|
|
7453
7193
|
|
|
@@ -7458,27 +7198,21 @@ curl -X POST http://127.0.0.1:3000/<slug>/v1/dev/reminders/<id> # fire one
|
|
|
7458
7198
|
|
|
7459
7199
|
`handle.dispatchReminder(id)` is the programmatic equivalent.
|
|
7460
7200
|
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
replaying stale payload details, because the agent re-reads the live
|
|
7465
|
-
state when it wakes.
|
|
7466
|
-
|
|
7467
|
-
## Schedule or reminder?
|
|
7201
|
+
Cancel reminders when their subject dies, for example on
|
|
7202
|
+
`pull_request.closed`. Keep wake prompts generic so the agent re-reads
|
|
7203
|
+
live state instead of replaying a stale payload.
|
|
7468
7204
|
|
|
7469
|
-
|
|
7205
|
+
## Schedules vs reminders
|
|
7470
7206
|
|
|
7471
7207
|
| | Schedule | Reminder |
|
|
7472
7208
|
| -------- | ---------------------------------------------------------- | ----------------------------------------------- |
|
|
7473
7209
|
| Defined | at deploy time, `agent/schedules/*` | at runtime, `createReminder` / `host.reminders` |
|
|
7474
7210
|
| Scope | global to the agent | one channel continuation (one conversation) |
|
|
7475
7211
|
| Session | starts a new task session (or hands off through `receive`) | wakes an existing conversation |
|
|
7476
|
-
| Cadence | cron (UTC) |
|
|
7212
|
+
| Cadence | cron (UTC) | `every`, `cron`, `delay`, or `at` |
|
|
7477
7213
|
| Dev mode | manual dispatch only | manual dispatch only (timers off) |
|
|
7478
7214
|
|
|
7479
|
-
##
|
|
7480
|
-
|
|
7481
|
-
Continue with these pages:
|
|
7215
|
+
## Related
|
|
7482
7216
|
|
|
7483
7217
|
- [Channels](/docs/reference/channels.md): `receive` and the delivery events
|
|
7484
7218
|
- [GitHub guide](/docs/guides/github.md): reminders in a real webhook loop
|
|
@@ -7492,9 +7226,12 @@ Source: /docs/reference/sessions.md
|
|
|
7492
7226
|
# Sessions, events, and streaming
|
|
7493
7227
|
|
|
7494
7228
|
A session keeps one conversation, its workspace, and an append-only
|
|
7495
|
-
record of every message and tool call.
|
|
7229
|
+
record of every message and tool call. Continue it with a continuation
|
|
7230
|
+
token, inspect it with a session ID, and follow progress on the NDJSON
|
|
7231
|
+
stream. Chat sessions wait for follow-ups; task sessions run once and
|
|
7232
|
+
stop.
|
|
7496
7233
|
|
|
7497
|
-
##
|
|
7234
|
+
## Session contents
|
|
7498
7235
|
|
|
7499
7236
|
Each session combines:
|
|
7500
7237
|
|
|
@@ -7502,12 +7239,12 @@ Each session combines:
|
|
|
7502
7239
|
- A conversation the caller can continue
|
|
7503
7240
|
- A workspace for local turns
|
|
7504
7241
|
- An NDJSON event stream
|
|
7505
|
-
-
|
|
7242
|
+
- State that lets the conversation resume after a restart
|
|
7506
7243
|
|
|
7507
7244
|
Sessions belong to the principal that created them. Follow-up, stream,
|
|
7508
7245
|
and list routes return `403` when another caller tries to access one.
|
|
7509
7246
|
|
|
7510
|
-
##
|
|
7247
|
+
## Session identifiers
|
|
7511
7248
|
|
|
7512
7249
|
Sessions have two identifiers because conversation routing and
|
|
7513
7250
|
inspection are different jobs.
|
|
@@ -7525,7 +7262,7 @@ accepted follow-up. Reusing a stale HTTP token returns `409`.
|
|
|
7525
7262
|
Use the continuation token to keep talking. Use the session ID to
|
|
7526
7263
|
observe or manage the stored session.
|
|
7527
7264
|
|
|
7528
|
-
##
|
|
7265
|
+
## Session modes
|
|
7529
7266
|
|
|
7530
7267
|
| Mode | Created by | What happens after a turn |
|
|
7531
7268
|
| --- | --- | --- |
|
|
@@ -7534,7 +7271,7 @@ observe or manage the stored session.
|
|
|
7534
7271
|
|
|
7535
7272
|
Task sessions don't accept follow-ups. Trying one returns `409`.
|
|
7536
7273
|
|
|
7537
|
-
##
|
|
7274
|
+
## Follow-ups
|
|
7538
7275
|
|
|
7539
7276
|
A follow-up to an idle chat session starts another turn. Admission when
|
|
7540
7277
|
the session is already busy depends on the channel:
|
|
@@ -7542,23 +7279,21 @@ the session is already busy depends on the channel:
|
|
|
7542
7279
|
| Path | Busy-session policy |
|
|
7543
7280
|
| --- | --- |
|
|
7544
7281
|
| HTTP playground / `POST /v1/session/:id` / MCP `ask` | **Preempt** (default): interrupt the in-flight turn, wait for it to settle, then run the new message |
|
|
7545
|
-
| Slack mentions / DMs / alert-watch | **Coalesce**: leave the active turn running
|
|
7282
|
+
| Slack mentions / DMs / alert-watch | **Coalesce**: leave the active turn running and queue the follow-up. The running turn may receive it at a tool boundary; any asks that remain become one follow-up turn when it finishes |
|
|
7546
7283
|
|
|
7547
7284
|
Pass `admission: "coalesce"` on `send()` to opt into the Slack policy from
|
|
7548
7285
|
other callers. Omit it (or pass `"preempt"`) to keep interrupt semantics.
|
|
7549
7286
|
|
|
7550
7287
|
`POST /v1/session/:id/stop` interrupts a turn without sending a new
|
|
7551
|
-
message.
|
|
7552
|
-
|
|
7553
|
-
Slack `stop` / `@agent stop` does the same for that thread
|
|
7554
|
-
pending coalesced
|
|
7288
|
+
message. The stream records `turn.failed` with `status: "cancelled"`;
|
|
7289
|
+
the session stays a chat session and can take another follow-up. A
|
|
7290
|
+
whole-message Slack `stop` / `@agent stop` does the same for that thread
|
|
7291
|
+
and clears pending coalesced follow-ups.
|
|
7555
7292
|
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
running, a read-effect call runs alongside the turn (see
|
|
7559
|
-
[Tools](/docs/reference/tools.md#call-a-tool-without-a-model-turn)).
|
|
7293
|
+
See [Tools](/docs/reference/tools.md#call-a-tool-without-a-model-turn) for direct-call
|
|
7294
|
+
behavior while a session is busy.
|
|
7560
7295
|
|
|
7561
|
-
##
|
|
7296
|
+
## Stream events
|
|
7562
7297
|
|
|
7563
7298
|
Each NDJSON line uses this envelope:
|
|
7564
7299
|
`{ type, index, sessionId, turnId?, at, data }`. The `index` increases
|
|
@@ -7580,13 +7315,11 @@ within one session. The `at` field is an ISO-8601 timestamp.
|
|
|
7580
7315
|
|
|
7581
7316
|
Pair `actions.requested` with `action.result` to reconstruct the tool
|
|
7582
7317
|
trajectory. Read `turn.completed.data.usage` for input, output, and
|
|
7583
|
-
cache token counts.
|
|
7584
|
-
`commit
|
|
7585
|
-
|
|
7586
|
-
`ctx.reject(message)` re-runs the same turn with that message so the
|
|
7587
|
-
model can revise while tools and the session filesystem are still up.
|
|
7318
|
+
cache token counts. With `agent/result.ts`, `turn.failed` is emitted when
|
|
7319
|
+
`commit` throws, the turn has no assistant text, or `ctx.reject(message)`
|
|
7320
|
+
doesn't lead to an accepted revision.
|
|
7588
7321
|
|
|
7589
|
-
##
|
|
7322
|
+
## Stream or replay events
|
|
7590
7323
|
|
|
7591
7324
|
One endpoint handles both live streaming and replay:
|
|
7592
7325
|
|
|
@@ -7594,27 +7327,27 @@ One endpoint handles both live streaming and replay:
|
|
|
7594
7327
|
curl -N 'http://127.0.0.1:3000/<slug>/v1/session/ses_…/stream?startIndex=0'
|
|
7595
7328
|
```
|
|
7596
7329
|
|
|
7597
|
-
Pass `startIndex` to continue after the last event you received
|
|
7598
|
-
or pass `0` to replay the
|
|
7330
|
+
Pass `startIndex` to continue after the last event you received,
|
|
7331
|
+
including after a server restart. Omit it or pass `0` to replay the
|
|
7332
|
+
full session before following new events.
|
|
7599
7333
|
`GET /v1/session/:id/events` returns a one-time dump without staying
|
|
7600
7334
|
connected.
|
|
7601
7335
|
|
|
7602
|
-
|
|
7603
|
-
state resumes from the Cursor SDK store.
|
|
7604
|
-
|
|
7605
|
-
## What goes into a local session workspace?
|
|
7336
|
+
## Local session workspace
|
|
7606
7337
|
|
|
7607
7338
|
The Agent SDK creates a workspace before the first local turn:
|
|
7608
7339
|
|
|
7609
7340
|
| Source path | Lands as |
|
|
7610
7341
|
| ---------------------------------- | ----------------------------------------------------------------------- |
|
|
7611
|
-
| `instructions.*` | `AGENTS.md` |
|
|
7612
7342
|
| `skills/*` | `.cursor/skills/<name>/SKILL.md` |
|
|
7613
7343
|
| agent tools (`execution: "agent"`) | scripts in the session workspace, with a catalog in `AGENTS.md` |
|
|
7614
7344
|
| `sandbox/workspace/**` | copied in as seed files |
|
|
7615
7345
|
| per-send `workspaceFiles` | written before the turn |
|
|
7616
7346
|
|
|
7617
|
-
|
|
7347
|
+
Instructions reach the model as its system prompt; they aren't written
|
|
7348
|
+
into the workspace. See [Instructions](/docs/reference/instructions.md#delivery).
|
|
7349
|
+
|
|
7350
|
+
Local turns use this workspace as their working directory. Parent
|
|
7618
7351
|
directories can contribute `AGENTS.md` and `.cursor` settings. Set
|
|
7619
7352
|
`local.cwd` when you need a clean parent directory. A channel can also
|
|
7620
7353
|
provide a different working directory for one session, such as a PR
|
|
@@ -7623,20 +7356,16 @@ worktree.
|
|
|
7623
7356
|
See [Agent config: local cwd](/docs/reference/agent-config.md#local-cwd) for the
|
|
7624
7357
|
inheritance rules.
|
|
7625
7358
|
|
|
7626
|
-
##
|
|
7359
|
+
## Session storage
|
|
7627
7360
|
|
|
7628
|
-
Local state lives under `--state-root`.
|
|
7629
|
-
a subdirectory named for the slug.
|
|
7361
|
+
Local session state lives under `--state-root`. A slugged mount stores
|
|
7362
|
+
it in a subdirectory named for the slug.
|
|
7630
7363
|
|
|
7631
7364
|
Deleting a session directory removes the session from the server: it
|
|
7632
7365
|
disappears from listings and can no longer be streamed or continued.
|
|
7633
7366
|
Cloud conversations remain on the Cursor backend.
|
|
7634
7367
|
|
|
7635
|
-
|
|
7636
|
-
repo. See
|
|
7637
|
-
[What goes into a local session workspace?](#what-goes-into-a-local-session-workspace).
|
|
7638
|
-
|
|
7639
|
-
## How do I inspect a saved event stream?
|
|
7368
|
+
## Inspect a saved event stream
|
|
7640
7369
|
|
|
7641
7370
|
Use `trajectory` with a saved trace:
|
|
7642
7371
|
|
|
@@ -7645,13 +7374,14 @@ agent-sdk trajectory --events <state-root>/traces/<sessionId>.ndjson
|
|
|
7645
7374
|
```
|
|
7646
7375
|
|
|
7647
7376
|
The command prints tool calls, the reply, and token usage in the same
|
|
7648
|
-
JSON shape as `run`.
|
|
7649
|
-
|
|
7377
|
+
JSON shape as `run`. Open the session's **Trace** view in the playground
|
|
7378
|
+
for a visual timeline.
|
|
7650
7379
|
|
|
7651
7380
|
## Related
|
|
7652
7381
|
|
|
7653
7382
|
- [HTTP API](/docs/reference/http-api.md)
|
|
7654
7383
|
- [Hooks](/docs/reference/hooks.md)
|
|
7384
|
+
- [Tools](/docs/reference/tools.md)
|
|
7655
7385
|
|
|
7656
7386
|
---
|
|
7657
7387
|
|
|
@@ -7667,15 +7397,15 @@ always-on [instructions](/docs/reference/instructions.md).
|
|
|
7667
7397
|
|
|
7668
7398
|
## Authoring forms
|
|
7669
7399
|
|
|
7670
|
-
|
|
7400
|
+
Skills support three authoring forms.
|
|
7671
7401
|
|
|
7672
7402
|
| Form | Reach for it when |
|
|
7673
7403
|
| --- | --- |
|
|
7674
|
-
| `agent/skills/<name>.md` |
|
|
7404
|
+
| `agent/skills/<name>.md` | Static Markdown. Optional `description` frontmatter; the first body line is the fallback. |
|
|
7675
7405
|
| `agent/skills/<name>/SKILL.md` plus siblings | A packaged directory with reference files (`references/…`). Requires `description` frontmatter. |
|
|
7676
7406
|
| `agent/skills/<name>.ts` | Generated content, with `defineSkill` from `@cursor/july/skills`. |
|
|
7677
7407
|
|
|
7678
|
-
|
|
7408
|
+
Use flat Markdown for static content:
|
|
7679
7409
|
|
|
7680
7410
|
```md
|
|
7681
7411
|
---
|
|
@@ -7689,8 +7419,8 @@ description: Use when a pull request needs a structured approval checklist.
|
|
|
7689
7419
|
3. Call `approve_pr` only after an explicit request; it requires approval.
|
|
7690
7420
|
```
|
|
7691
7421
|
|
|
7692
|
-
TypeScript
|
|
7693
|
-
files:
|
|
7422
|
+
Use TypeScript when the content must be generated or include inline
|
|
7423
|
+
sibling files:
|
|
7694
7424
|
|
|
7695
7425
|
```ts
|
|
7696
7426
|
import { defineSkill } from "@cursor/july/skills";
|
|
@@ -7702,40 +7432,29 @@ export default defineSkill({
|
|
|
7702
7432
|
});
|
|
7703
7433
|
```
|
|
7704
7434
|
|
|
7705
|
-
##
|
|
7706
|
-
|
|
7707
|
-
On the local runtime, skills land in the session workspace at
|
|
7708
|
-
`.cursor/skills/<name>/SKILL.md`, and the harness advertises and loads
|
|
7709
|
-
them natively. On the cloud runtime there is no session workspace, so
|
|
7710
|
-
the engine copies the same SKILL.md tree onto an Agent Store for native
|
|
7711
|
-
discovery:
|
|
7712
|
-
|
|
7713
|
-
- Hosted deployments write store-root `skills/<name>/`.
|
|
7714
|
-
- `agent-sdk serve` / `run` with a personal `CURSOR_API_KEY` write
|
|
7715
|
-
namespaced skills on the USER store so they cannot collide with the
|
|
7716
|
-
user's own skills.
|
|
7435
|
+
## Skill delivery
|
|
7717
7436
|
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7437
|
+
Local turns receive authored skills automatically. Hosted deployments
|
|
7438
|
+
and local `serve` or `run` processes with a personal `CURSOR_API_KEY`
|
|
7439
|
+
also make them available to cloud turns. Otherwise, a cloud turn sees
|
|
7440
|
+
only skills already in its checkout. `agent-sdk validate` warns when
|
|
7441
|
+
`runtime: "cloud"` is combined with authored skills.
|
|
7721
7442
|
|
|
7722
|
-
##
|
|
7443
|
+
## Skills, instructions, and tools
|
|
7723
7444
|
|
|
7724
7445
|
Instructions are always in context: identity, tool-choice rules, the
|
|
7725
7446
|
output contract. Keep them short. Skills load when relevant: procedures,
|
|
7726
7447
|
checklists, house style. Reach for a skill when the model needs to
|
|
7727
|
-
|
|
7448
|
+
follow something but only sometimes needs it loaded. Tools are typed,
|
|
7728
7449
|
executable behavior: anything that must be correct every time belongs in
|
|
7729
7450
|
tool code, not in prose the model might paraphrase.
|
|
7730
7451
|
|
|
7731
|
-
A good skill description is a routing rule, not a title. Say
|
|
7452
|
+
A good skill description is a routing rule, not a title. Say when to
|
|
7732
7453
|
use it, like "Use when a pull request needs a structured approval
|
|
7733
7454
|
checklist," because the description is all the model sees before
|
|
7734
7455
|
deciding to load it.
|
|
7735
7456
|
|
|
7736
|
-
##
|
|
7737
|
-
|
|
7738
|
-
Continue with these pages:
|
|
7457
|
+
## Related
|
|
7739
7458
|
|
|
7740
7459
|
- [Instructions](/docs/reference/instructions.md): what stays always-on
|
|
7741
7460
|
- [Tools](/docs/reference/tools.md): when prose needs to become code
|
|
@@ -7750,16 +7469,15 @@ Source: /docs/reference/subagents.md
|
|
|
7750
7469
|
# Subagents
|
|
7751
7470
|
|
|
7752
7471
|
A subagent is a specialist child agent the model can delegate to
|
|
7753
|
-
mid-turn. Each one
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
`subagent.called` and `subagent.completed`.
|
|
7472
|
+
mid-turn. Each one lives under `agent/subagents/<id>/` with a required
|
|
7473
|
+
`agent.ts`. Add `instructions.md` or inline `instructions` in `agent.ts`
|
|
7474
|
+
for a custom prompt. The parent model delegates through the `task` tool,
|
|
7475
|
+
and the stream records `subagent.called` and `subagent.completed`.
|
|
7758
7476
|
|
|
7759
7477
|
```text
|
|
7760
7478
|
agent/subagents/researcher/
|
|
7761
7479
|
├── agent.ts # description (required), model (optional)
|
|
7762
|
-
└── instructions.md #
|
|
7480
|
+
└── instructions.md # optional custom system prompt
|
|
7763
7481
|
```
|
|
7764
7482
|
|
|
7765
7483
|
```ts
|
|
@@ -7775,47 +7493,38 @@ export default defineAgent({
|
|
|
7775
7493
|
|
|
7776
7494
|
## Subagent rules
|
|
7777
7495
|
|
|
7778
|
-
`description` is required.
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
different one.
|
|
7496
|
+
`description` is required. The parent model uses it to decide whether
|
|
7497
|
+
to delegate, so write it as a routing rule ("Background research: …"),
|
|
7498
|
+
following the same discipline as a [skill](/docs/reference/skills.md) description.
|
|
7499
|
+
`model` is optional; omit it to inherit the parent's model, or set it
|
|
7500
|
+
to run the specialist on a different model.
|
|
7784
7501
|
|
|
7785
7502
|
Subagents inherit the parent's execution surface. Every per-subagent
|
|
7786
7503
|
capability directory is reported as a warning and ignored: `tools/`,
|
|
7787
|
-
`skills/`, `mcp-connections
|
|
7788
|
-
`
|
|
7789
|
-
|
|
7504
|
+
`skills/`, `extensions/`, `mcp-connections/`, `host-connections/`,
|
|
7505
|
+
`channels/`, `schedules/`, `reminders/`, `hooks/`, `sandbox/`, and
|
|
7506
|
+
nested `subagents/`.
|
|
7790
7507
|
|
|
7791
7508
|
Delegation needs both halves: the description makes it possible, and the
|
|
7792
7509
|
parent's [instructions](/docs/reference/instructions.md) make it happen. "When a
|
|
7793
7510
|
request needs background research, delegate to the `researcher`
|
|
7794
|
-
subagent."
|
|
7511
|
+
subagent." The parent routes; the specialist executes.
|
|
7795
7512
|
|
|
7796
|
-
##
|
|
7513
|
+
## Subagents and peers
|
|
7797
7514
|
|
|
7798
7515
|
Subagents split one job into roles inside a single agent. When the
|
|
7799
7516
|
specialist is independently useful, with its own tools, sessions, and
|
|
7800
7517
|
playground, make it a full agent. See
|
|
7801
7518
|
[Peer agents](/docs/guides/agent-to-agent.md#peer-or-subagent).
|
|
7802
7519
|
|
|
7803
|
-
##
|
|
7804
|
-
|
|
7805
|
-
Fan-out reviews: a PR-approval agent can delegate to two review
|
|
7806
|
-
subagents that read a host-prepared `pr/` evidence tree and report
|
|
7807
|
-
prioritized findings, which the parent embeds in its approval comment.
|
|
7808
|
-
|
|
7809
|
-
Keep the parent lean: a subagent with focused instructions usually
|
|
7810
|
-
works better than a longer parent prompt with conditional sections. The
|
|
7811
|
-
parent routes; the specialist executes.
|
|
7812
|
-
|
|
7813
|
-
## What's next
|
|
7814
|
-
|
|
7815
|
-
Continue with these pages:
|
|
7520
|
+
## Related
|
|
7816
7521
|
|
|
7817
7522
|
- [Skills](/docs/reference/skills.md): when a procedure is enough and a child agent
|
|
7818
7523
|
is overkill
|
|
7524
|
+
- [Peer agents](/docs/guides/agent-to-agent.md): independently useful
|
|
7525
|
+
specialists
|
|
7526
|
+
- [Agent config](/docs/reference/agent-config.md#harness-tools): `"task"` on the
|
|
7527
|
+
parent's tool allowlist
|
|
7819
7528
|
|
|
7820
7529
|
---
|
|
7821
7530
|
|
|
@@ -7826,18 +7535,16 @@ Source: /docs/reference/tools.md
|
|
|
7826
7535
|
A tool is a typed action the model can call: hit an API, run a query,
|
|
7827
7536
|
write a file. Each file in `agent/tools/` defines one tool, and the
|
|
7828
7537
|
filename becomes the tool name the model sees. Tools come in two
|
|
7829
|
-
execution flavors: server tools run
|
|
7538
|
+
execution flavors: server tools run on the serving host, and
|
|
7830
7539
|
agent tools run as scripts where the agent runs. Every server tool can
|
|
7831
7540
|
also be called directly, with no model turn.
|
|
7832
7541
|
|
|
7833
7542
|
## Define a server tool
|
|
7834
7543
|
|
|
7835
|
-
By default, `execute` runs
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
`--cloud-tools-url` is set; without either, the server warns at startup
|
|
7840
|
-
and cloud turns omit them.
|
|
7544
|
+
By default, `execute` runs on the serving host with full access to
|
|
7545
|
+
`process.env` and your `agent/lib/` code. Set `--public-url` or
|
|
7546
|
+
`--cloud-tools-url` to make server tools available to cloud turns;
|
|
7547
|
+
without either, startup warns and cloud turns omit them.
|
|
7841
7548
|
|
|
7842
7549
|
```ts
|
|
7843
7550
|
// agent/tools/inspect_pr.ts
|
|
@@ -7996,7 +7703,7 @@ check nothing.
|
|
|
7996
7703
|
## Define an agent tool
|
|
7997
7704
|
|
|
7998
7705
|
Set `execution: "agent"` and the tool materializes as a shell script
|
|
7999
|
-
that runs where the Cursor agent runs: the local
|
|
7706
|
+
that runs where the Cursor agent runs: the local session workspace or
|
|
8000
7707
|
the cloud VM. The script receives JSON arguments on stdin and prints its
|
|
8001
7708
|
result on stdout. Use this flavor when the tool must run next to the
|
|
8002
7709
|
checkout the agent works in; on cloud, server tools stay available too
|
|
@@ -8019,23 +7726,16 @@ printf '%s\\n' "$message"
|
|
|
8019
7726
|
```
|
|
8020
7727
|
|
|
8021
7728
|
On the local runtime, scripts land in the session workspace with a
|
|
8022
|
-
catalog in `AGENTS.md`.
|
|
8023
|
-
on the first prompt.
|
|
7729
|
+
catalog in `AGENTS.md`.
|
|
8024
7730
|
|
|
8025
7731
|
## Tools from an MCP connection, advertised by name
|
|
8026
7732
|
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
local turn. See
|
|
8034
|
-
[MCP Connections](/docs/reference/connections.md#advertise-tools).
|
|
8035
|
-
Advertised tools ride the same execution path as authored server tools,
|
|
8036
|
-
and [direct tool calls](#call-a-tool-without-a-model-turn) address them
|
|
8037
|
-
by the same model-facing names: the call's session identity resolves the
|
|
8038
|
-
advertised listing when the authored lookup misses.
|
|
7733
|
+
Set `advertiseTools: true` on a connection to expose its MCP tools by
|
|
7734
|
+
name. Add per-session `auth` when credentials depend on the caller.
|
|
7735
|
+
Model calls and [direct tool calls](#call-a-tool-without-a-model-turn)
|
|
7736
|
+
use the same exposed names. See
|
|
7737
|
+
[MCP connections](/docs/reference/connections.md#advertise-tools) for the full
|
|
7738
|
+
contract.
|
|
8039
7739
|
|
|
8040
7740
|
## Gate a tool on human approval
|
|
8041
7741
|
|
|
@@ -8066,8 +7766,8 @@ runtime only, and parked calls don't survive a host restart.
|
|
|
8066
7766
|
## Call a tool without a model turn
|
|
8067
7767
|
|
|
8068
7768
|
Server tools can be called deterministically. You pick the tool and the
|
|
8069
|
-
input. Validation and execution
|
|
8070
|
-
|
|
7769
|
+
input. Validation and execution match a model-initiated call, and no
|
|
7770
|
+
Cursor API key is needed.
|
|
8071
7771
|
|
|
8072
7772
|
Over HTTP, with the same auth chain as the session API:
|
|
8073
7773
|
|
|
@@ -8093,51 +7793,43 @@ agent-sdk call inspect_pr \
|
|
|
8093
7793
|
Programmatically, `callTool(toolName, input, options?)` is available on
|
|
8094
7794
|
the serve handle, on channel route handlers and `onStart` args, and on
|
|
8095
7795
|
schedule `run` handlers, so a channel can mix deterministic calls with
|
|
8096
|
-
model turns
|
|
8097
|
-
the review prompt:
|
|
7796
|
+
model turns:
|
|
8098
7797
|
|
|
8099
7798
|
```ts
|
|
8100
7799
|
const outcome = await handle.callTool("inspect_pr", {
|
|
8101
7800
|
prUrl: "https://github.com/acme/checkout/pull/42",
|
|
8102
7801
|
});
|
|
7802
|
+
if (outcome.isError) {
|
|
7803
|
+
return outcome;
|
|
7804
|
+
}
|
|
8103
7805
|
// { toolName, callId, isError, result, durationMs }
|
|
8104
7806
|
```
|
|
8105
7807
|
|
|
8106
|
-
|
|
8107
|
-
when the call returns. Pass
|
|
8108
|
-
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
`
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
whose tools resolve state from the continuation key can serve it with
|
|
8132
|
-
no live session. Malformed tokens are rejected with
|
|
8133
|
-
`400 invalid_continuation_token`.
|
|
8134
|
-
|
|
8135
|
-
The error semantics match the model path. Unknown tools are rejected
|
|
8136
|
-
with the available names, agent-execution tools cannot be called on the
|
|
8137
|
-
host (`400`), schema-invalid input is a `400` before the tool body runs
|
|
8138
|
-
(Zod validates; plain JSON Schema passes through unvalidated), and a
|
|
8139
|
-
tool body that throws reports `isError: true` in the same envelope the
|
|
8140
|
-
model would see.
|
|
7808
|
+
Omit both identifiers to run against an ephemeral workspace that is
|
|
7809
|
+
removed when the call returns. Pass `sessionId` (HTTP body, `--session`,
|
|
7810
|
+
or `options.sessionId`) or `continuationToken` (`<channelId>:<key>` as
|
|
7811
|
+
`/v1/sessions` lists it) to bind the call. The two are mutually
|
|
7812
|
+
exclusive.
|
|
7813
|
+
|
|
7814
|
+
| Rule | What happens |
|
|
7815
|
+
| --- | --- |
|
|
7816
|
+
| Existing `sessionId`, or a token that maps to an existing session | Session workspace, owner check, and event recording |
|
|
7817
|
+
| Token with no matching session | Scratch workspace; the token's channel id and key are the call identity |
|
|
7818
|
+
| Busy session, `effect: "read"` (or an advertised MCP tool marked read-only) | Runs alongside the turn, reading the workspace as the turn left it; recorded under its own `turnId` |
|
|
7819
|
+
| Busy session, write or undeclared | `409 session_busy` until the turn finishes |
|
|
7820
|
+
| Session workspace cannot be created, read | Scratch workspace; the outcome has `scratchWorkspace: true` |
|
|
7821
|
+
| Session workspace cannot be created, write | `500 workspace_unavailable` |
|
|
7822
|
+
|
|
7823
|
+
| Error | When |
|
|
7824
|
+
| --- | --- |
|
|
7825
|
+
| `404 unknown_tool` | Name is not a callable server tool; the response lists available names |
|
|
7826
|
+
| `400 tool_not_callable` | Agent-execution tools cannot run on the host |
|
|
7827
|
+
| `400 invalid_tool_input` | Zod rejected the input before `execute`. Plain JSON Schema is forwarded unvalidated |
|
|
7828
|
+
| `400 invalid_continuation_token` | Malformed token, or passed together with `sessionId` |
|
|
7829
|
+
| `404 session_not_found` | `sessionId` does not exist |
|
|
7830
|
+
| `409 session_busy` | Write-effect call while a model turn is running |
|
|
7831
|
+
| `500 workspace_unavailable` | Write-effect call when the session workspace cannot be created |
|
|
7832
|
+
| `isError: true` | The tool body threw; same envelope the model would see |
|
|
8141
7833
|
|
|
8142
7834
|
## Design habits
|
|
8143
7835
|
|
|
@@ -8155,9 +7847,7 @@ wrong, no instruction change fixes it.
|
|
|
8155
7847
|
Gate side effects with `needsApproval`. Declare each tool's `effect` so
|
|
8156
7848
|
dry-run sessions can execute reads and stub writes.
|
|
8157
7849
|
|
|
8158
|
-
##
|
|
8159
|
-
|
|
8160
|
-
Continue with these pages:
|
|
7850
|
+
## Related
|
|
8161
7851
|
|
|
8162
7852
|
- [MCP connections](/docs/reference/connections.md): tools that come from MCP servers
|
|
8163
7853
|
instead
|
|
@@ -8765,7 +8455,7 @@ Match the visible symptom below. If `agent-sdk` is not on `PATH`, use
|
|
|
8765
8455
|
| File reads and greps fail repeatedly with `NGHTTP2_FRAME_SIZE_ERROR` | Run the agent under Node 22.13 or newer, never Bun. |
|
|
8766
8456
|
| The turn immediately reports a missing API key | Set `CURSOR_API_KEY`, `CURSOR_API_KEY_FILE`, or `CURSOR_SERVICE_ACCOUNT_KEY`, or run `agent-sdk login`. |
|
|
8767
8457
|
| Login succeeds but the model host rejects the key | Point login and model traffic at the same API host; check `CURSOR_API_BASE_URL` and `CURSOR_BACKEND_URL`. |
|
|
8768
|
-
| Cloud turns cannot reach local tools or skills | Give the cloud runtime a reachable `--public-url` and protected tool bridge, or move the required capability into the cloud checkout. See [agent runtime](/docs/reference/agent-config.md#
|
|
8458
|
+
| Cloud turns cannot reach local tools or skills | Give the cloud runtime a reachable `--public-url` and protected tool bridge, or move the required capability into the cloud checkout. See [agent runtime](/docs/reference/agent-config.md#runtime). |
|
|
8769
8459
|
|
|
8770
8460
|
## A turn behaves unexpectedly
|
|
8771
8461
|
|