@cursor/bdk 0.2.23 → 0.2.25

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 (421) hide show
  1. package/AGENTS.md +1 -0
  2. package/dist/artifacts.d.ts +1 -1
  3. package/dist/artifacts.js +1 -1
  4. package/dist/bin/agent-serve.d.ts +1 -1
  5. package/dist/bin/agent-serve.js +48 -12
  6. package/dist/channels/bitbucket/bitbucket-channel.js +1 -1
  7. package/dist/channels/bitbucket/bitbucket-webhook.d.ts +3 -2
  8. package/dist/channels/bitbucket/bitbucket-webhook.d.ts.map +1 -1
  9. package/dist/channels/bitbucket/bitbucket-webhook.js +14 -9
  10. package/dist/channels/change-monitors/change-monitors-channel.js +1 -1
  11. package/dist/channels/deployments/deployments-channel.js +1 -1
  12. package/dist/channels/github/github-channel.d.ts.map +1 -1
  13. package/dist/channels/github/github-channel.js +10 -19
  14. package/dist/channels/gitlab/gitlab-channel.js +1 -1
  15. package/dist/channels/issues/issues-channel.js +1 -1
  16. package/dist/channels/origin/origin-channel.js +1 -1
  17. package/dist/channels/pagerduty/api.d.ts +74 -0
  18. package/dist/channels/pagerduty/api.d.ts.map +1 -0
  19. package/dist/channels/pagerduty/api.js +101 -0
  20. package/dist/channels/pagerduty/defaults.d.ts +42 -0
  21. package/dist/channels/pagerduty/defaults.d.ts.map +1 -0
  22. package/dist/channels/pagerduty/defaults.js +132 -0
  23. package/dist/channels/pagerduty/events.d.ts +24 -0
  24. package/dist/channels/pagerduty/events.d.ts.map +1 -0
  25. package/dist/channels/pagerduty/events.js +38 -0
  26. package/dist/channels/pagerduty/index.d.ts +31 -0
  27. package/dist/channels/pagerduty/index.d.ts.map +1 -0
  28. package/dist/channels/pagerduty/index.js +30 -0
  29. package/dist/channels/pagerduty/pagerduty-channel.d.ts +64 -0
  30. package/dist/channels/pagerduty/pagerduty-channel.d.ts.map +1 -0
  31. package/dist/channels/pagerduty/pagerduty-channel.js +195 -0
  32. package/dist/channels/pagerduty/pagerduty-webhook.d.ts +70 -0
  33. package/dist/channels/pagerduty/pagerduty-webhook.d.ts.map +1 -0
  34. package/dist/channels/pagerduty/pagerduty-webhook.js +280 -0
  35. package/dist/channels/pagerduty/payload.d.ts +33 -0
  36. package/dist/channels/pagerduty/payload.d.ts.map +1 -0
  37. package/dist/channels/pagerduty/payload.js +150 -0
  38. package/dist/channels/pagerduty/replay.d.ts +35 -0
  39. package/dist/channels/pagerduty/replay.d.ts.map +1 -0
  40. package/dist/channels/pagerduty/replay.js +115 -0
  41. package/dist/channels/pagerduty/secrets.d.ts +16 -0
  42. package/dist/channels/pagerduty/secrets.d.ts.map +1 -0
  43. package/dist/channels/pagerduty/secrets.js +23 -0
  44. package/dist/channels/pagerduty/self-user.d.ts +51 -0
  45. package/dist/channels/pagerduty/self-user.d.ts.map +1 -0
  46. package/dist/channels/pagerduty/self-user.js +157 -0
  47. package/dist/channels/pagerduty/state.d.ts +31 -0
  48. package/dist/channels/pagerduty/state.d.ts.map +1 -0
  49. package/dist/channels/pagerduty/state.js +30 -0
  50. package/dist/channels/pagerduty/types.d.ts +217 -0
  51. package/dist/channels/pagerduty/types.d.ts.map +1 -0
  52. package/dist/channels/pagerduty/types.js +1 -0
  53. package/dist/channels/runs/runs-channel.js +1 -1
  54. package/dist/channels/slack/tool-approval-events.js +5 -5
  55. package/dist/channels.d.ts +14 -1
  56. package/dist/channels.d.ts.map +1 -1
  57. package/dist/channels.js +24 -9
  58. package/dist/docs/404.html +3 -3
  59. package/dist/docs/assets/{app.AXQcJZaf.js → app.BjS1QEI4.js} +4 -4
  60. package/dist/docs/assets/chunks/@localSearchIndexroot.oGqZumnJ.js +1 -0
  61. package/dist/docs/assets/chunks/{VPLocalSearchBox.hlZ2vmun.js → VPLocalSearchBox.BOuvjb5Y.js} +2 -2
  62. package/dist/docs/assets/chunks/{arc.9KNWdH-l.js → arc.3WR6Jf-y.js} +1 -1
  63. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.BfGzkBHI.js → architectureDiagram-Q4EWVU46.Dtb6Dqh6.js} +1 -1
  64. package/dist/docs/assets/chunks/{baseUniq.Btk8-2Rs.js → baseUniq.BUyrgrZE.js} +1 -1
  65. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.BmHm9OH5.js → blockDiagram-DXYQGD6D.BVLV_voZ.js} +1 -1
  66. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.9POrbDHJ.js → c4Diagram-AHTNJAMY.jXJ1q70M.js} +1 -1
  67. package/dist/docs/assets/chunks/channel.Dt4aweTm.js +1 -0
  68. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.YWZVSM6S.js → chunk-4BX2VUAB.zz1SMBvK.js} +1 -1
  69. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.Cxr_SFgw.js → chunk-4TB4RGXK.CzYKuv3I.js} +1 -1
  70. package/dist/docs/assets/chunks/{chunk-55IACEB6.DtiJyPlD.js → chunk-55IACEB6.C7_tcJZD.js} +1 -1
  71. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.b5gNHJPH.js → chunk-EDXVE4YY.DeTwQPVO.js} +1 -1
  72. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.DmN9yA_M.js → chunk-FMBD7UC4.DhMTl7ut.js} +1 -1
  73. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.Dfm3xgV5.js → chunk-OYMX7WX6.Me7f5hEp.js} +1 -1
  74. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.sXNxDcJA.js → chunk-QZHKN3VN.D0E0Bb6g.js} +1 -1
  75. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.DgBnDUV7.js → chunk-YZCP3GAM.CdOOBFYL.js} +1 -1
  76. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.DGUHZs6j.js +1 -0
  77. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.DGUHZs6j.js +1 -0
  78. package/dist/docs/assets/chunks/clone.DWf3k0Z0.js +1 -0
  79. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.D18MEcoN.js → cose-bilkent-S5V4N54A.BNbGESzN.js} +1 -1
  80. package/dist/docs/assets/chunks/{dagre-KV5264BT.CSf3tihh.js → dagre-KV5264BT.zU7Lu_xJ.js} +1 -1
  81. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.cbfzAfoC.js → diagram-5BDNPKRD.B9qOdE5h.js} +1 -1
  82. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.6i6P3uu9.js → diagram-G4DWMVQ6.D8X-sf77.js} +1 -1
  83. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.B9HAIfN6.js → diagram-MMDJMWI5.CW7MvMlE.js} +1 -1
  84. package/dist/docs/assets/chunks/{diagram-TYMM5635.B9baAjUv.js → diagram-TYMM5635.J489G0Nd.js} +1 -1
  85. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.DaBmX_GN.js → erDiagram-SMLLAGMA.BkW7tGfs.js} +1 -1
  86. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.CJqQJjkb.js → flowDiagram-DWJPFMVM.jc9iWORD.js} +1 -1
  87. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.CIXBLQhC.js → ganttDiagram-T4ZO3ILL.B-UQfd9E.js} +1 -1
  88. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.CDgentto.js → gitGraphDiagram-UUTBAWPF.DFzrTSlJ.js} +1 -1
  89. package/dist/docs/assets/chunks/{graph.BWHn6JBQ.js → graph.C5IB6_e_.js} +1 -1
  90. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.d9VU_ts_.js → infoDiagram-42DDH7IO.DwF0-c8L.js} +1 -1
  91. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.BNO79Prj.js → ishikawaDiagram-UXIWVN3A.fBaTqzE7.js} +1 -1
  92. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.CPgUTM1R.js → journeyDiagram-VCZTEJTY.CM8gDVJy.js} +1 -1
  93. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.idl0Eoe1.js → kanban-definition-6JOO6SKY.YiD1p0LB.js} +1 -1
  94. package/dist/docs/assets/chunks/{layout.BY7DIMr6.js → layout.6Um-DVJT.js} +1 -1
  95. package/dist/docs/assets/chunks/{linear.DYaUDrHd.js → linear.DcTeg4Hn.js} +1 -1
  96. package/dist/docs/assets/chunks/{min.V6MWb1UC.js → min.CIxkY8Fe.js} +1 -1
  97. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.BRlJXuFS.js → mindmap-definition-QFDTVHPH.D4QM_voR.js} +1 -1
  98. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.BIhkDLcB.js → pieDiagram-DEJITSTG.nmB309G1.js} +1 -1
  99. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.Bw-_VEL3.js → quadrantDiagram-34T5L4WZ.D1HtZR3C.js} +1 -1
  100. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.DolEGwxw.js → requirementDiagram-MS252O5E.CZgQWob-.js} +1 -1
  101. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.hMM-8BhN.js → sankeyDiagram-XADWPNL6.DtiBfU-P.js} +1 -1
  102. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.Bg_CRVDy.js → sequenceDiagram-FGHM5R23.Cld4gDSt.js} +1 -1
  103. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.DNWdl34_.js → stateDiagram-FHFEXIEX.DatP823_.js} +1 -1
  104. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.C0571l4D.js +1 -0
  105. package/dist/docs/assets/chunks/{theme.CBW1oolh.js → theme.D5jbBys7.js} +2 -2
  106. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.Cr1wJ1mB.js → timeline-definition-GMOUNBTQ.DwQLI2be.js} +1 -1
  107. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.BltDV9j7.js → vennDiagram-DHZGUBPP.a5yMfnsa.js} +1 -1
  108. package/dist/docs/assets/chunks/{wardley-RL74JXVD.BWPaUhOs.js → wardley-RL74JXVD.B-FXivgT.js} +1 -1
  109. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.nsADqCCo.js → wardleyDiagram-NUSXRM2D.Dz--Opy3.js} +1 -1
  110. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.CCwbO3dK.js → xychartDiagram-5P7HB3ND.Dl8w8TeT.js} +1 -1
  111. package/dist/docs/assets/{deployment.md.CtSJ6sF9.js → deployment.md.3MMWuPeV.js} +5 -5
  112. package/dist/docs/assets/{deployment.md.CtSJ6sF9.lean.js → deployment.md.3MMWuPeV.lean.js} +1 -1
  113. package/dist/docs/assets/{guides_cloud-agents.md.CBK7W0-O.js → guides_cloud-agents.md.BzbzcOyj.js} +2 -2
  114. package/dist/docs/assets/{guides_cloud-agents.md.CBK7W0-O.lean.js → guides_cloud-agents.md.BzbzcOyj.lean.js} +1 -1
  115. package/dist/docs/assets/{guides_opentelemetry.md.ByW1Fs7b.js → guides_opentelemetry.md.DBQtp7_V.js} +13 -5
  116. package/dist/docs/assets/{guides_opentelemetry.md.ByW1Fs7b.lean.js → guides_opentelemetry.md.DBQtp7_V.lean.js} +1 -1
  117. package/dist/docs/assets/guides_pagerduty.md.BHXMcMtx.js +60 -0
  118. package/dist/docs/assets/guides_pagerduty.md.BHXMcMtx.lean.js +1 -0
  119. package/dist/docs/assets/{reference_agent-config.md.DYA6ge6t.js → reference_agent-config.md.IplwL25I.js} +1 -2
  120. package/dist/docs/assets/{reference_agent-config.md.DYA6ge6t.lean.js → reference_agent-config.md.IplwL25I.lean.js} +1 -1
  121. package/dist/docs/assets/{reference_channels.md.DYg0CLud.js → reference_channels.md.Bxaa020x.js} +1 -1
  122. package/dist/docs/assets/{reference_cli.md.DB7Llw3T.js → reference_cli.md.1o_TqKdt.js} +7 -2
  123. package/dist/docs/assets/{reference_cli.md.DB7Llw3T.lean.js → reference_cli.md.1o_TqKdt.lean.js} +1 -1
  124. package/dist/docs/assets/{reference_extensions.md.OUacPetl.js → reference_extensions.md.DKxTuCIw.js} +11 -8
  125. package/dist/docs/assets/{reference_extensions.md.OUacPetl.lean.js → reference_extensions.md.DKxTuCIw.lean.js} +1 -1
  126. package/dist/docs/assets/{reference_instructions.md.DrcHZXig.js → reference_instructions.md.BYMVxAkw.js} +4 -4
  127. package/dist/docs/assets/{reference_instructions.md.DrcHZXig.lean.js → reference_instructions.md.BYMVxAkw.lean.js} +1 -1
  128. package/dist/docs/assets/{reference_schedules.md.BqWnJES4.js → reference_schedules.md.03Ryy9ca.js} +3 -3
  129. package/dist/docs/assets/{reference_tools.md.08XR7lIl.js → reference_tools.md.-6pypsWt.js} +1 -1
  130. package/dist/docs/assets/{style.Dwls12uf.css → style.nMsabY-V.css} +1 -1
  131. package/dist/docs/assets/templates_agentic-owners.md.CTEnR0jp.js +13 -0
  132. package/dist/docs/assets/{templates_agentic-owners.md.CvmABtia.lean.js → templates_agentic-owners.md.CTEnR0jp.lean.js} +1 -1
  133. package/dist/docs/building-with-agents.html +37 -37
  134. package/dist/docs/deployment.html +42 -42
  135. package/dist/docs/deployment.md +9 -4
  136. package/dist/docs/evals.html +37 -37
  137. package/dist/docs/guides/agent-to-agent.html +37 -37
  138. package/dist/docs/guides/bitbucket.html +37 -37
  139. package/dist/docs/guides/cloud-agents.html +38 -38
  140. package/dist/docs/guides/cloud-agents.md +1 -0
  141. package/dist/docs/guides/convert-automation.html +37 -37
  142. package/dist/docs/guides/export-grokbot.html +37 -37
  143. package/dist/docs/guides/github.html +37 -37
  144. package/dist/docs/guides/gitlab.html +37 -37
  145. package/dist/docs/guides/grokbot-agents.html +37 -37
  146. package/dist/docs/guides/hooks.html +37 -37
  147. package/dist/docs/guides/improve.html +37 -37
  148. package/dist/docs/guides/jev.html +37 -37
  149. package/dist/docs/guides/mcp-oauth.html +37 -37
  150. package/dist/docs/guides/migrate.html +37 -37
  151. package/dist/docs/guides/opentelemetry.html +49 -41
  152. package/dist/docs/guides/opentelemetry.md +54 -3
  153. package/dist/docs/guides/pagerduty.html +119 -0
  154. package/dist/docs/guides/pagerduty.md +336 -0
  155. package/dist/docs/guides/slack.html +37 -37
  156. package/dist/docs/guides/webhooks.html +37 -37
  157. package/dist/docs/hashmap.json +1 -1
  158. package/dist/docs/hillclimbing.html +37 -37
  159. package/dist/docs/index.html +37 -37
  160. package/dist/docs/llms-full.txt +510 -42
  161. package/dist/docs/llms.txt +1 -0
  162. package/dist/docs/quickstart.html +37 -37
  163. package/dist/docs/reference/agent-config.html +38 -39
  164. package/dist/docs/reference/agent-config.md +0 -1
  165. package/dist/docs/reference/artifacts.html +37 -37
  166. package/dist/docs/reference/channels.html +38 -38
  167. package/dist/docs/reference/channels.md +2 -1
  168. package/dist/docs/reference/cli.html +43 -38
  169. package/dist/docs/reference/cli.md +27 -0
  170. package/dist/docs/reference/connections.html +37 -37
  171. package/dist/docs/reference/evals.html +37 -37
  172. package/dist/docs/reference/extensions.html +47 -44
  173. package/dist/docs/reference/extensions.md +15 -9
  174. package/dist/docs/reference/hooks.html +37 -37
  175. package/dist/docs/reference/http-api.html +37 -37
  176. package/dist/docs/reference/instructions.html +40 -40
  177. package/dist/docs/reference/instructions.md +5 -1
  178. package/dist/docs/reference/memory.html +37 -37
  179. package/dist/docs/reference/playground.html +36 -36
  180. package/dist/docs/reference/project-layout.html +37 -37
  181. package/dist/docs/reference/prompt.html +37 -37
  182. package/dist/docs/reference/schedules.html +40 -40
  183. package/dist/docs/reference/sessions.html +36 -36
  184. package/dist/docs/reference/skills.html +37 -37
  185. package/dist/docs/reference/subagents.html +37 -37
  186. package/dist/docs/reference/tools.html +39 -39
  187. package/dist/docs/reference/tools.md +1 -0
  188. package/dist/docs/templates/agentic-owners.html +42 -43
  189. package/dist/docs/templates/agentic-owners.md +55 -23
  190. package/dist/docs/templates/grokbot-agents.html +37 -37
  191. package/dist/docs/templates/security-reviewer.html +37 -37
  192. package/dist/docs/templates/thermo-quality-review.html +37 -37
  193. package/dist/docs/templates/thermo-review.html +37 -37
  194. package/dist/docs/templates/triage.html +37 -37
  195. package/dist/docs/troubleshooting.html +36 -36
  196. package/dist/extensions/cursor-cloud-agents/extension.d.ts +2 -0
  197. package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -1
  198. package/dist/extensions/cursor-cloud-agents/extension.js +2 -1
  199. package/dist/extensions/cursor-cloud-agents/lib/backend.d.ts +1 -0
  200. package/dist/extensions/cursor-cloud-agents/lib/backend.d.ts.map +1 -1
  201. package/dist/extensions/cursor-cloud-agents/lib/backend.js +2 -1
  202. package/dist/extensions/cursor-cloud-agents/lib/fleet.js +1 -1
  203. package/dist/extensions/cursor-cloud-agents/lib/inputs.d.ts +1 -1
  204. package/dist/extensions/cursor-cloud-agents/lib/inputs.d.ts.map +1 -1
  205. package/dist/extensions/cursor-cloud-agents/lib/inputs.js +1 -1
  206. package/dist/extensions/cursor-cloud-agents/reminders/cloud-agent-stop-watch.js +1 -1
  207. package/dist/extensions/cursor-cloud-agents/tools/launch.js +1 -1
  208. package/dist/extensions/cursor-cloud-agents/tools/list.js +1 -1
  209. package/dist/extensions/cursor-cloud-agents/tools/reply.js +1 -1
  210. package/dist/extensions/cursor-grokbot-agents/extension.js +1 -1
  211. package/dist/extensions/cursor-grokbot-agents/lib/backend.js +1 -1
  212. package/dist/extensions/cursor-grokbot-agents/lib/contacts.js +1 -1
  213. package/dist/extensions/cursor-grokbot-agents/lib/inputs.d.ts +1 -1
  214. package/dist/extensions/cursor-grokbot-agents/lib/inputs.d.ts.map +1 -1
  215. package/dist/extensions/cursor-grokbot-agents/lib/inputs.js +1 -1
  216. package/dist/extensions/cursor-grokbot-agents/tools/ask.js +1 -1
  217. package/dist/extensions/cursor-grokbot-agents/tools/check.js +1 -1
  218. package/dist/extensions/cursor-grokbot-agents/tools/interrupt.js +1 -1
  219. package/dist/extensions/cursor-grokbot-agents/tools/list.js +1 -1
  220. package/dist/extensions/improve/extension.js +1 -1
  221. package/dist/extensions/jev/extension.js +1 -1
  222. package/dist/extensions/jev/tools/evaluate.js +1 -1
  223. package/dist/extensions/slack-communication/extension.js +1 -1
  224. package/dist/extensions/slack-communication/tools/delete-message.js +1 -1
  225. package/dist/extensions/slack-communication/tools/edit-message.js +1 -1
  226. package/dist/extensions/slack-communication/tools/post-card.js +1 -1
  227. package/dist/extensions/slack-communication/tools/post-file.js +1 -1
  228. package/dist/extensions/slack-communication/tools/post-update.js +1 -1
  229. package/dist/extensions/slack-communication/tools/react.js +1 -1
  230. package/dist/extensions/slack-communication/tools/set-status.js +1 -1
  231. package/dist/extensions.d.ts +1 -1
  232. package/dist/extensions.js +1 -1
  233. package/dist/internal/approval-gate.d.ts +4 -2
  234. package/dist/internal/approval-gate.d.ts.map +1 -1
  235. package/dist/internal/approval-gate.js +2 -1
  236. package/dist/internal/builtin-tools/artifacts.d.ts.map +1 -1
  237. package/dist/internal/builtin-tools/artifacts.js +46 -13
  238. package/dist/internal/builtin-tools/reminders.js +1 -1
  239. package/dist/internal/channel-architecture.d.ts +1 -1
  240. package/dist/internal/channel-architecture.d.ts.map +1 -1
  241. package/dist/internal/channel-architecture.js +4 -2
  242. package/dist/internal/cli-deploy.d.ts.map +1 -1
  243. package/dist/internal/cli-deploy.js +21 -12
  244. package/dist/internal/cli-pagerduty.d.ts +32 -0
  245. package/dist/internal/cli-pagerduty.d.ts.map +1 -0
  246. package/dist/internal/cli-pagerduty.js +242 -0
  247. package/dist/internal/continuation-channel.d.ts.map +1 -1
  248. package/dist/internal/continuation-channel.js +7 -0
  249. package/dist/internal/continuation-identity.d.ts +11 -3
  250. package/dist/internal/continuation-identity.d.ts.map +1 -1
  251. package/dist/internal/continuation-identity.js +83 -0
  252. package/dist/internal/convert-automation/convert-workflow.js +1 -1
  253. package/dist/internal/convert-grokbot/answers.js +1 -1
  254. package/dist/internal/convert-grokbot/recipe.d.ts +1 -1
  255. package/dist/internal/convert-grokbot/recipe.d.ts.map +1 -1
  256. package/dist/internal/convert-grokbot/recipe.js +1 -1
  257. package/dist/internal/cursor/backend-client.d.ts +1 -1
  258. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  259. package/dist/internal/cursor/backend-client.js +1 -1
  260. package/dist/internal/cursor/credentials.d.ts +1 -1
  261. package/dist/internal/cursor/credentials.d.ts.map +1 -1
  262. package/dist/internal/cursor/credentials.js +1 -1
  263. package/dist/internal/deploy-client.js +1 -1
  264. package/dist/internal/deploy-manifest.d.ts +11 -4
  265. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  266. package/dist/internal/deploy-manifest.js +19 -6
  267. package/dist/internal/discovery/agent-config.d.ts.map +1 -1
  268. package/dist/internal/discovery/agent-config.js +10 -10
  269. package/dist/internal/discovery/agent.d.ts.map +1 -1
  270. package/dist/internal/discovery/agent.js +10 -10
  271. package/dist/internal/discovery/channels.d.ts.map +1 -1
  272. package/dist/internal/discovery/channels.js +20 -16
  273. package/dist/internal/discovery/context.d.ts +16 -0
  274. package/dist/internal/discovery/context.d.ts.map +1 -1
  275. package/dist/internal/discovery/context.js +66 -0
  276. package/dist/internal/discovery/cursor-plugin.js +1 -1
  277. package/dist/internal/discovery/extension-overlay.d.ts.map +1 -1
  278. package/dist/internal/discovery/extension-overlay.js +2 -6
  279. package/dist/internal/discovery/info.d.ts.map +1 -1
  280. package/dist/internal/discovery/info.js +3 -0
  281. package/dist/internal/discovery/instructions.d.ts.map +1 -1
  282. package/dist/internal/discovery/instructions.js +3 -6
  283. package/dist/internal/discovery/modules.d.ts.map +1 -1
  284. package/dist/internal/discovery/modules.js +3 -6
  285. package/dist/internal/discovery/project.d.ts +6 -0
  286. package/dist/internal/discovery/project.d.ts.map +1 -1
  287. package/dist/internal/discovery/project.js +27 -5
  288. package/dist/internal/discovery/runtime.d.ts.map +1 -1
  289. package/dist/internal/discovery/runtime.js +8 -8
  290. package/dist/internal/discovery.d.ts +1 -1
  291. package/dist/internal/discovery.d.ts.map +1 -1
  292. package/dist/internal/discovery.js +1 -1
  293. package/dist/internal/expected-delivery-failure.d.ts.map +1 -1
  294. package/dist/internal/expected-delivery-failure.js +6 -0
  295. package/dist/internal/factory-resource-channel.d.ts +1 -1
  296. package/dist/internal/factory-resource-channel.d.ts.map +1 -1
  297. package/dist/internal/filesystem/sdk-schemas.d.ts +1 -1
  298. package/dist/internal/filesystem/sdk-schemas.d.ts.map +1 -1
  299. package/dist/internal/filesystem/sdk-schemas.js +5 -4
  300. package/dist/internal/filesystem/tools.js +1 -1
  301. package/dist/internal/hmac-secret-values.d.ts +48 -0
  302. package/dist/internal/hmac-secret-values.d.ts.map +1 -0
  303. package/dist/internal/hmac-secret-values.js +68 -0
  304. package/dist/internal/host-otel.d.ts +2 -1
  305. package/dist/internal/host-otel.d.ts.map +1 -1
  306. package/dist/internal/host-otel.js +20 -6
  307. package/dist/internal/host-platforms.d.ts.map +1 -1
  308. package/dist/internal/host-platforms.js +8 -2
  309. package/dist/internal/hosted-delivery-protocol.d.ts +4 -0
  310. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  311. package/dist/internal/hosted-delivery.d.ts +7 -0
  312. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  313. package/dist/internal/hosted-delivery.js +19 -17
  314. package/dist/internal/hosting.d.ts +6 -0
  315. package/dist/internal/hosting.d.ts.map +1 -1
  316. package/dist/internal/hosting.js +9 -0
  317. package/dist/internal/init-scaffold.js +1 -1
  318. package/dist/internal/interview/agent-questions.d.ts +1 -1
  319. package/dist/internal/interview/agent-questions.d.ts.map +1 -1
  320. package/dist/internal/interview/agent-questions.js +1 -1
  321. package/dist/internal/interview/question.d.ts +1 -1
  322. package/dist/internal/interview/question.d.ts.map +1 -1
  323. package/dist/internal/interview/question.js +1 -1
  324. package/dist/internal/json-schema.d.ts +7 -7
  325. package/dist/internal/json-schema.d.ts.map +1 -1
  326. package/dist/internal/json-schema.js +14 -17
  327. package/dist/internal/mcp-endpoint.js +1 -1
  328. package/dist/internal/otel/collector.d.ts.map +1 -1
  329. package/dist/internal/otel/collector.js +50 -19
  330. package/dist/internal/otel/config.d.ts +10 -1
  331. package/dist/internal/otel/config.d.ts.map +1 -1
  332. package/dist/internal/otel/config.js +47 -10
  333. package/dist/internal/otel/http.d.ts +1 -1
  334. package/dist/internal/otel/http.d.ts.map +1 -1
  335. package/dist/internal/otel/http.js +1 -1
  336. package/dist/internal/otel/runtime.d.ts +17 -14
  337. package/dist/internal/otel/runtime.d.ts.map +1 -1
  338. package/dist/internal/otel/runtime.js +203 -237
  339. package/dist/internal/package-inline-stdio.d.ts.map +1 -1
  340. package/dist/internal/package-inline-stdio.js +21 -5
  341. package/dist/internal/process-memory-telemetry.d.ts +1 -1
  342. package/dist/internal/process-memory-telemetry.d.ts.map +1 -1
  343. package/dist/internal/process-memory-telemetry.js +1 -1
  344. package/dist/internal/sdk-runner.d.ts +2 -3
  345. package/dist/internal/sdk-runner.d.ts.map +1 -1
  346. package/dist/internal/sdk-runner.js +30 -6
  347. package/dist/internal/secret-alternatives.d.ts +11 -0
  348. package/dist/internal/secret-alternatives.d.ts.map +1 -0
  349. package/dist/internal/secret-alternatives.js +13 -0
  350. package/dist/internal/server.d.ts.map +1 -1
  351. package/dist/internal/server.js +27 -15
  352. package/dist/internal/session-engine.d.ts +9 -1
  353. package/dist/internal/session-engine.d.ts.map +1 -1
  354. package/dist/internal/session-engine.js +30 -4
  355. package/dist/internal/slack-provision-client.js +1 -1
  356. package/dist/internal/sqlite-experimental-warning.d.ts +2 -0
  357. package/dist/internal/sqlite-experimental-warning.d.ts.map +1 -0
  358. package/dist/internal/sqlite-experimental-warning.js +22 -0
  359. package/dist/internal/store-api-protocol.d.ts +1 -1
  360. package/dist/internal/store-api-protocol.d.ts.map +1 -1
  361. package/dist/internal/store-api-protocol.js +1 -1
  362. package/dist/internal/testing/conversation-identity-vectors.d.ts +6 -1
  363. package/dist/internal/testing/conversation-identity-vectors.d.ts.map +1 -1
  364. package/dist/internal/testing/conversation-identity-vectors.js +34 -0
  365. package/dist/internal/testing/hmac-secret-vectors.d.ts +38 -0
  366. package/dist/internal/testing/hmac-secret-vectors.d.ts.map +1 -0
  367. package/dist/internal/testing/hmac-secret-vectors.js +89 -0
  368. package/dist/internal/testing/pagerduty-continuation-fixtures.d.ts +42 -0
  369. package/dist/internal/testing/pagerduty-continuation-fixtures.d.ts.map +1 -0
  370. package/dist/internal/testing/pagerduty-continuation-fixtures.js +175 -0
  371. package/dist/internal/update-check.d.ts +1 -1
  372. package/dist/internal/update-check.d.ts.map +1 -1
  373. package/dist/internal/update-check.js +1 -1
  374. package/dist/internal/zod-schema.d.ts +14 -0
  375. package/dist/internal/zod-schema.d.ts.map +1 -0
  376. package/dist/internal/zod-schema.js +22 -0
  377. package/dist/otel.d.ts +1 -2
  378. package/dist/otel.d.ts.map +1 -1
  379. package/dist/otel.js +0 -1
  380. package/dist/playground/assets/cursor-icons-16-DmHBTm1-.woff2 +0 -0
  381. package/dist/playground/assets/index-BdMwybMt.css +1 -0
  382. package/dist/playground/assets/index-CHk6O92d.js +62 -0
  383. package/dist/playground/index.html +2 -2
  384. package/dist/tools.d.ts +14 -11
  385. package/dist/tools.d.ts.map +1 -1
  386. package/dist/tools.js +4 -3
  387. package/dist/types.d.ts +67 -16
  388. package/dist/types.d.ts.map +1 -1
  389. package/docs/deployment.md +9 -4
  390. package/docs/guides/cloud-agents.md +1 -0
  391. package/docs/guides/opentelemetry.md +54 -3
  392. package/docs/guides/pagerduty.md +341 -0
  393. package/docs/reference/agent-config.md +0 -1
  394. package/docs/reference/channels.md +2 -1
  395. package/docs/reference/cli.md +27 -0
  396. package/docs/reference/extensions.md +15 -9
  397. package/docs/reference/instructions.md +5 -1
  398. package/docs/reference/tools.md +1 -0
  399. package/docs/templates/agentic-owners.md +55 -23
  400. package/package.json +24 -19
  401. package/skills/migrate-v2/SKILL.md +1 -1
  402. package/skills/otel/SKILL.md +24 -7
  403. package/templates/agentic-owners/README.md +6 -1
  404. package/templates/agentic-owners/bot/lib/owners/decision.ts +31 -5
  405. package/templates/agentic-owners/bot/lib/owners/globalOverride.ts +60 -0
  406. package/templates/agentic-owners/bot/lib/owners/match.ts +85 -19
  407. package/templates/agentic-owners/bot/lib/owners/parse.ts +133 -2
  408. package/templates/agentic-owners/bot/lib/owners/types.ts +23 -0
  409. package/dist/docs/assets/chunks/@localSearchIndexroot.B3j7LFef.js +0 -1
  410. package/dist/docs/assets/chunks/channel.RoCpi7X1.js +0 -1
  411. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.oxdmwwqk.js +0 -1
  412. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.oxdmwwqk.js +0 -1
  413. package/dist/docs/assets/chunks/clone.BkguoIMm.js +0 -1
  414. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.7W-btjJ2.js +0 -1
  415. package/dist/docs/assets/templates_agentic-owners.md.CvmABtia.js +0 -14
  416. package/dist/playground/assets/cursor-icons-16-gwXtdAvu.woff2 +0 -0
  417. package/dist/playground/assets/index-BtsbIqV9.css +0 -1
  418. package/dist/playground/assets/index-CD8VRa25.js +0 -71
  419. /package/dist/docs/assets/{reference_channels.md.DYg0CLud.lean.js → reference_channels.md.Bxaa020x.lean.js} +0 -0
  420. /package/dist/docs/assets/{reference_schedules.md.BqWnJES4.lean.js → reference_schedules.md.03Ryy9ca.lean.js} +0 -0
  421. /package/dist/docs/assets/{reference_tools.md.08XR7lIl.lean.js → reference_tools.md.-6pypsWt.lean.js} +0 -0
