@cursor/july 0.1.112 → 0.1.113

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 (211) 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.CAeK13eM.js} +4 -4
  11. package/dist/docs/assets/chunks/@localSearchIndexroot.Ck9E52Ls.js +1 -0
  12. package/dist/docs/assets/chunks/{VPLocalSearchBox.CR3KTF0X.js → VPLocalSearchBox.C9LbPHod.js} +1 -1
  13. package/dist/docs/assets/chunks/{arc.CVVqBOdS.js → arc.CmMq2zmS.js} +1 -1
  14. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CJHGP4ki.js → architectureDiagram-Q4EWVU46.CCXB8Uj5.js} +1 -1
  15. package/dist/docs/assets/chunks/{baseUniq.r7UVVRBP.js → baseUniq.CyQo6eLe.js} +1 -1
  16. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.DKmMaTre.js → blockDiagram-DXYQGD6D.JYq6w91N.js} +1 -1
  17. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.DDJsntUO.js → c4Diagram-AHTNJAMY.BRV8GPJJ.js} +1 -1
  18. package/dist/docs/assets/chunks/channel.BHiYmnZ4.js +1 -0
  19. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.BK2rKt6W.js → chunk-4BX2VUAB.Bv4ooYQR.js} +1 -1
  20. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.DRLV8RnF.js → chunk-4TB4RGXK.t4JtKPcj.js} +1 -1
  21. package/dist/docs/assets/chunks/{chunk-55IACEB6.DaKjxtb7.js → chunk-55IACEB6.34lCHj9Y.js} +1 -1
  22. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.C5sPCIT1.js → chunk-EDXVE4YY.BSwrPNrt.js} +1 -1
  23. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.CSGWyNTB.js → chunk-FMBD7UC4.Beeun-R-.js} +1 -1
  24. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.D5tK9XEr.js → chunk-OYMX7WX6.BUUFUcJc.js} +1 -1
  25. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.BeZGd1UZ.js → chunk-QZHKN3VN.B2XjHzN_.js} +1 -1
  26. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.U_tfWwQR.js → chunk-YZCP3GAM.CLYG8znk.js} +1 -1
  27. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.Degh8l90.js +1 -0
  28. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.Degh8l90.js +1 -0
  29. package/dist/docs/assets/chunks/clone.BIywbczV.js +1 -0
  30. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.DVeRXIb6.js → cose-bilkent-S5V4N54A.DVEa6fZp.js} +1 -1
  31. package/dist/docs/assets/chunks/{dagre-KV5264BT.BpKJAeRZ.js → dagre-KV5264BT.C9PZQK-S.js} +1 -1
  32. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.BQOtrd1Z.js → diagram-5BDNPKRD.DoN0uv3Y.js} +1 -1
  33. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.CSDAhjPI.js → diagram-G4DWMVQ6.Czv3duqx.js} +1 -1
  34. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.Dpztst2S.js → diagram-MMDJMWI5.BinJ5kWb.js} +1 -1
  35. package/dist/docs/assets/chunks/{diagram-TYMM5635.qJHRizHR.js → diagram-TYMM5635.DW326M4K.js} +1 -1
  36. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.vbDotH3l.js → erDiagram-SMLLAGMA.U2pR_OA7.js} +1 -1
  37. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.CqS_ZQr4.js → flowDiagram-DWJPFMVM.ByWJXeYK.js} +1 -1
  38. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.DTLdR4pN.js → ganttDiagram-T4ZO3ILL.OquF0Rtg.js} +1 -1
  39. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.D04lnbnr.js → gitGraphDiagram-UUTBAWPF.Bpn01P7X.js} +1 -1
  40. package/dist/docs/assets/chunks/{graph.BlfqLJsM.js → graph.CNRB6ETL.js} +1 -1
  41. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.tAooImWA.js → infoDiagram-42DDH7IO.CqhknMWi.js} +1 -1
  42. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.ClUsVqnJ.js → ishikawaDiagram-UXIWVN3A.C6xpR2af.js} +1 -1
  43. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.C3tUgyCg.js → journeyDiagram-VCZTEJTY.Cg5f7oB3.js} +1 -1
  44. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.CtD9-QCe.js → kanban-definition-6JOO6SKY.Cx9YTwlU.js} +1 -1
  45. package/dist/docs/assets/chunks/{layout.D38U-LnT.js → layout.ljS-wFtK.js} +1 -1
  46. package/dist/docs/assets/chunks/{linear.BJmssyhN.js → linear.jSxNrsFC.js} +1 -1
  47. package/dist/docs/assets/chunks/{min.DNgXoouU.js → min.Cum8AlQw.js} +1 -1
  48. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.Dcp6cxeu.js → mindmap-definition-QFDTVHPH.BLiysLpe.js} +1 -1
  49. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.CLDw6zIs.js → pieDiagram-DEJITSTG.BoIDyuKF.js} +1 -1
  50. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.CYaeeY4c.js → quadrantDiagram-34T5L4WZ.DLkpDytR.js} +1 -1
  51. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.gMYuRpq2.js → requirementDiagram-MS252O5E.DqTVqSu2.js} +1 -1
  52. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.CZqyHFbc.js → sankeyDiagram-XADWPNL6.CG_6FF7j.js} +1 -1
  53. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.BTsCjUDN.js → sequenceDiagram-FGHM5R23.BIp9602K.js} +1 -1
  54. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.CftT9mLJ.js → stateDiagram-FHFEXIEX.COSXsD9I.js} +1 -1
  55. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.qrxrbFsX.js +1 -0
  56. package/dist/docs/assets/chunks/{theme.B_7J9ZsV.js → theme.CXJ7PNwy.js} +2 -2
  57. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.DbU3WUNw.js → timeline-definition-GMOUNBTQ.CXdVqkLq.js} +1 -1
  58. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.ixsq-q2u.js → vennDiagram-DHZGUBPP.CZxGuc4r.js} +1 -1
  59. package/dist/docs/assets/chunks/wardley-RL74JXVD.3oVgfqQk.js +162 -0
  60. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.C0ewvgbp.js → wardleyDiagram-NUSXRM2D.6_irCgGJ.js} +1 -1
  61. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.nAEhF4bO.js → xychartDiagram-5P7HB3ND.TRPe92m3.js} +1 -1
  62. package/dist/docs/assets/{evals.md.BYvfZ-PO.js → evals.md.D3Y3Aixt.js} +2 -2
  63. package/dist/docs/assets/{evals.md.BYvfZ-PO.lean.js → evals.md.D3Y3Aixt.lean.js} +1 -1
  64. package/dist/docs/assets/guides_agent-to-agent.md.CD4T5FIl.js +41 -0
  65. package/dist/docs/assets/guides_agent-to-agent.md.CD4T5FIl.lean.js +1 -0
  66. package/dist/docs/assets/guides_jev.md.F5fAkkfN.js +189 -0
  67. package/dist/docs/assets/guides_jev.md.F5fAkkfN.lean.js +1 -0
  68. package/dist/docs/assets/{reference_connections.md.CmyrlXfY.js → reference_connections.md.Je9dMsdd.js} +1 -1
  69. package/dist/docs/assets/{reference_extensions.md.Ceq-qT8d.js → reference_extensions.md.Cv5aLCz_.js} +1 -1
  70. package/dist/docs/assets/{reference_subagents.md.BHsSMMyO.js → reference_subagents.md.Dl16gcBj.js} +2 -2
  71. package/dist/docs/assets/{reference_subagents.md.BHsSMMyO.lean.js → reference_subagents.md.Dl16gcBj.lean.js} +1 -1
  72. package/dist/docs/assets/{reference_tools.md.BYzUTeVA.js → reference_tools.md.B1dH1lpa.js} +2 -2
  73. package/dist/docs/assets/{reference_tools.md.BYzUTeVA.lean.js → reference_tools.md.B1dH1lpa.lean.js} +1 -1
  74. package/dist/docs/building-with-agents.html +35 -35
  75. package/dist/docs/deployment.html +36 -36
  76. package/dist/docs/evals.html +36 -36
  77. package/dist/docs/evals.md +3 -0
  78. package/dist/docs/guides/agent-to-agent.html +65 -54
  79. package/dist/docs/guides/agent-to-agent.md +73 -68
  80. package/dist/docs/guides/bitbucket.html +35 -35
  81. package/dist/docs/guides/cloud-agents.html +35 -35
  82. package/dist/docs/guides/convert-automation.html +35 -35
  83. package/dist/docs/guides/github.html +35 -35
  84. package/dist/docs/guides/gitlab.html +35 -35
  85. package/dist/docs/guides/grokbot-agents.html +35 -35
  86. package/dist/docs/guides/improve.html +36 -36
  87. package/dist/docs/guides/jev.html +248 -0
  88. package/dist/docs/guides/jev.md +348 -0
  89. package/dist/docs/guides/mcp-oauth.html +36 -36
  90. package/dist/docs/guides/opentelemetry.html +35 -35
  91. package/dist/docs/guides/slack.html +35 -35
  92. package/dist/docs/guides/webhooks.html +35 -35
  93. package/dist/docs/hashmap.json +1 -1
  94. package/dist/docs/hillclimbing.html +35 -35
  95. package/dist/docs/index.html +35 -35
  96. package/dist/docs/llms-full.txt +434 -68
  97. package/dist/docs/llms.txt +2 -1
  98. package/dist/docs/quickstart.html +35 -35
  99. package/dist/docs/reference/agent-config.html +35 -35
  100. package/dist/docs/reference/artifacts.html +35 -35
  101. package/dist/docs/reference/channels.html +35 -35
  102. package/dist/docs/reference/cli.html +35 -35
  103. package/dist/docs/reference/connections.html +37 -37
  104. package/dist/docs/reference/connections.md +1 -1
  105. package/dist/docs/reference/evals.html +35 -35
  106. package/dist/docs/reference/extensions.html +37 -37
  107. package/dist/docs/reference/extensions.md +1 -0
  108. package/dist/docs/reference/hooks.html +35 -35
  109. package/dist/docs/reference/http-api.html +35 -35
  110. package/dist/docs/reference/instructions.html +35 -35
  111. package/dist/docs/reference/playground.html +35 -35
  112. package/dist/docs/reference/project-layout.html +35 -35
  113. package/dist/docs/reference/prompt.html +35 -35
  114. package/dist/docs/reference/schedules.html +35 -35
  115. package/dist/docs/reference/sessions.html +35 -35
  116. package/dist/docs/reference/skills.html +35 -35
  117. package/dist/docs/reference/subagents.html +37 -37
  118. package/dist/docs/reference/subagents.md +1 -1
  119. package/dist/docs/reference/tools.html +37 -37
  120. package/dist/docs/reference/tools.md +4 -0
  121. package/dist/docs/templates/agentic-owners.html +35 -35
  122. package/dist/docs/templates/pr-autofixer.html +35 -35
  123. package/dist/docs/templates/security-reviewer.html +35 -35
  124. package/dist/docs/templates/thermo-quality-review.html +35 -35
  125. package/dist/docs/templates/thermo-review.html +35 -35
  126. package/dist/docs/templates/triage.html +35 -35
  127. package/dist/docs/troubleshooting.html +35 -35
  128. package/dist/extensions/jev/extension.d.ts +43 -0
  129. package/dist/extensions/jev/extension.d.ts.map +1 -0
  130. package/dist/extensions/jev/extension.js +47 -0
  131. package/dist/extensions/jev/lib/evaluate.d.ts +101 -0
  132. package/dist/extensions/jev/lib/evaluate.d.ts.map +1 -0
  133. package/dist/extensions/jev/lib/evaluate.js +167 -0
  134. package/dist/extensions/jev/skills/gated-write.md +25 -0
  135. package/dist/extensions/jev/skills/questions.md +33 -0
  136. package/dist/extensions/jev/tools/evaluate.d.ts +4 -0
  137. package/dist/extensions/jev/tools/evaluate.d.ts.map +1 -0
  138. package/dist/extensions/jev/tools/evaluate.js +88 -0
  139. package/dist/extensions.d.ts +1 -1
  140. package/dist/extensions.d.ts.map +1 -1
  141. package/dist/extensions.js +2 -0
  142. package/dist/internal/advertise-tools.d.ts.map +1 -1
  143. package/dist/internal/advertise-tools.js +6 -0
  144. package/dist/internal/discovery/connections.d.ts.map +1 -1
  145. package/dist/internal/discovery/connections.js +18 -0
  146. package/dist/internal/discovery/extensions.d.ts.map +1 -1
  147. package/dist/internal/discovery/extensions.js +8 -4
  148. package/dist/internal/discovery/info.d.ts.map +1 -1
  149. package/dist/internal/discovery/info.js +1 -0
  150. package/dist/internal/hosted-delivery-protocol.d.ts +3 -0
  151. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  152. package/dist/internal/hosted-delivery-protocol.js +1 -0
  153. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  154. package/dist/internal/hosted-delivery.js +15 -25
  155. package/dist/internal/hosted-execution-diag.d.ts +12 -4
  156. package/dist/internal/hosted-execution-diag.d.ts.map +1 -1
  157. package/dist/internal/hosted-execution-diag.js +26 -4
  158. package/dist/internal/hosted-execution-flush.d.ts +1 -0
  159. package/dist/internal/hosted-execution-flush.d.ts.map +1 -1
  160. package/dist/internal/hosted-execution-flush.js +4 -2
  161. package/dist/internal/server.d.ts.map +1 -1
  162. package/dist/internal/server.js +17 -9
  163. package/dist/internal/session-engine.d.ts +4 -1
  164. package/dist/internal/session-engine.d.ts.map +1 -1
  165. package/dist/internal/session-engine.js +28 -4
  166. package/dist/playground/assets/index-DSMAewbx.css +1 -0
  167. package/dist/playground/assets/{index-B1c1LeIf.js → index-De_lpFxE.js} +43 -43
  168. package/dist/playground/index.html +2 -2
  169. package/dist/types.d.ts +23 -3
  170. package/dist/types.d.ts.map +1 -1
  171. package/docs/evals.md +3 -0
  172. package/docs/guides/agent-to-agent.md +74 -69
  173. package/docs/guides/jev.md +353 -0
  174. package/docs/reference/connections.md +1 -1
  175. package/docs/reference/extensions.md +1 -0
  176. package/docs/reference/subagents.md +1 -1
  177. package/docs/reference/tools.md +4 -0
  178. package/package.json +8 -1
  179. package/src/bin/agent-serve.ts +2 -3
  180. package/src/channels/checks.ts +8 -0
  181. package/src/channels/origin/checks.ts +3 -1
  182. package/src/channels/slack/dispatch.ts +7 -2
  183. package/src/extensions/jev/extension.ts +95 -0
  184. package/src/extensions/jev/lib/evaluate.ts +289 -0
  185. package/src/extensions/jev/skills/gated-write.md +25 -0
  186. package/src/extensions/jev/skills/questions.md +33 -0
  187. package/src/extensions/jev/tools/evaluate.ts +90 -0
  188. package/src/extensions.ts +2 -0
  189. package/src/internal/advertise-tools.ts +6 -0
  190. package/src/internal/discovery/connections.ts +21 -0
  191. package/src/internal/discovery/extensions.ts +12 -4
  192. package/src/internal/discovery/info.ts +1 -0
  193. package/src/internal/hosted-delivery-protocol.ts +4 -0
  194. package/src/internal/hosted-delivery.ts +15 -0
  195. package/src/internal/hosted-execution-diag.ts +33 -4
  196. package/src/internal/hosted-execution-flush.ts +4 -0
  197. package/src/internal/server.ts +26 -12
  198. package/src/internal/session-engine.ts +30 -4
  199. package/src/types.ts +24 -3
  200. package/dist/docs/assets/chunks/@localSearchIndexroot.QmjDU6Jh.js +0 -1
  201. package/dist/docs/assets/chunks/channel.BjpoSbz_.js +0 -1
  202. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.BgxOlMHw.js +0 -1
  203. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.BgxOlMHw.js +0 -1
  204. package/dist/docs/assets/chunks/clone.DRuGBKZC.js +0 -1
  205. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.-43J68xB.js +0 -1
  206. package/dist/docs/assets/chunks/wardley-RL74JXVD.WRXz-Dux.js +0 -162
  207. package/dist/docs/assets/guides_agent-to-agent.md.8oDTfu-E.js +0 -30
  208. package/dist/docs/assets/guides_agent-to-agent.md.8oDTfu-E.lean.js +0 -1
  209. package/dist/playground/assets/index-CK2LX3iD.css +0 -1
  210. /package/dist/docs/assets/{reference_connections.md.CmyrlXfY.lean.js → reference_connections.md.Je9dMsdd.lean.js} +0 -0
  211. /package/dist/docs/assets/{reference_extensions.md.Ceq-qT8d.lean.js → reference_extensions.md.Cv5aLCz_.lean.js} +0 -0
