@cursor/bdk 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -1154
- package/dist/bin/agent-serve.js +17 -11
- package/dist/channels/github/github-channel.d.ts +4 -4
- package/dist/channels/github/github-channel.js +5 -5
- package/dist/channels/slack/eval-directive.js +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/assets/{app.4kQ8Db_q.js → app.CJLKDVza.js} +4 -4
- package/dist/docs/assets/{building-with-agents.md.-fcjCmJU.js → building-with-agents.md.BPjPFxFg.js} +2 -2
- package/dist/docs/assets/{building-with-agents.md.-fcjCmJU.lean.js → building-with-agents.md.BPjPFxFg.lean.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.Bq-pxRXm.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DY1RwB8Q.js → VPLocalSearchBox.BW9mrQmq.js} +1 -1
- package/dist/docs/assets/chunks/{arc.CxE_fSPK.js → arc.D8ZOvM1m.js} +1 -1
- package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CPX426ui.js → architectureDiagram-Q4EWVU46.CXEKhLW-.js} +1 -1
- package/dist/docs/assets/chunks/{baseUniq.CB52JrKG.js → baseUniq.BJkVKblr.js} +1 -1
- package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.J0cNaQCL.js → blockDiagram-DXYQGD6D.DQDbHxor.js} +1 -1
- package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.DJn3vEGT.js → c4Diagram-AHTNJAMY.ByMD6LYM.js} +1 -1
- package/dist/docs/assets/chunks/channel.DCU8W1RP.js +1 -0
- package/dist/docs/assets/chunks/{chunk-4BX2VUAB.Dao618F6.js → chunk-4BX2VUAB.Dtq1aVI9.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-4TB4RGXK.QW8Rhjai.js → chunk-4TB4RGXK.BL_XrkoQ.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-55IACEB6.DfRLLKF_.js → chunk-55IACEB6.BDPXu94_.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-EDXVE4YY.CIV2ApKQ.js → chunk-EDXVE4YY.DhGOQj4k.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-FMBD7UC4.BEheSuxp.js → chunk-FMBD7UC4.DSF5nr8v.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-OYMX7WX6.CUN88ENB.js → chunk-OYMX7WX6.Day7wayw.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-QZHKN3VN.CgqCs8b_.js → chunk-QZHKN3VN.CpBEC0zA.js} +1 -1
- package/dist/docs/assets/chunks/{chunk-YZCP3GAM.iCH0nnTJ.js → chunk-YZCP3GAM.X_7rY1rx.js} +1 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.DwpXsM06.js +1 -0
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.DwpXsM06.js +1 -0
- package/dist/docs/assets/chunks/clone.DH6Mx2zB.js +1 -0
- package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.BLcUxhWE.js → cose-bilkent-S5V4N54A.BVRmi2ko.js} +1 -1
- package/dist/docs/assets/chunks/{dagre-KV5264BT.Ep7LofOm.js → dagre-KV5264BT.Dei9oslB.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-5BDNPKRD.Bzf4GSQ4.js → diagram-5BDNPKRD._M-efGt7.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.DD6Jh-eM.js → diagram-G4DWMVQ6.D1Vmhfsj.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-MMDJMWI5.oOIl8bWd.js → diagram-MMDJMWI5.cE1bmvAC.js} +1 -1
- package/dist/docs/assets/chunks/{diagram-TYMM5635.DHs85Ade.js → diagram-TYMM5635.DkXAfznP.js} +1 -1
- package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.BIb5ghCk.js → erDiagram-SMLLAGMA.DH_pSwPg.js} +1 -1
- package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.DV4paY9k.js → flowDiagram-DWJPFMVM.kAWVN9j1.js} +1 -1
- package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.AyEKA6_v.js → ganttDiagram-T4ZO3ILL.8r0w49-p.js} +1 -1
- package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.BltiCDFo.js → gitGraphDiagram-UUTBAWPF.BDa7Bi1i.js} +1 -1
- package/dist/docs/assets/chunks/{graph.DzuEYGdC.js → graph.BMPXHz_B.js} +1 -1
- package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.BV2l981J.js → infoDiagram-42DDH7IO.BmlcqewS.js} +1 -1
- package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.BA4Izf-m.js → ishikawaDiagram-UXIWVN3A.CVSEQSul.js} +1 -1
- package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.DjaFbFS3.js → journeyDiagram-VCZTEJTY.BpeWJ5n-.js} +1 -1
- package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.CfTFieDs.js → kanban-definition-6JOO6SKY.DHbDXuxB.js} +1 -1
- package/dist/docs/assets/chunks/{layout.DzfWqTBV.js → layout.CzrCDgkP.js} +1 -1
- package/dist/docs/assets/chunks/{linear.BO6mpulV.js → linear.HwBsflwN.js} +1 -1
- package/dist/docs/assets/chunks/{min.BGgTadgT.js → min.DqGHolT3.js} +1 -1
- package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.DPuIXVWY.js → mindmap-definition-QFDTVHPH.ZYGlOawh.js} +1 -1
- package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.BOnl3bBg.js → pieDiagram-DEJITSTG.C2KRXlNR.js} +1 -1
- package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.DNB6Ckdc.js → quadrantDiagram-34T5L4WZ.CHj3Qefp.js} +1 -1
- package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.D5-Qo7vb.js → requirementDiagram-MS252O5E.B1L4Tf7k.js} +1 -1
- package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.8t65cesf.js → sankeyDiagram-XADWPNL6.dNR2yi1B.js} +1 -1
- package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.CaG07BdS.js → sequenceDiagram-FGHM5R23.BrvQ3C6m.js} +1 -1
- package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.TKOweTB6.js → stateDiagram-FHFEXIEX.BtehEykA.js} +1 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.kzD0-U89.js +1 -0
- package/dist/docs/assets/chunks/{theme.Dx-JhpTB.js → theme.BDHBZUkP.js} +2 -2
- package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.fE53zQ2s.js → timeline-definition-GMOUNBTQ.Bn7nhqEN.js} +1 -1
- package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.DJsZZaJg.js → vennDiagram-DHZGUBPP.DKhc38sz.js} +1 -1
- package/dist/docs/assets/chunks/wardley-RL74JXVD.DOXQ0w8J.js +162 -0
- package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.CMZ-Ru_t.js → wardleyDiagram-NUSXRM2D.Bbq5B2Ic.js} +1 -1
- package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.XXrhBc7a.js → xychartDiagram-5P7HB3ND.B77HE1K8.js} +1 -1
- package/dist/docs/assets/{deployment.md.UhnJIMr-.js → deployment.md.BdqTiGdc.js} +4 -4
- package/dist/docs/assets/{deployment.md.UhnJIMr-.lean.js → deployment.md.BdqTiGdc.lean.js} +1 -1
- package/dist/docs/assets/{evals.md.CCAtNcuL.js → evals.md.C851kViu.js} +3 -3
- package/dist/docs/assets/{evals.md.CCAtNcuL.lean.js → evals.md.C851kViu.lean.js} +1 -1
- package/dist/docs/assets/{guides_agent-to-agent.md.CGkicXeB.js → guides_agent-to-agent.md.Cps5NiCV.js} +2 -2
- package/dist/docs/assets/{guides_agent-to-agent.md.CGkicXeB.lean.js → guides_agent-to-agent.md.Cps5NiCV.lean.js} +1 -1
- package/dist/docs/assets/{guides_bitbucket.md.Cb3LPKt3.js → guides_bitbucket.md.BB6fqD-M.js} +2 -2
- package/dist/docs/assets/{guides_bitbucket.md.Cb3LPKt3.lean.js → guides_bitbucket.md.BB6fqD-M.lean.js} +1 -1
- package/dist/docs/assets/{guides_cloud-agents.md.BuEkDCwo.js → guides_cloud-agents.md.CWJjS9No.js} +2 -2
- package/dist/docs/assets/{guides_cloud-agents.md.BuEkDCwo.lean.js → guides_cloud-agents.md.CWJjS9No.lean.js} +1 -1
- package/dist/docs/assets/{guides_convert-automation.md.Ci-Y2iD5.js → guides_convert-automation.md.DMEX9nF-.js} +3 -3
- package/dist/docs/assets/{guides_convert-automation.md.Ci-Y2iD5.lean.js → guides_convert-automation.md.DMEX9nF-.lean.js} +1 -1
- package/dist/docs/assets/{guides_github.md.Bq9kQU9B.js → guides_github.md.Cr1Xlf-m.js} +3 -3
- package/dist/docs/assets/{guides_github.md.Bq9kQU9B.lean.js → guides_github.md.Cr1Xlf-m.lean.js} +1 -1
- package/dist/docs/assets/{guides_gitlab.md.BM27P43u.js → guides_gitlab.md.CMpmFi4M.js} +2 -2
- package/dist/docs/assets/{guides_gitlab.md.BM27P43u.lean.js → guides_gitlab.md.CMpmFi4M.lean.js} +1 -1
- package/dist/docs/assets/{guides_grokbot-agents.md.yxVbSlKA.js → guides_grokbot-agents.md.tD1smFhU.js} +2 -2
- package/dist/docs/assets/{guides_grokbot-agents.md.yxVbSlKA.lean.js → guides_grokbot-agents.md.tD1smFhU.lean.js} +1 -1
- package/dist/docs/assets/{guides_hooks.md.BWoiNaMq.js → guides_hooks.md.5Ce3NXxZ.js} +2 -2
- package/dist/docs/assets/{guides_hooks.md.BWoiNaMq.lean.js → guides_hooks.md.5Ce3NXxZ.lean.js} +1 -1
- package/dist/docs/assets/{guides_improve.md.COtL-6ft.js → guides_improve.md.CRrYq22s.js} +2 -2
- package/dist/docs/assets/{guides_improve.md.COtL-6ft.lean.js → guides_improve.md.CRrYq22s.lean.js} +1 -1
- package/dist/docs/assets/{guides_jev.md.CRcgmjDb.js → guides_jev.md.D7XH4JH3.js} +2 -2
- package/dist/docs/assets/{guides_jev.md.CRcgmjDb.lean.js → guides_jev.md.D7XH4JH3.lean.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.Cu6mhZ_3.js → guides_mcp-oauth.md.DR3zhC9r.js} +2 -2
- package/dist/docs/assets/{guides_mcp-oauth.md.Cu6mhZ_3.lean.js → guides_mcp-oauth.md.DR3zhC9r.lean.js} +1 -1
- package/dist/docs/assets/{guides_opentelemetry.md.DLlIB5rv.js → guides_opentelemetry.md.jcPNrQbH.js} +8 -6
- package/dist/docs/assets/{guides_opentelemetry.md.DLlIB5rv.lean.js → guides_opentelemetry.md.jcPNrQbH.lean.js} +1 -1
- package/dist/docs/assets/{guides_slack.md.diqqXTTm.js → guides_slack.md.Bn-WupSE.js} +8 -8
- package/dist/docs/assets/{guides_slack.md.diqqXTTm.lean.js → guides_slack.md.Bn-WupSE.lean.js} +1 -1
- package/dist/docs/assets/{guides_webhooks.md.D0furjw0.js → guides_webhooks.md.BBvAm_VF.js} +2 -2
- package/dist/docs/assets/{guides_webhooks.md.D0furjw0.lean.js → guides_webhooks.md.BBvAm_VF.lean.js} +1 -1
- package/dist/docs/assets/{hillclimbing.md.Biy0m-Qb.js → hillclimbing.md.Dxvd-0gT.js} +2 -2
- package/dist/docs/assets/{hillclimbing.md.Biy0m-Qb.lean.js → hillclimbing.md.Dxvd-0gT.lean.js} +1 -1
- package/dist/docs/assets/index.md.Dxxr7pFa.js +27 -0
- package/dist/docs/assets/{index.md.CVc_oOA3.lean.js → index.md.Dxxr7pFa.lean.js} +1 -1
- package/dist/docs/assets/{quickstart.md.CHpHPBUN.js → quickstart.md.BK5gjHM2.js} +2 -2
- package/dist/docs/assets/{quickstart.md.CHpHPBUN.lean.js → quickstart.md.BK5gjHM2.lean.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.Cj5uBKp4.js → reference_agent-config.md.DrtLxWgR.js} +4 -4
- package/dist/docs/assets/{reference_agent-config.md.Cj5uBKp4.lean.js → reference_agent-config.md.DrtLxWgR.lean.js} +1 -1
- package/dist/docs/assets/{reference_artifacts.md.CQfKq8F2.js → reference_artifacts.md.DLV9MZES.js} +2 -2
- package/dist/docs/assets/{reference_artifacts.md.CQfKq8F2.lean.js → reference_artifacts.md.DLV9MZES.lean.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.mbNtKCiR.js → reference_channels.md.LbNIJBwd.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.mbNtKCiR.lean.js → reference_channels.md.LbNIJBwd.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.DgeLTO18.js → reference_cli.md.BsgDqYPh.js} +4 -4
- package/dist/docs/assets/{reference_cli.md.DgeLTO18.lean.js → reference_cli.md.BsgDqYPh.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.COq--gAm.js → reference_connections.md.Bljpve-y.js} +4 -4
- package/dist/docs/assets/{reference_connections.md.COq--gAm.lean.js → reference_connections.md.Bljpve-y.lean.js} +1 -1
- package/dist/docs/assets/{reference_evals.md.CJm3uCUm.js → reference_evals.md.D5i8PuXJ.js} +2 -2
- package/dist/docs/assets/{reference_evals.md.CJm3uCUm.lean.js → reference_evals.md.D5i8PuXJ.lean.js} +1 -1
- package/dist/docs/assets/{reference_extensions.md.pa2tN-e4.js → reference_extensions.md.OUacPetl.js} +3 -3
- package/dist/docs/assets/{reference_extensions.md.pa2tN-e4.lean.js → reference_extensions.md.OUacPetl.lean.js} +1 -1
- package/dist/docs/assets/{reference_hooks.md.DbthhtIR.js → reference_hooks.md.C5LCJ1R3.js} +2 -2
- package/dist/docs/assets/{reference_hooks.md.DbthhtIR.lean.js → reference_hooks.md.C5LCJ1R3.lean.js} +1 -1
- package/dist/docs/assets/{reference_http-api.md.BZOvhCqY.js → reference_http-api.md.DbFNOubV.js} +1 -1
- package/dist/docs/assets/{reference_instructions.md.Bdwscs4G.js → reference_instructions.md.DrcHZXig.js} +2 -2
- package/dist/docs/assets/{reference_instructions.md.Bdwscs4G.lean.js → reference_instructions.md.DrcHZXig.lean.js} +1 -1
- package/dist/docs/assets/reference_playground.md.1hx0gcIu.js +1 -0
- package/dist/docs/assets/{reference_playground.md.BdQzRJc2.lean.js → reference_playground.md.1hx0gcIu.lean.js} +1 -1
- package/dist/docs/assets/{reference_project-layout.md.CpLQ9j4K.js → reference_project-layout.md.C2JMRh7p.js} +2 -2
- package/dist/docs/assets/{reference_prompt.md.BQZB4eaV.js → reference_prompt.md.DqPh71XN.js} +3 -3
- package/dist/docs/assets/{reference_prompt.md.BQZB4eaV.lean.js → reference_prompt.md.DqPh71XN.lean.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.BVU5EFbz.js → reference_schedules.md.BuJ8fgMa.js} +2 -2
- package/dist/docs/assets/{reference_schedules.md.BVU5EFbz.lean.js → reference_schedules.md.BuJ8fgMa.lean.js} +1 -1
- package/dist/docs/assets/reference_sessions.md.CM5zo3w4.js +1 -0
- package/dist/docs/assets/{reference_sessions.md.DeRUItHD.lean.js → reference_sessions.md.CM5zo3w4.lean.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.Cy00QMKS.js → reference_skills.md.ClkMoQsV.js} +2 -2
- package/dist/docs/assets/{reference_skills.md.Cy00QMKS.lean.js → reference_skills.md.ClkMoQsV.lean.js} +1 -1
- package/dist/docs/assets/{reference_subagents.md.B8oyeXOI.js → reference_subagents.md.gmPt5J-M.js} +2 -2
- package/dist/docs/assets/{reference_subagents.md.B8oyeXOI.lean.js → reference_subagents.md.gmPt5J-M.lean.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.hg2Wi5Bq.js → reference_tools.md.v3SXVSs_.js} +2 -2
- package/dist/docs/assets/{reference_tools.md.hg2Wi5Bq.lean.js → reference_tools.md.v3SXVSs_.lean.js} +1 -1
- package/dist/docs/assets/{templates_agentic-owners.md.BykUiZ8j.js → templates_agentic-owners.md.CvmABtia.js} +2 -2
- package/dist/docs/assets/templates_grokbot-agents.md.2sydjFiO.js +5 -0
- package/dist/docs/assets/templates_grokbot-agents.md.2sydjFiO.lean.js +1 -0
- package/dist/docs/assets/{templates_security-reviewer.md.DXMmKl_o.js → templates_security-reviewer.md.Gh6EF9Us.js} +3 -2
- package/dist/docs/assets/{templates_security-reviewer.md.DXMmKl_o.lean.js → templates_security-reviewer.md.Gh6EF9Us.lean.js} +1 -1
- package/dist/docs/assets/{templates_thermo-quality-review.md.Dg1p1MsG.js → templates_thermo-quality-review.md.B77UyTrX.js} +2 -2
- package/dist/docs/assets/{templates_thermo-quality-review.md.Dg1p1MsG.lean.js → templates_thermo-quality-review.md.B77UyTrX.lean.js} +1 -1
- package/dist/docs/assets/{templates_thermo-review.md.Dlylkowj.js → templates_thermo-review.md.DRJ7mC5U.js} +2 -2
- package/dist/docs/assets/{templates_thermo-review.md.Dlylkowj.lean.js → templates_thermo-review.md.DRJ7mC5U.lean.js} +1 -1
- package/dist/docs/assets/templates_triage.md.CNN6b0JZ.js +9 -0
- package/dist/docs/assets/{templates_triage.md.CvJyx81N.lean.js → templates_triage.md.CNN6b0JZ.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.Bscj6ODe.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.Cw5PKa3t.lean.js → troubleshooting.md.Bscj6ODe.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +36 -36
- package/dist/docs/building-with-agents.md +0 -3
- package/dist/docs/deployment.html +38 -38
- package/dist/docs/deployment.md +2 -9
- package/dist/docs/evals.html +37 -37
- package/dist/docs/evals.md +2 -5
- package/dist/docs/guides/agent-to-agent.html +36 -36
- package/dist/docs/guides/agent-to-agent.md +0 -3
- package/dist/docs/guides/bitbucket.html +36 -36
- package/dist/docs/guides/bitbucket.md +0 -3
- package/dist/docs/guides/cloud-agents.html +36 -36
- package/dist/docs/guides/cloud-agents.md +0 -4
- package/dist/docs/guides/convert-automation.html +37 -37
- package/dist/docs/guides/convert-automation.md +2 -5
- package/dist/docs/guides/github.html +37 -37
- package/dist/docs/guides/github.md +1 -4
- package/dist/docs/guides/gitlab.html +36 -36
- package/dist/docs/guides/gitlab.md +0 -3
- package/dist/docs/guides/grokbot-agents.html +37 -37
- package/dist/docs/guides/grokbot-agents.md +1 -4
- package/dist/docs/guides/hooks.html +36 -36
- package/dist/docs/guides/hooks.md +0 -3
- package/dist/docs/guides/improve.html +36 -36
- package/dist/docs/guides/improve.md +0 -3
- package/dist/docs/guides/jev.html +36 -36
- package/dist/docs/guides/jev.md +0 -3
- package/dist/docs/guides/mcp-oauth.html +37 -37
- package/dist/docs/guides/mcp-oauth.md +1 -4
- package/dist/docs/guides/opentelemetry.html +42 -40
- package/dist/docs/guides/opentelemetry.md +4 -5
- package/dist/docs/guides/slack.html +43 -43
- package/dist/docs/guides/slack.md +14 -24
- package/dist/docs/guides/webhooks.html +36 -36
- package/dist/docs/guides/webhooks.md +0 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +36 -36
- package/dist/docs/hillclimbing.md +0 -3
- package/dist/docs/index.html +38 -38
- package/dist/docs/index.md +9 -16
- package/dist/docs/llms-full.txt +153 -234
- package/dist/docs/llms.txt +1 -0
- package/dist/docs/quickstart.html +36 -36
- package/dist/docs/quickstart.md +2 -7
- package/dist/docs/reference/agent-config.html +38 -38
- package/dist/docs/reference/agent-config.md +4 -7
- package/dist/docs/reference/artifacts.html +36 -36
- package/dist/docs/reference/artifacts.md +0 -3
- package/dist/docs/reference/channels.html +37 -37
- package/dist/docs/reference/channels.md +1 -6
- package/dist/docs/reference/cli.html +38 -38
- package/dist/docs/reference/cli.md +7 -14
- package/dist/docs/reference/connections.html +38 -38
- package/dist/docs/reference/connections.md +7 -10
- package/dist/docs/reference/evals.html +36 -36
- package/dist/docs/reference/evals.md +0 -3
- package/dist/docs/reference/extensions.html +37 -37
- package/dist/docs/reference/extensions.md +2 -5
- package/dist/docs/reference/hooks.html +36 -36
- package/dist/docs/reference/hooks.md +0 -3
- package/dist/docs/reference/http-api.html +37 -37
- package/dist/docs/reference/http-api.md +1 -1
- package/dist/docs/reference/instructions.html +36 -36
- package/dist/docs/reference/instructions.md +0 -3
- package/dist/docs/reference/playground.html +36 -36
- package/dist/docs/reference/playground.md +0 -3
- package/dist/docs/reference/project-layout.html +37 -37
- package/dist/docs/reference/project-layout.md +2 -2
- package/dist/docs/reference/prompt.html +37 -37
- package/dist/docs/reference/prompt.md +0 -3
- package/dist/docs/reference/schedules.html +36 -36
- package/dist/docs/reference/schedules.md +0 -3
- package/dist/docs/reference/sessions.html +36 -36
- package/dist/docs/reference/sessions.md +0 -3
- package/dist/docs/reference/skills.html +36 -36
- package/dist/docs/reference/skills.md +0 -3
- package/dist/docs/reference/subagents.html +36 -36
- package/dist/docs/reference/subagents.md +0 -3
- package/dist/docs/reference/tools.html +36 -36
- package/dist/docs/reference/tools.md +1 -5
- package/dist/docs/templates/agentic-owners.html +37 -37
- package/dist/docs/templates/agentic-owners.md +2 -3
- package/dist/docs/templates/grokbot-agents.html +64 -0
- package/dist/docs/templates/grokbot-agents.md +55 -0
- package/dist/docs/templates/security-reviewer.html +38 -37
- package/dist/docs/templates/security-reviewer.md +7 -11
- package/dist/docs/templates/thermo-quality-review.html +37 -37
- package/dist/docs/templates/thermo-quality-review.md +5 -8
- package/dist/docs/templates/thermo-review.html +37 -37
- package/dist/docs/templates/thermo-review.md +5 -7
- package/dist/docs/templates/triage.html +39 -39
- package/dist/docs/templates/triage.md +8 -4
- package/dist/docs/troubleshooting.html +36 -36
- package/dist/docs/troubleshooting.md +3 -7
- package/dist/evals.d.ts +2 -2
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +14 -7
- package/dist/internal/eval-runner.js +7 -4
- package/dist/internal/init-interview.d.ts +0 -1
- package/dist/internal/init-interview.d.ts.map +1 -1
- package/dist/internal/init-interview.js +15 -24
- package/dist/internal/legacy-command-guard.d.ts +4 -1
- package/dist/internal/legacy-command-guard.d.ts.map +1 -1
- package/dist/internal/legacy-command-guard.js +11 -2
- package/dist/internal/platform-timers.d.ts +8 -1
- package/dist/internal/platform-timers.d.ts.map +1 -1
- package/dist/internal/platform-timers.js +10 -2
- package/dist/internal/reminder-control-plane-protocol.d.ts +8 -1
- package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -1
- package/dist/internal/reminder-runner.d.ts +5 -0
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +27 -1
- package/dist/internal/resolve-prod-target.d.ts +3 -0
- package/dist/internal/resolve-prod-target.d.ts.map +1 -1
- package/dist/internal/resolve-prod-target.js +2 -1
- package/dist/internal/run-client.d.ts +10 -1
- package/dist/internal/run-client.d.ts.map +1 -1
- package/dist/internal/run-client.js +152 -51
- package/dist/internal/server.d.ts +6 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +20 -8
- package/dist/internal/session-links.d.ts.map +1 -1
- package/dist/internal/session-links.js +8 -7
- package/dist/internal/sessions-client.d.ts +1 -0
- package/dist/internal/sessions-client.d.ts.map +1 -1
- package/dist/internal/sessions-client.js +2 -0
- package/docs/README.md +9 -16
- package/docs/building-with-agents.md +0 -3
- package/docs/deployment.md +2 -9
- package/docs/evals.md +2 -5
- package/docs/guides/agent-to-agent.md +0 -3
- package/docs/guides/bitbucket.md +0 -3
- package/docs/guides/cloud-agents.md +0 -4
- package/docs/guides/convert-automation.md +2 -5
- package/docs/guides/github.md +1 -4
- package/docs/guides/gitlab.md +0 -3
- package/docs/guides/grokbot-agents.md +1 -4
- package/docs/guides/hooks.md +0 -3
- package/docs/guides/improve.md +0 -3
- package/docs/guides/jev.md +0 -3
- package/docs/guides/mcp-oauth.md +1 -4
- package/docs/guides/opentelemetry.md +4 -5
- package/docs/guides/slack.md +14 -24
- package/docs/guides/webhooks.md +0 -3
- package/docs/hillclimbing.md +0 -3
- package/docs/quickstart.md +2 -7
- package/docs/reference/agent-config.md +4 -7
- package/docs/reference/artifacts.md +0 -3
- package/docs/reference/channels.md +1 -6
- package/docs/reference/cli.md +7 -14
- package/docs/reference/connections.md +7 -10
- package/docs/reference/evals.md +0 -3
- package/docs/reference/extensions.md +2 -5
- package/docs/reference/hooks.md +0 -3
- package/docs/reference/http-api.md +1 -1
- package/docs/reference/instructions.md +0 -3
- package/docs/reference/playground.md +0 -3
- package/docs/reference/project-layout.md +2 -2
- package/docs/reference/prompt.md +0 -3
- package/docs/reference/schedules.md +0 -3
- package/docs/reference/sessions.md +0 -3
- package/docs/reference/skills.md +0 -3
- package/docs/reference/subagents.md +0 -3
- package/docs/reference/tools.md +1 -5
- package/docs/templates/agentic-owners.md +2 -3
- package/docs/templates/grokbot-agents.md +60 -0
- package/docs/templates/security-reviewer.md +7 -11
- package/docs/templates/thermo-quality-review.md +5 -8
- package/docs/templates/thermo-review.md +5 -7
- package/docs/templates/triage.md +8 -4
- package/docs/troubleshooting.md +3 -7
- package/package.json +2 -2
- package/templates/agentic-owners/README.md +0 -3
- package/templates/agents-md/README.md +4 -3
- package/templates/agents-md/evals/agents.eval.ts +1 -0
- package/templates/code-wiki/README.md +0 -3
- package/templates/code-wiki/bot/instructions.md +4 -4
- package/templates/demo/README.md +0 -3
- package/templates/grokbot-agents/README.md +4 -6
- package/templates/security-help/README.md +12 -6
- package/templates/security-reviewer/README.md +5 -6
- package/templates/security-reviewer/bot/tools/post_findings.ts +8 -8
- package/templates/thermo-quality-review/README.md +0 -3
- package/templates/thermo-quality-review/bot/tools/post_findings.ts +8 -8
- package/templates/thermo-review/README.md +0 -3
- package/templates/thermo-review/bot/tools/post_findings.ts +8 -8
- package/templates/triage/README.md +0 -3
- package/templates/triage/overlays/jira/README.md +0 -3
- package/templates/triage/overlays/linear/README.md +0 -3
- package/dist/docs/assets/chunks/@localSearchIndexroot.CvuAJ0My.js +0 -1
- package/dist/docs/assets/chunks/channel.BoNycAoN.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.C4x07Gkj.js +0 -1
- package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.C4x07Gkj.js +0 -1
- package/dist/docs/assets/chunks/clone.Db22cH_-.js +0 -1
- package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CuqmyQc4.js +0 -1
- package/dist/docs/assets/chunks/wardley-RL74JXVD.844kyrjl.js +0 -162
- package/dist/docs/assets/index.md.CVc_oOA3.js +0 -27
- package/dist/docs/assets/reference_playground.md.BdQzRJc2.js +0 -1
- package/dist/docs/assets/reference_sessions.md.DeRUItHD.js +0 -1
- package/dist/docs/assets/templates_triage.md.CvJyx81N.js +0 -9
- package/dist/docs/assets/troubleshooting.md.Cw5PKa3t.js +0 -1
- /package/dist/docs/assets/{reference_http-api.md.BZOvhCqY.lean.js → reference_http-api.md.DbFNOubV.lean.js} +0 -0
- /package/dist/docs/assets/{reference_project-layout.md.CpLQ9j4K.lean.js → reference_project-layout.md.C2JMRh7p.lean.js} +0 -0
- /package/dist/docs/assets/{templates_agentic-owners.md.BykUiZ8j.lean.js → templates_agentic-owners.md.CvmABtia.lean.js} +0 -0
package/README.md
CHANGED
|
@@ -1,1185 +1,107 @@
|
|
|
1
1
|
# Grok Bot Development Kit (BDK)
|
|
2
2
|
|
|
3
|
-
Grok Bot Development Kit (BDK)
|
|
4
|
-
|
|
3
|
+
The Grok Bot Development Kit (BDK) is how Cursor builds bots and
|
|
4
|
+
agents. It is the open-source version of the engine behind Bugbot,
|
|
5
|
+
Security Review, and Approval Bot.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
A BDK project is a folder of Markdown and TypeScript. Combine model
|
|
8
|
+
judgment with deterministic code, then make the result available in
|
|
9
|
+
source control, Slack, issue trackers, and Cursor.
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
npm install --global @cursor/bdk
|
|
10
|
-
bdk init ./my-bot
|
|
11
|
-
cd my-bot
|
|
12
|
-
bdk dev
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
BDK is a filesystem-first framework for building and serving Cursor bots and
|
|
16
|
-
agents. Define a project as ordinary files: Markdown for prose and TypeScript
|
|
17
|
-
for typed behavior. The framework discovers those files, compiles them into a
|
|
18
|
-
manifest, and serves the project over channels with the Cursor SDK
|
|
19
|
-
(`@cursor/sdk`) and harness as the execution engine.
|
|
20
|
-
|
|
21
|
-
**User-facing documentation lives in [`docs/`](./docs/README.md)**.
|
|
22
|
-
After the package publishes, open it with `bdk docs`, or at `/docs` on every
|
|
23
|
-
running `bdk serve` host. It covers getting started, concepts, guides (Slack,
|
|
24
|
-
GitHub webhooks, approvals, and agent-to-agent), evals, hillclimbing,
|
|
25
|
-
deployment, troubleshooting, and reference pages for each folder. This README
|
|
26
|
-
is the compact package reference.
|
|
27
|
-
|
|
28
|
-
Instead of one large configuration object, each part of the agent gets a
|
|
29
|
-
clear home. Instructions go in one file, tools in one folder, channels in
|
|
30
|
-
another; a file's location says what it does, and its path gives it its
|
|
31
|
-
name. There is no registry to keep in sync: add the file and it is
|
|
32
|
-
discovered, move or rename it and its identity moves with it.
|
|
33
|
-
|
|
34
|
-
```text
|
|
35
|
-
my-agent/
|
|
36
|
-
├── package.json
|
|
37
|
-
└── bot/
|
|
38
|
-
├── agent.ts # runtime config: the Cursor model
|
|
39
|
-
├── instructions.md # the always-on system prompt
|
|
40
|
-
├── tools/
|
|
41
|
-
│ └── get_weather.ts # one typed tool per file
|
|
42
|
-
├── skills/
|
|
43
|
-
│ └── forecast.md # on-demand procedures (SKILL.md convention)
|
|
44
|
-
├── mcp-connections/
|
|
45
|
-
│ └── linear.ts # tools from external MCP servers
|
|
46
|
-
├── subagents/
|
|
47
|
-
│ └── researcher/ # specialist child agents
|
|
48
|
-
├── channels/
|
|
49
|
-
│ └── webhook.ts # HTTP surfaces beyond the built-in session API
|
|
50
|
-
├── hooks/
|
|
51
|
-
│ └── audit.ts # observe the runtime event stream
|
|
52
|
-
├── storage.ts # optional durable storage
|
|
53
|
-
├── artifacts.ts # optional artifact kinds and retention
|
|
54
|
-
├── result.ts # optional host commit on the final assistant text
|
|
55
|
-
├── otel.ts # optional OpenTelemetry export
|
|
56
|
-
├── playground/ # optional custom playground tool chips
|
|
57
|
-
├── schedules/
|
|
58
|
-
│ └── heartbeat.md # cron-driven runs
|
|
59
|
-
├── sandbox/workspace/ # files seeded into each session's workspace
|
|
60
|
-
└── lib/ # shared code (import-only, never discovered)
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Scaffold a starter project with `bdk init ./my-agent`. It writes
|
|
64
|
-
`AGENTS.md`, `.gitignore`, `package.json`, `tsconfig.json`, `bot/agent.ts`,
|
|
65
|
-
`bot/instructions.md`, `bot/tools/echo.ts`, and `bot/hooks/memory.ts`.
|
|
66
|
-
The project serves immediately and type-checks with `npm run check`. From
|
|
67
|
-
there, grow it folder by folder. The
|
|
68
|
-
[docs](./docs/README.md) walk a weather agent from a single
|
|
69
|
-
`get_weather` tool through skills, channels, evals, and deployment.
|
|
70
|
-
|
|
71
|
-
Serve one project with `bdk serve --dir ./my-agent --dev`, or point
|
|
72
|
-
`serve` at a folder of agent projects to mount every child under its
|
|
73
|
-
directory name.
|
|
74
|
-
|
|
75
|
-
## Node only: do not run under Bun
|
|
76
|
-
|
|
77
|
-
When published, `@cursor/bdk` requires **Node 22.13+** and supplies the
|
|
78
|
-
`bdk` binary. Do not run it under Bun: Bun's HTTP/2 client
|
|
79
|
-
corrupts the Cursor SDK's local harness tool-result streams
|
|
80
|
-
(`NGHTTP2_FRAME_SIZE_ERROR`), so every built-in read/grep the model
|
|
81
|
-
makes fails and turns degrade into failed-read retry loops.
|
|
82
|
-
|
|
83
|
-
## Serving many agents at once
|
|
84
|
-
|
|
85
|
-
Point `serve` at a **folder of agent projects** and it hosts all of them on
|
|
86
|
-
one port, each under its own slug (its directory name):
|
|
87
|
-
|
|
88
|
-
```text
|
|
89
|
-
bdk serve --dir ./agents --dev
|
|
90
|
-
# 2 agents listening
|
|
91
|
-
# playground <printed URL>
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
`serve` always uses multi-agent layout by default: agents are mounted under
|
|
95
|
-
`/<slug>/v1/*` with an index at `/`. A directory that is itself an agent
|
|
96
|
-
project is mounted under its directory name. Opt into the unslugged
|
|
97
|
-
`/v1/*` surface with `serve(dir, { mode: "single" })`.
|
|
98
|
-
|
|
99
|
-
In multi-agent mode:
|
|
100
|
-
|
|
101
|
-
- `GET /` is a web index listing every agent, linking to its playground;
|
|
102
|
-
`GET /v1/agents` is the JSON equivalent.
|
|
103
|
-
- `GET /v1/health` is host-level liveness (for ALB/ECS); each agent also has
|
|
104
|
-
`/<slug>/v1/health`.
|
|
105
|
-
- each agent is fully namespaced: `/<slug>/v1/session`,
|
|
106
|
-
`/<slug>/v1/session/:id/stream`, `/<slug>/playground`, `/<slug>/v1/info`,
|
|
107
|
-
custom channels at `/<slug>/v1/channels/<id>`, etc.
|
|
108
|
-
- sessions are isolated per agent (`<stateRoot>/<slug>/`), and the playground
|
|
109
|
-
gains a "← all agents" link back to the index.
|
|
110
|
-
- point the terminal client at a slug:
|
|
111
|
-
`bdk chat --url http://127.0.0.1:3000/weather-agent`.
|
|
112
|
-
|
|
113
|
-
Slugs come from directory names and must match `[A-Za-z0-9][A-Za-z0-9_-]*`
|
|
114
|
-
and not collide with the reserved `v1` / `playground` / `docs` path
|
|
115
|
-
segments.
|
|
116
|
-
|
|
117
|
-
## Agent-to-agent: every agent is an MCP server
|
|
118
|
-
|
|
119
|
-
Every mounted agent also serves the **Model Context Protocol** over
|
|
120
|
-
streamable HTTP at `/<slug>/v1/mcp` (or `/v1/mcp` in single mode), so other
|
|
121
|
-
agents, and any MCP client, can delegate work to it. The surface is
|
|
122
|
-
stateless (session identity travels in tool arguments) and runs the same
|
|
123
|
-
route auth chain as the session API. Tools:
|
|
124
|
-
|
|
125
|
-
| Tool | Behavior |
|
|
126
|
-
| ---- | -------- |
|
|
127
|
-
| `ask` | Send a message; runs a model turn in **this agent's own session, tools, and context** and returns `{ status, sessionId, reply }`. Omit `sessionId` for a fresh session; pass it to follow up. |
|
|
128
|
-
| `check` | Wait for / poll a running session (`waitSeconds: 0` for a non-blocking poll). |
|
|
129
|
-
| `call_tool` | Call one of the agent's deterministic server tools directly (no model turn). Registered only when the agent has server tools. |
|
|
130
|
-
|
|
131
|
-
Waits are bounded (~50s, below MCP client request timeouts): a long turn
|
|
132
|
-
returns `status: "running"` and the caller keeps waiting with `check`.
|
|
133
|
-
Sessions created this way live on the `mcp` channel, bind to the calling
|
|
134
|
-
principal, and show up in the playground and `GET /v1/sessions` like any
|
|
135
|
-
other session.
|
|
136
|
-
|
|
137
|
-
**Peer MCP connections** make delegation first-class between agents on the
|
|
138
|
-
same host. Author an MCP connection whose transport is a peer slug:
|
|
139
|
-
|
|
140
|
-
```ts
|
|
141
|
-
// agents/concierge/bot/mcp-connections/weather.ts
|
|
142
|
-
import { defineConnection } from "@cursor/bdk/connections";
|
|
11
|
+
## Why use it
|
|
143
12
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
description: "Delegate weather questions to the weather agent.",
|
|
147
|
-
});
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
The parent model then sees the peer's `ask` / `check` (/ `call_tool`) tools
|
|
151
|
-
under the `weather` server name: subagent-style delegation where the peer
|
|
152
|
-
keeps its **own** instructions, tools, MCP connections, and sessions. Peer URLs
|
|
153
|
-
resolve when the server starts, so `run` and `eval` ephemeral ports work.
|
|
154
|
-
Local-runtime turns, host-side `ctx.host.mcp`, and channel handlers use
|
|
155
|
-
loopback under the default `localDevStrict()` auth. Turns that do not run on
|
|
156
|
-
the serve host require `--public-url`; without it, BDK omits peers from those
|
|
157
|
-
turns and prints a warning.
|
|
158
|
-
|
|
159
|
-
Unknown peer slugs and self-references fail at serve startup. Peers require
|
|
160
|
-
the multi-agent layout (each agent mounted under its slug). There is no
|
|
161
|
-
cross-host loop protection yet: if agent A's instructions delegate to B and
|
|
162
|
-
B's delegate back to A, they can recurse. Scope each agent's delegation
|
|
163
|
-
instructions narrowly (the concierge above delegates *weather questions* to
|
|
164
|
-
`weather-agent`, not everything).
|
|
165
|
-
|
|
166
|
-
```text
|
|
167
|
-
bdk serve --dir ./agents --dev
|
|
168
|
-
bdk chat --url http://127.0.0.1:3000/concierge \
|
|
169
|
-
--message "What's the weather in Paris right now?"
|
|
170
|
-
# concierge → weather.ask → weather-agent's own session/tools → reply
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
## Quick start
|
|
174
|
-
|
|
175
|
-
A minimal agent is two files.
|
|
13
|
+
- **Bots and agents live in your repo.** Review, version, and ship
|
|
14
|
+
instructions, tools, and evals with the rest of your code.
|
|
176
15
|
|
|
177
|
-
|
|
16
|
+
- **Cursor runs the loop.** Your project gets Cursor's models, tool
|
|
17
|
+
calling, skills, MCP, and subagents.
|
|
178
18
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
`bot/agent.ts`:
|
|
184
|
-
|
|
185
|
-
```ts
|
|
186
|
-
import { defineAgent } from "@cursor/bdk";
|
|
187
|
-
|
|
188
|
-
export default defineAgent({
|
|
189
|
-
// optional: defaults to grok-4.5 with effort=high and fast=true
|
|
190
|
-
});
|
|
191
|
-
```
|
|
19
|
+
- **Use it where you work.** Trigger a project from source-control
|
|
20
|
+
events, Slack threads, custom webhooks, or schedules.
|
|
192
21
|
|
|
193
|
-
|
|
194
|
-
|
|
22
|
+
- **Test normal TypeScript.** Add evals and unit tests without a
|
|
23
|
+
separate configuration language.
|
|
195
24
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
# or: export CURSOR_API_KEY=key_...
|
|
199
|
-
bdk serve --dir . --port 3000
|
|
200
|
-
# e.g. playground at http://127.0.0.1:3000/<dirname>/playground
|
|
201
|
-
```
|
|
25
|
+
- **Choose where it runs.** Deploy to Cursor-managed hosting or run
|
|
26
|
+
the process on your infrastructure.
|
|
202
27
|
|
|
203
|
-
|
|
204
|
-
the agent directory name):
|
|
28
|
+
## When to use BDK
|
|
205
29
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
30
|
+
| | Cursor Automations | Grok Bot | BDK |
|
|
31
|
+
| --- | --- | --- | --- |
|
|
32
|
+
| **Use for** | Repeatable jobs driven by a prompt and trigger | Interactive agents you work with in Cursor | Agents that need custom code, integrations, tests, or deployment choices |
|
|
33
|
+
| **You define** | A prompt, model, and trigger in the dashboard | Instructions, skills, and connected tools in the app | A versioned Markdown and TypeScript project |
|
|
34
|
+
| **Where it runs** | Cursor-managed | Cursor-managed | Cursor-managed hosting or your infrastructure |
|
|
35
|
+
| **Choose it when** | The job fits a schedule or event trigger | You want an agent without creating a software project | You want deterministic code around model judgment and a project your team can review and test |
|
|
211
36
|
|
|
212
|
-
|
|
213
|
-
# {"type":"session.started",...}
|
|
214
|
-
# {"type":"message.appended","data":{"delta":"I can","text":"I can"},...}
|
|
215
|
-
# {"type":"message.completed",...}
|
|
216
|
-
# {"type":"turn.completed",...}
|
|
217
|
-
# {"type":"session.waiting",...}
|
|
218
|
-
```
|
|
37
|
+
## Get started
|
|
219
38
|
|
|
220
|
-
|
|
221
|
-
|
|
39
|
+
BDK requires Node 22.13 or newer. Install `@cursor/bdk`, create a
|
|
40
|
+
project, and start the development server:
|
|
222
41
|
|
|
223
42
|
```bash
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
Inspect the discovered surface at any time:
|
|
230
|
-
|
|
231
|
-
```text
|
|
232
|
-
bdk info --dir . # or GET /<slug>/v1/info on a running server
|
|
233
|
-
bdk validate --dir . # exit non-zero on error diagnostics
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
## Terminal client
|
|
237
|
-
|
|
238
|
-
`bdk chat` talks to a running server over the same public API and
|
|
239
|
-
renders the reply live: streamed text, tool calls, and a per-turn usage
|
|
240
|
-
footer. Pass `--json` for a compact trajectory (same shape as `run`).
|
|
241
|
-
|
|
242
|
-
```text
|
|
243
|
-
# interactive REPL against a local server
|
|
244
|
-
bdk chat --url http://127.0.0.1:3000
|
|
245
|
-
|
|
246
|
-
# one-shot (good for piping / scripts)
|
|
247
|
-
bdk chat --url http://127.0.0.1:3000 --message "Weather in Paris?"
|
|
248
|
-
|
|
249
|
-
# JSON trajectory (for coding agents / scripts)
|
|
250
|
-
bdk chat --url http://127.0.0.1:3000 --message "hello" --json
|
|
251
|
-
|
|
252
|
-
# against an authed server
|
|
253
|
-
bdk chat --url https://my-agent.example.com --bearer-token "$TOKEN"
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
## Agent loop
|
|
257
|
-
|
|
258
|
-
Coding agents should prefer the JSON-first commands: edit files → inspect
|
|
259
|
-
→ run a turn → assert with filesystem evals.
|
|
260
|
-
|
|
261
|
-
```text
|
|
262
|
-
bdk validate --dir .
|
|
263
|
-
bdk info --dir . --json
|
|
264
|
-
|
|
265
|
-
# Ephemeral server + one (or more) turns; JSON trajectory on stdout
|
|
266
|
-
bdk run --dir . --message "What's the temperature in NYC?"
|
|
267
|
-
|
|
268
|
-
# Optional event log for later summarization
|
|
269
|
-
bdk run --dir . --message "..." --events /tmp/run.ndjson
|
|
270
|
-
bdk trajectory --events /tmp/run.ndjson
|
|
271
|
-
|
|
272
|
-
# Scaffold (or print the setup guide with no directory)
|
|
273
|
-
bdk init ./my-agent
|
|
274
|
-
bdk init
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
`run` / `eval` boot a temporary server on port `0` with a temp `stateRoot`
|
|
278
|
-
outside the project so session workspaces do not inherit ambient monorepo
|
|
279
|
-
`AGENTS.md` / `.cursor` rules. Pass `--url` to target an already-running
|
|
280
|
-
agent instead.
|
|
281
|
-
|
|
282
|
-
### Evals
|
|
283
|
-
|
|
284
|
-
Author cases under `evals/**/*.eval.ts` with `defineEval`. Drive the
|
|
285
|
-
agent and assert inline:
|
|
286
|
-
|
|
287
|
-
```ts
|
|
288
|
-
import { defineEval, includes } from "@cursor/bdk/evals";
|
|
289
|
-
|
|
290
|
-
export default defineEval({
|
|
291
|
-
description: "Uses get_weather for temperature questions.",
|
|
292
|
-
tags: ["smoke"],
|
|
293
|
-
async test(t) {
|
|
294
|
-
await t.send("What's the temperature in NYC?");
|
|
295
|
-
t.succeeded();
|
|
296
|
-
t.calledTool("get_weather");
|
|
297
|
-
t.check(t.reply, includes(/°|[FC]/));
|
|
298
|
-
},
|
|
299
|
-
});
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
Case id is the path under `evals/` for a single-`test` file, or
|
|
303
|
-
`<fileId>/<case.id>` when using `cases` in one file.
|
|
304
|
-
|
|
305
|
-
Use `t.judge` when wording needs an LLM grader. The built-in JUnit and
|
|
306
|
-
Artifacts reporters write CI results and per-case evidence.
|
|
307
|
-
|
|
308
|
-
Every project with evals needs `evals/evals.config.ts` with a required
|
|
309
|
-
`maxConcurrency` (hard-capped at 200 due to model provider request limits).
|
|
310
|
-
Playground batches are in-memory by default; declare an `evals` table in
|
|
311
|
-
`bot/storage.ts` (`defineStorage`) to keep them across serve restarts.
|
|
312
|
-
Optional `maxPlaygroundRuns` caps how many batches the playground /
|
|
313
|
-
`/v1/dev/evals*` history keeps (default 20):
|
|
314
|
-
|
|
315
|
-
```ts
|
|
316
|
-
import { defineEvalConfig } from "@cursor/bdk/evals";
|
|
317
|
-
|
|
318
|
-
export default defineEvalConfig({
|
|
319
|
-
maxConcurrency: 20,
|
|
320
|
-
// Optional: playground /v1/dev/evals history window (default 20):
|
|
321
|
-
// maxPlaygroundRuns: 50,
|
|
322
|
-
});
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
```text
|
|
326
|
-
bdk eval --dir . --list
|
|
327
|
-
bdk eval --dir . --json
|
|
328
|
-
bdk eval --dir . weather/nyc # one datapoint
|
|
329
|
-
bdk eval --dir . weather # whole file
|
|
330
|
-
bdk eval --dir . weather forecast # multiple files
|
|
331
|
-
bdk eval --dir . --tag smoke
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
See [`docs/`](./docs/README.md) for the full documentation set,
|
|
335
|
-
[`AGENTS.md`](./AGENTS.md) for the coding-agent guide, and
|
|
336
|
-
[`skills/`](./skills/) for task-shaped guides (create an agent, author
|
|
337
|
-
evals, hillclimb, GitHub webhooks, Slack setup, debugging).
|
|
338
|
-
|
|
339
|
-
## Web playground
|
|
340
|
-
|
|
341
|
-
Every served agent ships with a built-in playground. The default multi-agent
|
|
342
|
-
mode serves it at `http://127.0.0.1:3000/<slug>/playground`.
|
|
343
|
-
`--mode single` uses `http://127.0.0.1:3000/playground`. The playground
|
|
344
|
-
uses the same public HTTP API for manual testing and demo recordings:
|
|
345
|
-
|
|
346
|
-
- chat with the agent and watch text/reasoning stream live, rendered as
|
|
347
|
-
markdown (headings, lists, tables, blockquotes, links) with syntax
|
|
348
|
-
highlighting for fenced code blocks (C-like languages, Python, shell,
|
|
349
|
-
and diffs),
|
|
350
|
-
- invoke custom channels as **slash commands** in the composer (e.g. a
|
|
351
|
-
`/drive https://github.com/org/repo/pull/1` channel route). Routes from `GET /v1/info`,
|
|
352
|
-
with `/help` and autocomplete; same HTTP as the Agent surface **Try**
|
|
353
|
-
buttons,
|
|
354
|
-
- see tool calls inline (args, output, error state) as `actions.requested`
|
|
355
|
-
/ `action.result` events arrive,
|
|
356
|
-
- browse the sessions you own (chat, custom-channel, and schedule
|
|
357
|
-
task sessions) and replay their event streams. In `--dev` on loopback,
|
|
358
|
-
or with `--allow-anonymous`, the list includes every principal,
|
|
359
|
-
- dispatch schedules by hand in dev mode,
|
|
360
|
-
- inspect the discovered agent surface (tools, skills, subagents, MCP
|
|
361
|
-
connections, channels, hooks),
|
|
362
|
-
- flip on the raw NDJSON pane to see the exact wire events.
|
|
363
|
-
|
|
364
|
-
`bdk serve` serves the playground bundle. Disable it with
|
|
365
|
-
`--no-playground` (CLI) or `serve(dir, { playground: false })`. When
|
|
366
|
-
serving many agents, each has its own playground at `/<slug>/playground`
|
|
367
|
-
and `/` is an index of them all (see "Serving many agents at once").
|
|
368
|
-
`serve --dev` prints a playground URL; open that URL if the UI looks stale.
|
|
369
|
-
|
|
370
|
-
To share the server beyond localhost (a tunnel, a LAN address, a phone),
|
|
371
|
-
pass `--bearer-token <secret>` (or `serve(dir, { authToken })`). That
|
|
372
|
-
replaces the loopback-only default with `bearerAuth(secret)` on every
|
|
373
|
-
channel that doesn't author its own auth. The default
|
|
374
|
-
`localDevStrict()` only admits direct loopback callers, rejects
|
|
375
|
-
proxy-forwarding headers (`X-Forwarded-For`, `X-Real-IP`, `Forwarded`,
|
|
376
|
-
`X-Forwarded-Host`), and requires a loopback `Host` header, so
|
|
377
|
-
same-host reverse proxies / tunnels do not accidentally re-expose the
|
|
378
|
-
default routes. Open the playground on the remote device and paste the
|
|
379
|
-
token into the top-right field.
|
|
380
|
-
|
|
381
|
-
Session follow-up, stream, and list routes also bind to the principal that
|
|
382
|
-
created the session (`403` when a different admitted principal addresses
|
|
383
|
-
someone else's handle).
|
|
384
|
-
|
|
385
|
-
## How it runs on the Cursor harness
|
|
386
|
-
|
|
387
|
-
Each session is one Cursor SDK agent. Turns run on this host.
|
|
388
|
-
|
|
389
|
-
Authored files reach the model as instructions, tools, skills, and
|
|
390
|
-
workspace seed files. Sessions and their event
|
|
391
|
-
streams survive server restarts. Reconnect with `?startIndex=` to
|
|
392
|
-
replay.
|
|
393
|
-
|
|
394
|
-
## Folder structure
|
|
395
|
-
|
|
396
|
-
### `agent.ts`
|
|
397
|
-
|
|
398
|
-
```ts
|
|
399
|
-
import { defineAgent } from "@cursor/bdk";
|
|
400
|
-
|
|
401
|
-
export default defineAgent({
|
|
402
|
-
model: {
|
|
403
|
-
id: "grok-4.5",
|
|
404
|
-
params: [
|
|
405
|
-
{ id: "effort", value: "high" },
|
|
406
|
-
{ id: "fast", value: "true" },
|
|
407
|
-
],
|
|
408
|
-
}, // optional; this is the default
|
|
409
|
-
});
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
`model` accepts a Cursor model id string or `{ id, params }`. When omitted
|
|
413
|
-
on the root agent, BDK defaults to `grok-4.5` with `effort=high`
|
|
414
|
-
and `fast=true`.
|
|
415
|
-
|
|
416
|
-
Turns use the Cursor SDK local harness on this machine. Authored tools,
|
|
417
|
-
skills, and sandbox seeds apply.
|
|
418
|
-
|
|
419
|
-
### Instructions
|
|
420
|
-
|
|
421
|
-
`bot/instructions.md` is the always-on system prompt (required on the
|
|
422
|
-
root agent). When the prompt needs to be generated, use
|
|
423
|
-
`bot/instructions.ts` with `defineInstructions({ markdown })` or a plain
|
|
424
|
-
string default export, or split prose across a `bot/instructions/`
|
|
425
|
-
directory (composed in filename order).
|
|
426
|
-
|
|
427
|
-
### Tools (`bot/tools/*.ts`)
|
|
428
|
-
|
|
429
|
-
One file per tool; the filename is the tool name the model sees.
|
|
430
|
-
|
|
431
|
-
`execution` chooses where the tool body runs:
|
|
432
|
-
|
|
433
|
-
| Value | Behavior |
|
|
434
|
-
| ----- | -------- |
|
|
435
|
-
| `"server"` (default) | Runs on the serve host. Requires `execute`. |
|
|
436
|
-
| `"agent"` | Materialized into the agent environment as a shell script. Requires `script` (JSON on stdin, result on stdout). |
|
|
437
|
-
|
|
438
|
-
Server tool (default):
|
|
439
|
-
|
|
440
|
-
```ts
|
|
441
|
-
import { defineTool } from "@cursor/bdk/tools";
|
|
442
|
-
import { z } from "zod";
|
|
443
|
-
|
|
444
|
-
export default defineTool({
|
|
445
|
-
description: "Get the current weather for a city.",
|
|
446
|
-
// execution: "server", // default
|
|
447
|
-
inputSchema: z.object({ city: z.string() }),
|
|
448
|
-
async execute({ city }, ctx) {
|
|
449
|
-
return { city, condition: "Sunny", temperatureF: 72 };
|
|
450
|
-
},
|
|
451
|
-
});
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
A server tool can call `decide` from
|
|
455
|
-
[`@cursor/bdk/extensions/jev`](./docs/guides/jev.md) for a risk tier or
|
|
456
|
-
a finding gate. Jev is not the turn model on `defineAgent`.
|
|
457
|
-
|
|
458
|
-
Human-in-the-loop: set `needsApproval: true` (or an
|
|
459
|
-
`(input) => boolean` predicate on validated args) so the host parks the in-flight
|
|
460
|
-
tool call until a human approves or denies. The turn stays running; the
|
|
461
|
-
stream emits `action.approval_requested` / `action.approval_resolved`.
|
|
462
|
-
|
|
463
|
-
**Resolve surfaces** (park is always on when `needsApproval` is set):
|
|
464
|
-
|
|
465
|
-
- Playground Approve / Deny buttons
|
|
466
|
-
- HTTP: `POST /v1/session/:sessionId/approvals/:callId` with
|
|
467
|
-
`{"decision":"approve"|"deny"}`
|
|
468
|
-
- **Slack** (opt-in channel surface): set `toolApprovals: true` on
|
|
469
|
-
`slackChannel`, and enable `interactivity` in the Slack app
|
|
470
|
-
manifest:
|
|
471
|
-
|
|
472
|
-
```ts
|
|
473
|
-
import { slackChannel } from "@cursor/bdk/channels/slack";
|
|
474
|
-
|
|
475
|
-
export default slackChannel({
|
|
476
|
-
credentials: { /* … */ },
|
|
477
|
-
toolApprovals: true, // posts Block Kit Approve/Deny + routes clicks
|
|
478
|
-
});
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
Or compose the builders yourself:
|
|
482
|
-
|
|
483
|
-
```typescript
|
|
484
|
-
import {
|
|
485
|
-
buildDefaultEvents,
|
|
486
|
-
buildToolApprovalEvents,
|
|
487
|
-
slackChannel,
|
|
488
|
-
} from "@cursor/bdk/channels/slack";
|
|
489
|
-
|
|
490
|
-
export default slackChannel({
|
|
491
|
-
deliverDefaults: false,
|
|
492
|
-
// Required so Socket Mode routes Approve/Deny clicks when composing
|
|
493
|
-
// buildToolApprovalEvents by hand (toolApprovals: true also enables this).
|
|
494
|
-
interactivity: true,
|
|
495
|
-
events: {
|
|
496
|
-
...buildDefaultEvents({ credentials }),
|
|
497
|
-
...buildToolApprovalEvents({ credentials }),
|
|
498
|
-
},
|
|
499
|
-
});
|
|
500
|
-
```
|
|
501
|
-
|
|
502
|
-
In `--dev`, the playground can list and stream Slack sessions, and Approve/Deny
|
|
503
|
-
parked tools on those sessions (audit `by` records the HTTP caller). That bridge
|
|
504
|
-
does **not** open cross-owner approval for HTTP sessions. Production and
|
|
505
|
-
bearer-auth hosts stay strict: Slack resolve must come from Slack interactivity
|
|
506
|
-
(or a matching principal).
|
|
507
|
-
|
|
508
|
-
`--allow-anonymous` is for trusted-network demos only. Every HTTP caller shares
|
|
509
|
-
the same `anonymous` principal. Prefer `--bearer-token` when the host is shared.
|
|
510
|
-
|
|
511
|
-
Slack cards show **redacted / truncated** args for Block Kit limits; execution
|
|
512
|
-
still uses the full validated tool input. Review sensitive tools in the
|
|
513
|
-
playground or a private surface when args may exceed the card.
|
|
514
|
-
|
|
515
|
-
Example tool:
|
|
516
|
-
|
|
517
|
-
```ts
|
|
518
|
-
export default defineTool({
|
|
519
|
-
description: "Post a weather alert to ops.",
|
|
520
|
-
needsApproval: true,
|
|
521
|
-
inputSchema: z.object({
|
|
522
|
-
city: z.string(),
|
|
523
|
-
message: z.string(),
|
|
524
|
-
}),
|
|
525
|
-
async execute({ city, message }) {
|
|
526
|
-
return { posted: true, city, message };
|
|
527
|
-
},
|
|
528
|
-
});
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
Approvals are only supported for `execution: "server"` tools on the
|
|
532
|
-
`local` runtime. Exact resume of a parked SDK tool call does **not**
|
|
533
|
-
survive host process restart. Pending approvals left after a crash are
|
|
534
|
-
treated as interrupted.
|
|
535
|
-
Agent tool (runs in the Cursor agent workspace):
|
|
536
|
-
|
|
537
|
-
```ts
|
|
538
|
-
import { defineTool } from "@cursor/bdk/tools";
|
|
539
|
-
import { z } from "zod";
|
|
540
|
-
|
|
541
|
-
export default defineTool({
|
|
542
|
-
description: "Echo a message from the agent workspace.",
|
|
543
|
-
execution: "agent",
|
|
544
|
-
inputSchema: z.object({ message: z.string() }),
|
|
545
|
-
script: `#!/usr/bin/env bash
|
|
546
|
-
set -euo pipefail
|
|
547
|
-
message=$(python3 -c 'import json,sys; print(json.load(sys.stdin)["message"])')
|
|
548
|
-
printf '%s\\n' "$message"
|
|
549
|
-
`,
|
|
550
|
-
});
|
|
43
|
+
npm install --global @cursor/bdk
|
|
44
|
+
bdk init ./my-bot
|
|
45
|
+
cd my-bot
|
|
46
|
+
bdk dev
|
|
551
47
|
```
|
|
552
48
|
|
|
553
|
-
|
|
554
|
-
plain JSON Schema object (forwarded as-is). `outputSchema` advertises a
|
|
555
|
-
structured result schema. The host doesn't validate results against it.
|
|
556
|
-
Plain objects fill `structuredContent` automatically. Envelope results set
|
|
557
|
-
it explicitly next to `content` and `isError`. For server tools, `ctx` carries
|
|
558
|
-
`{ toolCallId, session, workspaceDir }`.
|
|
559
|
-
|
|
560
|
-
#### Deterministic tool calls
|
|
561
|
-
|
|
562
|
-
Server tools can also be called **deterministically**. You pick the tool
|
|
563
|
-
and the input, no model turn decides anything. The input is validated
|
|
564
|
-
against the tool's schema and `execute` runs in-process; the result comes
|
|
565
|
-
back exactly as the model would receive it. No Cursor API key is needed.
|
|
566
|
-
|
|
567
|
-
Over HTTP (`POST /v1/tools/:toolName`, same auth chain as the session API):
|
|
49
|
+
For a one-off scaffold without a global install:
|
|
568
50
|
|
|
569
51
|
```bash
|
|
570
|
-
|
|
571
|
-
-H 'content-type: application/json' \
|
|
572
|
-
-d '{"input":{"city":"NYC"}}'
|
|
573
|
-
# {"ok":true,"toolName":"get_weather","callId":"tool_get_weather_...",
|
|
574
|
-
# "isError":false,"result":{...},"durationMs":12}
|
|
52
|
+
npx @cursor/bdk init ./my-bot
|
|
575
53
|
```
|
|
576
54
|
|
|
577
|
-
|
|
578
|
-
|
|
55
|
+
Open the project in Cursor. BDK uses `bot/` for the agent and keeps
|
|
56
|
+
`evals/` at the project root:
|
|
579
57
|
|
|
580
58
|
```text
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
"agent"` tools cannot be called on the host (400), schema-invalid input is a
|
|
611
|
-
400 before the tool body runs (zod schemas validate; plain JSON Schema
|
|
612
|
-
inputs pass through unvalidated, matching the model path), and a tool body
|
|
613
|
-
that throws is reported as `isError: true` with the same
|
|
614
|
-
`{ content, isError }` envelope the model would see.
|
|
615
|
-
|
|
616
|
-
### Skills (`bot/skills/*`)
|
|
617
|
-
|
|
618
|
-
Skills follow the `SKILL.md` convention: model-loadable procedures the
|
|
619
|
-
harness advertises by description and loads on demand. Author them as flat
|
|
620
|
-
markdown (`skills/forecast.md`, optional `description` frontmatter. The
|
|
621
|
-
first body line is the fallback), packaged directories
|
|
622
|
-
(`skills/research/SKILL.md` plus `references/…`, which require `description`
|
|
623
|
-
frontmatter), or TypeScript (`defineSkill` from
|
|
624
|
-
`@cursor/bdk/skills`) when content must be generated.
|
|
625
|
-
|
|
626
|
-
### MCP connections (`bot/mcp-connections/*.ts`)
|
|
627
|
-
|
|
628
|
-
```ts
|
|
629
|
-
import { defineConnection } from "@cursor/bdk/connections";
|
|
630
|
-
|
|
631
|
-
export default defineConnection({
|
|
632
|
-
url: "https://mcp.linear.app/mcp",
|
|
633
|
-
headers: { authorization: `Bearer ${process.env.LINEAR_TOKEN}` },
|
|
634
|
-
});
|
|
635
|
-
```
|
|
636
|
-
|
|
637
|
-
The filename becomes the MCP server name. `{ command, args, env, cwd }`
|
|
638
|
-
declares a local stdio server instead. `{ tools }` authors TypeScript
|
|
639
|
-
handlers that BDK packages as stdio MCP for the agent
|
|
640
|
-
environment, including a repo-less cloud VM. `{ agent: "<slug>" }` declares a
|
|
641
|
-
**peer MCP connection** to another agent mounted on the same serve host (see
|
|
642
|
-
"Agent-to-agent: every agent is an MCP server").
|
|
643
|
-
|
|
644
|
-
`{ cursorAccount: true }` declares a **Cursor account MCP connection**: the
|
|
645
|
-
agent gets the MCP connectors the signed-in Cursor account already
|
|
646
|
-
authorized (dashboard → MCP) with zero token plumbing. Every tool executes
|
|
647
|
-
on the Cursor backend with the account's stored OAuth credentials; raw
|
|
648
|
-
tokens never reach the serve host, session workspaces, or traces. Omit
|
|
649
|
-
`servers`, or pass `servers: "*"`, to forward every connected HTTP/SSE
|
|
650
|
-
connector. Pass `servers: ["Linear", ...]` to expose only named connectors.
|
|
651
|
-
|
|
652
|
-
```ts
|
|
653
|
-
// bot/mcp-connections/account.ts: every connected connector
|
|
654
|
-
export default defineConnection({
|
|
655
|
-
cursorAccount: true,
|
|
656
|
-
advertiseTools: true,
|
|
657
|
-
});
|
|
658
|
-
// same, spelled out:
|
|
659
|
-
export default defineConnection({
|
|
660
|
-
cursorAccount: true,
|
|
661
|
-
servers: "*",
|
|
662
|
-
advertiseTools: true,
|
|
663
|
-
});
|
|
664
|
-
// only Linear:
|
|
665
|
-
export default defineConnection({
|
|
666
|
-
cursorAccount: true,
|
|
667
|
-
servers: ["Linear"],
|
|
668
|
-
advertiseTools: true,
|
|
669
|
-
});
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
Name the file `account.ts`. `cursor.ts` collides with the IDE `cursor` MCP
|
|
673
|
-
namespace. `advertiseTools: true` puts connector tools on local turns by
|
|
674
|
-
name.
|
|
675
|
-
|
|
676
|
-
Requirements and behavior:
|
|
677
|
-
|
|
678
|
-
- The host must be signed in (`bdk login`, `CURSOR_API_KEY`, or `CURSOR_SERVICE_ACCOUNT_KEY`);
|
|
679
|
-
`serve` fails fast at startup otherwise, and logs each connector's live
|
|
680
|
-
status (`connected` / `needsAuth` / `error`) as it starts.
|
|
681
|
-
- Local turns and host-side calls go through a loopback bridge route guarded
|
|
682
|
-
by a per-boot secret.
|
|
683
|
-
- Backend execution covers the account's HTTP/SSE servers; stdio servers
|
|
684
|
-
cannot run server-side (author a `{ command }` MCP connection for those).
|
|
685
|
-
- **Exposure**: whoever can talk to the agent can drive these connectors
|
|
686
|
-
(they are ordinary agent tools). `serve` refuses to start when
|
|
687
|
-
`--allow-anonymous` is combined with Cursor account MCP connections; use
|
|
688
|
-
`--bearer-token` on shared hosts.
|
|
689
|
-
|
|
690
|
-
Every MCP connection is available in three places:
|
|
691
|
-
|
|
692
|
-
1. the Cursor agent, via SDK `mcpServers`
|
|
693
|
-
2. the serve host, for in-process tools via `ctx.host.mcp`
|
|
694
|
-
3. channel / schedule handlers, via `args.host.mcp` (deterministic; no agent loop)
|
|
695
|
-
|
|
696
|
-
```ts
|
|
697
|
-
export default defineTool({
|
|
698
|
-
description: "Search Linear issues.",
|
|
699
|
-
inputSchema: z.object({ query: z.string() }),
|
|
700
|
-
async execute({ query }, ctx) {
|
|
701
|
-
return ctx.host.mcp.callTool("linear", "list_issues", { query });
|
|
702
|
-
},
|
|
703
|
-
});
|
|
704
|
-
```
|
|
705
|
-
|
|
706
|
-
```ts
|
|
707
|
-
// bot/channels/webhook.ts: call MCP directly from a webhook
|
|
708
|
-
POST("/sync", {
|
|
709
|
-
bodySchema: z.object({}),
|
|
710
|
-
handler: async (_req, { host }) => {
|
|
711
|
-
const result = await host.mcp.callTool("linear", "list_issues", {});
|
|
712
|
-
return Response.json(result);
|
|
713
|
-
},
|
|
714
|
-
});
|
|
715
|
-
```
|
|
716
|
-
|
|
717
|
-
`host.mcp.names()` lists MCP connection names; `listTools(name)` and
|
|
718
|
-
`callTool(name, tool, args)` open the client lazily on first use.
|
|
719
|
-
|
|
720
|
-
### Subagents (`bot/subagents/<id>/`)
|
|
721
|
-
|
|
722
|
-
A subagent is its own directory with the same `agent.ts` +
|
|
723
|
-
`instructions.md` shape. `description` is required. The parent model reads
|
|
724
|
-
it to decide when to delegate, and `model` is optional (`inherit` by
|
|
725
|
-
default). On the Cursor harness, subagents run as SDK custom subagents:
|
|
726
|
-
they inherit the parent's execution surface, so per-subagent `tools/`,
|
|
727
|
-
`skills/`, and `mcp-connections/` are reported as warnings and ignored for now.
|
|
728
|
-
|
|
729
|
-
### Extensions (`bot/extensions/<ns>.ts`)
|
|
730
|
-
|
|
731
|
-
An extension is a package of agent contributions mounted with one file;
|
|
732
|
-
the filename is the namespace and every contribution appears as
|
|
733
|
-
`<ns>__<name>`. A Cursor plugin mounts the same way with `cursorPlugin`.
|
|
734
|
-
|
|
735
|
-
```ts
|
|
736
|
-
// bot/extensions/ci.ts
|
|
737
|
-
import ci from "@acme/ci-triage";
|
|
738
|
-
export default ci({ org: "acme", token: process.env.BUILDKITE_TOKEN! });
|
|
739
|
-
|
|
740
|
-
// bot/extensions/notion.ts
|
|
741
|
-
import { cursorPlugin } from "@cursor/bdk/extensions";
|
|
742
|
-
export default cursorPlugin({
|
|
743
|
-
path: "plugins/notion-workspace",
|
|
744
|
-
variables: { NOTION_TOKEN: process.env.NOTION_TOKEN! },
|
|
745
|
-
});
|
|
746
|
-
```
|
|
747
|
-
|
|
748
|
-
Mount as a directory (`bot/extensions/<ns>/extension.ts`) to overlay
|
|
749
|
-
any slot; `disableTool()`, `disableConnection()`, and `disable()` remove
|
|
750
|
-
a contribution. Mounting a plugin trusts it like authored code. Details
|
|
751
|
-
in [Extensions](./docs/reference/extensions.md).
|
|
752
|
-
|
|
753
|
-
### Channels (`bot/channels/*.ts`)
|
|
754
|
-
|
|
755
|
-
The **built-in HTTP channel** is always mounted (under `/<slug>` in the
|
|
756
|
-
default multi-agent layout; at the server root with `mode: "single"`):
|
|
757
|
-
|
|
758
|
-
- `POST /v1/session`: start a session (`{"message": "..."}`; returns
|
|
759
|
-
`sessionId` + `continuationToken`)
|
|
760
|
-
- `POST /v1/session/:sessionId`: follow-up (`{"message", "continuationToken"}`;
|
|
761
|
-
rotates the token; works for any chat session including custom channels like
|
|
762
|
-
`drive`; `409` on stale tokens or task sessions;
|
|
763
|
-
`403` if the caller is not the session owner)
|
|
764
|
-
- `GET /v1/session/:sessionId/stream?startIndex=N`: replay + live NDJSON
|
|
765
|
-
(same owner check)
|
|
766
|
-
- `GET /v1/session/:sessionId/approvals`: pending human-in-the-loop
|
|
767
|
-
tool approvals for the session
|
|
768
|
-
- `POST /v1/session/:sessionId/approvals/:callId`: approve or deny
|
|
769
|
-
(`{"decision":"approve"|"deny"}`)
|
|
770
|
-
- `GET /v1/sessions`: sessions owned by the calling principal
|
|
771
|
-
- `POST /v1/tools/:toolName`: call a server tool deterministically
|
|
772
|
-
(`{"input": {...}, "sessionId"?}`; see "Deterministic tool calls")
|
|
773
|
-
- `GET /v1/health`, `GET /v1/info`: liveness and the manifest snapshot
|
|
774
|
-
|
|
775
|
-
**Custom channels** declare their own routes (mounted under
|
|
776
|
-
`/v1/channels/<id>`), observe stream events for the sessions they own, and
|
|
777
|
-
control their continuation-token format (e.g. a thread id):
|
|
778
|
-
|
|
779
|
-
```ts
|
|
780
|
-
import { defineChannel, POST } from "@cursor/bdk/channels";
|
|
781
|
-
import { z } from "zod";
|
|
782
|
-
|
|
783
|
-
export default defineChannel({
|
|
784
|
-
routes: [
|
|
785
|
-
POST("/message", {
|
|
786
|
-
description: "Enqueue a chat turn on this channel",
|
|
787
|
-
bodySchema: z.object({
|
|
788
|
-
message: z.string(),
|
|
789
|
-
thread: z.string().optional(),
|
|
790
|
-
}),
|
|
791
|
-
handler: async (_req, { send, body }) => {
|
|
792
|
-
const { message, thread } = body;
|
|
793
|
-
// `auth` defaults to the request principal resolved by the auth chain.
|
|
794
|
-
const session = await send(message, {
|
|
795
|
-
continuationToken: thread, // stable key: same thread, same session
|
|
796
|
-
});
|
|
797
|
-
return Response.json({ sessionId: session.id });
|
|
798
|
-
},
|
|
799
|
-
}),
|
|
800
|
-
],
|
|
801
|
-
events: {
|
|
802
|
-
"message.completed"(event, channel, ctx) {
|
|
803
|
-
// deliver the reply back to the surface that owns this channel
|
|
804
|
-
},
|
|
805
|
-
},
|
|
806
|
-
});
|
|
807
|
-
```
|
|
808
|
-
|
|
809
|
-
`GET` requires a Zod `querySchema` and `POST` / `PUT` / `PATCH` require a
|
|
810
|
-
Zod `bodySchema` at compile time. Plain JSON Schema objects will not
|
|
811
|
-
type-check. Use `z.object({})` or `z.unknown()` when the surface is
|
|
812
|
-
intentionally open. Schemas are validated by the host before the handler
|
|
813
|
-
runs (handlers get typed `args.body` / `args.query`) and projected on
|
|
814
|
-
`GET /v1/info` so the playground Agent surface can **Try** the route, and
|
|
815
|
-
so the composer can offer matching **slash commands** (e.g. `/drive`).
|
|
816
|
-
|
|
817
|
-
Route handlers receive a Fetch `Request` and helpers: `send`, `getSession`,
|
|
818
|
-
`receive` (cross-channel hand-off), `params`, `requestIp`, `auth`, `host`
|
|
819
|
-
(shared host services: MCP / GitHub / Slack; same as tool `ctx.host`), and
|
|
820
|
-
`waitUntil`. Channel `state` declares initial per-session adapter state,
|
|
821
|
-
persisted across events; handlers receive it on `channel.state`.
|
|
822
|
-
|
|
823
|
-
**Auth**: channel routes and the session API run an auth-policy chain
|
|
824
|
-
(`auth` on the channel). The host index, docs, and health routes run no
|
|
825
|
-
auth. The default policy is `[localDevStrict()]`: direct loopback
|
|
826
|
-
callers only, with proxy-forwarding headers and non-loopback `Host`
|
|
827
|
-
rejected, so nothing is exposed publicly until you add real auth
|
|
828
|
-
(`bearerAuth(...)`, a custom policy, or the explicit `allowAll()`).
|
|
829
|
-
|
|
830
|
-
**Slack** (`@cursor/bdk/channels/slack`): a platform channel pack
|
|
831
|
-
that defaults to **Socket Mode**. Author `bot/channels/slack.ts` with
|
|
832
|
-
`slackChannel()`:
|
|
833
|
-
|
|
834
|
-
```ts
|
|
835
|
-
import { slackChannel } from "@cursor/bdk/channels/slack";
|
|
836
|
-
|
|
837
|
-
// Single agent: SLACK_BOT_TOKEN + SLACK_APP_TOKEN
|
|
838
|
-
export default slackChannel();
|
|
839
|
-
|
|
840
|
-
// Multi-agent serve: one Slack app (and token pair) per agent
|
|
841
|
-
export default slackChannel({ envPrefix: "WEATHER_AGENT" });
|
|
842
|
-
// → WEATHER_AGENT_SLACK_BOT_TOKEN + WEATHER_AGENT_SLACK_APP_TOKEN
|
|
843
|
-
```
|
|
844
|
-
|
|
845
|
-
Transport uses `@slack/socket-mode` + `@slack/web-api`. Socket Mode starts
|
|
846
|
-
on channel mount when both tokens are present; otherwise the channel stays
|
|
847
|
-
**idle** (`channel idle … missing credentials`) so multi-agent serve can
|
|
848
|
-
mount agents that do not have Slack tokens configured yet.
|
|
849
|
-
|
|
850
|
-
The pack dispatches via `waitUntil`, streams assistant text (`chat.startStream` /
|
|
851
|
-
`appendStream` / `stopStream`) with postMessage fallback, shows rotating status
|
|
852
|
-
+ tool thinking steps, and sets thread titles / suggested prompts. Handlers may
|
|
853
|
-
return a prepared `message` or `workspaceFiles` to host-prepare PR
|
|
854
|
-
reviews from an `@mention`.
|
|
855
|
-
|
|
856
|
-
**Engagement:** by default the agent is summoned, never proactive. It
|
|
857
|
-
dispatches only on `app_mention` and DMs. Channel watch is an explicit opt-in:
|
|
858
|
-
|
|
859
|
-
```ts
|
|
860
|
-
export default slackChannel({
|
|
861
|
-
envPrefix: "TRIAGE",
|
|
862
|
-
engagement: {
|
|
863
|
-
// mentions / directMessages default to true
|
|
864
|
-
channelPosts: {
|
|
865
|
-
allow: ["#triage-alerts"], // explicit allowlist only; no wildcard
|
|
866
|
-
posts: "top-level", // default: never dispatch on thread replies
|
|
867
|
-
debounceMs: 15_000, // optional: let rapid edits settle
|
|
868
|
-
},
|
|
869
|
-
},
|
|
870
|
-
onChannelPost: async (ctx, message) => {
|
|
871
|
-
// Same contract as onAppMention: return null to skip.
|
|
872
|
-
return message.markdown.length > 20 ? {} : null;
|
|
873
|
-
},
|
|
874
|
-
});
|
|
875
|
-
```
|
|
876
|
-
|
|
877
|
-
Watched posts dispatch with the same thread-scoped principal as mentions
|
|
878
|
-
(so a later `@mention` continues the session) plus an
|
|
879
|
-
`engagement: "channel_post"` auth attribute. Posts that mention the bot are
|
|
880
|
-
left to the `app_mention` path; bot-authored posts never dispatch; deleting
|
|
881
|
-
a post inside the debounce window cancels its dispatch. The Slack app must
|
|
882
|
-
subscribe to `message.channels` / `message.groups`
|
|
883
|
-
(`bdk slack create --channel-posts`) and be a member of each watched channel. Watched channels surface in
|
|
884
|
-
`info` via `meta.slackChannelPosts`.
|
|
885
|
-
|
|
886
|
-
**HITL compose:** park/resume is independent (`needsApproval` on tools). Opt in
|
|
887
|
-
to Slack delivery with `toolApprovals: true` (or spread
|
|
888
|
-
`buildToolApprovalEvents` into `events` and set `interactivity: true` on
|
|
889
|
-
`slackChannel` so Approve/Deny buttons resolve). That posts Block Kit
|
|
890
|
-
Approve/Deny cards and routes Socket Mode `interactive` clicks to
|
|
891
|
-
`resolveApproval`. Enable `interactivity: true` on
|
|
892
|
-
`buildSlackManifest` when you use that surface. Threads bind with
|
|
893
|
-
`continuationToken = channelId:threadTs`. Dev and prod are
|
|
894
|
-
**separate Slack apps**. Requires `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN`
|
|
895
|
-
(App-Level Token with `connections:write`).
|
|
896
|
-
|
|
897
|
-
`bdk slack create` mints one dedicated bot and writes
|
|
898
|
-
`<DIR>_SLACK_*` plus `envPrefix` from the directory name. Keep the
|
|
899
|
-
channel file as `slack-app.ts` when the same app should carry tool
|
|
900
|
-
approvals or channel watch.
|
|
901
|
-
|
|
902
|
-
For Socket Mode apps (channel watch / approvals), run
|
|
903
|
-
`bdk slack create`. It opens the dashboard wizard, creates and
|
|
904
|
-
installs the app, and writes the token pair to `.env.local`. To own the
|
|
905
|
-
Slack app yourself, run `bdk slack init --manual` and paste the
|
|
906
|
-
manifests at api.slack.com.
|
|
907
|
-
|
|
908
|
-
CLI (`bdk slack …`; guided setup in `skills/setup-slack/SKILL.md`):
|
|
909
|
-
|
|
910
|
-
```text
|
|
911
|
-
bdk slack create --dir ./my-agent # dashboard wizard (dev app)
|
|
912
|
-
bdk slack create --dir ./my-agent --prod # prod app
|
|
913
|
-
bdk slack init --manual --dir ./my-agent # manifests for api.slack.com
|
|
914
|
-
bdk slack setup
|
|
915
|
-
bdk slack doctor --prefix MY_AGENT
|
|
916
|
-
```
|
|
917
|
-
|
|
918
|
-
**GitHub** (`@cursor/bdk/channels/github`): a webhook channel pack
|
|
919
|
-
(Eve-compatible dispatch). Author `bot/channels/github.ts` with
|
|
920
|
-
`githubChannel()` and declare inbound hooks:
|
|
921
|
-
|
|
922
|
-
```ts
|
|
923
|
-
import { defaultGitHubAuth, githubChannel } from "@cursor/bdk/channels/github";
|
|
924
|
-
|
|
925
|
-
export default githubChannel({
|
|
926
|
-
botName: "my-agent", // or GITHUB_APP_SLUG
|
|
927
|
-
cursorAccount: {
|
|
928
|
-
repos: ["owner/repo"],
|
|
929
|
-
// permissions?: "read" | "pr-write" | "contents-write" (default pr-write)
|
|
930
|
-
},
|
|
931
|
-
onPullRequest: (ctx, pr) =>
|
|
932
|
-
pr.action === "opened" ? { auth: defaultGitHubAuth(ctx) } : null,
|
|
933
|
-
onCheckSuite: (ctx, suite) =>
|
|
934
|
-
suite.conclusion === "failure" ? { task: () => triage(ctx) } : null,
|
|
935
|
-
});
|
|
936
|
-
```
|
|
937
|
-
|
|
938
|
-
Mounts at `POST /<slug>/v1/channels/github`. When a webhook secret is set the
|
|
939
|
-
channel verifies `X-Hub-Signature-256` before parsing (the HMAC becomes the
|
|
940
|
-
request auth); without one it stays loopback-only (`localDevStrict()`), except
|
|
941
|
-
under `serve --dev`, which admits unsigned loopback deliveries so
|
|
942
|
-
`gh webhook forward` and fixtures work with zero config. Hooks return
|
|
943
|
-
`{ auth }` to start a model turn as the actor, `{ task }` for host-side work
|
|
944
|
-
(202 ACK, runs past GitHub's ~10s timeout), or `null` to skip.
|
|
945
|
-
|
|
946
|
-
**Testing GitHub agents locally.** `cursorAccount` uses the host Cursor
|
|
947
|
-
credential (`bdk login`, `CURSOR_API_KEY`, or
|
|
948
|
-
`CURSOR_SERVICE_ACCOUNT_KEY`) for both Cursor SCM events and a refreshing
|
|
949
|
-
repo-scoped GitHub credential used
|
|
950
|
-
by `ctx.github`, `ctx.host.github`, and child `gh` commands. Default
|
|
951
|
-
`permissions: "pr-write"` covers comments without `contents:write`; opt up to
|
|
952
|
-
`"contents-write"` when the agent must push or post merge-box checks.
|
|
953
|
-
Enabling `progress.commitStatus` opts hosted `cursorAccount` up to that
|
|
954
|
-
tier so github-proxy mints `checks:write`. Without `cursorAccount`, API
|
|
955
|
-
auth prefers GitHub App installation tokens when `GITHUB_APP_ID` /
|
|
956
|
-
`GITHUB_APP_PRIVATE_KEY` (and an installation id) are set, then falls back to
|
|
957
|
-
`GITHUB_TOKEN` / `GH_TOKEN` or `gh auth login`. The channel publishes the
|
|
958
|
-
webhook events it dispatches on (derived from the declared hooks, or pinned
|
|
959
|
-
via `webhookEvents`), so `bdk github …` can forward live
|
|
960
|
-
deliveries with zero hand-listing. It wraps [`gh webhook
|
|
961
|
-
forward`](https://docs.github.com/en/webhooks/testing-and-troubleshooting-webhooks/using-the-github-cli-to-forward-webhooks-for-testing):
|
|
962
|
-
|
|
963
|
-
```text
|
|
964
|
-
# One-time: gh + the cli/gh-webhook extension
|
|
965
|
-
bdk github doctor --install
|
|
966
|
-
|
|
967
|
-
# Terminal A: serve the agent (dev accepts unsigned loopback deliveries)
|
|
968
|
-
bdk serve --dir ./my-agent --dev
|
|
969
|
-
|
|
970
|
-
# Terminal B: forward this repo's deliveries to the discovered github channel
|
|
971
|
-
# (URL + events auto-derived; repo inferred from the git remote). No secret
|
|
972
|
-
# needed against a --dev server; set GITHUB_WEBHOOK_SECRET to verify signatures.
|
|
973
|
-
bdk github forward --dir ./my-agent
|
|
974
|
-
|
|
975
|
-
# Inspect what would be forwarded (URL + events per agent)
|
|
976
|
-
bdk github events --dir ./agents --json
|
|
977
|
-
|
|
978
|
-
# Forward to EVERY discovered github channel at once
|
|
979
|
-
bdk github forward --dir ./agents
|
|
980
|
-
```
|
|
981
|
-
|
|
982
|
-
When several channels match (e.g. a folder of agent projects with more than
|
|
983
|
-
one github channel), one forwarder fans out to all of them: `gh webhook
|
|
984
|
-
forward` runs against a local proxy that re-posts each raw (still-signed)
|
|
985
|
-
delivery to the channels whose event set matches. This is required. GitHub
|
|
986
|
-
allows only one forwarder per repo, and `gh webhook forward` targets a single
|
|
987
|
-
URL, so N processes would collide with `Hook already exists`.
|
|
988
|
-
|
|
989
|
-
`gh webhook forward` needs **admin** on the repo (or org owner for `--org`).
|
|
990
|
-
It registers a real webhook, and authenticates its relay with the GitHub CLI's
|
|
991
|
-
own login. If `GITHUB_TOKEN` / `GH_TOKEN` is set in your env, deliveries fail
|
|
992
|
-
with **HTTP 401** (the relay rejects env tokens); blank it for the command
|
|
993
|
-
(`GITHUB_TOKEN= GH_TOKEN= bdk github forward …`) or `unset` it.
|
|
994
|
-
`bdk github doctor` / `forward` warn when they detect this.
|
|
995
|
-
|
|
996
|
-
Pass `--repo owner/repo` / `--org ORG` to override the inferred target,
|
|
997
|
-
`--events a,b,c` to narrow the set, `--url` for a custom endpoint (e.g. a
|
|
998
|
-
tunnel), and `--slug` / `--channel` to forward to just one of several agents.
|
|
999
|
-
Against a `--dev` server no secret is needed; set `GITHUB_WEBHOOK_SECRET` (or
|
|
1000
|
-
`--secret`) to exercise signature verification (required for a non-dev target).
|
|
1001
|
-
Only one forwarder per repo/org at a time (a GitHub limitation). Fixture replay
|
|
1002
|
-
still works too: `POST` a saved payload with an `x-github-event` header (no
|
|
1003
|
-
signature needed in `--dev`).
|
|
1004
|
-
|
|
1005
|
-
**No admin? Hillclimbing? Use `github replay`.** `gh webhook forward` needs repo
|
|
1006
|
-
admin and a live event. `bdk github replay <pr_url>` instead **reads**
|
|
1007
|
-
the PR (pull access is enough: no admin, no relay, and `GITHUB_TOKEN` is fine)
|
|
1008
|
-
and synthesizes GitHub-shaped payloads it POSTs straight at the channel:
|
|
1009
|
-
|
|
1010
|
-
```text
|
|
1011
|
-
# Replay a pull_request delivery for a PR to the discovered channel
|
|
1012
|
-
bdk github replay https://github.com/owner/repo/pull/123 --dir ./my-agent
|
|
1013
|
-
|
|
1014
|
-
# Replay everything the channel listens for (its declared events), CI failing
|
|
1015
|
-
bdk github replay owner/repo#123 --dir ./my-agent --events '*' --conclusion failure
|
|
1016
|
-
|
|
1017
|
-
# Inspect payloads without POSTing (and snapshot them as reusable fixtures)
|
|
1018
|
-
bdk github replay owner/repo#123 --dir ./my-agent --events '*' --dry-run --out fixtures/github
|
|
1019
|
-
```
|
|
1020
|
-
|
|
1021
|
-
`--events` defaults to `pull_request` (`*` = the channel's declared events);
|
|
1022
|
-
`--action` / `--conclusion` / `--comment` / `--context` tune each synthesized
|
|
1023
|
-
event; `--secret` (or `GITHUB_WEBHOOK_SECRET`) signs them so a secret-configured
|
|
1024
|
-
channel verifies. Because replay sends a clean, signed loopback request, it
|
|
1025
|
-
passes both the `localDevStrict()` and `allowAll()`+signature auth modes, and
|
|
1026
|
-
it's fully deterministic, which is what hillclimbing wants.
|
|
1027
|
-
|
|
1028
|
-
**Production alternative: pull from Cursor (`--cursor-events`).** If the
|
|
1029
|
-
Cursor GitHub App is on the repo, `serve --cursor-events --repo owner/repo`
|
|
1030
|
-
long-polls `/v0/scm-events` with the host's Cursor account (no public URL /
|
|
1031
|
-
repo admin). Offset + consumer id live under `<state-root>/cursor-events/`.
|
|
1032
|
-
The stream is read as your Cursor user, so the flag **requires a signed-in
|
|
1033
|
-
host** (`bdk login`, `CURSOR_API_KEY`, `CURSOR_SERVICE_ACCOUNT_KEY`, or `serve({ apiKey })`).
|
|
1034
|
-
Serve fails fast rather than starting with a relay that can never receive
|
|
1035
|
-
events.
|
|
1036
|
-
|
|
1037
|
-
### Hooks (`bot/hooks/*.ts`)
|
|
1038
|
-
Observe-only subscribers that run after each event is recorded: audit
|
|
1039
|
-
logs, metrics, mirroring transcripts into your own store. Keys are event
|
|
1040
|
-
types (or `*`); handler errors are logged, never fatal.
|
|
1041
|
-
|
|
1042
|
-
### Schedules (`bot/schedules/*`)
|
|
1043
|
-
|
|
1044
|
-
Markdown form (fire-and-forget task session):
|
|
1045
|
-
|
|
1046
|
-
```md
|
|
1047
|
-
---
|
|
1048
|
-
cron: "0 9 * * 1-5"
|
|
1049
|
-
---
|
|
1050
|
-
|
|
1051
|
-
Pull open incidents and post a summary to the metrics endpoint.
|
|
1052
|
-
```
|
|
1053
|
-
|
|
1054
|
-
Handler form (full control, hand off to a channel):
|
|
1055
|
-
|
|
1056
|
-
```ts
|
|
1057
|
-
import { defineSchedule } from "@cursor/bdk/schedules";
|
|
1058
|
-
import webhook from "../channels/webhook.js";
|
|
1059
|
-
|
|
1060
|
-
export default defineSchedule({
|
|
1061
|
-
cron: "*/30 * * * *",
|
|
1062
|
-
async run({ receive, waitUntil, appAuth, mcp }) {
|
|
1063
|
-
// optional: await mcp.callTool("units", "celsius_to_fahrenheit", { value: 0 });
|
|
1064
|
-
waitUntil(
|
|
1065
|
-
receive(webhook, {
|
|
1066
|
-
message: "Check for new critical alerts. Report only when there are any.",
|
|
1067
|
-
auth: appAuth,
|
|
1068
|
-
})
|
|
1069
|
-
);
|
|
1070
|
-
},
|
|
1071
|
-
});
|
|
1072
|
-
```
|
|
1073
|
-
|
|
1074
|
-
Cron expressions are standard 5-field, evaluated in UTC with minute
|
|
1075
|
-
granularity. In production mode (`bdk serve`) schedules fire on
|
|
1076
|
-
cadence; in dev mode (`--dev`) they never fire automatically. Dispatch one
|
|
1077
|
-
by hand, exactly once, through the same path production uses:
|
|
59
|
+
my-bot/
|
|
60
|
+
├── package.json
|
|
61
|
+
├── bot/
|
|
62
|
+
│ ├── agent.ts
|
|
63
|
+
│ ├── instructions.md
|
|
64
|
+
│ ├── tools/
|
|
65
|
+
│ ├── skills/
|
|
66
|
+
│ ├── mcp-connections/
|
|
67
|
+
│ ├── subagents/
|
|
68
|
+
│ ├── channels/
|
|
69
|
+
│ ├── hooks/
|
|
70
|
+
│ └── schedules/
|
|
71
|
+
└── evals/
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Describe the bot or agent in Cursor, or edit the files yourself.
|
|
75
|
+
|
|
76
|
+
## Start from a template
|
|
77
|
+
|
|
78
|
+
Pass a template to `bdk init` when one matches your goal:
|
|
79
|
+
|
|
80
|
+
| Template | Capability |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| `grokbot-agents` | Consult named Grok Bot agents |
|
|
83
|
+
| `security-reviewer` | Review pull requests for exploitable bugs |
|
|
84
|
+
| `thermo-quality-review` | Review structural code quality |
|
|
85
|
+
| `thermo-review` | Review bugs and breakage |
|
|
86
|
+
| `agentic-owners` | Apply owners policies to pull requests |
|
|
87
|
+
| `triage-linear` or `triage-jira` | Triage tracker issues |
|
|
1078
88
|
|
|
1079
89
|
```bash
|
|
1080
|
-
|
|
1081
|
-
|
|
90
|
+
bdk init ./security-reviewer --template security-reviewer
|
|
91
|
+
bdk init ./grokbot --template grokbot-agents
|
|
1082
92
|
```
|
|
1083
93
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
Two handles do two jobs: the **continuation token** resumes a conversation
|
|
1087
|
-
(owned by the channel; one active continuation per session, stale tokens
|
|
1088
|
-
rejected), and the **session id** streams and inspects it (owned by the
|
|
1089
|
-
runtime).
|
|
1090
|
-
|
|
1091
|
-
### Reminders
|
|
1092
|
-
|
|
1093
|
-
Per-session durable wakes (distinct from deploy-time `bot/schedules/`):
|
|
1094
|
-
|
|
1095
|
-
```ts
|
|
1096
|
-
await handle.createReminder({
|
|
1097
|
-
purpose: "ci_recheck",
|
|
1098
|
-
channelId: "drive",
|
|
1099
|
-
continuationToken: "pr-owner-repo-1",
|
|
1100
|
-
delay: "2h",
|
|
1101
|
-
prompt: "Re-check CI. Only act if still failing.",
|
|
1102
|
-
until: "Cancel once CI is green or the PR is merged.",
|
|
1103
|
-
});
|
|
1104
|
-
```
|
|
1105
|
-
|
|
1106
|
-
Host/policy packs may pass `run` (return `stop` / `skip` / `delivered`)
|
|
1107
|
-
instead of prompts. `--dev` does not auto-fire reminders. Dispatch one
|
|
1108
|
-
with `POST /v1/dev/reminders/:id` or `handle.dispatchReminder`. Run
|
|
1109
|
-
handlers are in-memory. After a restart those reminders are disarmed
|
|
1110
|
-
(`handler_lost_on_restart`); re-arm from enroll/policy.
|
|
1111
|
-
|
|
1112
|
-
The NDJSON stream vocabulary: one JSON object per line, each carrying
|
|
1113
|
-
`{ type, index, sessionId, turnId?, at, data }`:
|
|
1114
|
-
|
|
1115
|
-
| Event | Meaning |
|
|
1116
|
-
| --------------------- | -------------------------------------------------------------- |
|
|
1117
|
-
| `session.started` | A durable session was created. |
|
|
1118
|
-
| `message.received` | An inbound user message was accepted. |
|
|
1119
|
-
| `turn.started` | A turn began. |
|
|
1120
|
-
| `step.started` / `step.completed` | Model step boundaries (with duration). |
|
|
1121
|
-
| `reasoning.appended` / `reasoning.completed` | Reasoning deltas and the block end. |
|
|
1122
|
-
| `message.appended` | Assistant text delta (with cumulative text so far). |
|
|
1123
|
-
| `message.completed` | A finalized assistant text block (`finishReason`: `stop` or `tool_call`). |
|
|
1124
|
-
| `actions.requested` | The model requested a tool call (streams before execution). |
|
|
1125
|
-
| `action.approval_requested` | A `needsApproval` tool is parked awaiting a human. |
|
|
1126
|
-
| `action.approval_resolved` | Human approved or denied the parked tool call. |
|
|
1127
|
-
| `action.result` | A tool call returned (`output`, `isError`). |
|
|
1128
|
-
| `subagent.called` / `subagent.completed` | Delegation to a subagent. |
|
|
1129
|
-
| `turn.completed` | The turn finished (`result`, `usage`). |
|
|
1130
|
-
| `turn.failed` | The turn failed (`message`). |
|
|
1131
|
-
| `session.waiting` | The session parked, ready for the next message. |
|
|
1132
|
-
| `session.completed` / `session.failed` | Terminal states for task-mode (schedule) sessions. |
|
|
1133
|
-
|
|
1134
|
-
The stream is durable: reconnect with `?startIndex=<n>` to replay from any
|
|
1135
|
-
point, or from 0 to rewind the whole session.
|
|
1136
|
-
|
|
1137
|
-
## Serving programmatically
|
|
1138
|
-
|
|
1139
|
-
```ts
|
|
1140
|
-
import { serve } from "@cursor/bdk";
|
|
1141
|
-
|
|
1142
|
-
const handle = await serve("./my-agent", {
|
|
1143
|
-
port: 3000,
|
|
1144
|
-
apiKey: process.env.CURSOR_API_KEY, // optional: see credential order below
|
|
1145
|
-
});
|
|
1146
|
-
console.log(`listening on ${handle.url}`);
|
|
1147
|
-
// handle.dispatchSchedule("heartbeat"), handle.project, await handle.close()
|
|
1148
|
-
```
|
|
1149
|
-
|
|
1150
|
-
The Cursor credential resolves in one order everywhere (SDK turns and
|
|
1151
|
-
Cursor account MCP connections): explicit `apiKey` option / `--api-key`
|
|
1152
|
-
→ `CURSOR_API_KEY` → `CURSOR_API_KEY_FILE` (hosted default
|
|
1153
|
-
`/run/cursor/secrets/CURSOR_API_KEY` when unset) → `CURSOR_SERVICE_ACCOUNT_KEY`
|
|
1154
|
-
→ the key stored by `bdk login`. A bind file wins over
|
|
1155
|
-
`CURSOR_SERVICE_ACCOUNT_KEY`. `whoami` shows
|
|
1156
|
-
which one is active; `logout` removes the stored key (revoke it in the
|
|
1157
|
-
Cursor dashboard to kill it outright).
|
|
1158
|
-
|
|
1159
|
-
Local-dev note: login/account RPCs honor `CURSOR_API_BASE_URL` while the
|
|
1160
|
-
Cursor SDK harness honors `CURSOR_BACKEND_URL`. When pointing at a
|
|
1161
|
-
non-production backend, set **both** to the same URL. A key minted on one
|
|
1162
|
-
backend is rejected by the other.
|
|
1163
|
-
|
|
1164
|
-
`serve` refuses to start when discovery produced error diagnostics; run
|
|
1165
|
-
`bdk validate` (or read `project.diagnostics`) to see why.
|
|
1166
|
-
|
|
1167
|
-
State lives under the project state directory (override with
|
|
1168
|
-
`--state-root`). Forget a conversation by removing that session from
|
|
1169
|
-
state.
|
|
94
|
+
`--template triage` selects `triage-linear`.
|
|
1170
95
|
|
|
1171
|
-
|
|
1172
|
-
also loads ambient project config from ancestor directories. Nested git
|
|
1173
|
-
checkouts default `local.cwd` to a per-project cache directory under
|
|
1174
|
-
`~/.cache`. Point `cwd` at a checkout only when the agent should inherit
|
|
1175
|
-
that tree.
|
|
96
|
+
## Next steps
|
|
1176
97
|
|
|
1177
|
-
|
|
98
|
+
Run `bdk docs` to open the full documentation. By default,
|
|
99
|
+
`bdk serve` also serves the same documentation at `/docs`.
|
|
1178
100
|
|
|
1179
|
-
|
|
1180
|
-
It also rejects nested subagents, WebSocket channel routes, and custom
|
|
1181
|
-
sandbox backends. Discord and Teams do not have channel packs. Use an
|
|
1182
|
-
authored `defineChannel` integration for those platforms.
|
|
101
|
+
The docs include:
|
|
1183
102
|
|
|
1184
|
-
|
|
1185
|
-
|
|
103
|
+
- A complete PR reviewer quickstart
|
|
104
|
+
- GitHub, Slack, webhook, and MCP guides
|
|
105
|
+
- Evals and hillclimbing
|
|
106
|
+
- Deployment and troubleshooting
|
|
107
|
+
- Project layout, CLI, and API reference
|