@@ -1,8 +1,8 @@
1
- import{_ as e,c as t,o as a,a3 as i}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"OpenTelemetry","description":"Send agent traces and metrics to an OTLP collector, follow one conversation, and add domain telemetry.","frontmatter":{"title":"OpenTelemetry","description":"Send agent traces and metrics to an OTLP collector, follow one conversation, and add domain telemetry."},"headers":[],"relativePath":"guides/opentelemetry.md","filePath":"guides/opentelemetry.md"}'),n={name:"guides/opentelemetry.md"};function o(l,s,r,p,h,d){return a(),t("div",null,[...s[0]||(s[0]=[i(`<h1 id="observe-an-agent-with-opentelemetry" tabindex="-1">Observe an agent with OpenTelemetry <a class="header-anchor" href="#observe-an-agent-with-opentelemetry" aria-label="Permalink to &quot;Observe an agent with OpenTelemetry&quot;">​</a></h1><p>OpenTelemetry connects an agent turn to the observability system your team already uses. Once you configure an OTLP collector, each request, model turn, tool call, and subagent appears alongside token, tool, and cost metrics from the serve process.</p><p>Export is opt-in. Nothing leaves the process until you configure a destination.</p><h2 id="connect-an-otlp-collector" tabindex="-1">Connect an OTLP collector <a class="header-anchor" href="#connect-an-otlp-collector" aria-label="Permalink to &quot;Connect an OTLP collector&quot;">​</a></h2><p>Set the collector endpoint, start the agent, and send it a message. You should see an <code>agent_sdk.http</code> request span and an <code>agent_sdk.turn</code> trace, with any tool or subagent work nested under the turn.</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> OTEL_EXPORTER_OTLP_ENDPOINT</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">https://otel.example.com</span></span>
1
+ import{_ as e,c as a,o as t,a3 as i}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"OpenTelemetry","description":"Send agent traces and metrics to an OTLP collector, follow one conversation, and add domain telemetry.","frontmatter":{"title":"OpenTelemetry","description":"Send agent traces and metrics to an OTLP collector, follow one conversation, and add domain telemetry."},"headers":[],"relativePath":"guides/opentelemetry.md","filePath":"guides/opentelemetry.md"}'),n={name:"guides/opentelemetry.md"};function o(l,s,h,p,r,d){return t(),a("div",null,[...s[0]||(s[0]=[i(`<h1 id="observe-an-agent-with-opentelemetry" tabindex="-1">Observe an agent with OpenTelemetry <a class="header-anchor" href="#observe-an-agent-with-opentelemetry" aria-label="Permalink to &quot;Observe an agent with OpenTelemetry&quot;">​</a></h1><p>OpenTelemetry connects an agent turn to the observability system your team already uses. Once you configure an OTLP collector, each request, model turn, tool call, and subagent appears alongside token, tool, and cost metrics from the serve process.</p><p>Export is opt-in. Nothing leaves the process until you configure a destination.</p><h2 id="connect-an-otlp-collector" tabindex="-1">Connect an OTLP collector <a class="header-anchor" href="#connect-an-otlp-collector" aria-label="Permalink to &quot;Connect an OTLP collector&quot;">​</a></h2><p>Set the collector endpoint, start the agent, and send it a message. You should see an <code>agent_sdk.http</code> request span and an <code>agent_sdk.turn</code> trace, with any tool or subagent work nested under the turn.</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> OTEL_EXPORTER_OTLP_ENDPOINT</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">https://otel.example.com</span></span>
2
2
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> OTEL_EXPORTER_OTLP_HEADERS</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;Authorization=Bearer </span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$OTEL_TOKEN</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span></span>
3
3
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> OTEL_SERVICE_NAME</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">incident-agent</span></span>
4
4
  <span class="line"></span>
