@cursor/july 0.1.112 → 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.
Files changed (305) hide show
  1. package/README.md +4 -0
  2. package/dist/bin/agent-serve.js +2 -3
  3. package/dist/channels/checks.d.ts +10 -0
  4. package/dist/channels/checks.d.ts.map +1 -1
  5. package/dist/channels/origin/checks.d.ts +1 -1
  6. package/dist/channels/origin/checks.d.ts.map +1 -1
  7. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  8. package/dist/channels/slack/dispatch.js +6 -2
  9. package/dist/docs/404.html +2 -2
  10. package/dist/docs/assets/{app.DxTdhphC.js → app.BqkJwOZ-.js} +4 -4
  11. package/dist/docs/assets/chunks/@localSearchIndexroot.BnSgidYE.js +1 -0
  12. package/dist/docs/assets/chunks/{VPLocalSearchBox.CR3KTF0X.js → VPLocalSearchBox.BJAi2KiV.js} +1 -1
  13. package/dist/docs/assets/chunks/{arc.CVVqBOdS.js → arc.BZpXTgvV.js} +1 -1
  14. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CJHGP4ki.js → architectureDiagram-Q4EWVU46.WYI-7F-Y.js} +1 -1
  15. package/dist/docs/assets/chunks/{baseUniq.r7UVVRBP.js → baseUniq.CZaUPpg0.js} +1 -1
  16. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.DKmMaTre.js → blockDiagram-DXYQGD6D.D6UES2pD.js} +1 -1
  17. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.DDJsntUO.js → c4Diagram-AHTNJAMY.cwebIe4i.js} +1 -1
  18. package/dist/docs/assets/chunks/channel.DdM5EfNW.js +1 -0
  19. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.BK2rKt6W.js → chunk-4BX2VUAB.fVyFnjxg.js} +1 -1
  20. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.DRLV8RnF.js → chunk-4TB4RGXK.BanufG1c.js} +1 -1
  21. package/dist/docs/assets/chunks/{chunk-55IACEB6.DaKjxtb7.js → chunk-55IACEB6.VaSMz5-2.js} +1 -1
  22. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.C5sPCIT1.js → chunk-EDXVE4YY.CN2diZOM.js} +1 -1
  23. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.CSGWyNTB.js → chunk-FMBD7UC4.g4ivypu3.js} +1 -1
  24. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.D5tK9XEr.js → chunk-OYMX7WX6.GZXKn9JJ.js} +1 -1
  25. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BeZGd1UZ.js → chunk-QZHKN3VN.itXxJZCd.js} +1 -1
  26. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.U_tfWwQR.js → chunk-YZCP3GAM.-rw2GfvX.js} +1 -1
  27. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.CjfGHeg2.js +1 -0
  28. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.CjfGHeg2.js +1 -0
  29. package/dist/docs/assets/chunks/clone.wSOICb_f.js +1 -0
  30. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.DVeRXIb6.js → cose-bilkent-S5V4N54A.CmaI5br0.js} +1 -1
  31. package/dist/docs/assets/chunks/{dagre-KV5264BT.BpKJAeRZ.js → dagre-KV5264BT.4wY9S4Kt.js} +1 -1
  32. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.BQOtrd1Z.js → diagram-5BDNPKRD.Pc3c0u9W.js} +1 -1
  33. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.CSDAhjPI.js → diagram-G4DWMVQ6.CYrWz-nj.js} +1 -1
  34. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.Dpztst2S.js → diagram-MMDJMWI5.Bgj5hukb.js} +1 -1
  35. package/dist/docs/assets/chunks/{diagram-TYMM5635.qJHRizHR.js → diagram-TYMM5635.DGMEXalS.js} +1 -1
  36. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.vbDotH3l.js → erDiagram-SMLLAGMA.GepTV9Im.js} +1 -1
  37. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.CqS_ZQr4.js → flowDiagram-DWJPFMVM.DVKywg3j.js} +1 -1
  38. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.DTLdR4pN.js → ganttDiagram-T4ZO3ILL.C7qt9Mlo.js} +1 -1
  39. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.D04lnbnr.js → gitGraphDiagram-UUTBAWPF.U30_r82P.js} +1 -1
  40. package/dist/docs/assets/chunks/{graph.BlfqLJsM.js → graph.CyyMyAWv.js} +1 -1
  41. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.tAooImWA.js → infoDiagram-42DDH7IO.Dn9ACW3y.js} +1 -1
  42. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.ClUsVqnJ.js → ishikawaDiagram-UXIWVN3A.DlIdIGOA.js} +1 -1
  43. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.C3tUgyCg.js → journeyDiagram-VCZTEJTY.DZj4vy4E.js} +1 -1
  44. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.CtD9-QCe.js → kanban-definition-6JOO6SKY.Dl63eMUV.js} +1 -1
  45. package/dist/docs/assets/chunks/{layout.D38U-LnT.js → layout.BLHZLWPH.js} +1 -1
  46. package/dist/docs/assets/chunks/{linear.BJmssyhN.js → linear.aXKGKaNw.js} +1 -1
  47. package/dist/docs/assets/chunks/{min.DNgXoouU.js → min.zWnFcpcc.js} +1 -1
  48. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.Dcp6cxeu.js → mindmap-definition-QFDTVHPH.Qs4MQBea.js} +1 -1
  49. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.CLDw6zIs.js → pieDiagram-DEJITSTG.BmPHgsk7.js} +1 -1
  50. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CYaeeY4c.js → quadrantDiagram-34T5L4WZ.D5MQ3gwA.js} +1 -1
  51. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.gMYuRpq2.js → requirementDiagram-MS252O5E.CkdUFrO7.js} +1 -1
  52. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.CZqyHFbc.js → sankeyDiagram-XADWPNL6.KZrljrAV.js} +1 -1
  53. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.BTsCjUDN.js → sequenceDiagram-FGHM5R23.XMoEW-Lx.js} +1 -1
  54. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.CftT9mLJ.js → stateDiagram-FHFEXIEX.BmTzePLj.js} +1 -1
  55. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.Cu5X28zZ.js +1 -0
  56. package/dist/docs/assets/chunks/{theme.B_7J9ZsV.js → theme.BfQzpxsg.js} +2 -2
  57. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.DbU3WUNw.js → timeline-definition-GMOUNBTQ.Dug0oamp.js} +1 -1
  58. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.ixsq-q2u.js → vennDiagram-DHZGUBPP.BOTHrEFu.js} +1 -1
  59. package/dist/docs/assets/chunks/wardley-RL74JXVD.DXy2i1LS.js +162 -0
  60. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.C0ewvgbp.js → wardleyDiagram-NUSXRM2D.CoXKdfi6.js} +1 -1
  61. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.nAEhF4bO.js → xychartDiagram-5P7HB3ND.DXoSCjAW.js} +1 -1
  62. package/dist/docs/assets/{deployment.md.D2jQZuFx.js → deployment.md.D2YX7u_I.js} +1 -1
  63. package/dist/docs/assets/{evals.md.BYvfZ-PO.js → evals.md.D3Y3Aixt.js} +2 -2
  64. package/dist/docs/assets/{evals.md.BYvfZ-PO.lean.js → evals.md.D3Y3Aixt.lean.js} +1 -1
  65. package/dist/docs/assets/guides_agent-to-agent.md.C6kPY8nu.js +41 -0
  66. package/dist/docs/assets/guides_agent-to-agent.md.C6kPY8nu.lean.js +1 -0
  67. package/dist/docs/assets/{guides_cloud-agents.md.Cp1O3u-X.js → guides_cloud-agents.md.BPJqTZjT.js} +1 -1
  68. package/dist/docs/assets/{guides_grokbot-agents.md.CMhZNdEU.js → guides_grokbot-agents.md.CzV715v8.js} +1 -1
  69. package/dist/docs/assets/guides_hooks.md.BT9GLwEp.js +50 -0
  70. package/dist/docs/assets/guides_hooks.md.BT9GLwEp.lean.js +1 -0
  71. package/dist/docs/assets/guides_jev.md.DeSCqMaO.js +151 -0
  72. package/dist/docs/assets/guides_jev.md.DeSCqMaO.lean.js +1 -0
  73. package/dist/docs/assets/reference_agent-config.md.BRxAlnRy.js +36 -0
  74. package/dist/docs/assets/{reference_agent-config.md.DGPyw7ms.lean.js → reference_agent-config.md.BRxAlnRy.lean.js} +1 -1
  75. package/dist/docs/assets/reference_artifacts.md.KRX0sAdt.js +18 -0
  76. package/dist/docs/assets/reference_artifacts.md.KRX0sAdt.lean.js +1 -0
  77. package/dist/docs/assets/reference_channels.md.DZr14vm7.js +23 -0
  78. package/dist/docs/assets/reference_channels.md.DZr14vm7.lean.js +1 -0
  79. package/dist/docs/assets/{reference_connections.md.CmyrlXfY.js → reference_connections.md.DJGUCxrr.js} +18 -30
  80. package/dist/docs/assets/{reference_connections.md.CmyrlXfY.lean.js → reference_connections.md.DJGUCxrr.lean.js} +1 -1
  81. package/dist/docs/assets/{reference_evals.md.DNJzM_yf.js → reference_evals.md.C6umwNC6.js} +6 -7
  82. package/dist/docs/assets/reference_evals.md.C6umwNC6.lean.js +1 -0
  83. package/dist/docs/assets/{reference_extensions.md.Ceq-qT8d.js → reference_extensions.md.DbNYu-DP.js} +3 -3
  84. package/dist/docs/assets/{reference_extensions.md.Ceq-qT8d.lean.js → reference_extensions.md.DbNYu-DP.lean.js} +1 -1
  85. package/dist/docs/assets/reference_hooks.md.BfOkhTU0.js +45 -0
  86. package/dist/docs/assets/{reference_hooks.md.B7uzNENk.lean.js → reference_hooks.md.BfOkhTU0.lean.js} +1 -1
  87. package/dist/docs/assets/reference_http-api.md.DdwtBeCj.js +11 -0
  88. package/dist/docs/assets/{reference_http-api.md.CduHavZ2.lean.js → reference_http-api.md.DdwtBeCj.lean.js} +1 -1
  89. package/dist/docs/assets/reference_instructions.md.B2mcIzT6.js +14 -0
  90. package/dist/docs/assets/reference_instructions.md.B2mcIzT6.lean.js +1 -0
  91. package/dist/docs/assets/reference_playground.md.CyrQD_n3.js +1 -0
  92. package/dist/docs/assets/reference_playground.md.CyrQD_n3.lean.js +1 -0
  93. package/dist/docs/assets/reference_project-layout.md.BEMzxAkq.js +19 -0
  94. package/dist/docs/assets/{reference_project-layout.md.BGhgpy9V.lean.js → reference_project-layout.md.BEMzxAkq.lean.js} +1 -1
  95. package/dist/docs/assets/reference_prompt.md.BFrqjHFL.js +9 -0
  96. package/dist/docs/assets/reference_prompt.md.BFrqjHFL.lean.js +1 -0
  97. package/dist/docs/assets/reference_schedules.md.BB9N3tRR.js +47 -0
  98. package/dist/docs/assets/reference_schedules.md.BB9N3tRR.lean.js +1 -0
  99. package/dist/docs/assets/reference_sessions.md.BBp-GIt-.js +1 -0
  100. package/dist/docs/assets/{reference_sessions.md.1_6Vyv7x.lean.js → reference_sessions.md.BBp-GIt-.lean.js} +1 -1
  101. package/dist/docs/assets/reference_skills.md.BVmi3UJ_.js +15 -0
  102. package/dist/docs/assets/{reference_skills.md.DjQkRefx.lean.js → reference_skills.md.BVmi3UJ_.lean.js} +1 -1
  103. package/dist/docs/assets/reference_subagents.md.DRoRy2Uj.js +10 -0
  104. package/dist/docs/assets/{reference_subagents.md.BHsSMMyO.lean.js → reference_subagents.md.DRoRy2Uj.lean.js} +1 -1
  105. package/dist/docs/assets/{reference_tools.md.BYzUTeVA.js → reference_tools.md.CgocLDX1.js} +10 -7
  106. package/dist/docs/assets/{reference_tools.md.BYzUTeVA.lean.js → reference_tools.md.CgocLDX1.lean.js} +1 -1
  107. package/dist/docs/assets/troubleshooting.md.HY95rCCz.js +1 -0
  108. package/dist/docs/building-with-agents.html +35 -35
  109. package/dist/docs/deployment.html +37 -37
  110. package/dist/docs/deployment.md +1 -1
  111. package/dist/docs/evals.html +36 -36
  112. package/dist/docs/evals.md +3 -0
  113. package/dist/docs/guides/agent-to-agent.html +65 -54
  114. package/dist/docs/guides/agent-to-agent.md +73 -69
  115. package/dist/docs/guides/bitbucket.html +35 -35
  116. package/dist/docs/guides/cloud-agents.html +36 -36
  117. package/dist/docs/guides/cloud-agents.md +1 -1
  118. package/dist/docs/guides/convert-automation.html +35 -35
  119. package/dist/docs/guides/github.html +35 -35
  120. package/dist/docs/guides/gitlab.html +35 -35
  121. package/dist/docs/guides/grokbot-agents.html +37 -37
  122. package/dist/docs/guides/grokbot-agents.md +1 -1
  123. package/dist/docs/guides/hooks.html +109 -0
  124. package/dist/docs/guides/hooks.md +111 -0
  125. package/dist/docs/guides/improve.html +36 -36
  126. package/dist/docs/guides/jev.html +210 -0
  127. package/dist/docs/guides/jev.md +291 -0
  128. package/dist/docs/guides/mcp-oauth.html +36 -36
  129. package/dist/docs/guides/opentelemetry.html +35 -35
  130. package/dist/docs/guides/slack.html +35 -35
  131. package/dist/docs/guides/webhooks.html +35 -35
  132. package/dist/docs/hashmap.json +1 -1
  133. package/dist/docs/hillclimbing.html +35 -35
  134. package/dist/docs/index.html +35 -35
  135. package/dist/docs/llms-full.txt +1338 -1282
  136. package/dist/docs/llms.txt +9 -7
  137. package/dist/docs/quickstart.html +35 -35
  138. package/dist/docs/reference/agent-config.html +42 -46
  139. package/dist/docs/reference/agent-config.md +48 -81
  140. package/dist/docs/reference/artifacts.html +39 -40
  141. package/dist/docs/reference/artifacts.md +71 -70
  142. package/dist/docs/reference/channels.html +41 -61
  143. package/dist/docs/reference/channels.md +134 -201
  144. package/dist/docs/reference/cli.html +35 -35
  145. package/dist/docs/reference/connections.html +54 -66
  146. package/dist/docs/reference/connections.md +98 -134
  147. package/dist/docs/reference/evals.html +42 -43
  148. package/dist/docs/reference/evals.md +42 -50
  149. package/dist/docs/reference/extensions.html +39 -39
  150. package/dist/docs/reference/extensions.md +10 -13
  151. package/dist/docs/reference/hooks.html +39 -67
  152. package/dist/docs/reference/hooks.md +72 -146
  153. package/dist/docs/reference/http-api.html +39 -39
  154. package/dist/docs/reference/http-api.md +137 -161
  155. package/dist/docs/reference/instructions.html +39 -39
  156. package/dist/docs/reference/instructions.md +21 -36
  157. package/dist/docs/reference/playground.html +36 -36
  158. package/dist/docs/reference/playground.md +26 -43
  159. package/dist/docs/reference/project-layout.html +38 -38
  160. package/dist/docs/reference/project-layout.md +12 -17
  161. package/dist/docs/reference/prompt.html +42 -42
  162. package/dist/docs/reference/prompt.md +18 -13
  163. package/dist/docs/reference/schedules.html +56 -91
  164. package/dist/docs/reference/schedules.md +52 -99
  165. package/dist/docs/reference/sessions.html +36 -36
  166. package/dist/docs/reference/sessions.md +36 -40
  167. package/dist/docs/reference/skills.html +38 -38
  168. package/dist/docs/reference/skills.md +15 -26
  169. package/dist/docs/reference/subagents.html +38 -38
  170. package/dist/docs/reference/subagents.md +21 -31
  171. package/dist/docs/reference/tools.html +45 -42
  172. package/dist/docs/reference/tools.md +49 -64
  173. package/dist/docs/templates/agentic-owners.html +35 -35
  174. package/dist/docs/templates/pr-autofixer.html +35 -35
  175. package/dist/docs/templates/security-reviewer.html +35 -35
  176. package/dist/docs/templates/thermo-quality-review.html +35 -35
  177. package/dist/docs/templates/thermo-review.html +35 -35
  178. package/dist/docs/templates/triage.html +35 -35
  179. package/dist/docs/troubleshooting.html +36 -36
  180. package/dist/docs/troubleshooting.md +1 -1
  181. package/dist/extensions/jev/extension.d.ts +43 -0
  182. package/dist/extensions/jev/extension.d.ts.map +1 -0
  183. package/dist/extensions/jev/extension.js +47 -0
  184. package/dist/extensions/jev/lib/evaluate.d.ts +101 -0
  185. package/dist/extensions/jev/lib/evaluate.d.ts.map +1 -0
  186. package/dist/extensions/jev/lib/evaluate.js +167 -0
  187. package/dist/extensions/jev/skills/gated-write.md +25 -0
  188. package/dist/extensions/jev/skills/questions.md +33 -0
  189. package/dist/extensions/jev/tools/evaluate.d.ts +4 -0
  190. package/dist/extensions/jev/tools/evaluate.d.ts.map +1 -0
  191. package/dist/extensions/jev/tools/evaluate.js +88 -0
  192. package/dist/extensions.d.ts +1 -1
  193. package/dist/extensions.d.ts.map +1 -1
  194. package/dist/extensions.js +2 -0
  195. package/dist/internal/advertise-tools.d.ts.map +1 -1
  196. package/dist/internal/advertise-tools.js +6 -0
  197. package/dist/internal/discovery/connections.d.ts.map +1 -1
  198. package/dist/internal/discovery/connections.js +18 -0
  199. package/dist/internal/discovery/extensions.d.ts.map +1 -1
  200. package/dist/internal/discovery/extensions.js +8 -4
  201. package/dist/internal/discovery/info.d.ts.map +1 -1
  202. package/dist/internal/discovery/info.js +1 -0
  203. package/dist/internal/hosted-delivery-protocol.d.ts +3 -0
  204. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  205. package/dist/internal/hosted-delivery-protocol.js +1 -0
  206. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  207. package/dist/internal/hosted-delivery.js +15 -25
  208. package/dist/internal/hosted-execution-diag.d.ts +12 -4
  209. package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
  210. package/dist/internal/hosted-execution-diag.js +26 -4
  211. package/dist/internal/hosted-execution-flush.d.ts +1 -0
  212. package/dist/internal/hosted-execution-flush.d.ts.map +1 -1
  213. package/dist/internal/hosted-execution-flush.js +4 -2
  214. package/dist/internal/server.d.ts.map +1 -1
  215. package/dist/internal/server.js +17 -9
  216. package/dist/internal/session-engine.d.ts +4 -1
  217. package/dist/internal/session-engine.d.ts.map +1 -1
  218. package/dist/internal/session-engine.js +28 -4
  219. package/dist/playground/assets/index-C61EWMBK.css +1 -0
  220. package/dist/playground/assets/{index-B1c1LeIf.js → index-CrMWlgUU.js} +43 -43
  221. package/dist/playground/index.html +2 -2
  222. package/dist/types.d.ts +23 -3
  223. package/dist/types.d.ts.map +1 -1
  224. package/docs/deployment.md +1 -1
  225. package/docs/evals.md +3 -0
  226. package/docs/guides/agent-to-agent.md +74 -70
  227. package/docs/guides/cloud-agents.md +1 -1
  228. package/docs/guides/grokbot-agents.md +1 -1
  229. package/docs/guides/hooks.md +116 -0
  230. package/docs/guides/jev.md +296 -0
  231. package/docs/reference/agent-config.md +48 -81
  232. package/docs/reference/artifacts.md +72 -71
  233. package/docs/reference/channels.md +135 -202
  234. package/docs/reference/connections.md +99 -135
  235. package/docs/reference/evals.md +43 -51
  236. package/docs/reference/extensions.md +10 -13
  237. package/docs/reference/hooks.md +72 -146
  238. package/docs/reference/http-api.md +137 -161
  239. package/docs/reference/instructions.md +22 -37
  240. package/docs/reference/playground.md +26 -43
  241. package/docs/reference/project-layout.md +12 -17
  242. package/docs/reference/prompt.md +20 -15
  243. package/docs/reference/schedules.md +52 -99
  244. package/docs/reference/sessions.md +36 -40
  245. package/docs/reference/skills.md +15 -26
  246. package/docs/reference/subagents.md +21 -31
  247. package/docs/reference/tools.md +49 -64
  248. package/docs/troubleshooting.md +1 -1
  249. package/package.json +8 -1
  250. package/src/bin/agent-serve.ts +2 -3
  251. package/src/channels/checks.ts +8 -0
  252. package/src/channels/origin/checks.ts +3 -1
  253. package/src/channels/slack/dispatch.ts +7 -2
  254. package/src/extensions/jev/extension.ts +95 -0
  255. package/src/extensions/jev/lib/evaluate.ts +289 -0
  256. package/src/extensions/jev/skills/gated-write.md +25 -0
  257. package/src/extensions/jev/skills/questions.md +33 -0
  258. package/src/extensions/jev/tools/evaluate.ts +90 -0
  259. package/src/extensions.ts +2 -0
  260. package/src/internal/advertise-tools.ts +6 -0
  261. package/src/internal/discovery/connections.ts +21 -0
  262. package/src/internal/discovery/extensions.ts +12 -4
  263. package/src/internal/discovery/info.ts +1 -0
  264. package/src/internal/hosted-delivery-protocol.ts +4 -0
  265. package/src/internal/hosted-delivery.ts +15 -0
  266. package/src/internal/hosted-execution-diag.ts +33 -4
  267. package/src/internal/hosted-execution-flush.ts +4 -0
  268. package/src/internal/server.ts +26 -12
  269. package/src/internal/session-engine.ts +30 -4
  270. package/src/types.ts +24 -3
  271. package/dist/docs/assets/chunks/@localSearchIndexroot.QmjDU6Jh.js +0 -1
  272. package/dist/docs/assets/chunks/channel.BjpoSbz_.js +0 -1
  273. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.BgxOlMHw.js +0 -1
  274. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.BgxOlMHw.js +0 -1
  275. package/dist/docs/assets/chunks/clone.DRuGBKZC.js +0 -1
  276. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.-43J68xB.js +0 -1
  277. package/dist/docs/assets/chunks/wardley-RL74JXVD.WRXz-Dux.js +0 -162
  278. package/dist/docs/assets/guides_agent-to-agent.md.8oDTfu-E.js +0 -30
  279. package/dist/docs/assets/guides_agent-to-agent.md.8oDTfu-E.lean.js +0 -1
  280. package/dist/docs/assets/reference_agent-config.md.DGPyw7ms.js +0 -40
  281. package/dist/docs/assets/reference_artifacts.md.Bu_4HmsD.js +0 -19
  282. package/dist/docs/assets/reference_artifacts.md.Bu_4HmsD.lean.js +0 -1
  283. package/dist/docs/assets/reference_channels.md.nFWbzAic.js +0 -43
  284. package/dist/docs/assets/reference_channels.md.nFWbzAic.lean.js +0 -1
  285. package/dist/docs/assets/reference_evals.md.DNJzM_yf.lean.js +0 -1
  286. package/dist/docs/assets/reference_hooks.md.B7uzNENk.js +0 -73
  287. package/dist/docs/assets/reference_http-api.md.CduHavZ2.js +0 -11
  288. package/dist/docs/assets/reference_instructions.md.CU1My5My.js +0 -14
  289. package/dist/docs/assets/reference_instructions.md.CU1My5My.lean.js +0 -1
  290. package/dist/docs/assets/reference_playground.md.Ch2d0Iqi.js +0 -1
  291. package/dist/docs/assets/reference_playground.md.Ch2d0Iqi.lean.js +0 -1
  292. package/dist/docs/assets/reference_project-layout.md.BGhgpy9V.js +0 -19
  293. package/dist/docs/assets/reference_prompt.md.Ccp0R53H.js +0 -1
  294. package/dist/docs/assets/reference_prompt.md.Ccp0R53H.lean.js +0 -1
  295. package/dist/docs/assets/reference_schedules.md.B2Nm6FaD.js +0 -82
  296. package/dist/docs/assets/reference_schedules.md.B2Nm6FaD.lean.js +0 -1
  297. package/dist/docs/assets/reference_sessions.md.1_6Vyv7x.js +0 -1
  298. package/dist/docs/assets/reference_skills.md.DjQkRefx.js +0 -15
  299. package/dist/docs/assets/reference_subagents.md.BHsSMMyO.js +0 -10
  300. package/dist/docs/assets/troubleshooting.md.mnfFG2Em.js +0 -1
  301. package/dist/playground/assets/index-CK2LX3iD.css +0 -1
  302. /package/dist/docs/assets/{deployment.md.D2jQZuFx.lean.js → deployment.md.D2YX7u_I.lean.js} +0 -0
  303. /package/dist/docs/assets/{guides_cloud-agents.md.Cp1O3u-X.lean.js → guides_cloud-agents.md.BPJqTZjT.lean.js} +0 -0
  304. /package/dist/docs/assets/{guides_grokbot-agents.md.CMhZNdEU.lean.js → guides_grokbot-agents.md.CzV715v8.lean.js} +0 -0
  305. /package/dist/docs/assets/{troubleshooting.md.mnfFG2Em.lean.js → troubleshooting.md.HY95rCCz.lean.js} +0 -0