@@ -366,6 +366,9 @@ This smoke case asks for a PR verdict, requires the read-only inspection
366
366
  tool, and fails if the agent tries to approve. The CLI reports all three
367
367
  decisions together instead of stopping at the first miss.
368
368
 
369
+ Use the [Jev extension](/docs/guides/jev.md) when host code needs a typed
370
+ choice, score, or boolean before it writes.
371
+
369
372
  ```ts
370
373
  // evals/readiness.eval.ts
371
374
  import { defineEval, includes } from "@cursor/july/evals";
@@ -606,32 +609,21 @@ moves the freeze line instead of proving the change.
606
609
 
607
610
  Source: /docs/guides/agent-to-agent.md
608
611
 
609
- # Agent-to-agent
612
+ # Peer agents
610
613
 
611
614
  A peer connection lets one agent ask another agent on the same host for
612
615
  help. The specialist keeps its own instructions, tools, and session,
613
616
  while the caller decides when to delegate and returns the answer to the
614
- user.
615
-
616
- ## How do I wire two agents?
617
+ user. Co-host both projects under one `agent-sdk` process.
617
618
 
618
- Put both projects under one directory, then point the concierge at the
619
- specialist's mount slug. When a user asks about weather, the concierge
620
- calls the peer's `ask` tool, the weather agent runs in its own context,
621
- and the concierge returns that answer.
619
+ ## Delegate a question to a specialist
622
620
 
623
- ```text
624
- agents/
625
- concierge/
626
- agent/instructions.md
627
- agent/mcp-connections/weather.ts
628
- weather-agent/
629
- agent/agent.ts
630
- agent/instructions.md
631
- ```
621
+ Ask the concierge about the weather and it hands the question to the
622
+ specialist. The weather agent answers in its own context, then the
623
+ concierge returns that answer to you.
632
624
 
633
625
  ```ts