5
- <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> serve</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dev</span></span></code></pre></div><p>The default protocol is OTLP/HTTP protobuf. If you already call <code>serve()</code> from TypeScript, you can configure the same destination in code:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { serve } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/bdk&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
5
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> serve</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dev</span></span></code></pre></div><p>Metrics use delta temporality by default. For Grafana Cloud, set <code>OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE</code> to <code>cumulative</code>. Grafana Cloud rejects delta metrics.</p><p>The default protocol is OTLP/HTTP protobuf. If you already call <code>serve()</code> from TypeScript, you can configure the same destination in code:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { serve } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/bdk&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
6
6
  <span class="line"></span>
7
7
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> serve</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;.&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
8
8
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> otel: {</span></span>
@@ -16,7 +16,15 @@ import{_ as e,c as t,o as a,a3 as i}from"./chunks/framework.BNw1pucY.js";const k
16
16
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
17
17
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ],</span></span>
18
18
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
19
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>Use environment variables when you start the agent with <code>bdk serve</code>. Use <code>serve({ otel })</code> when your TypeScript application starts the server itself. When that application already uses OpenTelemetry, BDK sends its traces, metrics, and logs to the collector configured here.</p><h2 id="follow-one-conversation" tabindex="-1">Follow one conversation <a class="header-anchor" href="#follow-one-conversation" aria-label="Permalink to &quot;Follow one conversation&quot;">​</a></h2><p>Copy the complete session ID from the playground or session API, then filter your observability system on either <code>agent_sdk.session_id</code> or <code>cursor.conversation.id</code>. Every turn in that conversation carries the same value, including follow-ups and tool work.</p><p>The trace shape stays small:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>request: agent_sdk.http</span></span>
19
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>Use environment variables when you start the agent with <code>bdk serve</code>. Use <code>serve({ otel })</code> when your TypeScript application starts the server itself. When that application already uses OpenTelemetry, BDK sends its traces, metrics, and logs to the collector configured here.</p><h2 id="export-from-a-hosted-agent" tabindex="-1">Export from a hosted agent <a class="header-anchor" href="#export-from-a-hosted-agent" aria-label="Permalink to &quot;Export from a hosted agent&quot;">​</a></h2><p>Set the collector endpoint and headers as secrets, and add the collector host to <code>hosting.egressDomains</code>. The host is a hostname with no scheme and no path. The first request loads the secrets, and export starts with those headers.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// bot/agent.ts</span></span>
20
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineAgent } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/bdk&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
21
+ <span class="line"></span>
22
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineAgent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
23
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> hosting: {</span></span>
24
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> egressDomains: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;otlp-gateway-prod-us-east-0.grafana.net&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
25
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> secretNames: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;OTEL_EXPORTER_OTLP_ENDPOINT&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;OTEL_EXPORTER_OTLP_HEADERS&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
26
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
27
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> secrets</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> set</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> my-agent</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> OTEL_EXPORTER_OTLP_ENDPOINT</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> OTEL_EXPORTER_OTLP_HEADERS</span></span></code></pre></div><p><code>OTEL_EXPORTER_OTLP_HEADERS</code> is a comma-separated list of <code>name=value</code> pairs. Each value is URL-encoded, so a space is <code>%20</code> (<code>Authorization=Basic%20...</code>).</p><p>A later <code>bdk secrets set</code> changes the headers on the next export. You do not redeploy to rotate a token. The URL, service name, resource attributes, signals, sample ratio, metric export interval, and metrics temporality stay as they were on the first export. Redeploy to change one of those. BDK logs a warning when one of them changes on a running agent.</p><p>When an exporter host is missing from <code>hosting.egressDomains</code>, BDK logs an error that names the host. Add the host and redeploy.</p><p>Spans and metrics from before the first request are not exported, including spans from channel <code>onStart</code>. If the OpenTelemetry config fails, BDK logs the error and the request still completes.</p><p>Logs stay off until <code>serve({ otel })</code> sets <code>logs</code>, or until <code>OTEL_LOGS_EXPORTER</code> is <code>otlp</code>. Prompt text and tool payloads stay off until you set <code>OTEL_LOG_USER_PROMPTS</code> or <code>OTEL_LOG_TOOL_CONTENT</code>.</p><h2 id="follow-one-conversation" tabindex="-1">Follow one conversation <a class="header-anchor" href="#follow-one-conversation" aria-label="Permalink to &quot;Follow one conversation&quot;">​</a></h2><p>Copy the complete session ID from the playground or session API, then filter your observability system on either <code>agent_sdk.session_id</code> or <code>cursor.conversation.id</code>. Every turn in that conversation carries the same value, including follow-ups and tool work.</p><p>The trace shape stays small:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>request: agent_sdk.http</span></span>
20
28
  <span class="line"><span></span></span>
21
29
  <span class="line"><span>turn: agent_sdk.turn</span></span>
22
30
  <span class="line"><span> |- agent_sdk.tool</span></span>
@@ -32,6 +40,6 @@ import{_ as e,c as t,o as a,a3 as i}from"./chunks/framework.BNw1pucY.js";const k
32
40
  <span class="line"></span>
33
41
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">ctx.host.otel.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">record</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;support.approval.duration_ms&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1420</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
34
42
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> outcome: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;approved&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
35
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>This API is available in tools, hooks, and channel handlers. A session-bound context adds <code>cursor.conversation.id</code> and <code>agent_sdk.agent</code> automatically, so custom measurements join the first-party telemetry without extra plumbing.</p><p>Prefix custom names with your team or agent. First-party metric names and join keys are reserved, and this surface does not create custom spans.</p><h2 id="choose-signals" tabindex="-1">Choose signals <a class="header-anchor" href="#choose-signals" aria-label="Permalink to &quot;Choose signals&quot;">​</a></h2><p>Once export has a destination, traces and metrics are on by default; logs remain off until you opt in.</p><table tabindex="0"><thead><tr><th>Signal</th><th>What appears</th></tr></thead><tbody><tr><td>Traces</td><td>HTTP requests, turns, tools, and subagents</td></tr><tr><td>Metrics</td><td>Token usage, tool calls, cost, and BDK session or turn counts</td></tr><tr><td>Logs</td><td>Session events, after you enable log export</td></tr></tbody></table><p>The first metrics to look for are <code>cursor.token.usage</code>, <code>cursor.tool.calls</code>, and <code>cursor.cost.usage</code>. Configure <code>traces: false</code>, <code>metrics: false</code>, or <code>logs: true</code> under <code>serve({ otel })</code> when you need a different signal mix.</p><h2 id="control-what-leaves-the-process" tabindex="-1">Control what leaves the process <a class="header-anchor" href="#control-what-leaves-the-process" aria-label="Permalink to &quot;Control what leaves the process&quot;">​</a></h2><p>Traces include structure, tool names, usage metrics, and span status. A failed tool&#39;s status includes a short failure reason. A tool or subagent that is still open when the turn ends gets ERROR status with the reason <code>no result</code>. User prompts, tool arguments, and full tool results stay off the wire until you opt in.</p><p>Turn on logs first, then opt into prompt or tool content separately:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> OTEL_LOGS_EXPORTER</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">otlp</span></span>
43
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>This API is available in tools, hooks, and channel handlers. A session-bound context adds <code>cursor.conversation.id</code> and <code>agent_sdk.agent</code> automatically, so custom measurements join the first-party telemetry without extra plumbing.</p><p>Prefix custom names with your team or agent. First-party metric names and join keys are reserved, and this surface does not create custom spans.</p><h2 id="choose-signals" tabindex="-1">Choose signals <a class="header-anchor" href="#choose-signals" aria-label="Permalink to &quot;Choose signals&quot;">​</a></h2><p>Once export has a destination, traces and metrics are on by default; logs remain off until you opt in.</p><table tabindex="0"><thead><tr><th>Signal</th><th>What appears</th></tr></thead><tbody><tr><td>Traces</td><td>HTTP requests, turns, tools, and subagents</td></tr><tr><td>Metrics</td><td>Token usage, tool calls, cost, and BDK session or turn counts</td></tr><tr><td>Logs</td><td>Session events, after you enable log export</td></tr></tbody></table><p>The first metrics to look for are <code>cursor.token.usage</code>, <code>cursor.tool.calls</code>, and <code>cursor.cost.usage</code>. Configure <code>traces: false</code>, <code>metrics: false</code>, or <code>logs: true</code> under <code>serve({ otel })</code> when you need a different signal mix.</p><h2 id="control-what-leaves-the-process" tabindex="-1">Control what leaves the process <a class="header-anchor" href="#control-what-leaves-the-process" aria-label="Permalink to &quot;Control what leaves the process&quot;">​</a></h2><p>Traces include structure, tool names, usage metrics, and span status. A failed tool&#39;s span status and its <code>action.result</code> log include a short failure reason. A tool or subagent that is still open when the turn ends gets ERROR status with the reason <code>no result</code>. User prompts, tool arguments, and full tool results stay off the wire until you opt in.</p><p>Turn on logs first, then opt into prompt or tool content separately:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> OTEL_LOGS_EXPORTER</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">otlp</span></span>
36
44
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> OTEL_LOG_USER_PROMPTS</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span></span>
37
- <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> OTEL_LOG_TOOL_CONTENT</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span></span></code></pre></div><p><code>OTEL_LOG_USER_PROMPTS</code> exports user text. <code>OTEL_LOG_TOOL_CONTENT</code> exports tool inputs, outputs, and failure details. Enable either only when the collector&#39;s access and retention policies are appropriate for that data.</p><p>The same controls are available as <code>logs: { userPrompts, toolContent }</code> under <code>serve({ otel })</code>.</p><h2 id="related" tabindex="-1">Related <a class="header-anchor" href="#related" aria-label="Permalink to &quot;Related&quot;">​</a></h2><ul><li><a href="./../../skills/otel/SKILL.html"><code>skills/otel/SKILL.md</code></a>: compact configuration and custom-metric reference for coding agents</li><li><a href="./../reference/hooks.html">Hooks</a>: emit domain telemetry from session events</li><li><a href="./../deployment.html">Deployment</a>: set collector endpoints and secrets on hosted or self-hosted agents</li><li><a href="https://cursor.com/docs/enterprise/opentelemetry-export" target="_blank" rel="noreferrer">Cursor enterprise OpenTelemetry Export</a>: send organization-wide Cursor telemetry to the same collector</li></ul>`,38)])])}const E=e(n,[["render",o]]);export{k as __pageData,E as default};
45
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> OTEL_LOG_TOOL_CONTENT</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span></span></code></pre></div><p><code>OTEL_LOG_USER_PROMPTS</code> exports user text. <code>OTEL_LOG_TOOL_CONTENT</code> exports tool inputs, outputs, and failure details. Enable either only when the collector&#39;s access and retention policies are appropriate for that data.</p><p>The same controls are available as <code>logs: { userPrompts, toolContent }</code> under <code>serve({ otel })</code>.</p><h2 id="related" tabindex="-1">Related <a class="header-anchor" href="#related" aria-label="Permalink to &quot;Related&quot;">​</a></h2><ul><li><a href="./../../skills/otel/SKILL.html"><code>skills/otel/SKILL.md</code></a>: compact configuration and custom-metric reference for coding agents</li><li><a href="./../reference/hooks.html">Hooks</a>: emit domain telemetry from session events</li><li><a href="./../deployment.html">Deployment</a>: declare <code>hosting.egressDomains</code> and set collector secrets on a hosted agent</li><li><a href="https://cursor.com/docs/enterprise/opentelemetry-export" target="_blank" rel="noreferrer">Cursor enterprise OpenTelemetry Export</a>: send organization-wide Cursor telemetry to the same collector</li></ul>`,48)])])}const E=e(n,[["render",o]]);export{k as __pageData,E as default};
@@ -1 +1 @@
1
- import{_ as e,c as t,o as a,a3 as i}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"OpenTelemetry","description":"Send agent traces and metrics to an OTLP collector, follow one conversation, and add domain telemetry.","frontmatter":{"title":"OpenTelemetry","description":"Send agent traces and metrics to an OTLP collector, follow one conversation, and add domain telemetry."},"headers":[],"relativePath":"guides/opentelemetry.md","filePath":"guides/opentelemetry.md"}'),n={name:"guides/opentelemetry.md"};function o(l,s,r,p,h,d){return a(),t("div",null,[...s[0]||(s[0]=[i("",38)])])}const E=e(n,[["render",o]]);export{k as __pageData,E as default};
1
+ import{_ as e,c as a,o as t,a3 as i}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"OpenTelemetry","description":"Send agent traces and metrics to an OTLP collector, follow one conversation, and add domain telemetry.","frontmatter":{"title":"OpenTelemetry","description":"Send agent traces and metrics to an OTLP collector, follow one conversation, and add domain telemetry."},"headers":[],"relativePath":"guides/opentelemetry.md","filePath":"guides/opentelemetry.md"}'),n={name:"guides/opentelemetry.md"};function o(l,s,h,p,r,d){return t(),a("div",null,[...s[0]||(s[0]=[i("",48)])])}const E=e(n,[["render",o]]);export{k as __pageData,E as default};
@@ -0,0 +1,60 @@
1
+ import{_ as e,c as i,o as a,a3 as t}from"./chunks/framework.BNw1pucY.js";const c=JSON.parse('{"title":"PagerDuty","description":"Respond to PagerDuty incidents: investigate a page, follow it through acknowledgement and resolution, and ignore your own actions.","frontmatter":{"title":"PagerDuty","description":"Respond to PagerDuty incidents: investigate a page, follow it through acknowledgement and resolution, and ignore your own actions."},"headers":[],"relativePath":"guides/pagerduty.md","filePath":"guides/pagerduty.md"}'),n={name:"guides/pagerduty.md"};function h(l,s,d,p,r,o){return a(),i("div",null,[...s[0]||(s[0]=[t(`<h1 id="pagerduty-agents" tabindex="-1">PagerDuty agents <a class="header-anchor" href="#pagerduty-agents" aria-label="Permalink to &quot;PagerDuty agents&quot;">​</a></h1><p>A PagerDuty agent wakes when an incident triggers, investigates it, and writes what it found back to the incident. <code>pagerdutyChannel()</code> receives PagerDuty&#39;s v3 webhooks, verifies them, and keeps every later event for the same incident in one session, so the agent sees an acknowledgement, a note, or a responder&#39;s reply in the context of the investigation it already started. Every setting has a default read from a well-known secret, so the channel needs no configuration beyond its hooks; see <a href="#connect">Connect</a> for the variables.</p><h2 id="investigate-a-new-incident" tabindex="-1">Investigate a new incident <a class="header-anchor" href="#investigate-a-new-incident" aria-label="Permalink to &quot;Investigate a new incident&quot;">​</a></h2><p>When an incident triggers, the agent starts a turn with the incident&#39;s title, service, urgency, and link. It reads whatever the investigation needs, and with <code>deliverReplies: true</code> its reply is posted as a note on the incident, where the person on call already looks.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// bot/channels/pagerduty.ts</span></span>
2
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defaultPagerDutyAuth, pagerdutyChannel } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/bdk/channels/pagerduty&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
3
+ <span class="line"></span>
4
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pagerdutyChannel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
5
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> deliverReplies: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
6
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onIncident</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
7
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (event.eventType </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;incident.triggered&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
8
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
9
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
10
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
11
+ <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // \`auth\` starts a model turn running as the event&#39;s PagerDuty actor.</span></span>
12
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> auth: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">defaultPagerDutyAuth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(ctx),</span></span>
13
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Investigate PagerDuty incident #\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">event</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">incident</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">number</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">event</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">incident</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">title</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
14
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> context: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Service: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">event</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">incident</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">service</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">summary</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ??</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;unknown&quot;}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
15
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
16
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
17
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>Reply notes are off unless you set <code>deliverReplies: true</code>, so the channel writes nothing to PagerDuty on its own. An agent that writes to PagerDuty through its own path, such as a service that audits each write, leaves it off and posts only what it chooses, from <code>events</code> or <code>ctx.pagerduty</code>.</p><p>With <code>deliverReplies: true</code>, the channel posts each completed reply as a note on the session&#39;s incident, and a short note if a turn fails, using the <code>PAGERDUTY_TOKEN</code> secret. The note goes to the incident in the verified event&#39;s state, so the model never chooses which incident it writes to. Eval runs and agents without a token post nothing. Nothing is posted until the channel knows the agent&#39;s own PagerDuty user (see <a href="#ignore-your-own-actions">Ignore your own actions</a>), because each note comes back as a webhook event that only the echo skip keeps from starting another turn. Handlers you write in <code>events</code> replace the built-in ones.</p><p>Hooks also get <code>ctx.pagerduty</code>, a REST client with the channel&#39;s credentials, for reads and writes of their own:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">onIncident</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
18
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> incident</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ctx.pagerduty.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">getIncident</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event.incident.id);</span></span>
19
+ <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // …</span></span>
20
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">},</span></span></code></pre></div><p>Hosted, the agent also declares PagerDuty&#39;s API host and the token:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// bot/agent.ts</span></span>
21
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineAgent } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/bdk&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
22
+ <span class="line"></span>
23
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineAgent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
24
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> architecture: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;v2&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
25
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> hosting: {</span></span>
26
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> egressDomains: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;api.pagerduty.com&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
27
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> secretNames: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;PAGERDUTY_TOKEN&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
28
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
29
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><h2 id="follow-the-incident-in-one-session" tabindex="-1">Follow the incident in one session <a class="header-anchor" href="#follow-the-incident-in-one-session" aria-label="Permalink to &quot;Follow the incident in one session&quot;">​</a></h2><p>People act on an incident while the agent investigates: someone acknowledges it, adds a note, pulls in a responder, or resolves it. Return a dispatch for those events too, and each one arrives in the session that is already working on the incident, with the earlier findings in context.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">onIncident</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
30
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> followUps</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;incident.acknowledged&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;incident.reassigned&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;incident.resolved&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">];</span></span>
31
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (event.eventType </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;incident.triggered&quot;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &amp;&amp;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">followUps.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">includes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event.eventType)) {</span></span>
32
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
33
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
34
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
35
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> auth: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">defaultPagerDutyAuth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(ctx),</span></span>
36
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`\${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">event</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">eventType</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} by \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">ctx</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">agent</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">?.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">summary</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ??</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;PagerDuty&quot;}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
37
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
38
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">},</span></span>
39
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">onNote</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">note</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
40
+ <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
41
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> auth: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">defaultPagerDutyAuth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(ctx),</span></span>
42
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> message: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`Note on the incident: \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">note</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">content</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
43
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> };</span></span>
44
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">},</span></span></code></pre></div><p>Add these to the same <code>pagerdutyChannel()</code> declaration as the investigation handler.</p><h2 id="ignore-your-own-actions" tabindex="-1">Ignore your own actions <a class="header-anchor" href="#ignore-your-own-actions" aria-label="Permalink to &quot;Ignore your own actions&quot;">​</a></h2><p>PagerDuty sends the agent&#39;s own changes back as webhook events: the note it posted, or an acknowledgement or resolve made through its PagerDuty user. The channel acknowledges those events without running a hook or starting a turn. The same action by a person is still delivered.</p><p>The channel finds the agent&#39;s user in this order, on each delivery:</p><ol><li>The <code>selfUserIds</code> option, when you pass one. Nothing below is used.</li><li>The <code>PAGERDUTY_USER_ID</code> secret: one PagerDuty user id.</li><li>The user <code>PAGERDUTY_TOKEN</code> acts as, which PagerDuty reports at <code>GET /users/me</code>.</li></ol><p>When none of these names a user, echo skip is off. <code>bdk deploy</code> warns while neither <code>PAGERDUTY_USER_ID</code> nor <code>PAGERDUTY_TOKEN</code> is set, and the agent logs a warning when its token names no single user.</p><p>Inference depends on the kind of token:</p><table tabindex="0"><thead><tr><th><code>PAGERDUTY_TOKEN</code></th><th>Inferred user</th></tr></thead><tbody><tr><td>User token REST API key</td><td>The key&#39;s own user</td></tr><tr><td>OAuth user token (Classic User OAuth or Scoped OAuth), written as <code>Bearer &lt;token&gt;</code></td><td>The user who authorized the app</td></tr><tr><td>General access (account-level) REST API key</td><td>The user whose email is exactly <code>PAGERDUTY_FROM_EMAIL</code>, if set</td></tr><tr><td>Scoped OAuth app token (client credentials)</td><td>The user whose email is exactly <code>PAGERDUTY_FROM_EMAIL</code>, if set</td></tr></tbody></table><p>PagerDuty serves <a href="https://developer.pagerduty.com/api-reference/0b6f8b0c3e8d1-get-the-current-user" target="_blank" rel="noreferrer"><code>GET /users/me</code></a> only to a user-level API key or a token from an OAuth flow, not to an account-level key. An app token <a href="https://docs.pagerduty.com/developer/private-apps" target="_blank" rel="noreferrer">acts as the app</a>, not as a user. With either, the channel looks up <code>PAGERDUTY_FROM_EMAIL</code>, the <code>From</code> user the token writes as, through <code>GET /users?query=</code> and uses the one user whose email matches exactly. The inferred id is kept in the agent&#39;s memory for an hour per token, never in agent storage, and an unresolved answer is retried after five minutes. Hosted, the lookup needs <code>api.pagerduty.com</code> (or your <code>PAGERDUTY_API_BASE_URL</code> host) in <code>hosting.egressDomains</code>, the same entry write-backs need.</p><p>A read-only agent with no token sets the id directly:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> secrets</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> set</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> incident-responder</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> PAGERDUTY_USER_ID</span></span></code></pre></div><p><code>PAGERDUTY_USER_ID</code> holds one id because a deployment has one token and so acts as one PagerDuty user. To skip several users, or to keep the id in code, pass <code>selfUserIds</code>:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> pagerdutyChannel</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
45
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> selfUserIds: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;PBOT001&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
46
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onIncident</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">ctx</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ({ auth: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">defaultPagerDutyAuth</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(ctx) }),</span></span>
47
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p><code>selfUserIds: { secretName: &quot;OTHER_NAME&quot; }</code> reads one id from another secret and never falls back to inference.</p><h2 id="events" tabindex="-1">Events <a class="header-anchor" href="#events" aria-label="Permalink to &quot;Events&quot;">​</a></h2><p>Each hook receives one family of v3 events:</p><table tabindex="0"><thead><tr><th>Hook</th><th>Events</th></tr></thead><tbody><tr><td><code>onIncident</code></td><td><code>incident.triggered</code>, <code>.acknowledged</code>, <code>.unacknowledged</code>, <code>.escalated</code>, <code>.reassigned</code>, <code>.delegated</code>, <code>.resolved</code>, <code>.reopened</code>, <code>.priority_updated</code>, <code>.incident_type.changed</code></td></tr><tr><td><code>onNote</code></td><td><code>incident.annotated</code></td></tr><tr><td><code>onResponder</code></td><td><code>incident.responder.added</code>, <code>incident.responder.replied</code></td></tr><tr><td><code>onEvent</code></td><td>Everything else, such as status updates and workflow events</td></tr></tbody></table><p>Without <code>onIncident</code>, a triggered or reopened incident starts a turn and other lifecycle events are acknowledged. Notes, responder events, and the rest are acknowledged until you add their hook. Each hook returns one of three decisions:</p><table tabindex="0"><thead><tr><th>Return</th><th>What happens</th></tr></thead><tbody><tr><td><code>{ auth }</code></td><td>Start or continue a model turn as the event&#39;s actor</td></tr><tr><td><code>{ task }</code></td><td>Acknowledge the webhook, then run host code that may also call <code>send</code></td></tr><tr><td><code>null</code></td><td>Skip the event</td></tr></tbody></table><h2 id="incident-affinity" tabindex="-1">Incident affinity <a class="header-anchor" href="#incident-affinity" aria-label="Permalink to &quot;Incident affinity&quot;">​</a></h2><p>Every event for one incident joins one session, keyed on the incident id. Lifecycle events carry the incident, and notes and responder events name it by reference, so all of them reach the same session.</p><p>A re-trigger after a resolve is a new PagerDuty incident, so it starts a new session. <code>ctx.incidentKey</code> carries the dedup key of the alert that opened an incident (its <code>incident_key</code>, set per alert by a Datadog monitor, a Sentry issue, or a Grafana rule), for an agent that wants to recall what it found the last time the same alert fired.</p><h2 id="connect" tabindex="-1">Connect <a class="header-anchor" href="#connect" aria-label="Permalink to &quot;Connect&quot;">​</a></h2><p>Create a v3 webhook subscription in PagerDuty for the services that should wake the agent, and point it at <code>https://&lt;your-host&gt;/&lt;slug&gt;/v1/channels/pagerduty</code>. Then set the channel&#39;s secrets on the deployment. Locally the same names are environment variables.</p><table tabindex="0"><thead><tr><th>Variable</th><th>Used for</th><th>Override</th></tr></thead><tbody><tr><td><code>PAGERDUTY_WEBHOOK_SECRET</code></td><td>Verifying <code>X-PagerDuty-Signature</code>. Hosted, the platform checks it before any compute starts and answers a bad delivery with <code>401</code></td><td><code>webhookSecret: { secretName }</code></td></tr><tr><td><code>PAGERDUTY_USER_ID</code></td><td>Skipping the agent&#39;s own actions: its PagerDuty user id. Optional when <code>PAGERDUTY_TOKEN</code> names a user</td><td><code>selfUserIds: [ids]</code> or <code>{ secretName }</code></td></tr><tr><td><code>PAGERDUTY_TOKEN</code></td><td>Reply notes (with <code>deliverReplies: true</code>), <code>ctx.pagerduty</code>, and inferring the agent&#39;s user: a REST API key, or an OAuth token as <code>Bearer &lt;token&gt;</code></td><td><code>token: { secretName }</code></td></tr><tr><td><code>PAGERDUTY_FROM_EMAIL</code></td><td>The <code>From</code> user PagerDuty requires for writes made with an account-level key or app token, and the user inferred for those tokens</td><td><code>from: { secretName }</code></td></tr><tr><td><code>PAGERDUTY_API_BASE_URL</code></td><td>The REST host, such as <code>https://api.eu.pagerduty.com</code>. Defaults to <code>https://api.pagerduty.com</code></td><td><code>apiBaseUrl</code></td></tr></tbody></table><p>Set <code>token</code>, <code>from</code>, and <code>apiBaseUrl</code> on <code>pagerdutyChannel()</code>; they cover reply notes, <code>ctx.pagerduty</code>, and inference. <code>createPagerDutyClient()</code> takes the same options for code outside the channel.</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> deploy</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --dir</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> .</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --slug</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> incident-responder</span></span>
48
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> secrets</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> set</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> incident-responder</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> PAGERDUTY_WEBHOOK_SECRET</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> PAGERDUTY_TOKEN</span></span>
49
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> secrets</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> list</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> incident-responder</span></span></code></pre></div><p><code>bdk deploy</code> warns until <code>PAGERDUTY_WEBHOOK_SECRET</code> is set, and until either <code>PAGERDUTY_USER_ID</code> or <code>PAGERDUTY_TOKEN</code> is. The next delivery uses a new value without another deploy.</p><h3 id="several-subscriptions" tabindex="-1">Several subscriptions <a class="header-anchor" href="#several-subscriptions" aria-label="Permalink to &quot;Several subscriptions&quot;">​</a></h3><p>PagerDuty gives each webhook subscription its own signing secret, so an agent fed by several subscriptions (one per service, say) needs all of them. Put them in <code>PAGERDUTY_WEBHOOK_SECRET</code>, one per line:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>&lt;signing secret of subscription 1&gt;</span></span>
50
+ <span class="line"><span>&lt;signing secret of subscription 2&gt;</span></span></code></pre></div><p>A delivery is admitted when any <code>v1=</code> signature in its <code>X-PagerDuty-Signature</code> header matches any line. Each line is trimmed, blank lines are ignored, and a value without a line break is one secret, used as-is. The value holds at most 32 secrets. Past that, every delivery is rejected rather than checked against only some of them.</p><p>Keep the list in a file, since <code>bdk secrets list</code> never shows values, and set it from stdin, which keeps the line breaks:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> secrets</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> set</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> incident-responder</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> PAGERDUTY_WEBHOOK_SECRET</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> pagerduty-webhook-secrets.txt</span></span></code></pre></div><p>Rotate by adding before removing. Add the new secret as a line before PagerDuty starts signing with it, for example before creating the replacement subscription. Remove the old line only once nothing signs with the old secret, for example after deleting the subscription it replaced. While both are live, a delivery signed with either secret verifies, including one whose header carries both signatures. Removing the old line first rejects those deliveries until the new one is added.</p><p>The same format works for every <code>hmacSignatureAuth()</code> secret, including <code>GITHUB_WEBHOOK_SECRET</code> and <code>BITBUCKET_WEBHOOK_SECRET</code>. It needs <code>@cursor/bdk</code> 0.2.25 or later. Earlier versions check the signature again in the agent with the whole value as one secret, so they reject every delivery once the value has a second line.</p><p>Only signature checks read the value as a list. Everywhere else it is used whole: a <code>sharedSecretAuth()</code> header compares the entire value, and a <code>\${NAME}</code> template in an MCP connection&#39;s <code>headers</code> would put the line breaks into the header. Keep a list secret for webhook signing only.</p><p>Until <code>PAGERDUTY_WEBHOOK_SECRET</code> is set, the route accepts only local traffic: loopback deliveries under <code>bdk dev</code>, nothing in production.</p><h2 id="test-locally" tabindex="-1">Test locally <a class="header-anchor" href="#test-locally" aria-label="Permalink to &quot;Test locally&quot;">​</a></h2><p><code>bdk pagerduty replay</code> posts synthesized v3 deliveries for one incident to the running agent, in order. With <code>PAGERDUTY_WEBHOOK_SECRET</code> unset, <code>bdk dev</code> admits them unsigned from loopback; with it set, replay signs them the way PagerDuty does:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> &amp;</span></span>
51
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> pagerduty</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> replay</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --events</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> triggered,acknowledged,annotated,resolved</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
52
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --comment</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;Rolled back the 09:30 deploy.&quot;</span></span></code></pre></div><p>The trigger comes from PagerDuty itself, and the later events come from a person, so each one joins the session the trigger started. Pass an incident id to start another session, <code>--dry-run</code> to print the bodies, or <code>--out fixtures/pagerduty</code> to save them as fixtures for <a href="./../evals.html">evals</a>. <code>bdk pagerduty events</code> lists the channels and the events each accepts.</p><p>To post a real delivery saved from the webhook&#39;s delivery log, sign it with the secret:</p><div class="language-bash vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">bash</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> PAGERDUTY_WEBHOOK_SECRET</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">local-test-secret</span></span>
53
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">bdk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dev</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> &amp;</span></span>
54
+ <span class="line"></span>
55
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">body</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">fixtures/pagerduty/incident-triggered.json</span></span>
56
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">signature</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">openssl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> dgst</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -sha256</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -hmac</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$PAGERDUTY_WEBHOOK_SECRET</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -hex</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> &lt;</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$body</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> |</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> awk</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;{print $NF}&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
57
+ <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">curl</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -X</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> POST</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> http://127.0.0.1:3000/v1/channels/pagerduty</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
58
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -H</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;content-type: application/json&#39;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
59
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> -H</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;x-pagerduty-signature: v1=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$signature</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> \\</span></span>
60
+ <span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> --data-binary</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">$body</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span></span></code></pre></div><p>Set <code>event.agent.id</code> in a saved body to the agent&#39;s own user id to see the delivery skipped as an echo.</p><h2 id="practices" tabindex="-1">Practices <a class="header-anchor" href="#practices" aria-label="Permalink to &quot;Practices&quot;">​</a></h2><ul><li><p>Write back from host code with the incident in channel state or <code>ctx</code>, never from an incident id the model produced.</p></li><li><p>Make sure the agent knows its own user before it acts on incidents, so its own notes and resolves do not wake it again: a user-level token, a <code>PAGERDUTY_FROM_EMAIL</code> with an account-level key, or <code>PAGERDUTY_USER_ID</code>.</p></li><li><p>Scope the webhook subscription to the services the agent responds to; every delivery it sends reaches the channel.</p></li></ul><h2 id="related" tabindex="-1">Related <a class="header-anchor" href="#related" aria-label="Permalink to &quot;Related&quot;">​</a></h2><ul><li><a href="./../reference/channels.html">Channels reference</a>: channel hooks, dispatch decisions, and session behavior</li><li><a href="./webhooks.html">Webhooks and custom channels</a>: direct webhook auth and reply delivery</li><li><a href="./../evals.html">Evals</a>: turn saved PagerDuty payloads into regression fixtures</li></ul>`,63)])])}const E=e(n,[["render",h]]);export{c as __pageData,E as default};
@@ -0,0 +1 @@
1
+ import{_ as e,c as i,o as a,a3 as t}from"./chunks/framework.BNw1pucY.js";const c=JSON.parse('{"title":"PagerDuty","description":"Respond to PagerDuty incidents: investigate a page, follow it through acknowledgement and resolution, and ignore your own actions.","frontmatter":{"title":"PagerDuty","description":"Respond to PagerDuty incidents: investigate a page, follow it through acknowledgement and resolution, and ignore your own actions."},"headers":[],"relativePath":"guides/pagerduty.md","filePath":"guides/pagerduty.md"}'),n={name:"guides/pagerduty.md"};function h(l,s,d,p,r,o){return a(),i("div",null,[...s[0]||(s[0]=[t("",63)])])}const E=e(n,[["render",h]]);export{c as __pageData,E as default};
@@ -1,4 +1,4 @@
1
- import{_ as e,c as i,o as t,a3 as a}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Agent config","description":"defineAgent at bot/agent.ts: the model, local workspace, and programmatic serving.","frontmatter":{"title":"Agent config","description":"defineAgent at bot/agent.ts: the model, local workspace, and programmatic serving."},"headers":[],"relativePath":"reference/agent-config.md","filePath":"reference/agent-config.md"}'),n={name:"reference/agent-config.md"};function o(l,s,d,h,r,p){return t(),i("div",null,[...s[0]||(s[0]=[a(`<h1 id="agent-config" tabindex="-1">Agent config <a class="header-anchor" href="#agent-config" aria-label="Permalink to &quot;Agent config&quot;">​</a></h1><p><code>bot/agent.ts</code> default-exports <code>defineAgent(config)</code>: which model runs the agent and its local harness defaults. Everything is optional on the root agent.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineAgent } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/bdk&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
1
+ import{_ as e,c as t,o as i,a3 as a}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Agent config","description":"defineAgent at bot/agent.ts: the model, local workspace, and programmatic serving.","frontmatter":{"title":"Agent config","description":"defineAgent at bot/agent.ts: the model, local workspace, and programmatic serving."},"headers":[],"relativePath":"reference/agent-config.md","filePath":"reference/agent-config.md"}'),n={name:"reference/agent-config.md"};function o(l,s,d,h,r,p){return i(),t("div",null,[...s[0]||(s[0]=[a(`<h1 id="agent-config" tabindex="-1">Agent config <a class="header-anchor" href="#agent-config" aria-label="Permalink to &quot;Agent config&quot;">​</a></h1><p><code>bot/agent.ts</code> default-exports <code>defineAgent(config)</code>: which model runs the agent and its local harness defaults. Everything is optional on the root agent.</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineAgent } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@cursor/bdk&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
2
2
  <span class="line"></span>