@@ -1,30 +0,0 @@
1
- import{_ as e,c as a,o as t,a3 as i}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Agent-to-agent","description":"Let one Agent SDK agent consult an independent specialist, continue its session, or call its deterministic tools.","frontmatter":{"title":"Agent-to-agent","description":"Let one Agent SDK agent consult an independent specialist, continue its session, or call its deterministic tools."},"headers":[],"relativePath":"guides/agent-to-agent.md","filePath":"guides/agent-to-agent.md"}'),n={name:"guides/agent-to-agent.md"};function l(o,s,h,p,r,d){return t(),a("div",null,[...s[0]||(s[0]=[i(`<h1 id="agent-to-agent" tabindex="-1">Agent-to-agent <a class="header-anchor" href="#agent-to-agent" aria-label="Permalink to &quot;Agent-to-agent&quot;">​</a></h1><p>A peer connection lets one agent ask another agent on the same host for help. The specialist keeps its own instructions, tools, and session, while the caller decides when to delegate and returns the answer to the user.</p><h2 id="how-do-i-wire-two-agents" tabindex="-1">How do I wire two agents? <a class="header-anchor" href="#how-do-i-wire-two-agents" aria-label="Permalink to &quot;How do I wire two agents?&quot;">​</a></h2><p>Put both projects under one directory, then point the concierge at the specialist&#39;s mount slug. When a user asks about weather, the concierge calls the peer&#39;s <code>ask</code> tool, the weather agent runs in its own context, and the concierge returns that answer.</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>agents/</span></span>
2
- <span class="line"><span> concierge/</span></span>
3
- <span class="line"><span> agent/instructions.md</span></span>
4
- <span class="line"><span> agent/mcp-connections/weather.ts</span></span>
5
- <span class="line"><span> weather-agent/</span></span>
6
- <span class="line"><span> agent/agent.ts</span></span>
7
- <span class="line"><span> agent/instructions.md</span></span></code></pre></div><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// agents/concierge/agent/mcp-connections/weather.ts</span></span>
8
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineConnection } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july/connections&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
9
- <span class="line"></span>
10
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineConnection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
11
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> agent: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;weather-agent&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
12
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;Delegate weather questions to the weather specialist.&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
13
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>Give the concierge a narrow routing rule:</p><div class="language-md vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">md</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">When a request needs current weather, ask the </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\`weather\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> peer. Return its</span></span>
14
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">answer without delegating the same request again.</span></span></code></pre></div><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> ./agents</span></span>
15
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">agent-sdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> chat</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --url</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> http://127.0.0.1:3000/concierge</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
16
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;What&#39;s the weather in Paris right now?&quot;</span></span></code></pre></div><p>The connection filename becomes the MCP server name. The <code>agent</code> value is the specialist&#39;s mount slug, normally its directory name.</p><h2 id="continue-the-specialist-s-conversation" tabindex="-1">Continue the specialist&#39;s conversation <a class="header-anchor" href="#continue-the-specialist-s-conversation" aria-label="Permalink to &quot;Continue the specialist&#39;s conversation&quot;">​</a></h2><p>The first <code>ask</code> returns a peer <code>sessionId</code>. Pass that ID into the next <code>ask</code> when the specialist should remember its earlier work instead of starting with fresh context.</p><div class="language-json vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">{</span></span>
17
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> &quot;message&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;How does that compare with tomorrow?&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
18
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> &quot;sessionId&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;&lt;session-id&gt;&quot;</span></span>
19
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>The peer owns this session. Follow-ups resume its instructions and tool history without merging them into the concierge&#39;s conversation.</p><h2 id="wait-for-long-running-specialist-work" tabindex="-1">Wait for long-running specialist work <a class="header-anchor" href="#wait-for-long-running-specialist-work" aria-label="Permalink to &quot;Wait for long-running specialist work&quot;">​</a></h2><p><code>ask</code> waits for a bounded time. If the specialist is still working, it returns <code>status: &quot;running&quot;</code> with the session ID, allowing the caller to do other work and check again later.</p><div class="language-json vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">{</span></span>
20
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> &quot;sessionId&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;&lt;session-id&gt;&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
21
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> &quot;waitSeconds&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">20</span></span>
22
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>Call the peer&#39;s <code>check</code> tool with that input. It returns the final reply when the turn settles, or another running status when more time is needed.</p><h2 id="call-a-deterministic-peer-tool" tabindex="-1">Call a deterministic peer tool <a class="header-anchor" href="#call-a-deterministic-peer-tool" aria-label="Permalink to &quot;Call a deterministic peer tool&quot;">​</a></h2><p>When the specialist has a server tool and no second model turn should make a decision, call its <code>call_tool</code> endpoint through the peer connection. This example runs <code>get_forecast</code> in the weather agent&#39;s workspace and returns its structured result to the concierge tool.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ctx.host.mcp.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">callTool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;weather&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;call_tool&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
23
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> toolName: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;get_forecast&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
24
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> input: { city: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;Paris&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
25
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
26
- <span class="line"></span>
27
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
28
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ok: result.isError </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
29
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> forecast: result.structuredContent </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">??</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
30
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><p><code>call_tool</code> appears only when the peer declares at least one deterministic server tool.</p><h2 id="peer-or-subagent" tabindex="-1">Peer or subagent? <a class="header-anchor" href="#peer-or-subagent" aria-label="Permalink to &quot;Peer or subagent?&quot;">​</a></h2><p>Use a <a href="./../reference/subagents.html">subagent</a> to split one agent&#39;s job into roles that share its project. Use a peer when the specialist is a complete agent you would also run, inspect, or expose on its own.</p><table tabindex="0"><thead><tr><th></th><th>Subagent</th><th>Peer</th></tr></thead><tbody><tr><td>Context</td><td>Child role inside one agent</td><td>Independent agent and session</td></tr><tr><td>Tools and connections</td><td>Inherits the parent project</td><td>Owns its project surface</td></tr><tr><td>Reachability</td><td>Parent only</td><td>Other co-hosted agents and MCP clients</td></tr></tbody></table><h2 id="peer-sessions" tabindex="-1">Peer sessions <a class="header-anchor" href="#peer-sessions" aria-label="Permalink to &quot;Peer sessions&quot;">​</a></h2><p>Calls through <code>ask</code> create sessions on the peer&#39;s <code>mcp</code> channel. They use the caller&#39;s authenticated principal and appear in the peer&#39;s playground, so the same authorization boundary applies to starts, follow-ups, and checks.</p><p>There is no automatic recursion guard between peers. Give each caller a one-way routing rule so agent A cannot delegate the same work to B and receive it back from B.</p><h2 id="run-peers-on-one-host" tabindex="-1">Run peers on one host <a class="header-anchor" href="#run-peers-on-one-host" aria-label="Permalink to &quot;Run peers on one host&quot;">​</a></h2><p>Peers require the default multi-agent layout and one shared <code>serve</code> process. Unknown slugs and self-references fail at startup. Cursor-managed hosting deploys one agent per slug, so use subagents there instead of peer connections.</p><p>For a self-hosted cloud-runtime caller, expose the shared process with <code>--public-url</code> and protect it with <code>--bearer-token</code>. The <a href="./../deployment.html">Deployment guide</a> owns that hosting setup.</p><h2 id="related" tabindex="-1">Related <a class="header-anchor" href="#related" aria-label="Permalink to &quot;Related&quot;">​</a></h2><ul><li><a href="./../reference/connections.html#peer-mcp-connection">MCP connections</a>: peer configuration and connection naming</li><li><a href="./../reference/http-api.html#mcp-endpoint">MCP endpoint</a>: exact <code>ask</code>, <code>check</code>, and <code>call_tool</code> schemas</li><li><a href="./../reference/subagents.html">Subagents</a>: specialists inside one agent</li><li><a href="./../deployment.html">Deployment</a>: secure shared-host setup</li></ul>`,33)])])}const g=e(n,[["render",l]]);export{k as __pageData,g as default};
@@ -1 +0,0 @@
1
- import{_ as e,c as a,o as t,a3 as i}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Agent-to-agent","description":"Let one Agent SDK agent consult an independent specialist, continue its session, or call its deterministic tools.","frontmatter":{"title":"Agent-to-agent","description":"Let one Agent SDK agent consult an independent specialist, continue its session, or call its deterministic tools."},"headers":[],"relativePath":"guides/agent-to-agent.md","filePath":"guides/agent-to-agent.md"}'),n={name:"guides/agent-to-agent.md"};function l(o,s,h,p,r,d){return t(),a("div",null,[...s[0]||(s[0]=[i("",33)])])}const g=e(n,[["render",l]]);export{k as __pageData,g as default};
@@ -1,40 +0,0 @@
1
- import{_ as e,c as t,o as i,a3 as a}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Agent config","description":"defineAgent at agent/agent.ts: the model, the local and cloud runtimes, and serving programmatically.","frontmatter":{"title":"Agent config","description":"defineAgent at agent/agent.ts: the model, the local and cloud runtimes, and serving programmatically."},"headers":[],"relativePath":"reference/agent-config.md","filePath":"reference/agent-config.md"}'),n={name:"reference/agent-config.md"};function o(l,s,d,r,h,c){return i(),t("div",null,[...s[0]||(s[0]=[a(`<h1 id="agent-config-agent-agent-ts" tabindex="-1">Agent config (<code>agent/agent.ts</code>) <a class="header-anchor" href="#agent-config-agent-agent-ts" aria-label="Permalink to &quot;Agent config (\`agent/agent.ts\`)&quot;">​</a></h1><p><code>agent/agent.ts</code> default-exports <code>defineAgent(config)</code>: which model runs the agent, where turns execute, and runtime-specific defaults. Everything is optional on the root agent.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineAgent } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
2
- <span class="line"></span>
3
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineAgent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
4
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> model: {</span></span>
5
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;grok-4.5&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
6
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> params: [</span></span>
7
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;effort&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, value: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;high&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
8
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;fast&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, value: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;true&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
9
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ],</span></span>
10
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// optional; this is the default</span></span>
11
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> runtime: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;local&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// default, or &quot;cloud&quot;</span></span>
12
- <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // cloud: {</span></span>
13
- <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // repos: [{ url: &quot;https://github.com/org/repo&quot;, startingRef: &quot;main&quot; }],</span></span>
14
- <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // },</span></span>
15
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="fields-on-defineagent" tabindex="-1">Fields on <code>defineAgent</code> <a class="header-anchor" href="#fields-on-defineagent" aria-label="Permalink to &quot;Fields on \`defineAgent\`&quot;">​</a></h2><p><code>defineAgent</code> accepts these fields.</p><table tabindex="0"><thead><tr><th>Field</th><th>Type</th><th>Meaning</th></tr></thead><tbody><tr><td><code>model</code></td><td>string or <code>{ id, params }</code></td><td>Cursor model for turns. Defaults to <code>grok-4.5</code> with <code>effort=high</code>, <code>fast=true</code> on the root agent. Subagents omit it to inherit.</td></tr><tr><td><code>name</code></td><td>string</td><td>Display name override. Defaults to the package name or directory name.</td></tr><tr><td><code>description</code></td><td>string</td><td>What the agent is for. Required on subagents; the parent model reads it to decide when to delegate. Documentation-only on the root.</td></tr><tr><td><code>instructions</code></td><td>string</td><td>Inline instructions. Prefer <code>instructions.md</code>; this exists for subagents and generated configs.</td></tr><tr><td><code>runtime</code></td><td><code>&quot;local&quot;</code> or <code>&quot;cloud&quot;</code></td><td>Where turns execute. Default <code>&quot;local&quot;</code>.</td></tr><tr><td><code>cloud</code></td><td>object</td><td>Cloud agent defaults: repos, env, envVars, forwarded to the Cursor SDK. Used when <code>runtime</code> is <code>&quot;cloud&quot;</code>, and as the base merged under per-session <code>cloud</code> send options.</td></tr><tr><td><code>local</code></td><td><code>{ cwd?, workspaceDir?, sandbox? }</code></td><td>Local harness defaults; ignored for cloud turns. See <a href="#local-options">Local options</a>.</td></tr><tr><td><code>hosting</code></td><td><code>{ egressDomains?, secretNames? }</code></td><td>Managed-hosting declarations read by <code>agent-sdk deploy</code>: the pod&#39;s egress allowlist and the secret names the agent expects. Ignored by local serving.</td></tr><tr><td><code>concurrency</code></td><td><code>{ maxRunningTurns? }</code></td><td>Engine-wide turn admission limit. See <a href="#concurrency">Concurrency</a>.</td></tr><tr><td><code>builtinTools</code></td><td><code>{ reminders? }</code></td><td>Framework-provided model-facing tools, opted in per capability. See <a href="#built-in-tools">Built-in tools</a>.</td></tr><tr><td><code>tools</code></td><td><code>ToolName[]</code></td><td>Allowlist of built-in harness tools offered to the model. Unset = the model&#39;s full standard toolset. See <a href="#allowlist-built-in-harness-tools">Allowlist built-in harness tools</a>.</td></tr></tbody></table><h2 id="choose-a-model" tabindex="-1">Choose a model <a class="header-anchor" href="#choose-a-model" aria-label="Permalink to &quot;Choose a model&quot;">​</a></h2><p><code>model</code> is a Cursor model id string, or <code>{ id, params }</code>. Effort and speed are params, not id suffixes. The SDK rejects suffix-style ids like <code>grok-4.5-fast</code>:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">model</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
16
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> id</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;grok-4.5&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
17
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: [</span></span>
18
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;effort&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, value: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;high&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
19
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;fast&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, value: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;true&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
20
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ],</span></span>
21
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>A plain string works when you don&#39;t need params:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">model</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;composer-2.5&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span></code></pre></div><h2 id="choose-a-runtime" tabindex="-1">Choose a runtime <a class="header-anchor" href="#choose-a-runtime" aria-label="Permalink to &quot;Choose a runtime&quot;">​</a></h2><p><code>runtime: &quot;local&quot;</code> (the default) runs turns on the Cursor SDK harness on this machine. Server tools, skills, sandbox seeds, and tool approvals all apply.</p><p><code>runtime: &quot;cloud&quot;</code> runs turns on Cursor cloud agents (<code>bc-…</code> ids). Pass a <code>cloud</code> block with the repos the VM carries. Server tools stay reachable over authenticated HTTP MCP back to the serve host when <code>--public-url</code> or <code>--cloud-tools-url</code> is set (omitted with a warning otherwise), and instructions and agent-tool catalogs are prepended to the first prompt, because the local session workspace is not the cloud VM.</p><p><code>validate</code> warns when <code>runtime: &quot;cloud&quot;</code> is combined with agent tools (they are described on the first prompt instead of written to the VM), when skills or sandbox seeds are present (they sync onto an Agent Store rather than the session workspace), and when the <code>cloud</code> block is missing.</p><h2 id="local-options" tabindex="-1">Local options <a class="header-anchor" href="#local-options" aria-label="Permalink to &quot;Local options&quot;">​</a></h2><p><code>local</code> sets local-harness defaults, all ignored for cloud turns.</p><p><code>local.workspaceDir</code> points every session at one shared harness cwd, for agents that work inside an existing checkout. It takes precedence over <code>cwd</code>, and a per-send <code>workspaceDir</code> still wins over both. The SDK keys its local executor (rules, skills, MCP, ignore mappings) on the harness cwd, so a shared directory resolves the workspace once per serve process instead of once per session. The trade: sessions share a working tree, so a file one turn writes is visible to the next.</p><p><code>local.sandbox</code> runs the harness inside Cursor&#39;s local sandbox. It&#39;s off by default, matching the SDK: shell then auto-approves and inherits the serve process environment, including any credentials the host holds. Turn it on for agents whose turns read untrusted input (webhook payloads, PR diffs, inbound chat); it&#39;s a real tool boundary rather than a prompt-level one.</p><h3 id="local-cwd" tabindex="-1">Local cwd <a class="header-anchor" href="#local-cwd" aria-label="Permalink to &quot;Local cwd&quot;">​</a></h3><p><code>local.cwd</code> sets the parent directory for local harness workspaces. Each session uses <code>&lt;cwd&gt;/&lt;sessionId&gt;</code> unless a per-send <code>workspaceDir</code> overrides it.</p><p>Session workspaces are real Cursor project directories. The harness loads <code>AGENTS.md</code> and <code>.cursor</code> config from ancestor directories. An agent nested in another git repo (a monorepo package) defaults to a per-project cache directory under <code>~/.cache</code> when you omit <code>cwd</code>, so the enclosing checkout does not leak rules, skills, or MCP servers into the turn. A standalone git root keeps the in-project session workspace. Point <code>cwd</code> at a checkout only when the agent should inherit that tree.</p><h2 id="allowlist-built-in-harness-tools" tabindex="-1">Allowlist built-in harness tools <a class="header-anchor" href="#allowlist-built-in-harness-tools" aria-label="Permalink to &quot;Allowlist built-in harness tools&quot;">​</a></h2><p>Use <code>tools</code> to limit which built-in Cursor harness tools the model can call. Omit it to keep the standard toolset. When you set it, the model gets only the tools you list. An empty list disables all native built-in tools. Because this field is an allowlist, new platform tools stay disabled until you add them.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineAgent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
22
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> model: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;composer-2.5&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
23
- <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Read-only triage agent: search and read only.</span></span>
24
- <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // No shell, no edits, no subagents.</span></span>
25
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> tools: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;read&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;grep&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;glob&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;ls&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
26
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>The Agent SDK always adds <code>&quot;mcp&quot;</code> to a configured allowlist. Authored server tools in <code>agent/tools/</code> use MCP to reach the model. MCP can also expose declared connections and servers from the harness directory&#39;s ambient <code>.cursor</code> config. To exclude a checkout&#39;s MCP servers, point <code>local.cwd</code> outside the checkout. See <a href="#local-cwd">Local cwd</a>. <code>local.sandbox</code> makes MCP tool calls fail closed.</p><p>Use the SDK&#39;s public tool names, including <code>&quot;shell&quot;</code>, <code>&quot;read&quot;</code>, <code>&quot;edit&quot;</code>, <code>&quot;grep&quot;</code>, <code>&quot;glob&quot;</code>, <code>&quot;ls&quot;</code>, and <code>&quot;task&quot;</code>. Unknown names fail the turn with a <code>ConfigurationError</code>.</p><p>Two names have broader effects:</p><ul><li><code>&quot;shell&quot;</code> also grants shell input. Tools with <code>execution: &quot;agent&quot;</code> need it to run their scripts. Discovery warns when your allowlist would prevent those tools from running.</li><li><code>&quot;task&quot;</code> lets the root agent start subagents. Each subagent keeps its own curated toolset.</li></ul><p>Tool allowlists work only with the local runtime. A <code>runtime: &quot;cloud&quot;</code> agent that sets <code>tools</code> fails at serve startup. The Agent SDK also refuses per-send cloud sessions from a hybrid agent with an allowlist. It won&#39;t run those sessions with unrestricted tool access.</p><p>The allowlist controls which tools the model can call. It does not isolate the serve host. For agents that process untrusted input, also set <code>local: { sandbox: true }</code>.</p><h2 id="cloud-options" tabindex="-1">Cloud options <a class="header-anchor" href="#cloud-options" aria-label="Permalink to &quot;Cloud options&quot;">​</a></h2><p>Cloud agent defaults forwarded to the Cursor SDK: <code>repos</code> (each <code>{ url, startingRef? }</code>), environment selection, <code>envVars</code>, and the rest. A local agent uses the same block as the base config when a channel opens a cloud-attached session per send (the <code>cloud</code> option on <a href="./channels.html#handler-arguments"><code>send</code></a>).</p><h2 id="concurrency" tabindex="-1">Concurrency <a class="header-anchor" href="#concurrency" aria-label="Permalink to &quot;Concurrency&quot;">​</a></h2><p><code>concurrency.maxRunningTurns</code> caps how many model turns run at once across all of the agent&#39;s sessions (positive integer, hard cap 200). When every slot is busy, newly admitted turns queue FIFO instead of failing: the stream records a durable <code>turn.queued</code> event with the queue position, <code>GET /v1/sessions</code> reports <code>queued: true</code>, and each queued turn starts as soon as a slot frees. A queued turn still counts as running for busy semantics: follow-ups preempt it, and direct write-effect tool calls get <code>409 session_busy</code>. Omit for unlimited.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineAgent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
27
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> concurrency: { maxRunningTurns: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
28
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="built-in-tools" tabindex="-1">Built-in tools <a class="header-anchor" href="#built-in-tools" aria-label="Permalink to &quot;Built-in tools&quot;">​</a></h2><p><code>builtinTools</code> opts into framework-provided model-facing tools. Each enabled capability materializes as ordinary server tools at discovery time, so turns, direct calls, <code>info</code>, and the playground treat them like authored tools. Authored tools with the same name win, with a warning, and like all server tools they run on the local runtime.</p><p><code>builtinTools: { reminders: true }</code> adds three tools bound to the current conversation over <code>host.reminders</code>: <code>reminders_create</code>, <code>reminders_list</code>, and <code>reminders_cancel</code>. Sessions without a continuation key can&#39;t arm reminders. See <a href="./schedules.html#reminders">Schedules and reminders</a>.</p><h2 id="generate-instructions" tabindex="-1">Generate instructions <a class="header-anchor" href="#generate-instructions" aria-label="Permalink to &quot;Generate instructions&quot;">​</a></h2><p>When the system prompt must be computed, author <code>agent/instructions.ts</code> instead of markdown:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineInstructions } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
29
- <span class="line"></span>
30
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineInstructions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
31
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> markdown: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`You are the on-call assistant for \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">process</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">env</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">TEAM_NAME</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}.\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
32
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>The directory form and the runtime mapping are in <a href="./instructions.html">Instructions</a>.</p><h2 id="serve-programmatically" tabindex="-1">Serve programmatically <a class="header-anchor" href="#serve-programmatically" aria-label="Permalink to &quot;Serve programmatically&quot;">​</a></h2><p><code>serve(dirOrProject, options)</code> embeds the server in your own process:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { serve } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
33
- <span class="line"></span>
34
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> handle</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> serve</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;./my-agent&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
35
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> port: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
36
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> apiKey: process.env.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">CURSOR_API_KEY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// optional; see credential order</span></span>
37
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
38
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`listening on \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handle</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">url</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
39
- <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// handle.callTool(...), handle.dispatchSchedule(&quot;heartbeat&quot;),</span></span>
40
- <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// handle.createReminder(...), handle.project, await handle.close()</span></span></code></pre></div><p>Host settings match the documented <a href="./cli.html">CLI</a> <code>serve</code> flags. <code>serve()</code> also accepts <code>discovery</code> (project-loading options) and <code>mode: &quot;single&quot; | &quot;multi&quot;</code>. The Cursor credential resolves in one order everywhere: explicit <code>apiKey</code>, then <code>CURSOR_API_KEY</code>, then <code>CURSOR_API_KEY_FILE</code> (hosted default <code>/run/cursor/secrets/CURSOR_API_KEY</code> when unset), then <code>CURSOR_SERVICE_ACCOUNT_KEY</code>, then the key stored by <code>agent-sdk login</code>. On a host that has both the service-account key and a bind file, the file principal wins.</p><h2 id="what-s-next" tabindex="-1">What&#39;s next <a class="header-anchor" href="#what-s-next" aria-label="Permalink to &quot;What&#39;s next&quot;">​</a></h2><p>Continue with these pages:</p><ul><li><a href="./instructions.html">Instructions</a>: the required half of a minimal agent</li><li><a href="./cli.html">CLI</a>: the <code>serve</code> flags <code>serve()</code> accepts</li></ul>`,50)])])}const u=e(n,[["render",o]]);export{k as __pageData,u as default};
@@ -1,19 +0,0 @@
1
- import{_ as a,c as e,o as i,a3 as t}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Artifacts","description":"Tag durable outputs (reviewed PRs, reports) so they persist across sessions, stream as events, and list over HTTP.","frontmatter":{"title":"Artifacts","description":"Tag durable outputs (reviewed PRs, reports) so they persist across sessions, stream as events, and list over HTTP."},"headers":[],"relativePath":"reference/artifacts.md","filePath":"reference/artifacts.md"}'),n={name:"reference/artifacts.md"};function d(o,s,r,l,h,p){return i(),e("div",null,[...s[0]||(s[0]=[t(`<h1 id="artifacts" tabindex="-1">Artifacts <a class="header-anchor" href="#artifacts" aria-label="Permalink to &quot;Artifacts&quot;">​</a></h1><p>An artifact marks a durable output the agent produced: a reviewed PR URL, a generated report, a decision record. Sessions come and go; artifacts persist across them, capped and listable, so the people supervising an agent see what it shipped without replaying event streams.</p><h2 id="declare-kinds" tabindex="-1">Declare kinds <a class="header-anchor" href="#declare-kinds" aria-label="Permalink to &quot;Declare kinds&quot;">​</a></h2><p>Author <code>agent/artifacts.ts</code> with <code>defineArtifacts</code> from <code>@cursor/july/artifacts</code>:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { z } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;zod&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
2
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineArtifacts } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july/artifacts&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
3
- <span class="line"></span>
4
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineArtifacts</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
5
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> kinds: {</span></span>
6
- <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;reviewed-pr&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
7
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;A pull request this agent reviewed.&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
8
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> schema: z.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ url: z.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(), verdict: z.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() }),</span></span>
9
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
10
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> report: { description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;A generated report.&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
11
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
12
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> agentTool: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
13
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p><code>defineArtifacts</code> accepts three fields. <code>kinds</code> declares the artifact kinds: with kinds declared, <code>tag</code> accepts only these; with none, any kind string is accepted freeform. Each kind&#39;s <code>description</code> says what it holds and doubles as the model-facing prompt for <code>tag_artifact</code>. An optional Zod <code>schema</code> validates payloads before they persist (the parsed output is stored, so defaults and coercions apply). <code>agentTool</code> exposes the model-facing <code>tag_artifact</code> tool generated from the kinds registry; it requires at least one declared kind. <code>max</code> is the retention cap, default 1000: on insert past the cap, the oldest-updated artifact is evicted.</p><h2 id="tag-from-host-code" tabindex="-1">Tag from host code <a class="header-anchor" href="#tag-from-host-code" aria-label="Permalink to &quot;Tag from host code&quot;">​</a></h2><p>Every handler surface carries <code>ctx.artifacts</code> (or <code>args.artifacts</code>), an <code>ArtifactsApi</code> with <code>tag</code> and <code>list</code>: tools, hooks, channel route handlers and <code>onStart</code>, schedule <code>run</code> handlers, and reminder <code>run</code> handlers. Tool and hook facades are session-bound, so <code>tag</code> auto-fills the <code>sessionId</code> (and <code>turnId</code> when known). Channel, schedule, and reminder facades are unbound; pass <code>sessionId</code> in the tag input to attribute one.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ctx.artifacts.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">tag</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
14
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> kind: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;reviewed-pr&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
15
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> key: prUrl,</span></span>
16
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> title: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Reviewed \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">prUrl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
17
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> data: { url: prUrl, verdict: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;approve&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
18
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p><code>key</code> is the upsert handle: tagging the same key again replaces the record instead of creating a new one, so re-reviewing a PR updates one row. A <code>contents</code> payload (string or bytes, with an optional <code>contentType</code>) attaches a file or blob served at <code>GET /v1/artifacts/:id/content</code>; re-tagging a keyed artifact without <code>contents</code> keeps the existing payload.</p><h2 id="let-the-model-tag" tabindex="-1">Let the model tag <a class="header-anchor" href="#let-the-model-tag" aria-label="Permalink to &quot;Let the model tag&quot;">​</a></h2><p>With <code>agentTool: true</code>, the <code>tag_artifact</code> server tool materializes from the kinds registry. Its description tells the model to tag notable outputs and lists each kind with its description, and its input schema is a discriminated union over the declared kinds, so a schema&#39;d kind is validated exactly like a host-side tag. An authored tool named <code>tag_artifact</code> shadows the built-in, with a warning.</p><h2 id="observe-and-list" tabindex="-1">Observe and list <a class="header-anchor" href="#observe-and-list" aria-label="Permalink to &quot;Observe and list&quot;">​</a></h2><p>Tagging emits an <code>artifact.tagged</code> event on the attributed session&#39;s stream, carrying the record: <code>id</code>, <code>kind</code>, <code>key</code>, <code>title</code>, <code>data</code>, and <code>source</code> (<code>&quot;host&quot;</code> for host code, <code>&quot;model&quot;</code> for <code>tag_artifact</code>). Hooks, channel <code>events</code>, and evals see it like any other <a href="./sessions.html#which-events-can-i-stream">stream event</a>.</p><p>Over HTTP:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">curl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;http://127.0.0.1:3000/&lt;slug&gt;/v1/artifacts?kind=reviewed-pr&amp;limit=20&#39;</span></span>
19
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">curl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;http://127.0.0.1:3000/&lt;slug&gt;/v1/artifacts/&lt;id&gt;/content&#39;</span></span></code></pre></div><p><code>GET /v1/artifacts</code> returns records newest-updated first, filterable by <code>kind</code> and <code>sessionId</code>. Session ownership applies, same as <code>/v1/sessions</code>. The playground renders tagged artifacts too.</p><h2 id="gate-evals-on-tagging" tabindex="-1">Gate evals on tagging <a class="header-anchor" href="#gate-evals-on-tagging" aria-label="Permalink to &quot;Gate evals on tagging&quot;">​</a></h2><p><code>t.taggedArtifact(kind?, predicate?)</code> gates an eval on at least one artifact tagged during the test turn, optionally of one kind and matching a predicate over the record:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">t.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">taggedArtifact</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;reviewed-pr&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">record</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> record.source </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;model&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h2 id="what-s-next" tabindex="-1">What&#39;s next <a class="header-anchor" href="#what-s-next" aria-label="Permalink to &quot;What&#39;s next&quot;">​</a></h2><p>Continue with these pages:</p><ul><li><a href="./sessions.html">Sessions and streaming</a>: the <code>artifact.tagged</code> event in the full vocabulary</li><li><a href="./tools.html">Tools</a>: the <code>ctx</code> that carries <code>artifacts</code></li><li><a href="./../evals.html">Evals</a>: the assertions <code>taggedArtifact</code> sits beside</li></ul>`,23)])])}const g=a(n,[["render",d]]);export{k as __pageData,g as default};
@@ -1 +0,0 @@
1
- import{_ as a,c as e,o as i,a3 as t}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Artifacts","description":"Tag durable outputs (reviewed PRs, reports) so they persist across sessions, stream as events, and list over HTTP.","frontmatter":{"title":"Artifacts","description":"Tag durable outputs (reviewed PRs, reports) so they persist across sessions, stream as events, and list over HTTP."},"headers":[],"relativePath":"reference/artifacts.md","filePath":"reference/artifacts.md"}'),n={name:"reference/artifacts.md"};function d(o,s,r,l,h,p){return i(),e("div",null,[...s[0]||(s[0]=[t("",23)])])}const g=a(n,[["render",d]]);export{k as __pageData,g as default};
@@ -1,43 +0,0 @@
1
- import{_ as s,c as t,o as a,a3 as i}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Channels","description":"The authoring reference for defineChannel, the built-in HTTP channel, route schemas, handler args, and the auth policies.","frontmatter":{"title":"Channels","description":"The authoring reference for defineChannel, the built-in HTTP channel, route schemas, handler args, and the auth policies."},"headers":[],"relativePath":"reference/channels.md","filePath":"reference/channels.md"}'),n={name:"reference/channels.md"};function o(h,e,l,r,d,c){return a(),t("div",null,[...e[0]||(e[0]=[i(`<h1 id="channels" tabindex="-1">Channels <a class="header-anchor" href="#channels" aria-label="Permalink to &quot;Channels&quot;">​</a></h1><p>A channel is the surface an agent lives on. The built-in HTTP session channel is always mounted. Custom channels declare their own routes under <code>/v1/channels/&lt;id&gt;</code>. The Slack and GitHub packs are prebuilt channels with platform transports. GitLab and Bitbucket packs cover their hosted and self-managed products. This page is the authoring reference; for the walkthrough, see the <a href="./../guides/webhooks.html">Webhooks guide</a>.</p><h2 id="built-in-http-channel" tabindex="-1">Built-in HTTP channel <a class="header-anchor" href="#built-in-http-channel" aria-label="Permalink to &quot;Built-in HTTP channel&quot;">​</a></h2><p>It&#39;s always mounted, under <code>/&lt;slug&gt;</code> in the default multi-agent layout: session create, follow-up, stream, stop, the sessions list, approvals, deterministic tool calls, health, and info. For the route-by-route contract, see the <a href="./http-api.html">HTTP API reference</a>.</p><h2 id="define-a-custom-channel" tabindex="-1">Define a custom channel <a class="header-anchor" href="#define-a-custom-channel" aria-label="Permalink to &quot;Define a custom channel&quot;">​</a></h2><p>Author <code>agent/channels/&lt;id&gt;.ts</code>. The filename is the channel id and the route prefix:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineChannel, POST } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july/channels&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
2
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { z } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;zod&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
3
- <span class="line"></span>
4
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineChannel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
5
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> routes: [</span></span>
6
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> POST</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;/review&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
7
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> description: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;Review a pull request on this channel&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
8
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> bodySchema: z.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">object</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
9
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> message: z.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
10
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> prUrl: z.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">url</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
11
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> thread: z.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">().</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">optional</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
12
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }),</span></span>
13
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> handler</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">_req</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">callTool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">send</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">body</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
14
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> prepared</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> callTool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;inspect_pr&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
15
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> prUrl: body.prUrl,</span></span>
16
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
17
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (prepared.isError) {</span></span>
18
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Response.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
19
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { error: prepared.errorMessage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">??</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;Could not inspect pull request&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
20
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { status: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">502</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
21
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
22
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
23
- <span class="line"></span>
24
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> session</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> send</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
25
- <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">body</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">message</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">\\n\\n</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">Read pr.json before answering.\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
26
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
27
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> continuationToken: body.thread </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">??</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`pr:\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">body</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">prUrl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
28
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> workspaceFiles: {</span></span>
29
- <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;pr.json&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(prepared.result, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">2</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">??</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;null&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
30
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
31
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
32
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
33
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> Response.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">json</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ sessionId: session.id });</span></span>
34
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
35
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }),</span></span>
36
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ],</span></span>
37
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> events: {</span></span>
38
- <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;message.completed&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">channel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
39
- <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // deliver the reply to the surface that owns this channel</span></span>
40
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
41
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
42
- <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // auth: [...], state: {...}, onStart(...), onStop(...)</span></span>
43
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>This example assumes <code>agent/tools/inspect_pr.ts</code> exists. The handler calls it before the model turn, so every review starts with validated PR data. It also derives a stable conversation key from the PR URL and writes the tool result to <code>pr.json</code>. Instructions can ask the model to inspect a PR, but host code guarantees it.</p><h2 id="route-verbs-and-schemas" tabindex="-1">Route verbs and schemas <a class="header-anchor" href="#route-verbs-and-schemas" aria-label="Permalink to &quot;Route verbs and schemas&quot;">​</a></h2><p><code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>PATCH</code>, and <code>DELETE</code> helpers build routes. Their schemas are Zod, enforced at compile time:</p><table tabindex="0"><thead><tr><th>Verb</th><th>Required schema</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>querySchema</code></td></tr><tr><td><code>POST</code> / <code>PUT</code> / <code>PATCH</code></td><td><code>bodySchema</code> (optional <code>querySchema</code>)</td></tr><tr><td><code>DELETE</code></td><td>both optional</td></tr></tbody></table><p>Plain JSON Schema objects won&#39;t type-check; use <code>z.object({})</code> or <code>z.unknown()</code> for intentionally open surfaces. The host validates before the handler runs. Handlers receive typed <code>args.body</code> and <code>args.query</code>, and empty POST bodies are coerced to <code>{}</code> first. Declared schemas are projected on <code>GET /v1/info</code>, which powers the playground&#39;s <strong>Try</strong> buttons and composer <strong>slash commands</strong>.</p><h2 id="handler-arguments" tabindex="-1">Handler arguments <a class="header-anchor" href="#handler-arguments" aria-label="Permalink to &quot;Handler arguments&quot;">​</a></h2><p>Handlers receive the Fetch <code>Request</code> and an args object:</p><table tabindex="0"><thead><tr><th>Member</th><th>What it is</th></tr></thead><tbody><tr><td><code>send(message, options?)</code></td><td>Run a model turn on this channel; returns the session handle (options below)</td></tr><tr><td><code>getSession(sessionId)</code></td><td>Look up an existing session on this channel</td></tr><tr><td><code>receive(channelDefinition, input)</code></td><td>Hand off to another channel (schedules use this)</td></tr><tr><td><code>callTool(name, input, options?)</code></td><td>Deterministic server-tool call (<a href="./tools.html#call-a-tool-without-a-model-turn">Tools</a>)</td></tr><tr><td><code>body</code>, <code>query</code>, <code>params</code></td><td>Validated payloads and <code>:param</code> path segments</td></tr><tr><td><code>auth</code></td><td>The <code>AuthContext</code> resolved by this route&#39;s auth chain</td></tr><tr><td><code>requestIp</code></td><td>The TCP peer address</td></tr><tr><td><code>host</code></td><td>Shared services: <code>host.mcp</code>, <code>host.github</code>, <code>host.slack</code>, <code>host.kv</code>, <code>host.files</code>, <code>host.reminders</code></td></tr><tr><td><code>waitUntil(promise)</code></td><td>Background work that outlives the response</td></tr><tr><td><code>sessionUrls(request, sessionId)</code></td><td>Absolute playground + trace URLs for a session on this mount</td></tr><tr><td><code>artifacts</code></td><td>Unbound <a href="./artifacts.html">artifacts</a> facade; pass <code>sessionId</code> in <code>tag</code> input to attribute one</td></tr></tbody></table><p><code>send</code> options: <code>continuationToken</code> (the conversation key), <code>admission</code> (<code>&quot;preempt&quot;</code> interrupts a busy session, the default; <code>&quot;coalesce&quot;</code> enqueues behind the running turn, the <a href="./sessions.html#what-happens-when-i-send-a-follow-up">Slack policy</a>), <code>workspaceFiles</code>, <code>workspaceDir</code>, <code>cloud</code> (attach cloud repos for this session), <code>auth</code> (defaults to the request principal), <code>state</code> (starting channel state for new sessions), <code>title</code> (session display title), and <code>purpose</code> (<code>&quot;eval&quot;</code> marks the session as regression traffic).</p><h2 id="events" tabindex="-1">Events <a class="header-anchor" href="#events" aria-label="Permalink to &quot;Events&quot;">​</a></h2><p>The <code>events</code> map subscribes the channel to stream events for the sessions it owns. Keys are event types from the <a href="./sessions.html#which-events-can-i-stream">event vocabulary</a>, or <code>&quot;*&quot;</code>. Handlers receive <code>(event, channel, ctx)</code>, where <code>channel.state</code> is the per-session adapter state, <code>ctx.session</code> is the session info, and <code>ctx.host</code> is the shared host services, bound to that session as in a <a href="./hooks.html#handler-context">hook</a>. This is where a channel delivers replies back to its surface.</p><h2 id="state-and-lifecycle" tabindex="-1">State and lifecycle <a class="header-anchor" href="#state-and-lifecycle" aria-label="Permalink to &quot;State and lifecycle&quot;">​</a></h2><p><code>state</code> declares the starting per-session adapter state (JSON), persisted on the session record. Routes and event handlers read and mutate it through <code>channel.state</code>. <code>onStart(args)</code> runs when the channel mounts. <code>onStop()</code> runs when the server stops.</p><p><code>onStart</code> receives the route helpers (<code>send</code>, <code>getSession</code>, <code>receive</code>, <code>callTool</code>, <code>host</code>, <code>waitUntil</code>, <code>artifacts</code>, <code>logger</code>) plus helpers for long-lived transports:</p><ul><li><code>emitAssistantMessage(sessionId, text)</code> appends an assistant message without a model turn, for host tasks that already produced the final text.</li><li><code>hasContinuationSession(token)</code> and <code>isContinuationBusy(token)</code> report whether a continuation token has a live session and whether a turn is in flight on it.</li><li><code>interruptContinuation(token)</code> stops the in-flight turn and clears coalesced follow-ups queued behind it.</li><li><code>resolveApproval(sessionId, callId, decision, auth, options?)</code> approves or denies a parked tool call, how Slack Block Kit buttons unblock a turn without the HTTP approvals route.</li></ul><h2 id="auth-policies" tabindex="-1">Auth policies <a class="header-anchor" href="#auth-policies" aria-label="Permalink to &quot;Auth policies&quot;">​</a></h2><p>Every route runs an auth-policy chain: the channel&#39;s <code>auth</code> array, or <code>[localDevStrict()]</code> when unset. A policy is a function <code>(request, info) =&gt; AuthContext | null</code> (async allowed); the first non-null wins, and a request no policy admits gets <code>401</code>.</p><table tabindex="0"><thead><tr><th>Policy</th><th>Admits</th></tr></thead><tbody><tr><td><code>localDevStrict()</code></td><td>Direct loopback callers with no proxy-forwarding headers (<code>X-Forwarded-For</code>, <code>X-Real-IP</code>, <code>Forwarded</code>, and <code>X-Forwarded-Host</code> are all rejected, so tunnels and same-host reverse proxies don&#39;t silently re-expose the route), plus a loopback <code>Host</code> header, which rejects DNS-rebinding callers that reach 127.0.0.1 with a remote hostname.</td></tr><tr><td><code>localDev()</code></td><td>Like <code>localDevStrict()</code> but without the <code>Host</code> check. An explicit, weaker opt-in.</td></tr><tr><td><code>loopbackOnly()</code></td><td>A loopback TCP peer, ignoring forwarding headers; for dev relays that legitimately carry them, like <code>gh webhook forward</code>.</td></tr><tr><td><code>bearerAuth(token)</code></td><td><code>Authorization: Bearer &lt;token&gt;</code>, compared in constant time. Also accepts a verifier function mapping a presented token to an <code>AuthContext</code>.</td></tr><tr><td><code>allowAll()</code></td><td>Everyone, as an <code>anonymous</code> principal. Only for surfaces protected upstream (an HMAC-verified webhook) or intentionally public.</td></tr><tr><td><code>publicEndpoint()</code></td><td>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.</td></tr></tbody></table><p><code>publicEndpoint()</code> applies only to custom channel routes. It does not open the built-in session or tool API.</p><p>The resolved <code>AuthContext</code> (<code>{ authenticator, principalId, principalType, attributes? }</code>) becomes the request principal. Sessions bind to the principal that created them, and follow-up, stream, and list routes enforce ownership (<code>403</code> otherwise).</p><p>Server flags interact with authored auth: <code>--bearer-token</code> swaps the default <code>localDevStrict()</code> for <code>bearerAuth(...)</code> on channels that don&#39;t author their own chain, and <code>--allow-anonymous</code> swaps it for <code>allowAll()</code>. Authored <code>auth</code> arrays always win over both. A channel that declares <code>[localDevStrict()]</code> stays loopback-only even on an <code>--allow-anonymous</code> host.</p><h2 id="first-class-channels" tabindex="-1">First class channels <a class="header-anchor" href="#first-class-channels" aria-label="Permalink to &quot;First class channels&quot;">​</a></h2><p><strong>Slack</strong> (<code>@cursor/july/channels/slack</code>): Socket Mode transport, streaming replies, engagement rules, approval cards, and a default block on Slack Connect / guest / other-workspace senders. Author <code>agent/channels/slack.ts</code> with <code>slackChannel()</code>. Guide: <a href="./../guides/slack.html">Slack</a>.</p><p><strong>GitHub</strong> (<code>@cursor/july/channels/github</code>): webhook dispatch with signature verification, per-event hooks returning <code>{ auth }</code> (a model turn), <code>{ task }</code> (host work), or <code>null</code>, and CLI tooling for replay and live forwarding. Author <code>agent/channels/github.ts</code> with <code>githubChannel()</code>. Opt-in <code>progress.commitStatus</code> and <code>progress.banner</code> converge a merge-box check and sticky PR comment from default stream events. Supports GitHub.com and GitHub Enterprise Server. Guide: <a href="./../guides/github.html">GitHub</a>.</p><p><strong>GitLab</strong> (<code>@cursor/july/channels/gitlab</code>): verified project hooks for merge requests, notes, pipelines, pushes, and custom event types. Supports GitLab.com and self-managed GitLab. Author <code>agent/channels/gitlab.ts</code> with <code>gitlabChannel()</code>. Guide: <a href="./../guides/gitlab.html">GitLab</a>.</p><p><strong>Bitbucket</strong> (<code>@cursor/july/channels/bitbucket</code>): verified repository hooks for pull requests, comments, pushes, and custom event types. Supports Bitbucket Cloud and Bitbucket Data Center through one normalized hook API. Author <code>agent/channels/bitbucket.ts</code> with <code>bitbucketChannel()</code>. Guide: <a href="./../guides/bitbucket.html">Bitbucket</a>.</p><p><strong>Deployments</strong> (<code>@cursor/july/channels/deployments</code>): pull deploy events. Declare <code>events</code> and handle each one in <code>onEvent</code>. Each event carries <code>deploySourceUri</code> and <code>deployVersion</code>. Author <code>agent/channels/deployments.ts</code> with <code>deploymentsChannel()</code>.</p><p>On Cursor-managed hosting, omit <code>deploySourceUris</code>. The deployment&#39;s watched repositories bind the event scope automatically. Name sources to narrow the scope or to drive the self-hosted pull relay. Subscribe per deploy source with <code>deploySourceUris</code> and narrow with <code>environments</code> or <code>events</code>. Each entry must match <code>Deployment.deploy_source_uri</code> as your deployment writer records it. Matching is case-insensitive but otherwise literal. It uses the host credential. A restart resumes rather than dropping events. An empty <code>deploySourceUris</code> list mounts the channel but starts no pull, so an env-configured agent stays inert until its deploy sources are set.</p><p><strong>Change Monitors</strong> (<code>@cursor/july/channels/change-monitors</code>): Change Monitor Checkpoint events. The channel publishes Factory <code>checkpoint.created</code> for every Checkpoint create. The agent filters the result (for example to the <code>issues</code> arm). The payload contains the full Checkpoint resource. This channel is scoped to Change Monitors, not generic Factory Checkpoints. There is no repository filter or resource filter. Author <code>agent/channels/change-monitors.ts</code> with <code>changeMonitorsChannel()</code>. It uses the host credential.</p><p><strong>Issues</strong> (<code>@cursor/july/channels/issues</code>): Factory issue events. The channel publishes <code>issue.created</code> for every Issue create. The agent filters if it needs a subset. The payload contains the full Issue resource. There is no repository filter or resource filter. Author <code>agent/channels/issues.ts</code> with <code>issuesChannel()</code>. It uses the host credential.</p><p>For other platforms like Discord or Teams, use the authored <code>defineChannel</code> webhook form.</p><h2 id="continuation-semantics" tabindex="-1">Continuation semantics <a class="header-anchor" href="#continuation-semantics" aria-label="Permalink to &quot;Continuation semantics&quot;">​</a></h2><p>Channels own their continuation-token format. The built-in HTTP channel mints opaque rotating tokens, Slack uses <code>channelId:threadTs</code>, and PR automations use keys like <code>pr:owner/repo#N</code>. Same token, same durable session; one active continuation per session; the HTTP channel returns <code>409</code> for stale tokens. For the full session model, see <a href="./sessions.html">Sessions</a>.</p><h2 id="what-s-next" tabindex="-1">What&#39;s next <a class="header-anchor" href="#what-s-next" aria-label="Permalink to &quot;What&#39;s next&quot;">​</a></h2><p>Continue with these pages:</p><ul><li><a href="./../guides/webhooks.html">Webhooks guide</a>: the same API, walked through</li><li><a href="./http-api.html">HTTP API</a>: session, discovery, and channel routes</li><li><a href="./sessions.html">Sessions and streaming</a>: the events channels subscribe to</li></ul>`,43)])])}const u=s(n,[["render",o]]);export{k as __pageData,u as default};
@@ -1 +0,0 @@
1
- import{_ as s,c as t,o as a,a3 as i}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Channels","description":"The authoring reference for defineChannel, the built-in HTTP channel, route schemas, handler args, and the auth policies.","frontmatter":{"title":"Channels","description":"The authoring reference for defineChannel, the built-in HTTP channel, route schemas, handler args, and the auth policies."},"headers":[],"relativePath":"reference/channels.md","filePath":"reference/channels.md"}'),n={name:"reference/channels.md"};function o(h,e,l,r,d,c){return a(),t("div",null,[...e[0]||(e[0]=[i("",43)])])}const u=s(n,[["render",o]]);export{k as __pageData,u as default};
@@ -1 +0,0 @@
1
- import{_ as i,c as a,o as e,a3 as t}from"./chunks/framework.BNw1pucY.js";const c=JSON.parse('{"title":"Evals","description":"Reference for eval discovery, cases, assertions, judges, configuration, fixtures, reporters, and runner output.","frontmatter":{"title":"Evals","description":"Reference for eval discovery, cases, assertions, judges, configuration, fixtures, reporters, and runner output."},"headers":[],"relativePath":"reference/evals.md","filePath":"reference/evals.md"}'),n={name:"reference/evals.md"};function d(l,s,h,r,p,o){return e(),a("div",null,[...s[0]||(s[0]=[t("",61)])])}const E=i(n,[["render",d]]);export{c as __pageData,E as default};
@@ -1,73 +0,0 @@
1
- import{_ as e,c as a,o as i,a3 as t}from"./chunks/framework.BNw1pucY.js";const c=JSON.parse('{"title":"Hooks","description":"Observe-only subscribers to the session event stream: audit logs, metrics, transcript mirrors, derived state.","frontmatter":{"title":"Hooks","description":"Observe-only subscribers to the session event stream: audit logs, metrics, transcript mirrors, derived state."},"headers":[],"relativePath":"reference/hooks.md","filePath":"reference/hooks.md"}'),n={name:"reference/hooks.md"};function h(o,s,l,d,r,p){return i(),a("div",null,[...s[0]||(s[0]=[t(`<h1 id="hooks" tabindex="-1">Hooks <a class="header-anchor" href="#hooks" aria-label="Permalink to &quot;Hooks&quot;">​</a></h1><p>A hook subscribes to the session event stream and runs a side effect after each event is recorded: an audit line, a metric, a copy of the transcript in your own store, or derived state for later turns. Hooks run in the serving process for every session of the agent, on local and cloud runtime turns alike.</p><p>Hooks observe. They can&#39;t change the turn, the prompt, or the reply, and a handler that throws is logged and skipped. Treat the event as read-only; later subscribers see the same object. That makes hooks safe to add to a production agent, and the wrong tool for anything that must happen before the model runs or must fail a turn; see <a href="#when-not-to-use-a-hook">When not to use a hook</a>.</p><p><code>defineHook</code> is unrelated to <a href="https://cursor.com/docs/agent/hooks" target="_blank" rel="noreferrer">Cursor Agent hooks</a>, the <code>.cursor/hooks.json</code> scripts that can observe, block, or modify the agent loop. Those still run inside a local session workspace.</p><h2 id="author-a-hook" tabindex="-1">Author a hook <a class="header-anchor" href="#author-a-hook" aria-label="Permalink to &quot;Author a hook&quot;">​</a></h2><p>Author <code>agent/hooks/&lt;name&gt;.ts</code> with <code>defineHook</code> from <code>@cursor/july/hooks</code>. This one meters tokens:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// agent/hooks/usage.ts</span></span>
2
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineHook } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july/hooks&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
3
- <span class="line"></span>
4
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineHook</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
5
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> events: {</span></span>
6
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;turn.completed&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
7
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (ctx.session.purpose </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;eval&quot;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> event.data.usage </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> undefined</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
8
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
9
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
10
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">inputTokens</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">outputTokens</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> event.data.usage;</span></span>
11
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ctx.host.otel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">increment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;acme.tokens.input&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, inputTokens);</span></span>
12
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ctx.host.otel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">increment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;acme.tokens.output&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, outputTokens);</span></span>
13
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
14
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;turn.failed&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">_event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
15
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ctx.host.otel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">increment</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;acme.turn.failed&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { channel: ctx.channel.id });</span></span>
16
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
17
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
18
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>Any module under <code>agent/hooks/</code>, subfolders included, is a hook named by its path without the extension: <code>agent/hooks/audit/usage.ts</code> is <code>audit/usage</code>. <code>*.test.ts</code> and <code>*.spec.ts</code> files are skipped. The default export must be <code>defineHook(...)</code>, names can&#39;t contain <code>__</code>, and an empty <code>events</code> map skips the hook with a warning; <code>agent-sdk validate</code> reports all three. An extension mounts its hooks as <code>&lt;ns&gt;__&lt;name&gt;</code>, and <code>disableHook()</code> removes one (<a href="./extensions.html#adjust-a-mounted-extension">Adjust a mounted extension</a>).</p><p><code>agent-sdk init</code> scaffolds <code>agent/hooks/memory.ts</code>, which exports <code>memoryHook()</code> from <code>@cursor/july/memory</code> and journals every turn for later sessions to read. Delete the file to opt out.</p><h2 id="events-and-payloads" tabindex="-1">Events and payloads <a class="header-anchor" href="#events-and-payloads" aria-label="Permalink to &quot;Events and payloads&quot;">​</a></h2><p>Keys are event types from the <a href="./sessions.html#which-events-can-i-stream">event vocabulary</a>, or <code>&quot;*&quot;</code> for every event. A typed key narrows <code>event.data</code>; a <code>&quot;*&quot;</code> handler receives the union, so switch on <code>event.type</code>. Every event carries the stream envelope <code>{ type, index, sessionId, turnId?, at, data }</code>, with <code>turnId</code> set on turn-scoped events.</p><p>The payloads hooks read most often:</p><table tabindex="0"><thead><tr><th>Event</th><th><code>event.data</code></th></tr></thead><tbody><tr><td><code>message.received</code></td><td><code>{ text }</code></td></tr><tr><td><code>turn.completed</code></td><td><code>{ result?, usage?, cost? }</code>. <code>usage</code> has <code>inputTokens</code>, <code>outputTokens</code>, <code>cacheReadTokens</code>, <code>cacheWriteTokens</code>, and optional <code>reasoningTokens</code>. <code>cost</code> has <code>totalUsd</code> and the <code>model</code> it was priced against</td></tr><tr><td><code>turn.failed</code></td><td><code>{ message }</code></td></tr><tr><td><code>actions.requested</code></td><td><code>{ calls: [{ callId, toolName, args? }] }</code>. A call with <code>parentCallId</code> belongs to a subagent</td></tr><tr><td><code>action.result</code></td><td><code>{ callId, toolName, output?, isError, stubbed? }</code>. <code>stubbed</code> means a dry-run session answered a write without running it</td></tr></tbody></table><p>The types are <code>SessionEvent</code>, <code>SessionEventType</code>, and <code>HookContext</code>, exported from <code>@cursor/july</code>.</p><h2 id="handler-context" tabindex="-1">Handler context <a class="header-anchor" href="#handler-context" aria-label="Permalink to &quot;Handler context&quot;">​</a></h2><table tabindex="0"><thead><tr><th>Member</th><th>What it is</th></tr></thead><tbody><tr><td><code>ctx.session</code></td><td>Read-only session info: <code>id</code>, <code>channelId</code>, <code>mode</code> (<code>chat</code> or <code>task</code>), <code>purpose</code> (<code>live</code> or <code>eval</code>), <code>auth</code>, plus <code>title</code> and <code>sdkAgentId</code> when set</td></tr><tr><td><code>ctx.agent</code></td><td><code>{ name }</code> of the agent the event belongs to</td></tr><tr><td><code>ctx.channel</code></td><td><code>{ id, continuationToken }</code>. The token is <code>null</code> when the session can&#39;t take follow-ups</td></tr><tr><td><code>ctx.host.kv</code></td><td>Durable JSON, shared by every session of the agent; the storage backend decides whether it survives a hosted replace. Prefix keys with <code>ctx.session.id</code> for per-session state</td></tr><tr><td><code>ctx.host.files</code></td><td>Durable files, bound to this session. Pass <code>{ scope: &quot;deployment&quot; }</code> for agent-wide files</td></tr><tr><td><code>ctx.host.otel</code></td><td>Counters, histograms, and tags, attributed to this session</td></tr><tr><td><code>ctx.host.mcp</code>, <code>ctx.host.github</code>, <code>ctx.host.slack</code></td><td>The same shared clients tools get</td></tr><tr><td><code>ctx.host.reminders</code></td><td>Per-session <a href="./schedules.html">reminders</a>, the same API tools get</td></tr><tr><td><code>ctx.artifacts</code></td><td>Session-bound <a href="./artifacts.html">artifacts</a> facade: <code>tag</code> fills in <code>sessionId</code> and <code>turnId</code></td></tr><tr><td><code>ctx.stateRoot</code></td><td>Absolute path of the local state root. It resets when a hosted deployment is replaced; keep derived state in <code>kv</code> or <code>files</code></td></tr></tbody></table><h2 id="when-hooks-run" tabindex="-1">When hooks run <a class="header-anchor" href="#when-hooks-run" aria-label="Permalink to &quot;When hooks run&quot;">​</a></h2><p>A hook runs after the event is durably recorded. It never delays the model turn and never sees an event that wasn&#39;t recorded.</p><p>Within one session, events dispatch in order, one at a time: the channel&#39;s <code>events</code> handlers first, then each hook in discovery order. Sessions don&#39;t wait on each other.</p><p>Two consequences:</p><ul><li>A slow handler holds up the next event&#39;s handlers for that session, not the model. Keep handlers short and queue anything slow.</li><li>Hooks fire for eval sessions too. Check <code>ctx.session.purpose === &quot;eval&quot;</code> before metering or paging.</li></ul><p>Each event reaches a hook at most once. A restart doesn&#39;t replay the log into hooks, so a mirror needs no dedupe, and the event log rather than the hook&#39;s copy is the source of truth.</p><h2 id="hooks-channel-events-or-evals" tabindex="-1">Hooks, channel events, or evals? <a class="header-anchor" href="#hooks-channel-events-or-evals" aria-label="Permalink to &quot;Hooks, channel events, or evals?&quot;">​</a></h2><p>All of them consume the same stream, for different jobs:</p><table tabindex="0"><thead><tr><th></th><th>Hooks</th><th>Channel <code>events</code></th><th>Evals</th></tr></thead><tbody><tr><td>Scope</td><td>every session of the agent</td><td>sessions the channel owns</td><td>one test turn</td></tr><tr><td>Job</td><td>observe: audit, metrics, mirrors, derived state</td><td>deliver: replies back to the channel&#39;s surface</td><td>assert: gates over the trajectory</td></tr><tr><td>Context</td><td><code>ctx.host</code>, <code>ctx.artifacts</code>, session info</td><td><code>channel.state</code>, <code>setContinuationToken</code>, <code>ctx.host</code>, session info</td><td>the <code>t</code> assertion helpers</td></tr><tr><td>Can affect the run</td><td>no</td><td>yes, it owns the surface</td><td>n/a</td></tr><tr><td>Authored at</td><td><code>agent/hooks/*.ts</code></td><td>channel config</td><td><code>evals/**/*.eval.ts</code></td></tr></tbody></table><h2 id="when-not-to-use-a-hook" tabindex="-1">When not to use a hook <a class="header-anchor" href="#when-not-to-use-a-hook" aria-label="Permalink to &quot;When not to use a hook&quot;">​</a></h2><table tabindex="0"><thead><tr><th>You want to</th><th>Use instead</th></tr></thead><tbody><tr><td>Add context before the model runs</td><td>The channel&#39;s <code>send</code> message and <code>workspaceFiles</code>, <code>instructions.md</code>, skills, or <code>sandbox/workspace/</code> seed files</td></tr><tr><td>Reply on Slack, comment on a PR, or post any other delivery</td><td>The channel&#39;s <code>events</code> map, or the Slack and GitHub packs</td></tr><tr><td>Show PR progress (merge-box check, sticky banner)</td><td><code>githubChannel({ progress: { commitStatus, banner } })</code>; see the <a href="./../templates/pr-autofixer.html">PR autofixer</a></td></tr><tr><td>Block, approve, or rewrite a tool call</td><td><a href="./tools.html#gate-a-tool-on-human-approval"><code>needsApproval</code></a> on the tool</td></tr><tr><td>Act on the final assistant text, reject it for a same-turn repair, or fail a bad turn</td><td><code>defineResult</code></td></tr><tr><td>Gate a change on behavior</td><td><a href="./../evals.html">Evals</a></td></tr></tbody></table><h2 id="patterns" tabindex="-1">Patterns <a class="header-anchor" href="#patterns" aria-label="Permalink to &quot;Patterns&quot;">​</a></h2><p>Usage metering is the <a href="#author-a-hook">authoring example</a>. Three more:</p><h3 id="alert-on-failure" tabindex="-1">Alert on failure <a class="header-anchor" href="#alert-on-failure" aria-label="Permalink to &quot;Alert on failure&quot;">​</a></h3><p><code>turn.failed</code> carries the message, and <code>ctx.session.id</code> points at the trace. Skip interrupted turns; those are preemptions, not failures. Read secrets inside the handler: hosted deployments bind them after the process starts, so a module-scope read stays empty. Give the call a timeout, since a stalled request holds up later handlers on that session.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// agent/hooks/page-on-failure.ts</span></span>
19
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineHook } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july/hooks&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
20
- <span class="line"></span>
21
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineHook</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
22
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> events: {</span></span>
23
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;turn.failed&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
24
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> pagerUrl</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> process.env.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">PAGER_WEBHOOK_URL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
25
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span></span>
26
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> pagerUrl </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> undefined</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ||</span></span>
27
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ctx.session.purpose </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;eval&quot;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ||</span></span>
28
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> event.data.message </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;turn interrupted&quot;</span></span>
29
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ) {</span></span>
30
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
31
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
32
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetch</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(pagerUrl, {</span></span>
33
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> method: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;POST&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
34
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> headers: { </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;content-type&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;application/json&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
35
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> body: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
36
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> agent: ctx.agent.name,</span></span>
37
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> session: ctx.session.id,</span></span>
38
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> channel: ctx.channel.id,</span></span>
39
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> message: event.data.message,</span></span>
40
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }),</span></span>
41
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> signal: AbortSignal.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">timeout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">5_000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
42
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
43
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
44
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
45
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="mirror-the-transcript" tabindex="-1">Mirror the transcript <a class="header-anchor" href="#mirror-the-transcript" aria-label="Permalink to &quot;Mirror the transcript&quot;">​</a></h3><p>Subscribe to <code>&quot;*&quot;</code> and write one file per event, skipping the <code>*.appended</code> deltas: they arrive per token, and <code>message.completed</code> carries the final text. Session scope keeps transcripts apart without a session id in the path. The mirror holds reasoning text and raw tool arguments and outputs, so pick the store accordingly, and write to your own store instead when you need cross-session queries.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// agent/hooks/mirror.ts</span></span>
46
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineHook } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july/hooks&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
47
- <span class="line"></span>
48
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineHook</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
49
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> events: {</span></span>
50
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;*&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
51
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (event.type.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">endsWith</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;.appended&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)) {</span></span>
52
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
53
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
54
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> name</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event.index).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">padStart</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">6</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;0&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
55
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ctx.host.files.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">write</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
56
- <span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> \`transcript/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">name</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}.json\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
57
- <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> JSON</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">stringify</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event)</span></span>
58
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> );</span></span>
59
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
60
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
61
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h3 id="keep-derived-state-across-a-replace" tabindex="-1">Keep derived state across a replace <a class="header-anchor" href="#keep-derived-state-across-a-replace" aria-label="Permalink to &quot;Keep derived state across a replace&quot;">​</a></h3><p>Write it to <code>ctx.host.kv</code> under a session-prefixed key; a tool reads it back with <code>ctx.host.kv.get</code>.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// agent/hooks/last-result.ts</span></span>
62
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineHook } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/july/hooks&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
63
- <span class="line"></span>
64
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineHook</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
65
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> events: {</span></span>
66
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;turn.completed&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
67
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ctx.host.kv.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">put</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`last-result/\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">ctx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">session</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">id</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
68
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> at: event.at,</span></span>
69
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> result: event.data.result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">??</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
70
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
71
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
72
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
73
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="test-and-debug-a-hook" tabindex="-1">Test and debug a hook <a class="header-anchor" href="#test-and-debug-a-hook" aria-label="Permalink to &quot;Test and debug a hook&quot;">​</a></h2><p>A hook definition is a plain object, so a unit test calls <code>hook.events[&quot;turn.completed&quot;]</code> directly with an event and a stub <code>HookContext</code>. Discovery skips <code>*.test.ts</code>, so the test can live next to the hook.</p><p>At runtime:</p><ul><li><code>agent-sdk validate --dir .</code> reports discovery errors and the empty-handlers warning.</li><li><code>agent-sdk info --dir . --json</code> lists the loaded hooks under <code>agents[].hooks</code>.</li><li>Send a turn with <code>agent-sdk dev</code> or <code>agent-sdk run --dir . --message &quot;…&quot;</code> and watch the serve log for <code>hook &quot;&lt;name&gt;&quot; handler for &lt;event&gt; threw: …</code>. <code>run</code> prints that log on stderr. On hosting, read it with <a href="./cli.html#logs"><code>agent-sdk logs</code></a>.</li></ul><h2 id="what-s-next" tabindex="-1">What&#39;s next <a class="header-anchor" href="#what-s-next" aria-label="Permalink to &quot;What&#39;s next&quot;">​</a></h2><p>Continue with these pages:</p><ul><li><a href="./sessions.html">Sessions and streaming</a>: the event vocabulary hooks observe</li><li><a href="./../guides/opentelemetry.html">OpenTelemetry</a>: OTLP traces and metrics from the same event stream</li><li><a href="./../deployment.html#observability">Deployment</a>: runtime logs and export paths</li><li><a href="./channels.html#events">Channels</a>: the delivery-side counterpart</li></ul>`,45)])])}const E=e(n,[["render",h]]);export{c as __pageData,E as default};