634
- // agents/concierge/agent/mcp-connections/weather.ts
626
+ // agent/mcp-connections/weather.ts
635
627
  import { defineConnection } from "@cursor/july/connections";
636
628
 
637
629
  export default defineConnection({
@@ -644,7 +636,7 @@ Give the concierge a narrow routing rule:
644
636
 
645
637
  ```md
646
638
  When a request needs current weather, ask the `weather` peer. Return its
647
- answer without delegating the same request again.
639
+ answer.
648
640
  ```
649
641
 
650
642
  ```bash
@@ -653,58 +645,69 @@ agent-sdk chat --url http://127.0.0.1:3000/concierge \
653
645
  --message "What's the weather in Paris right now?"
654
646
  ```
655
647
 
656
- The connection filename becomes the MCP server name. The `agent` value
657
- is the specialist's mount slug, normally its directory name.
648
+ The connection filename is the MCP server name the concierge calls, and
649
+ `agent` is the specialist's mount slug, normally its directory name.
658
650
 
659
- ## Continue the specialist's conversation
651
+ ## Continue the specialist's session
660
652
 
661
- The first `ask` returns a peer `sessionId`. Pass that ID into the next
662
- `ask` when the specialist should remember its earlier work instead of
663
- starting with fresh context.
653
+ Ask a follow-up about the same forecast and the specialist picks up
654
+ where it left off, with its own instructions and tool history still in
655
+ place. The first `ask` returns `{ status, sessionId, reply }` as text on
656
+ the `callTool` result. Parse `sessionId` and pass it on the next `ask`
657
+ so the peer remembers its earlier work instead of starting fresh.
664
658
 
665
- ```json
666
- {
667
- "message": "How does that compare with tomorrow?",
668
- "sessionId": "<session-id>"
659
+ ```ts
660
+ const first = await ctx.host.mcp.callTool("weather", "ask", {
661
+ message: "What's the weather in Paris right now?",
662
+ });
663
+ const firstText = first.content.find((part) => part.type === "text");
664
+ if (firstText?.text === undefined) {
665
+ throw new Error("weather ask returned no text payload");
669
666
  }
670
- ```
671
-
672
- The peer owns this session. Follow-ups resume its instructions and tool
673
- history without merging them into the concierge's conversation.
667
+ const { sessionId } = JSON.parse(firstText.text) as { sessionId: string };
674
668
 
675
- ## Wait for long-running specialist work
669
+ await ctx.host.mcp.callTool("weather", "ask", {
670
+ message: "How does that compare with tomorrow?",
671
+ sessionId,
672
+ });
673
+ ```
676
674
 
677
- `ask` waits for a bounded time. If the specialist is still working, it
678
- returns `status: "running"` with the session ID, allowing the caller to
679
- do other work and check again later.
675
+ If the specialist is still working, `ask` returns `status: "running"`
676
+ with the session ID, and you can do other work before calling `check`.
680
677
 
681
- ```json
682
- {
683
- "sessionId": "<session-id>",
684
- "waitSeconds": 20
685
- }
678
+ ```ts
679
+ await ctx.host.mcp.callTool("weather", "check", {
680
+ sessionId,
681
+ waitSeconds: 20,
682
+ });
686
683
  ```
687
684
 
688
- Call the peer's `check` tool with that input. It returns the final reply
689
- when the turn settles, or another running status when more time is
690
- needed.
685
+ The peer owns this session. Follow-ups stay on the specialist and leave
686
+ the concierge's conversation unchanged.
691
687
 
692
688
  ## Call a deterministic peer tool
693
689
 
694
- When the specialist has a server tool and no second model turn should
695
- make a decision, call its `call_tool` endpoint through the peer
696
- connection. This example runs `get_forecast` in the weather agent's
697
- workspace and returns its structured result to the concierge tool.
690
+ You need a forecast for Paris, and the weather agent already has
691
+ `get_forecast`. Host code calls that tool in the specialist's workspace
692
+ and the forecast comes back to the concierge, with no second model turn.
698
693
 
699
694
  ```ts
700
695
  const result = await ctx.host.mcp.callTool("weather", "call_tool", {
701
696
  toolName: "get_forecast",
702
697
  input: { city: "Paris" },
703
698
  });
699
+ const part = result.content.find((item) => item.type === "text");
700
+ if (part?.text === undefined) {
701
+ return { ok: false, forecast: null };
702
+ }
703
+ const payload = JSON.parse(part.text) as {
704
+ isError?: boolean;
705
+ result?: unknown;
706
+ };
704
707
 
705
708
  return {
706
- ok: result.isError !== true,
707
- forecast: result.structuredContent ?? null,
709
+ ok: result.isError !== true && payload.isError !== true,
710
+ forecast: payload.result ?? null,
708
711
  };
709
712
  ```
710
713
 
@@ -723,26 +726,31 @@ complete agent you would also run, inspect, or expose on its own.
723
726
  | Tools and connections | Inherits the parent project | Owns its project surface |
724
727
  | Reachability | Parent only | Other co-hosted agents and MCP clients |
725
728
 
726
- ## Peer sessions
729
+ ## Affinity
730
+
731
+ Follow-up `ask` and `check` calls resume the same specialist session
732
+ and run as the caller. Those turns show up in the peer's playground;
733
+ only that caller can continue or check the session.
727
734
 
728
- Calls through `ask` create sessions on the peer's `mcp` channel. They
729
- use the caller's authenticated principal and appear in the peer's
730
- playground, so the same authorization boundary applies to starts,
731
- follow-ups, and checks.
735
+ ## Practices
736
+
737
+ - Give each caller a one-way routing rule so agent A cannot send work
738
+ to B and receive the same request back.
732
739
 
733
- There is no automatic recursion guard between peers. Give each caller a
734
- one-way routing rule so agent A cannot delegate the same work to B and
735
- receive it back from B.
740
+ - Prefer `ask` when the specialist should reason. Use `call_tool` when
741
+ host code already knows which server tool to run.
736
742
 
737
- ## Run peers on one host
743
+ - Cursor-managed hosting deploys one agent per slug. Use
744
+ [subagents](/docs/reference/subagents.md) there instead of peer
745
+ connections.
738
746
 
739
- Peers require the default multi-agent layout and one shared `serve`
740
- process. Unknown slugs and self-references fail at startup.
741
- Cursor-managed hosting deploys one agent per slug, so use subagents
742
- there instead of peer connections.
747
+ ## Other hosts
743
748
 
744
- For a self-hosted cloud-runtime caller, expose the shared process with
745
- `--public-url` and protect it with `--bearer-token`. The
749
+ Peers need the default multi-agent layout and one shared process;
750
+ unknown slugs and self-references fail at startup.
751
+
752
+ For a self-hosted caller, expose the shared process with `--public-url`
753
+ and protect it with `--bearer-token`. The
746
754
  [Deployment guide](/docs/deployment.md) owns that hosting setup.
747
755
 
748
756
  ## Related
@@ -2307,6 +2315,359 @@ replace them.
2307
2315
 
2308
2316
  ---
2309
2317
 
2318
+ Source: /docs/guides/jev.md
2319
+
2320
+ # Use Jev in review tools
2321
+
2322
+ Use Jev for narrow decisions where your software factory needs a typed
2323
+ answer, not another paragraph. A review agent can filter speculative
2324
+ findings, classify pull request risk, choose a reviewer, or decide
2325
+ whether a merge needs a documentation follow-up. Jev returns a choice,
2326
+ score, or probability; your TypeScript decides what happens next.
2327
+
2328
+ Ask one question per judgment. If an approval depends on risk, test
2329
+ coverage, and the size of the change, ask three questions in one call
2330
+ and combine the answers in code.
2331
+
2332
+ Set `TYPESAFE_API_KEY`. The default model is `jev-latest`.
2333
+
2334
+ ```ts
2335
+ // agent/extensions/jev.ts
2336
+ import jev from "@cursor/july/extensions/jev";
2337
+
2338
+ export default jev();
2339
+ ```
2340
+
2341
+ ## Start only the review turns you need
2342
+
2343
+ You can call Jev from a channel hook before a model turn starts. When a
2344
+ pull request opens, this hook reads its title, labels, and filenames,
2345
+ then asks whether the change needs security review. A high probability
2346
+ starts the review. Otherwise the hook returns `null`, so the agent does
2347
+ not run and nothing is posted to GitHub.
2348
+
2349
+ ```ts
2350
+ // agent/channels/github.ts
2351
+ import {
2352
+ defaultGitHubAuth,
2353
+ githubChannel,
2354
+ } from "@cursor/july/channels/github";
2355
+ import { above, decide } from "@cursor/july/extensions/jev";
2356
+
2357
+ export default githubChannel({
2358
+ botName: "security-reviewer",
2359
+ cursorAccount: { repos: ["acme/checkout"] },
2360
+ onPullRequest: async (ctx, pr) => {
2361
+ if (pr.action !== "opened" && pr.action !== "ready_for_review") {
2362
+ return null;
2363
+ }
2364
+
2365
+ const octokit = await ctx.github.getOctokit();
2366
+ const [{ data }, files] = await Promise.all([
2367
+ octokit.rest.pulls.get({
2368
+ owner: ctx.repository.owner,
2369
+ repo: ctx.repository.name,
2370
+ pull_number: pr.number,
2371
+ }),
2372
+ octokit.paginate(octokit.rest.pulls.listFiles, {
2373
+ owner: ctx.repository.owner,
2374
+ repo: ctx.repository.name,
2375
+ pull_number: pr.number,
2376
+ }),
2377
+ ]);
2378
+ const answers = await decide({
2379
+ state: {
2380
+ title: data.title,
2381
+ body: data.body,
2382
+ labels: data.labels.map(label => label.name),
2383
+ files: files.map(file => file.filename),
2384
+ },
2385
+ questions: {
2386
+ review: {
2387
+ type: "boolean",
2388
+ instructions:
2389
+ "Does this change need security review? Answer yes for auth, permissions, secrets, request parsing, or external inputs.",
2390
+ },
2391
+ },
2392
+ });
2393
+
2394
+ if (!above(answers.review, 0.8)) {
2395
+ return null;
2396
+ }
2397
+ // `auth` starts a model turn running as the pull request sender.
2398
+ return { auth: defaultGitHubAuth(ctx) };
2399
+ },
2400
+ });
2401
+ ```
2402
+
2403
+ Only pull request metadata goes to Jev here. The review turn still reads
2404
+ the diff itself.
2405
+
2406
+ ## Filter findings before you post them
2407
+
2408
+ Let the chat model draft a finding, then ask Jev whether the finding is
2409
+ a real bug in the new code. Below your threshold, the tool returns and
2410
+ the author never sees the draft. Above it, the finding becomes a review
2411
+ comment.
2412
+
2413
+ ```ts
2414
+ // agent/tools/post_finding.ts
2415
+ import { parseGitHubPrContinuationKey } from "@cursor/july/channels/github";
2416
+ import { above, decide } from "@cursor/july/extensions/jev";
2417
+ import { defineTool } from "@cursor/july/tools";
2418
+ import { z } from "zod";
2419
+
2420
+ export default defineTool({
2421
+ description:
2422
+ "Post one security finding on this session's pull request. Call once. Hold when it is not a real bug.",
2423
+ inputSchema: z.object({
2424
+ title: z.string(),
2425
+ summary: z.string().describe("What the pull request changes."),
2426
+ draft: z.string().describe("The finding to post, one or two sentences."),
2427
+ }),
2428
+ async execute({ title, summary, draft }, ctx) {
2429
+ if (ctx.session.purpose === "eval") {
2430
+ return { posted: false, reason: "eval" };
2431
+ }
2432
+
2433
+ const ref = parseGitHubPrContinuationKey(ctx.session.continuationKey ?? "");
2434
+ if (ref === undefined) {
2435
+ throw new Error("post_finding requires a GitHub pull request session");
2436
+ }
2437
+
2438
+ const answers = await decide({
2439
+ state: { title, summary, draft },
2440
+ questions: {
2441
+ real: {
2442
+ type: "boolean",
2443
+ instructions:
2444
+ "Is the draft an exploitable bug in the new code, not a style note or a hypothetical?",
2445
+ },
2446
+ },
2447
+ });
2448
+
2449
+ if (!above(answers.real, 0.85)) {
2450
+ return { posted: false, reason: "clean" };
2451
+ }
2452
+
2453
+ const octokit = await ctx.host.github.getOctokit();
2454
+ await octokit.rest.pulls.createReview({
2455
+ owner: ref.owner,
2456
+ repo: ref.repo,
2457
+ pull_number: ref.number,
2458
+ event: "COMMENT",
2459
+ body: draft,
2460
+ });
2461
+ return {
2462
+ posted: true,
2463
+ pr: `${ref.owner}/${ref.repo}#${ref.number}`,
2464
+ };
2465
+ },
2466
+ });
2467
+ ```
2468
+
2469
+ ## Approve changes by risk tier
2470
+
2471
+ You can use the same pattern for Agentic Owners. Ask Jev to put the
2472
+ pull request in a closed set of risk tiers. Approve only a confident
2473
+ `very-low` or `low`; send everything else to a person.
2474
+
2475
+ ```ts
2476
+ import { decide, needsHuman } from "@cursor/july/extensions/jev";
2477
+
2478
+ const answers = await decide({
2479
+ state: { title, summary },
2480
+ questions: {
2481
+ risk: {
2482
+ type: "choice",
2483
+ instructions: "What risk tier is this pull request?",
2484
+ criteria: {
2485
+ "very-low": "docs, formatting, or a mechanical rename",
2486
+ low: "a local change with tests and no new trust boundary",
2487
+ medium: "auth, billing, or a behavior change callers depend on",
2488
+ high: "a likely exploit, data loss, or a broken public contract",
2489
+ },
2490
+ },
2491
+ },
2492
+ });
2493
+
2494
+ const tier = answers.risk.choice;
2495
+ if (needsHuman(answers.risk) || tier === "medium" || tier === "high") {
2496
+ return { verdict: "hold", tier };
2497
+ }
2498
+ return { verdict: "approve", tier };
2499
+ ```
2500
+
2501
+ Your GitHub tool resolves the pull request from `ctx.session` and posts
2502
+ that verdict. The model does not choose the repository, pull request, or
2503
+ approval event.
2504
+
2505
+ ## Open documentation follow-ups selectively
2506
+
2507
+ After a pull request merges, a code-wiki agent can ask whether the
2508
+ change introduced a durable fact that belongs in the docs. A low
2509
+ probability means no follow-up. A high probability opens a documentation
2510
+ pull request instead of turning every merge into churn.
2511
+
2512
+ ```ts
2513
+ import { above, decide } from "@cursor/july/extensions/jev";
2514
+ import { openDocsPullRequest } from "../lib/wiki";
2515
+
2516
+ const answers = await decide({
2517
+ state: { title, summary },
2518
+ questions: {
2519
+ updateDocs: {
2520
+ type: "boolean",
2521
+ instructions:
2522
+ "Does this merge change a durable contract that the project docs should explain?",
2523
+ },
2524
+ },
2525
+ });
2526
+
2527
+ if (!above(answers.updateDocs, 0.8)) {
2528
+ return { action: "skip" };
2529
+ }
2530
+ return openDocsPullRequest({ title, summary });
2531
+ ```
2532
+
2533
+ ## Write tools with Jev
2534
+
2535
+ `decide` is a regular async host function. Call it from a channel hook,
2536
+ server tool, or router. It returns the answer map directly. `evaluate`
2537
+ makes the same request and returns `{ answers }`.
2538
+
2539
+ Use a boolean for a yes-or-no gate, a choice for a closed set such as
2540
+ risk tiers or owners, and a score for an ordered rubric. `above` checks
2541
+ a boolean probability or score. `needsHuman` checks whether a boolean
2542
+ or the selected choice clears your confidence bar.
2543
+
2544
+ Keep the questions atomic and combine them in TypeScript. For example,
2545
+ ask separately whether a finding is real, whether its impact is
2546
+ user-visible, and whether the changed line is new. Your code owns the
2547
+ rule that decides whether all three are enough to post.
2548
+
2549
+ ## Let the agent ask Jev
2550
+
2551
+ Mounting the extension adds a read-only harness tool named
2552
+ `<namespace>__evaluate`. With the default `jev` filename, the model sees
2553
+ `jev__evaluate`.
2554
+
2555
+ The tool accepts one state and a list of boolean, choice, or score
2556
+ questions. It returns `{ answers }` and never posts, approves, or opens
2557
+ a pull request. Use it when the agent needs the result during the turn.
2558
+ Use `decide` inside a project tool when the answer and the write belong
2559
+ in one operation.
2560
+
2561
+ ## Skills included with the extension
2562
+
2563
+ The extension adds two skills by default:
2564
+
2565
+ - `jev__questions` teaches the model how to structure atomic questions,
2566
+ choose a question type, and read the answers.
2567
+
2568
+ - `jev__gated-write` teaches the model to put `decide` and the write in
2569
+ one server tool, hold on low confidence, and skip writes during evals.
2570
+
2571
+ The model sees each skill's description and loads the full procedure
2572
+ when it applies.
2573
+
2574
+ ## Choose what to mount
2575
+
2576
+ Both contribution groups are on by default. Turn off the harness tool
2577
+ when Jev should only run inside tools you wrote. Turn off the skills
2578
+ when your agent already has its own Jev instructions.
2579
+
2580
+ ```ts
2581
+ // agent/extensions/jev.ts
2582
+ import jev from "@cursor/july/extensions/jev";
2583
+
2584
+ export default jev({
2585
+ harnessTools: false,
2586
+ skills: true,
2587
+ });
2588
+ ```
2589
+
2590
+ `harnessTools: false` removes `jev__evaluate` from discovery.
2591
+ `skills: false` removes both Jev skills. These switches do not remove
2592
+ the exported helpers, so project tools can still import `decide`,
2593
+ `above`, and `needsHuman`.
2594
+
2595
+ ## Jev and trajectory evals
2596
+
2597
+ An eval checks a whole turn: the agent called the read, and it stayed
2598
+ off approve. `decide` is the one call inside the tool, before GitHub.
2599
+ Use the [Evals guide](/docs/evals.md) when you want the turn to keep
2600
+ behaving. Use `decide` when the tool itself needs a tier or a yes.
2601
+
2602
+ ## Test without the live API
2603
+
2604
+ Pass `fetch` and `apiKey` and the same `decide` path runs in a test.
2605
+
2606
+ ```ts
2607
+ import { decide } from "@cursor/july/extensions/jev";
2608
+
2609
+ const answers = await decide({
2610
+ state: {
2611
+ title: "Skip the refund auth check",
2612
+ summary: "acme/checkout#42 drops the session check on POST /refunds.",
2613
+ },
2614
+ questions: {
2615
+ risk: {
2616
+ type: "choice",
2617
+ instructions: "What risk tier is this pull request?",
2618
+ criteria: {
2619
+ "very-low": "docs, formatting, or a mechanical rename",
2620
+ low: "a local change with tests and no new trust boundary",
2621
+ medium: "auth, billing, or a behavior change callers depend on",
2622
+ high: "a likely exploit, data loss, or a broken public contract",
2623
+ },
2624
+ },
2625
+ },
2626
+ apiKey: "sk-test",
2627
+ fetch: async () =>
2628
+ new Response(
2629
+ JSON.stringify({
2630
+ answers: {
2631
+ risk: {
2632
+ type: "choice",
2633
+ choice: "high",
2634
+ probabilities: {
2635
+ "very-low": 0.02,
2636
+ low: 0.05,
2637
+ medium: 0.18,
2638
+ high: 0.75,
2639
+ },
2640
+ },
2641
+ },
2642
+ }),
2643
+ { status: 200 }
2644
+ ),
2645
+ });
2646
+ ```
2647
+
2648
+ ## Practices
2649
+
2650
+ - Pass the pull request title, a short summary, and the draft finding.
2651
+ Don't send the checkout.
2652
+
2653
+ - Calibrate `above` and `needsHuman` on pull requests you have already
2654
+ labeled. `needsHuman` defaults to `0.7`.
2655
+
2656
+ ## Related
2657
+
2658
+ - [Agentic owners](/docs/templates/agentic-owners.md): a risk tier, then
2659
+ the host approves or asks for reviewers
2660
+ - [Security reviewer](/docs/templates/security-reviewer.md): a finding, or
2661
+ no comment
2662
+ - [Thermo review](/docs/templates/thermo-review.md): bugs and breakage,
2663
+ posted the same way
2664
+ - [Code wiki](/docs/reference/cli.md#init): documentation
2665
+ follow-ups after a merge
2666
+ - [Evals](/docs/evals.md): checks on the full turn
2667
+ - [GitHub agents](/docs/guides/github.md): how the review gets onto the pull request
2668
+
2669
+ ---
2670
+
2310
2671
  Source: /docs/guides/mcp-oauth.md
2311
2672
 
2312
2673
  # Connect a private MCP server with OAuth
@@ -5534,7 +5895,7 @@ export default defineConnection({
5534
5895
  ```
5535
5896
 
5536
5897
  Unknown slugs and self-references fail `serve` at startup. Walkthrough:
5537
- [Agent-to-agent](/docs/guides/agent-to-agent.md#how-do-i-wire-two-agents).
5898
+ [Peer agents](/docs/guides/agent-to-agent.md#delegate-a-question-to-a-specialist).
5538
5899
 
5539
5900
  ## Every model-visible MCP connection is available in three places
5540
5901
 
@@ -6073,6 +6434,7 @@ namespace-neutral because the consumer chooses the final prefix.
6073
6434
  - [Cloud agents](/docs/guides/cloud-agents.md): delegate repository work
6074
6435
  through an extension
6075
6436
  - [Grok Bot agents](/docs/guides/grokbot-agents.md): consult named bots
6437
+ - [Jev](/docs/guides/jev.md): typed answers, then gated writes
6076
6438
  - [Self-improvement](/docs/guides/improve.md): propose source changes
6077
6439
  through pull requests
6078
6440
  - [Project layout](/docs/reference/project-layout.md): contribution slots
@@ -7436,7 +7798,7 @@ subagent."
7436
7798
  Subagents split one job into roles inside a single agent. When the
7437
7799
  specialist is independently useful, with its own tools, sessions, and
7438
7800
  playground, make it a full agent. See
7439
- [Agent-to-agent](/docs/guides/agent-to-agent.md#peer-or-subagent).
7801
+ [Peer agents](/docs/guides/agent-to-agent.md#peer-or-subagent).
7440
7802
 
7441
7803
  ## Patterns
7442
7804
 
@@ -7498,6 +7860,10 @@ code that runs it. With a Zod `inputSchema`, the input is validated before
7498
7860
  `execute` runs and the input type is inferred. A plain JSON Schema
7499
7861
  object is forwarded as-is and the input arrives as raw JSON.
7500
7862
 
7863
+ A server tool can call `decide` from
7864
+ [`@cursor/july/extensions/jev`](/docs/guides/jev.md) for a risk tier or a
7865
+ finding gate without a second model turn.
7866
+
7501
7867
  For multi-line descriptions, reminder prompts, and error messages, use
7502
7868
  [`prompt`](/docs/reference/prompt.md) so the string can sit indented with the surrounding
7503
7869
  TypeScript:
@@ -26,7 +26,7 @@
26
26
 
27
27
  ## Guides
28
28
 
29
- - [Agent-to-agent](/docs/guides/agent-to-agent.md): Let one Agent SDK agent consult an independent specialist, continue its session, or call its deterministic tools.
29
+ - [Peer agents](/docs/guides/agent-to-agent.md): Let one Agent SDK agent consult an independent specialist, continue its session, or call its deterministic tools.
30
30
  - [Bitbucket](/docs/guides/bitbucket.md): Review pull requests, answer comments, and triage pushes on Bitbucket Cloud or Data Center.
31
31
  - [Cursor cloud agents](/docs/guides/cloud-agents.md): Mount an extension that lets your agent delegate repository work, inspect the result, and steer or stop the cloud agent.
32
32
  - [Convert a Cursor Automation](/docs/guides/convert-automation.md): Turn a dashboard Automation into an Agent SDK project, then reconnect its actions and triggers.
@@ -34,6 +34,7 @@
34
34
  - [GitLab](/docs/guides/gitlab.md): Review merge requests, answer notes, and triage failed pipelines on GitLab.com or self-managed GitLab.
35
35
  - [Cursor Grok Bot agents](/docs/guides/grokbot-agents.md): Mount an extension that lets your agent consult named Grok Bot agents, wait for long replies, and interrupt work.
36
36
  - [Self-improvement](/docs/guides/improve.md): Let an agent propose a change to its own source through a branch and pull request, with review and deployment kept separate.
37
+ - [Jev](/docs/guides/jev.md): Use typed Jev decisions to filter review findings, route pull requests, and gate software-factory writes.
37
38
  - [Host MCP OAuth](/docs/guides/mcp-oauth.md): Authorize a private MCP server locally, constrain its tools, and carry its credentials onto a hosted agent.
38
39
  - [OpenTelemetry](/docs/guides/opentelemetry.md): Send agent traces and metrics to an OTLP collector, follow one conversation, and add domain telemetry.
39
40
  - [Slack](/docs/guides/slack.md): Wake your agent from mentions, DMs, and watched posts, then reply in the thread.