3
3
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineAgent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
4
4
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> model: {</span></span>
@@ -28,7 +28,6 @@ import{_ as e,c as i,o as t,a3 as a}from"./chunks/framework.BNw1pucY.js";const k
28
28
  <span class="line"></span>
29
29
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> handle</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> serve</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;./my-agent&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, {</span></span>
30
30
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> port: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">3000</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
31
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> apiKey: process.env.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">CURSOR_API_KEY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
32
31
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
33
32
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">\`listening on \${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">handle</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">url</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}\`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
34
33
  <span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// handle.callTool(...), handle.dispatchSchedule(&quot;heartbeat&quot;),</span></span>
@@ -1 +1 @@
1
- import{_ as e,c as i,o as t,a3 as a}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Agent config","description":"defineAgent at bot/agent.ts: the model, local workspace, and programmatic serving.","frontmatter":{"title":"Agent config","description":"defineAgent at bot/agent.ts: the model, local workspace, and programmatic serving."},"headers":[],"relativePath":"reference/agent-config.md","filePath":"reference/agent-config.md"}'),n={name:"reference/agent-config.md"};function o(l,s,d,h,r,p){return t(),i("div",null,[...s[0]||(s[0]=[a("",41)])])}const u=e(n,[["render",o]]);export{k as __pageData,u as default};
1
+ import{_ as e,c as t,o as i,a3 as a}from"./chunks/framework.BNw1pucY.js";const k=JSON.parse('{"title":"Agent config","description":"defineAgent at bot/agent.ts: the model, local workspace, and programmatic serving.","frontmatter":{"title":"Agent config","description":"defineAgent at bot/agent.ts: the model, local workspace, and programmatic serving."},"headers":[],"relativePath":"reference/agent-config.md","filePath":"reference/agent-config.md"}'),n={name:"reference/agent-config.md"};function o(l,s,d,h,r,p){return i(),t("div",null,[...s[0]||(s[0]=[a("",41)])])}const u=e(n,[["render",o]]);export{k as __pageData,u as default};
@@ -19,4 +19,4 @@ import{_ as t,c as s,o as a,a3 as n}from"./chunks/framework.BNw1pucY.js";const k
19
19
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
20
20
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }),</span></span>
21
21
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ],</span></span>
22
- <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>The route above is <code>POST /v1/channels/&lt;id&gt;/review</code>. Calls for the same pull request reuse one conversation because they pass the same continuation token.</p><h2 id="route-responses" tabindex="-1">Route responses <a class="header-anchor" href="#route-responses" aria-label="Permalink to &quot;Route responses&quot;">​</a></h2><p>A custom route acknowledges the caller and nothing more. On Cursor-managed hosting, the deployment answers every custom route with <code>202 Accepted</code> and an empty body as soon as the request arrives, then runs the handler. The caller never receives the handler&#39;s <code>Response</code>, so a route can&#39;t return a session ID, a computed result, or an error status. Requests rejected before the handler runs, such as a missing alias token or a failed <code>sharedSecretAuth</code> or <code>hmacSignatureAuth</code> check, still get <code>401</code>.</p><p>Deliver results through the channel&#39;s <a href="#events"><code>events</code></a> handlers, a callback to the system that sent the request, or a tool the turn calls. Local <code>serve</code> passes the handler&#39;s response through, so return <code>new Response(null, { status: 202 })</code> to keep local calls matching hosted ones.</p><h2 id="route-verbs-and-schemas" tabindex="-1">Route verbs and schemas <a class="header-anchor" href="#route-verbs-and-schemas" aria-label="Permalink to &quot;Route verbs and schemas&quot;">​</a></h2><p>Route paths must begin with <code>/</code>. The method helper determines which Zod schemas the route accepts:</p><table tabindex="0"><thead><tr><th>Helper</th><th>Schema contract</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>querySchema</code> is required</td></tr><tr><td><code>POST</code>, <code>PUT</code>, <code>PATCH</code></td><td><code>bodySchema</code> is required; <code>querySchema</code> is optional</td></tr><tr><td><code>DELETE</code></td><td>Both schemas are optional</td></tr></tbody></table><p>Plain JSON Schema objects don&#39;t type-check. Use <code>z.object({})</code> or <code>z.unknown()</code> for an open surface. The host validates the body and query before calling the handler, and an empty body is read as <code>{}</code>. A request that fails validation never reaches the handler; local <code>serve</code> answers it with <code>400</code>, while a hosted caller has already received its <code>202</code>. Declared schemas also appear in <code>GET /v1/info</code> for playground requests and slash commands.</p><h2 id="handler-arguments" tabindex="-1">Handler arguments <a class="header-anchor" href="#handler-arguments" aria-label="Permalink to &quot;Handler arguments&quot;">​</a></h2><p>Each handler receives the Fetch <code>Request</code> and a typed arguments object.</p><table tabindex="0"><thead><tr><th>Member</th><th>Contract</th></tr></thead><tbody><tr><td><code>send(message, options?)</code></td><td>Start or resume a session on this channel</td></tr><tr><td><code>getSession(sessionId)</code></td><td>Return this channel&#39;s session, or <code>null</code></td></tr><tr><td><code>receive(channel, input)</code></td><td>Hand work to another channel</td></tr><tr><td><code>callTool(name, input, options?)</code></td><td><a href="./tools.html#call-a-tool-without-a-model-turn">Call a server tool</a> without a model turn</td></tr><tr><td><code>body</code>, <code>query</code>, <code>params</code></td><td>Validated inputs and <code>:param</code> path segments</td></tr><tr><td><code>auth</code></td><td>The <code>AuthContext</code> returned by the route&#39;s auth chain</td></tr><tr><td><code>requestIp</code></td><td>The TCP peer address, or <code>null</code></td></tr><tr><td><code>host</code></td><td>Shared MCP, provider, storage, telemetry, and reminder services</td></tr><tr><td><code>waitUntil(promise)</code></td><td>Keep work running after the handler returns</td></tr><tr><td><code>sessionUrls(request, sessionId)</code></td><td>Build absolute playground and trace URLs for this mount</td></tr><tr><td><code>artifacts</code></td><td>List or tag <a href="./artifacts.html">artifacts</a>; pass <code>sessionId</code> when attributing one</td></tr></tbody></table><h3 id="send-options" tabindex="-1"><code>send</code> options <a class="header-anchor" href="#send-options" aria-label="Permalink to &quot;\`send\` options&quot;">​</a></h3><table tabindex="0"><thead><tr><th>Option</th><th>Contract</th></tr></thead><tbody><tr><td><code>continuationToken</code></td><td>Resume the session with this channel-local key, or create one when the key is new</td></tr><tr><td><code>admission</code></td><td><code>&quot;preempt&quot;</code> interrupts a busy turn; <code>&quot;coalesce&quot;</code> queues behind it. The default is <code>&quot;preempt&quot;</code></td></tr><tr><td><code>workspaceFiles</code></td><td>Add relative files for the next turn</td></tr><tr><td><code>workspaceDir</code></td><td>Use an absolute local working directory</td></tr><tr><td><code>auth</code></td><td>Set the session principal; defaults to the request principal</td></tr><tr><td><code>state</code></td><td>Set starting channel state for a new session</td></tr><tr><td><code>title</code></td><td>Set the display title for a new session</td></tr><tr><td><code>purpose</code></td><td>Use <code>&quot;eval&quot;</code> to mark a new session as regression traffic</td></tr><tr><td><code>dryRun</code></td><td>Run read tools and stub write tools for a new session</td></tr><tr><td><code>asOf</code></td><td>Freeze a new session at an ISO-8601 instant with a timezone</td></tr></tbody></table><p><code>send</code> returns a <code>ChannelSession</code>. Its <code>id</code> identifies the session, <code>continuationToken</code> contains its current channel key, and <code>isNew</code> says whether this call created it. A coalesced call also returns <code>coalesced: true</code>.</p><h2 id="events" tabindex="-1">Events <a class="header-anchor" href="#events" aria-label="Permalink to &quot;Events&quot;">​</a></h2><p>The <code>events</code> map subscribes the channel to stream events for the sessions it owns. Keys are event types from the <a href="./sessions.html#stream-events">event vocabulary</a>, or <code>&quot;*&quot;</code>. Each handler receives <code>(event, channel, ctx)</code>, including the session&#39;s <code>channel.state</code>, session info, and shared host services. Use these handlers to deliver progress and replies to the surface that owns the channel.</p><h2 id="session-state" tabindex="-1">Session state <a class="header-anchor" href="#session-state" aria-label="Permalink to &quot;Session state&quot;">​</a></h2><p><code>state</code> on the channel definition supplies starting JSON for each new session. A route can instead pass <code>state</code> to <code>send</code>; event handlers read and update the active value through <code>channel.state</code>.</p><h2 id="start-and-stop-a-channel" tabindex="-1">Start and stop a channel <a class="header-anchor" href="#start-and-stop-a-channel" aria-label="Permalink to &quot;Start and stop a channel&quot;">​</a></h2><p><code>onStart(args)</code> runs when the channel mounts, and <code>onStop()</code> runs when the host stops. <code>onStart</code> receives the route helpers plus these transport controls:</p><table tabindex="0"><thead><tr><th>Helper</th><th>Contract</th></tr></thead><tbody><tr><td><code>emitAssistantMessage(sessionId, text)</code></td><td>Append final assistant text without starting a model turn</td></tr><tr><td><code>hasContinuationSession(token)</code></td><td>Check whether a token maps to a session</td></tr><tr><td><code>isContinuationBusy(token)</code></td><td>Check whether a turn is active for a token</td></tr><tr><td><code>interruptContinuation(token)</code></td><td>Stop the active turn and clear queued coalesced follow-ups</td></tr></tbody></table><h2 id="auth-policies" tabindex="-1">Auth policies <a class="header-anchor" href="#auth-policies" aria-label="Permalink to &quot;Auth policies&quot;">​</a></h2><p>Every route runs the channel&#39;s <code>auth</code> array. The default is <code>[localDevStrict()]</code>. Policies may be asynchronous; the first one to return an <code>AuthContext</code> admits the request, and an all-null result returns <code>401</code>.</p><table tabindex="0"><thead><tr><th>Policy</th><th>Admits</th></tr></thead><tbody><tr><td><code>localDevStrict()</code></td><td>Direct loopback requests with a loopback hostname and no proxy-forwarding headers</td></tr><tr><td><code>localDev()</code></td><td>Direct loopback requests with no proxy-forwarding headers, without checking the hostname</td></tr><tr><td><code>loopbackOnly()</code></td><td>Any loopback TCP peer, including local relays that carry forwarding headers</td></tr><tr><td><code>bearerAuth(tokenOrVerify)</code></td><td>A matching bearer token, or a token accepted by the verifier</td></tr><tr><td><code>sharedSecretAuth({ header, secret })</code></td><td>A header matching the named environment or deployment secret</td></tr><tr><td><code>hmacSignatureAuth({ header, secret, prefix? })</code></td><td>A hex HMAC-SHA256 signature over the raw body using the named secret</td></tr><tr><td><code>allowAll()</code></td><td>Every caller as an anonymous principal</td></tr><tr><td><code>publicEndpoint()</code></td><td>Every caller on this custom channel; managed hosting also exposes the route without an alias token</td></tr></tbody></table><p>Use <code>allowAll()</code> only for an intentionally public surface or one protected upstream. With <code>publicEndpoint()</code>, the handler must verify the provider&#39;s signature. The policy applies only to custom channel routes; it doesn&#39;t open the built-in session or tool API.</p><p>The resolved <code>AuthContext</code> (<code>{ authenticator, principalId, principalType, attributes? }</code>) becomes the request principal. Sessions belong to the principal that created them, and other principals receive <code>403</code> on owned routes.</p><p>Server flags interact with authored auth: <code>--bearer-token</code> swaps the default <code>localDevStrict()</code> for <code>bearerAuth(...)</code> on channels that don&#39;t author their own chain, and <code>--allow-anonymous</code> swaps it for <code>allowAll()</code>. An authored <code>auth</code> array always takes precedence.</p><h2 id="prebuilt-channels" tabindex="-1">Prebuilt channels <a class="header-anchor" href="#prebuilt-channels" aria-label="Permalink to &quot;Prebuilt channels&quot;">​</a></h2><table tabindex="0"><thead><tr><th>Import</th><th>Function</th><th>Surface</th></tr></thead><tbody><tr><td><code>@cursor/bdk/channels/slack</code></td><td><code>slackChannel()</code></td><td>Slack messages, threads, and streaming replies. See <a href="./../guides/slack.html">Slack</a></td></tr><tr><td><code>@cursor/bdk/channels/github</code></td><td><code>githubChannel()</code></td><td>GitHub and GitHub Enterprise webhooks. See <a href="./../guides/github.html">GitHub</a></td></tr><tr><td><code>@cursor/bdk/channels/gitlab</code></td><td><code>gitlabChannel()</code></td><td>GitLab.com and self-managed GitLab hooks. See <a href="./../guides/gitlab.html">GitLab</a></td></tr><tr><td><code>@cursor/bdk/channels/bitbucket</code></td><td><code>bitbucketChannel()</code></td><td>Bitbucket Cloud and Data Center hooks. See <a href="./../guides/bitbucket.html">Bitbucket</a></td></tr><tr><td><code>@cursor/bdk/channels/deployments</code></td><td><code>deploymentsChannel()</code></td><td>Deployment events filtered by source, environment, or event name</td></tr></tbody></table><p>For other platforms like Discord or Teams, use the authored <code>defineChannel</code> route form.</p><h2 id="continuation-tokens" tabindex="-1">Continuation tokens <a class="header-anchor" href="#continuation-tokens" aria-label="Permalink to &quot;Continuation tokens&quot;">​</a></h2><p>Each channel defines its continuation-token format. The same token resumes the same conversation; the built-in HTTP channel rotates its opaque token after every accepted follow-up and returns <code>409</code> for a stale token. See <a href="./sessions.html#session-identifiers">Session identifiers</a> for the full contract.</p><h2 id="related" tabindex="-1">Related <a class="header-anchor" href="#related" aria-label="Permalink to &quot;Related&quot;">​</a></h2><ul><li><a href="./../guides/webhooks.html">Webhooks</a></li><li><a href="./http-api.html">HTTP API</a></li><li><a href="./sessions.html">Sessions</a></li><li><a href="./hooks.html">Hooks</a></li></ul>`,41)])])}const u=t(i,[["render",o]]);export{k as __pageData,u as default};
22
+ <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span></code></pre></div><p>The route above is <code>POST /v1/channels/&lt;id&gt;/review</code>. Calls for the same pull request reuse one conversation because they pass the same continuation token.</p><h2 id="route-responses" tabindex="-1">Route responses <a class="header-anchor" href="#route-responses" aria-label="Permalink to &quot;Route responses&quot;">​</a></h2><p>A custom route acknowledges the caller and nothing more. On Cursor-managed hosting, the deployment answers every custom route with <code>202 Accepted</code> and an empty body as soon as the request arrives, then runs the handler. The caller never receives the handler&#39;s <code>Response</code>, so a route can&#39;t return a session ID, a computed result, or an error status. Requests rejected before the handler runs, such as a missing alias token or a failed <code>sharedSecretAuth</code> or <code>hmacSignatureAuth</code> check, still get <code>401</code>.</p><p>Deliver results through the channel&#39;s <a href="#events"><code>events</code></a> handlers, a callback to the system that sent the request, or a tool the turn calls. Local <code>serve</code> passes the handler&#39;s response through, so return <code>new Response(null, { status: 202 })</code> to keep local calls matching hosted ones.</p><h2 id="route-verbs-and-schemas" tabindex="-1">Route verbs and schemas <a class="header-anchor" href="#route-verbs-and-schemas" aria-label="Permalink to &quot;Route verbs and schemas&quot;">​</a></h2><p>Route paths must begin with <code>/</code>. The method helper determines which Zod schemas the route accepts:</p><table tabindex="0"><thead><tr><th>Helper</th><th>Schema contract</th></tr></thead><tbody><tr><td><code>GET</code></td><td><code>querySchema</code> is required</td></tr><tr><td><code>POST</code>, <code>PUT</code>, <code>PATCH</code></td><td><code>bodySchema</code> is required; <code>querySchema</code> is optional</td></tr><tr><td><code>DELETE</code></td><td>Both schemas are optional</td></tr></tbody></table><p>Plain JSON Schema objects don&#39;t type-check. Use <code>z.object({})</code> or <code>z.unknown()</code> for an open surface. The host validates the body and query before calling the handler, and an empty body is read as <code>{}</code>. A request that fails validation never reaches the handler; local <code>serve</code> answers it with <code>400</code>, while a hosted caller has already received its <code>202</code>. Declared schemas also appear in <code>GET /v1/info</code> for playground requests and slash commands.</p><h2 id="handler-arguments" tabindex="-1">Handler arguments <a class="header-anchor" href="#handler-arguments" aria-label="Permalink to &quot;Handler arguments&quot;">​</a></h2><p>Each handler receives the Fetch <code>Request</code> and a typed arguments object.</p><table tabindex="0"><thead><tr><th>Member</th><th>Contract</th></tr></thead><tbody><tr><td><code>send(message, options?)</code></td><td>Start or resume a session on this channel</td></tr><tr><td><code>getSession(sessionId)</code></td><td>Return this channel&#39;s session, or <code>null</code></td></tr><tr><td><code>receive(channel, input)</code></td><td>Hand work to another channel</td></tr><tr><td><code>callTool(name, input, options?)</code></td><td><a href="./tools.html#call-a-tool-without-a-model-turn">Call a server tool</a> without a model turn</td></tr><tr><td><code>body</code>, <code>query</code>, <code>params</code></td><td>Validated inputs and <code>:param</code> path segments</td></tr><tr><td><code>auth</code></td><td>The <code>AuthContext</code> returned by the route&#39;s auth chain</td></tr><tr><td><code>requestIp</code></td><td>The TCP peer address, or <code>null</code></td></tr><tr><td><code>host</code></td><td>Shared MCP, provider, storage, telemetry, and reminder services</td></tr><tr><td><code>waitUntil(promise)</code></td><td>Keep work running after the handler returns</td></tr><tr><td><code>sessionUrls(request, sessionId)</code></td><td>Build absolute playground and trace URLs for this mount</td></tr><tr><td><code>artifacts</code></td><td>List or tag <a href="./artifacts.html">artifacts</a>; pass <code>sessionId</code> when attributing one</td></tr></tbody></table><h3 id="send-options" tabindex="-1"><code>send</code> options <a class="header-anchor" href="#send-options" aria-label="Permalink to &quot;\`send\` options&quot;">​</a></h3><table tabindex="0"><thead><tr><th>Option</th><th>Contract</th></tr></thead><tbody><tr><td><code>continuationToken</code></td><td>Resume the session with this channel-local key, or create one when the key is new</td></tr><tr><td><code>admission</code></td><td><code>&quot;preempt&quot;</code> interrupts a busy turn; <code>&quot;coalesce&quot;</code> queues behind it. The default is <code>&quot;preempt&quot;</code></td></tr><tr><td><code>workspaceFiles</code></td><td>Add relative files for the next turn</td></tr><tr><td><code>workspaceDir</code></td><td>Use an absolute local working directory</td></tr><tr><td><code>auth</code></td><td>Set the session principal; defaults to the request principal</td></tr><tr><td><code>state</code></td><td>Set starting channel state for a new session</td></tr><tr><td><code>title</code></td><td>Set the display title for a new session</td></tr><tr><td><code>purpose</code></td><td>Use <code>&quot;eval&quot;</code> to mark a new session as regression traffic</td></tr><tr><td><code>dryRun</code></td><td>Run read tools and stub write tools for a new session</td></tr><tr><td><code>asOf</code></td><td>Freeze a new session at an ISO-8601 instant with a timezone</td></tr></tbody></table><p><code>send</code> returns a <code>ChannelSession</code>. Its <code>id</code> identifies the session, <code>continuationToken</code> contains its current channel key, and <code>isNew</code> says whether this call created it. A coalesced call also returns <code>coalesced: true</code>.</p><h2 id="events" tabindex="-1">Events <a class="header-anchor" href="#events" aria-label="Permalink to &quot;Events&quot;">​</a></h2><p>The <code>events</code> map subscribes the channel to stream events for the sessions it owns. Keys are event types from the <a href="./sessions.html#stream-events">event vocabulary</a>, or <code>&quot;*&quot;</code>. Each handler receives <code>(event, channel, ctx)</code>, including the session&#39;s <code>channel.state</code>, session info, and shared host services. Use these handlers to deliver progress and replies to the surface that owns the channel.</p><h2 id="session-state" tabindex="-1">Session state <a class="header-anchor" href="#session-state" aria-label="Permalink to &quot;Session state&quot;">​</a></h2><p><code>state</code> on the channel definition supplies starting JSON for each new session. A route can instead pass <code>state</code> to <code>send</code>; event handlers read and update the active value through <code>channel.state</code>.</p><h2 id="start-and-stop-a-channel" tabindex="-1">Start and stop a channel <a class="header-anchor" href="#start-and-stop-a-channel" aria-label="Permalink to &quot;Start and stop a channel&quot;">​</a></h2><p><code>onStart(args)</code> runs when the channel mounts, and <code>onStop()</code> runs when the host stops. <code>onStart</code> receives the route helpers plus these transport controls:</p><table tabindex="0"><thead><tr><th>Helper</th><th>Contract</th></tr></thead><tbody><tr><td><code>emitAssistantMessage(sessionId, text)</code></td><td>Append final assistant text without starting a model turn</td></tr><tr><td><code>hasContinuationSession(token)</code></td><td>Check whether a token maps to a session</td></tr><tr><td><code>isContinuationBusy(token)</code></td><td>Check whether a turn is active for a token</td></tr><tr><td><code>interruptContinuation(token)</code></td><td>Stop the active turn and clear queued coalesced follow-ups</td></tr></tbody></table><h2 id="auth-policies" tabindex="-1">Auth policies <a class="header-anchor" href="#auth-policies" aria-label="Permalink to &quot;Auth policies&quot;">​</a></h2><p>Every route runs the channel&#39;s <code>auth</code> array. The default is <code>[localDevStrict()]</code>. Policies may be asynchronous; the first one to return an <code>AuthContext</code> admits the request, and an all-null result returns <code>401</code>.</p><table tabindex="0"><thead><tr><th>Policy</th><th>Admits</th></tr></thead><tbody><tr><td><code>localDevStrict()</code></td><td>Direct loopback requests with a loopback hostname and no proxy-forwarding headers</td></tr><tr><td><code>localDev()</code></td><td>Direct loopback requests with no proxy-forwarding headers, without checking the hostname</td></tr><tr><td><code>loopbackOnly()</code></td><td>Any loopback TCP peer, including local relays that carry forwarding headers</td></tr><tr><td><code>bearerAuth(tokenOrVerify)</code></td><td>A matching bearer token, or a token accepted by the verifier</td></tr><tr><td><code>sharedSecretAuth({ header, secret })</code></td><td>A header matching the named environment or deployment secret</td></tr><tr><td><code>hmacSignatureAuth({ header, secret, prefix?, separator? })</code></td><td>A hex HMAC-SHA256 signature over the raw body using the named secret. With <code>separator</code>, any of several signatures in the header. A secret holding one value per line verifies under any of them (at most 32, <code>@cursor/bdk</code> 0.2.25 or later)</td></tr><tr><td><code>allowAll()</code></td><td>Every caller as an anonymous principal</td></tr><tr><td><code>publicEndpoint()</code></td><td>Every caller on this custom channel; managed hosting also exposes the route without an alias token</td></tr></tbody></table><p>Use <code>allowAll()</code> only for an intentionally public surface or one protected upstream. With <code>publicEndpoint()</code>, the handler must verify the provider&#39;s signature. The policy applies only to custom channel routes; it doesn&#39;t open the built-in session or tool API.</p><p>The resolved <code>AuthContext</code> (<code>{ authenticator, principalId, principalType, attributes? }</code>) becomes the request principal. Sessions belong to the principal that created them, and other principals receive <code>403</code> on owned routes.</p><p>Server flags interact with authored auth: <code>--bearer-token</code> swaps the default <code>localDevStrict()</code> for <code>bearerAuth(...)</code> on channels that don&#39;t author their own chain, and <code>--allow-anonymous</code> swaps it for <code>allowAll()</code>. An authored <code>auth</code> array always takes precedence.</p><h2 id="prebuilt-channels" tabindex="-1">Prebuilt channels <a class="header-anchor" href="#prebuilt-channels" aria-label="Permalink to &quot;Prebuilt channels&quot;">​</a></h2><table tabindex="0"><thead><tr><th>Import</th><th>Function</th><th>Surface</th></tr></thead><tbody><tr><td><code>@cursor/bdk/channels/slack</code></td><td><code>slackChannel()</code></td><td>Slack messages, threads, and streaming replies. See <a href="./../guides/slack.html">Slack</a></td></tr><tr><td><code>@cursor/bdk/channels/github</code></td><td><code>githubChannel()</code></td><td>GitHub and GitHub Enterprise webhooks. See <a href="./../guides/github.html">GitHub</a></td></tr><tr><td><code>@cursor/bdk/channels/gitlab</code></td><td><code>gitlabChannel()</code></td><td>GitLab.com and self-managed GitLab hooks. See <a href="./../guides/gitlab.html">GitLab</a></td></tr><tr><td><code>@cursor/bdk/channels/bitbucket</code></td><td><code>bitbucketChannel()</code></td><td>Bitbucket Cloud and Data Center hooks. See <a href="./../guides/bitbucket.html">Bitbucket</a></td></tr><tr><td><code>@cursor/bdk/channels/pagerduty</code></td><td><code>pagerdutyChannel()</code></td><td>PagerDuty v3 incident webhooks. Replies post as incident notes only with <code>deliverReplies: true</code>. See <a href="./../guides/pagerduty.html">PagerDuty</a></td></tr><tr><td><code>@cursor/bdk/channels/deployments</code></td><td><code>deploymentsChannel()</code></td><td>Deployment events filtered by source, environment, or event name</td></tr></tbody></table><p>For other platforms like Discord or Teams, use the authored <code>defineChannel</code> route form.</p><h2 id="continuation-tokens" tabindex="-1">Continuation tokens <a class="header-anchor" href="#continuation-tokens" aria-label="Permalink to &quot;Continuation tokens&quot;">​</a></h2><p>Each channel defines its continuation-token format. The same token resumes the same conversation; the built-in HTTP channel rotates its opaque token after every accepted follow-up and returns <code>409</code> for a stale token. See <a href="./sessions.html#session-identifiers">Session identifiers</a> for the full contract.</p><h2 id="related" tabindex="-1">Related <a class="header-anchor" href="#related" aria-label="Permalink to &quot;Related&quot;">​</a></h2><ul><li><a href="./../guides/webhooks.html">Webhooks</a></li><li><a href="./http-api.html">HTTP API</a></li><li><a href="./sessions.html">Sessions</a></li><li><a href="./hooks.html">Hooks</a></li></ul>`,41)])])}const u=t(i,[["render",o]]);export{k as __pageData,u as default};