@cursor/july 0.1.42 → 0.1.45

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 (223) hide show
  1. package/AGENTS.md +1 -0
  2. package/dist/bin/agent-serve.js +3 -1
  3. package/dist/channels/github/api.d.ts +5 -0
  4. package/dist/channels/github/api.d.ts.map +1 -1
  5. package/dist/channels/github/api.js +18 -0
  6. package/dist/channels/github/defaults.d.ts +4 -5
  7. package/dist/channels/github/defaults.d.ts.map +1 -1
  8. package/dist/channels/github/defaults.js +27 -1
  9. package/dist/channels/github/github-channel.d.ts.map +1 -1
  10. package/dist/channels/github/github-channel.js +41 -10
  11. package/dist/channels/github/index.d.ts +1 -0
  12. package/dist/channels/github/index.d.ts.map +1 -1
  13. package/dist/channels/github/index.js +1 -0
  14. package/dist/channels/github/progress.d.ts +54 -0
  15. package/dist/channels/github/progress.d.ts.map +1 -0
  16. package/dist/channels/github/progress.js +168 -0
  17. package/dist/channels/github/state.d.ts +2 -0
  18. package/dist/channels/github/state.d.ts.map +1 -1
  19. package/dist/channels/github/state.js +1 -1
  20. package/dist/channels/github/types.d.ts +16 -4
  21. package/dist/channels/github/types.d.ts.map +1 -1
  22. package/dist/channels/slack/slack-channel.d.ts +4 -0
  23. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  24. package/dist/channels/slack/slack-channel.js +4 -0
  25. package/dist/channels.d.ts +17 -0
  26. package/dist/channels.d.ts.map +1 -1
  27. package/dist/channels.js +31 -0
  28. package/dist/docs/404.html +2 -2
  29. package/dist/docs/ab.html +4 -4
  30. package/dist/docs/assets/{app.C4-Gwi7g.js → app.fHnNXEJ6.js} +1 -1
  31. package/dist/docs/assets/chunks/@localSearchIndexroot.BMT0xM4I.js +1 -0
  32. package/dist/docs/assets/chunks/{VPLocalSearchBox.DDoLm843.js → VPLocalSearchBox.Cf6ghfFY.js} +1 -1
  33. package/dist/docs/assets/chunks/{theme.SbjGIiM0.js → theme.B_5-VLe8.js} +2 -2
  34. package/dist/docs/assets/{deployment.md.BHVjVqRa.js → deployment.md.Cdp4rTE4.js} +1 -1
  35. package/dist/docs/assets/{guides_github.md.R2QlpR75.js → guides_github.md.DSg0j9qj.js} +29 -3
  36. package/dist/docs/assets/{guides_github.md.R2QlpR75.lean.js → guides_github.md.DSg0j9qj.lean.js} +1 -1
  37. package/dist/docs/assets/guides_opentelemetry.md.Csn7ZI25.js +27 -0
  38. package/dist/docs/assets/guides_opentelemetry.md.Csn7ZI25.lean.js +1 -0
  39. package/dist/docs/assets/index.md.COeoSkcF.js +5 -0
  40. package/dist/docs/assets/index.md.COeoSkcF.lean.js +1 -0
  41. package/dist/docs/assets/{quickstart.md.rIbfahJM.js → quickstart.md.DZxBu44y.js} +18 -49
  42. package/dist/docs/assets/quickstart.md.DZxBu44y.lean.js +1 -0
  43. package/dist/docs/assets/{reference_agent-config.md.CRmkoxd6.js → reference_agent-config.md.XRpxctsA.js} +9 -4
  44. package/dist/docs/assets/{reference_agent-config.md.CRmkoxd6.lean.js → reference_agent-config.md.XRpxctsA.lean.js} +1 -1
  45. package/dist/docs/assets/{reference_channels.md.BIabFUAI.js → reference_channels.md.MN8iDy8V.js} +1 -1
  46. package/dist/docs/assets/{reference_cli.md.DqEqQpGn.js → reference_cli.md.BDmjPPAm.js} +2 -2
  47. package/dist/docs/assets/{reference_hooks.md.B40QAG6m.js → reference_hooks.md.4cbRRIIu.js} +2 -2
  48. package/dist/docs/assets/{reference_hooks.md.B40QAG6m.lean.js → reference_hooks.md.4cbRRIIu.lean.js} +1 -1
  49. package/dist/docs/assets/{reference_project-layout.md._XdeMahr.js → reference_project-layout.md.D3MdHM2z.js} +2 -1
  50. package/dist/docs/assets/{reference_tools.md.lSrsTxYJ.js → reference_tools.md.kJfJAP2m.js} +1 -1
  51. package/dist/docs/assets/templates_triage.md.CConZt1z.js +11 -0
  52. package/dist/docs/assets/templates_triage.md.CConZt1z.lean.js +1 -0
  53. package/dist/docs/building-with-agents.html +5 -5
  54. package/dist/docs/concepts.html +5 -5
  55. package/dist/docs/deployment.html +6 -6
  56. package/dist/docs/evals.html +4 -4
  57. package/dist/docs/example-agents/approval-buddy.html +4 -4
  58. package/dist/docs/example-agents/benny.html +4 -4
  59. package/dist/docs/example-agents/bugbot.html +4 -4
  60. package/dist/docs/example-agents/codebase-wiki.html +4 -4
  61. package/dist/docs/example-agents/codeowners-review.html +4 -4
  62. package/dist/docs/example-agents/concierge.html +4 -4
  63. package/dist/docs/example-agents/fsd.html +4 -4
  64. package/dist/docs/example-agents/index.html +5 -5
  65. package/dist/docs/example-agents/knowledge-base.html +4 -4
  66. package/dist/docs/example-agents/oncall.html +4 -4
  67. package/dist/docs/example-agents/security-reviewer.html +4 -4
  68. package/dist/docs/example-agents/slack-agent.html +4 -4
  69. package/dist/docs/example-agents/weather-agent.html +4 -4
  70. package/dist/docs/guides/agent-to-agent.html +4 -4
  71. package/dist/docs/guides/cloud-runtime.html +5 -5
  72. package/dist/docs/guides/github.html +33 -7
  73. package/dist/docs/guides/human-in-the-loop.html +4 -4
  74. package/dist/docs/guides/mcp-oauth.html +4 -4
  75. package/dist/docs/guides/opentelemetry.html +51 -0
  76. package/dist/docs/guides/slack.html +4 -4
  77. package/dist/docs/guides/webhooks.html +4 -4
  78. package/dist/docs/hashmap.json +1 -1
  79. package/dist/docs/hillclimbing.html +4 -4
  80. package/dist/docs/index.html +8 -27
  81. package/dist/docs/quickstart.html +24 -55
  82. package/dist/docs/reference/agent-config.html +12 -7
  83. package/dist/docs/reference/artifacts.html +4 -4
  84. package/dist/docs/reference/channels.html +6 -6
  85. package/dist/docs/reference/cli.html +7 -7
  86. package/dist/docs/reference/connections.html +4 -4
  87. package/dist/docs/reference/hooks.html +6 -6
  88. package/dist/docs/reference/http-api.html +4 -4
  89. package/dist/docs/reference/instructions.html +4 -4
  90. package/dist/docs/reference/playground.html +4 -4
  91. package/dist/docs/reference/project-layout.html +7 -6
  92. package/dist/docs/reference/prompt.html +4 -4
  93. package/dist/docs/reference/schedules.html +4 -4
  94. package/dist/docs/reference/sessions.html +4 -4
  95. package/dist/docs/reference/skills.html +4 -4
  96. package/dist/docs/reference/subagents.html +4 -4
  97. package/dist/docs/reference/tools.html +6 -6
  98. package/dist/docs/scaffolding-agents.html +4 -4
  99. package/dist/docs/storage.html +4 -4
  100. package/dist/docs/templates/triage.html +35 -0
  101. package/dist/docs/troubleshooting.html +4 -4
  102. package/dist/index.d.ts +3 -1
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +2 -1
  105. package/dist/internal/cli-ax.d.ts +1 -0
  106. package/dist/internal/cli-ax.d.ts.map +1 -1
  107. package/dist/internal/cli-ax.js +20 -5
  108. package/dist/internal/cli-deploy.d.ts.map +1 -1
  109. package/dist/internal/cli-deploy.js +38 -7
  110. package/dist/internal/deploy-client.d.ts +8 -0
  111. package/dist/internal/deploy-client.d.ts.map +1 -1
  112. package/dist/internal/deploy-client.js +5 -2
  113. package/dist/internal/discovery.d.ts.map +1 -1
  114. package/dist/internal/discovery.js +82 -13
  115. package/dist/internal/distribution.d.ts.map +1 -1
  116. package/dist/internal/distribution.js +1 -0
  117. package/dist/internal/host-otel.d.ts +25 -0
  118. package/dist/internal/host-otel.d.ts.map +1 -0
  119. package/dist/internal/host-otel.js +162 -0
  120. package/dist/internal/init-project.d.ts +24 -0
  121. package/dist/internal/init-project.d.ts.map +1 -1
  122. package/dist/internal/init-project.js +136 -17
  123. package/dist/internal/otel/attrs.d.ts +7 -0
  124. package/dist/internal/otel/attrs.d.ts.map +1 -0
  125. package/dist/internal/otel/attrs.js +13 -0
  126. package/dist/internal/otel/collector.d.ts +21 -0
  127. package/dist/internal/otel/collector.d.ts.map +1 -0
  128. package/dist/internal/otel/collector.js +605 -0
  129. package/dist/internal/otel/config.d.ts +42 -0
  130. package/dist/internal/otel/config.d.ts.map +1 -0
  131. package/dist/internal/otel/config.js +236 -0
  132. package/dist/internal/otel/http.d.ts +11 -0
  133. package/dist/internal/otel/http.d.ts.map +1 -0
  134. package/dist/internal/otel/http.js +97 -0
  135. package/dist/internal/otel/runtime.d.ts +21 -0
  136. package/dist/internal/otel/runtime.d.ts.map +1 -0
  137. package/dist/internal/otel/runtime.js +188 -0
  138. package/dist/internal/sdk-runner.d.ts +1 -1
  139. package/dist/internal/sdk-runner.d.ts.map +1 -1
  140. package/dist/internal/sdk-runner.js +1 -1
  141. package/dist/internal/server.d.ts.map +1 -1
  142. package/dist/internal/server.js +26 -1
  143. package/dist/internal/session-engine.d.ts +15 -2
  144. package/dist/internal/session-engine.d.ts.map +1 -1
  145. package/dist/internal/session-engine.js +58 -7
  146. package/dist/memory.d.ts +4 -0
  147. package/dist/memory.d.ts.map +1 -1
  148. package/dist/memory.js +4 -0
  149. package/dist/otel.d.ts +88 -0
  150. package/dist/otel.d.ts.map +1 -0
  151. package/dist/otel.js +64 -0
  152. package/dist/playground/assets/index-CZH9EFvO.css +1 -0
  153. package/dist/playground/assets/{index-B3HBneZZ.js → index-Dces8BDp.js} +34 -34
  154. package/dist/playground/index.html +2 -2
  155. package/dist/types.d.ts +103 -3
  156. package/dist/types.d.ts.map +1 -1
  157. package/docs/README.md +35 -105
  158. package/docs/deployment.md +2 -1
  159. package/docs/guides/github.md +79 -6
  160. package/docs/guides/opentelemetry.md +214 -0
  161. package/docs/quickstart.md +89 -227
  162. package/docs/reference/agent-config.md +52 -0
  163. package/docs/reference/channels.md +3 -1
  164. package/docs/reference/cli.md +2 -2
  165. package/docs/reference/hooks.md +21 -4
  166. package/docs/reference/project-layout.md +2 -0
  167. package/docs/reference/tools.md +5 -4
  168. package/docs/templates/triage.md +147 -0
  169. package/package.json +24 -2
  170. package/skills/create-agent/SKILL.md +2 -2
  171. package/skills/framework-map/SKILL.md +2 -0
  172. package/skills/otel/SKILL.md +98 -0
  173. package/src/bin/agent-serve.ts +3 -1
  174. package/src/channels/github/api.ts +22 -0
  175. package/src/channels/github/defaults.ts +27 -6
  176. package/src/channels/github/github-channel.ts +36 -1
  177. package/src/channels/github/index.ts +1 -0
  178. package/src/channels/github/progress.ts +243 -0
  179. package/src/channels/github/state.ts +3 -0
  180. package/src/channels/github/types.ts +12 -4
  181. package/src/channels/slack/slack-channel.ts +4 -0
  182. package/src/channels.ts +38 -0
  183. package/src/index.ts +7 -0
  184. package/src/internal/cli-ax.ts +21 -3
  185. package/src/internal/cli-deploy.ts +58 -3
  186. package/src/internal/deploy-client.ts +11 -0
  187. package/src/internal/discovery.ts +108 -4
  188. package/src/internal/distribution.ts +1 -0
  189. package/src/internal/host-otel.ts +252 -0
  190. package/src/internal/init-project.ts +160 -17
  191. package/src/internal/otel/attrs.ts +18 -0
  192. package/src/internal/otel/collector.ts +881 -0
  193. package/src/internal/otel/config.ts +307 -0
  194. package/src/internal/otel/http.ts +126 -0
  195. package/src/internal/otel/runtime.ts +271 -0
  196. package/src/internal/sdk-runner.ts +6 -0
  197. package/src/internal/server.ts +39 -1
  198. package/src/internal/session-engine.ts +83 -2
  199. package/src/memory.ts +4 -0
  200. package/src/otel.ts +155 -0
  201. package/src/types.ts +109 -3
  202. package/templates/triage/README.md +48 -0
  203. package/templates/triage/agent/agent.ts +14 -0
  204. package/templates/triage/agent/channels/intake.ts +20 -0
  205. package/templates/triage/agent/channels/slack.ts +3 -0
  206. package/templates/triage/agent/hooks/memory.ts +3 -0
  207. package/templates/triage/agent/instructions.md +27 -0
  208. package/templates/triage/agent/skills/triage-rubric.md +43 -0
  209. package/templates/triage/agent/tools/record_triage.ts +23 -0
  210. package/templates/triage/evals/evals.config.ts +5 -0
  211. package/templates/triage/evals/triage.eval.ts +43 -0
  212. package/templates/triage/package.json +18 -0
  213. package/templates/triage/tsconfig.json +12 -0
  214. package/dist/docs/assets/chunks/@localSearchIndexroot.BlU3A8EB.js +0 -1
  215. package/dist/docs/assets/index.md.BKpbkCa6.js +0 -24
  216. package/dist/docs/assets/index.md.BKpbkCa6.lean.js +0 -1
  217. package/dist/docs/assets/quickstart.md.rIbfahJM.lean.js +0 -1
  218. package/dist/playground/assets/index-Bqk9nplh.css +0 -1
  219. /package/dist/docs/assets/{deployment.md.BHVjVqRa.lean.js → deployment.md.Cdp4rTE4.lean.js} +0 -0
  220. /package/dist/docs/assets/{reference_channels.md.BIabFUAI.lean.js → reference_channels.md.MN8iDy8V.lean.js} +0 -0
  221. /package/dist/docs/assets/{reference_cli.md.DqEqQpGn.lean.js → reference_cli.md.BDmjPPAm.lean.js} +0 -0
  222. /package/dist/docs/assets/{reference_project-layout.md._XdeMahr.lean.js → reference_project-layout.md.D3MdHM2z.lean.js} +0 -0
  223. /package/dist/docs/assets/{reference_tools.md.lSrsTxYJ.lean.js → reference_tools.md.kJfJAP2m.lean.js} +0 -0
@@ -0,0 +1,147 @@
1
+ ---
2
+ title: "Ship a triage agent from the template"
3
+ description: "Scaffold the triage template, make its rubric yours, prove it with evals, and deploy it to Cursor-managed hosting."
4
+ ---
5
+
6
+ # Ship a triage agent from the template
7
+
8
+ The triage template is a working agent you own from the first command.
9
+ It reads a report, classifies it as a bug, a question, or feedback,
10
+ judges severity against a rubric, records a structured verdict, and
11
+ replies with the next step. This page walks the whole arc: scaffold,
12
+ first verdict, customize, prove, wire Slack, deploy.
13
+
14
+ Every file the template ships is yours to edit. The only dependency is
15
+ `@cursor/july` itself, pinned to the version the template was tested
16
+ against. Nothing phones home to a template registry.
17
+
18
+ ## Scaffold it
19
+
20
+ ```bash
21
+ npx @cursor/july init ./triage-agent --template triage
22
+ ```
23
+
24
+ One command with no prior install. It writes twelve files, runs
25
+ `npm install`, puts `agent-sdk` on your PATH, and offers a browser
26
+ sign-in when the machine has no Cursor credential. Model turns need
27
+ that credential, so sign in now rather than mid-flow:
28
+
29
+ ```bash
30
+ agent-sdk login
31
+ ```
32
+
33
+ The scaffold is a plain directory. Commit it to your own repo.
34
+
35
+ ## Get the first verdict
36
+
37
+ ```bash
38
+ cd triage-agent
39
+ agent-sdk dev
40
+ ```
41
+
42
+ Open the playground URL it prints and type a real report:
43
+
44
+ > Export to CSV has returned 500s since this morning. Request id 41ac.
45
+ > Retrying does not help.
46
+
47
+ Watch the turn. The agent reads the `triage-rubric` skill, calls
48
+ `record_triage` with a structured verdict, and replies in six lines or
49
+ fewer. The tool call renders inline, so you see the exact kind,
50
+ severity, and next step it recorded.
51
+
52
+ Integrations use the same door your playground does. The `intake`
53
+ channel accepts reports over HTTP:
54
+
55
+ ```bash
56
+ curl -X POST http://127.0.0.1:3000/triage-agent/v1/channels/intake/report \
57
+ -H 'content-type: application/json' \
58
+ -d '{"message":"How do I rotate staging API keys?","reporter":"dana"}'
59
+ ```
60
+
61
+ The composer also autocompletes `/report`, which drives this route.
62
+
63
+ ## Make the rubric yours
64
+
65
+ `agent/skills/triage-rubric.md` holds the judgment: what counts as a
66
+ bug, the tie-breakers, and the severity ladder. Edit it first. Your
67
+ team's definition of `urgent` belongs there, in plain markdown, and the
68
+ next turn uses it without a restart step.
69
+
70
+ `agent/instructions.md` owns the flow around the rubric: when to ask a
71
+ clarifying question, the one-call `record_triage` rule, and the reply
72
+ shape.
73
+
74
+ ## Prove it with evals
75
+
76
+ The template ships three smoke cases, one per kind. Run them after
77
+ every rubric edit:
78
+
79
+ ```bash
80
+ agent-sdk eval
81
+ ```
82
+
83
+ Each case sends a realistic report and asserts a verdict was recorded
84
+ with the expected kind. When you tighten the rubric, add a case for the
85
+ report style you tightened it for. The eval suite is the regression
86
+ net for prompt changes, so grow it with the rubric.
87
+
88
+ ## File verdicts into your tracker
89
+
90
+ `agent/tools/record_triage.ts` defines the verdict shape with a zod
91
+ schema and returns it. Point its `execute` at Linear, GitHub Issues, or
92
+ a webhook to file real tickets. Test the tool without a model turn:
93
+
94
+ ```bash
95
+ agent-sdk call record_triage --dir . --input '{
96
+ "kind": "bug",
97
+ "severity": "high",
98
+ "title": "CSV export 500s",
99
+ "summary": "Export returns 500 since this morning.",
100
+ "nextStep": "Check export service logs."
101
+ }'
102
+ ```
103
+
104
+ The call validates against the schema and runs your `execute` body
105
+ in-process, so tracker wiring gets a fast loop.
106
+
107
+ ## Wire it to Slack
108
+
109
+ The `slack` channel idles until its tokens exist, so local work never
110
+ blocks on Slack. When you want it live:
111
+
112
+ ```bash
113
+ agent-sdk slack setup
114
+ ```
115
+
116
+ The guided flow creates the Slack app and writes the token pair to
117
+ `.env.local`. Restart `agent-sdk dev`, invite the bot to a channel, and
118
+ @mention it with a report. The [Slack guide](../guides/slack.md) covers
119
+ channel watching and approvals when you outgrow mentions.
120
+
121
+ ## Deploy it
122
+
123
+ ```bash
124
+ agent-sdk deploy
125
+ ```
126
+
127
+ From your git checkout, `deploy` infers the repo, ref, and slug, builds
128
+ the ref on Cursor-managed hosting, and prints the hosted URL plus a
129
+ one-time alias token. Store the token. Production Slack tokens go in as
130
+ deployment secrets:
131
+
132
+ ```bash
133
+ agent-sdk secrets set SLACK_BOT_TOKEN SLACK_APP_TOKEN --slug triage-agent
134
+ agent-sdk deploy
135
+ ```
136
+
137
+ Check on it with `agent-sdk deployments`. The
138
+ [deployment guide](../deployment.md) covers self-hosting, storage, and
139
+ auth when you need them.
140
+
141
+ ## Where to go next
142
+
143
+ - Add a GitHub intake with the [GitHub guide](../guides/github.md), so
144
+ issue comments triage themselves.
145
+ - Persist verdicts across restarts with [storage](../storage.md).
146
+ - Measure rubric changes on live traffic with
147
+ [A/B metrics](../ab.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor/july",
3
- "version": "0.1.42",
3
+ "version": "0.1.45",
4
4
  "description": "(early alpha) Filesystem-first framework for defining Cursor agents as markdown and TypeScript and serving them over channels with the Cursor SDK.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "repository": {
@@ -31,6 +31,7 @@
31
31
  "!src/internal/tenant-mcp/**",
32
32
  "skills/**/*",
33
33
  "!skills/operate/**",
34
+ "templates/**/*",
34
35
  "docs/**/*.md",
35
36
  "!docs/.cursor/**",
36
37
  "package.json",
@@ -177,6 +178,12 @@
177
178
  "import": "./dist/storage-backends/cursor-hosted.js",
178
179
  "default": "./dist/storage-backends/cursor-hosted.js"
179
180
  },
181
+ "./otel": {
182
+ "anysphere-source": "./src/otel.ts",
183
+ "types": "./dist/otel.d.ts",
184
+ "import": "./dist/otel.js",
185
+ "default": "./dist/otel.js"
186
+ },
180
187
  "./package.json": {
181
188
  "anysphere-source": "./package.json",
182
189
  "bun": "./package.json",
@@ -208,10 +215,25 @@
208
215
  "node": ">=22.13"
209
216
  },
210
217
  "dependencies": {
211
- "@cursor/sdk": "1.0.26",
218
+ "@cursor/sdk": "1.0.27",
212
219
  "@modelcontextprotocol/sdk": "1.25.1",
213
220
  "@octokit/auth-app": "^7.2.0",
214
221
  "@octokit/rest": "^21.1.1",
222
+ "@opentelemetry/api": "^1.9.0",
223
+ "@opentelemetry/api-logs": "^0.208.0",
224
+ "@opentelemetry/core": "^2.6.1",
225
+ "@opentelemetry/exporter-logs-otlp-http": "^0.208.0",
226
+ "@opentelemetry/exporter-logs-otlp-proto": "^0.208.0",
227
+ "@opentelemetry/exporter-metrics-otlp-http": "^0.208.0",
228
+ "@opentelemetry/exporter-metrics-otlp-proto": "^0.208.0",
229
+ "@opentelemetry/exporter-trace-otlp-http": "^0.208.0",
230
+ "@opentelemetry/exporter-trace-otlp-proto": "^0.208.0",
231
+ "@opentelemetry/resources": "^2.6.1",
232
+ "@opentelemetry/sdk-logs": "^0.208.0",
233
+ "@opentelemetry/sdk-metrics": "^2.2.0",
234
+ "@opentelemetry/sdk-trace-base": "^2.6.1",
235
+ "@opentelemetry/sdk-trace-node": "^2.6.1",
236
+ "@opentelemetry/semantic-conventions": "^1.27.0",
215
237
  "@slack/socket-mode": "^2.0.7",
216
238
  "@slack/web-api": "^7.18.0",
217
239
  "croner": "^8.0.1",
@@ -16,8 +16,8 @@ channels working
16
16
  with the user, prove a turn runs end-to-end, and set up the improvement loop.
17
17
  Sibling skills: `framework-map` for orientation, `setup-slack` for Slack
18
18
  wiring, `mcp-auth` for host MCP OAuth, `github` for webhook-driven
19
- agents, `evals` for the eval API, `ab` for live A/B metrics, `hillclimb`
20
- for iteration once the agent runs.
19
+ agents, `evals` for the eval API, `ab` for live A/B metrics, `otel` for
20
+ OpenTelemetry export, `hillclimb` for iteration once the agent runs.
21
21
 
22
22
  Read `framework-map/SKILL.md` first if you haven't; treat the package
23
23
  `AGENTS.md` and `README.md` as ground truth for
@@ -63,6 +63,7 @@ path live under README "Folder structure".
63
63
  | `agent/hooks/*.ts` | Observe-only event subscribers (never fatal) |
64
64
  | `agent/ab.ts` or `agent/ab/*.ts` | Live A/B metrics (`defineAB`); sticky `split` + `onSample` |
65
65
  | `agent/ab.config.ts` | Optional A/B `maxPlaygroundSessions` / `persistSamples` / `persistSnapshots` |
66
+ | `agent/otel.ts` | OpenTelemetry export (`defineOtel`); also `OTEL_EXPORTER_OTLP_*` env |
66
67
  | `agent/schedules/*` | Cron-driven runs (UTC, 5-field; never auto-fire under `--dev`) |
67
68
  | `agent/sandbox/workspace/` | Files seeded into each session workspace (local runtime only) |
68
69
  | `agent/lib/` | Import-only shared code, never discovered |
@@ -151,6 +152,7 @@ folder mounts every sibling agent too.
151
152
  - Scaffolding → `packages/agent-serve/skills/create-agent/SKILL.md`
152
153
  - Evals → `packages/agent-serve/skills/evals/SKILL.md`
153
154
  - Live A/B metrics → `packages/agent-serve/skills/ab/SKILL.md`
155
+ - OpenTelemetry → `packages/agent-serve/skills/otel/SKILL.md`
154
156
  - GitHub webhooks → `packages/agent-serve/skills/github/SKILL.md`
155
157
  - Slack → `packages/agent-serve/skills/setup-slack/SKILL.md`
156
158
  - Host MCP OAuth → `packages/agent-serve/skills/mcp-auth/SKILL.md`
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: agentkit-otel
3
+ description: >-
4
+ Wire OpenTelemetry export for an Agent SDK agent (defineOtel, OTLP env,
5
+ traces/metrics/logs, ctx.host.otel). Use when adding observability,
6
+ Datadog/Grafana/OTLP export, session/turn/tool tracing, or custom metrics.
7
+ ---
8
+
9
+ # Agent SDK OpenTelemetry (`defineOtel`)
10
+
11
+ Push session, turn, tool, and subagent traces, plus token and cost
12
+ metrics, from the serve process to an OTLP collector. Logs are off
13
+ until you opt in.
14
+
15
+ Read [OpenTelemetry](../../docs/guides/opentelemetry.md) for the full
16
+ guide, including how this joins Cursor enterprise export.
17
+
18
+ ## Enable
19
+
20
+ Any one of:
21
+
22
+ 1. **Env.** Set `OTEL_EXPORTER_OTLP_ENDPOINT` (and optional
23
+ `OTEL_SERVICE_NAME`, `OTEL_EXPORTER_OTLP_HEADERS`,
24
+ `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf|http/json`).
25
+ Per-signal URLs work when the base URL is unset:
26
+ `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` / `_METRICS_ENDPOINT` /
27
+ `_LOGS_ENDPOINT`.
28
+ 2. **Authored.** `agent/otel.ts`:
29
+
30
+ ```ts
31
+ import { defineOtel } from "@cursor/july/otel";
32
+
33
+ export default defineOtel({
34
+ serviceName: "cursor",
35
+ exporters: [
36
+ {
37
+ url: "https://otel.example.com",
38
+ protocol: "http/protobuf",
39
+ headers: { Authorization: "Bearer …" },
40
+ },
41
+ ],
42
+ });
43
+ ```
44
+
45
+ 3. **Programmatic.** `serve(dir, { otel: { … } })`. Pass `otel: false`
46
+ to disable even when env or `agent/otel.ts` are set.
47
+
48
+ Multiple `exporters` fan out. Default protocol is `http/protobuf`.
49
+ Use `http/json` only when the collector requires it. `grpc` is ignored.
50
+
51
+ Precedence: `serve({ otel })` over `agent/otel.ts` over env.
52
+
53
+ ## Signals
54
+
55
+ | Signal | Default | What |
56
+ | --- | --- | --- |
57
+ | Traces | on | `agent_sdk.http` → `agent_sdk.session` → `agent_sdk.turn` → `agent_sdk.tool` / `agent_sdk.subagent` |
58
+ | Metrics | on | `cursor.token.usage`, `cursor.tool.calls`, `cursor.cost.usage`, plus `agent_sdk.*` counts and HTTP duration |
59
+ | Logs | off | Opt in with `logs: true`, `OTEL_LOGS_EXPORTER=otlp`, or `OTEL_LOG_USER_PROMPTS=1` / `OTEL_LOG_TOOL_CONTENT=1` |
60
+
61
+ Prompt text, tool payloads, and failure text stay off the wire unless
62
+ those flags are set.
63
+
64
+ ## Custom metrics (`ctx.host.otel`)
65
+
66
+ Always present. `increment` / `record` no-op without a meter.
67
+ `setAttributes` still tags the open session when a collector is
68
+ attached. Prefix names with team or agent. No custom spans. Reserved
69
+ metric names: `cursor.token.usage`, `cursor.tool.calls`,
70
+ `cursor.cost.usage`, `agent_sdk.session.count`,
71
+ `agent_sdk.turn.count`, `agent_sdk.subagent.count`,
72
+ `agent_sdk.http.duration`. Reserved attributes:
73
+ `cursor.conversation.id`, `agent_sdk.agent`, `agent_sdk.turn_id`,
74
+ `agent_sdk.framework`.
75
+
76
+ ```ts
77
+ ctx.host.otel.setAttributes({ "abc.ticket_id": "INC-123" });
78
+ ctx.host.otel.increment("abc.ticket.resolved");
79
+ ctx.host.otel.record("abc.approval.duration_ms", 1420);
80
+ ```
81
+
82
+ ## Attributes worth joining on
83
+
84
+ - `cursor.conversation.id` (session id)
85
+ - `cursor.tool.name` / `cursor.tool.kind` / `cursor.tool.status`
86
+ - `cursor.token.type`, `cursor.model.name`
87
+ - `agent_sdk.agent`, `agent_sdk.turn_id`, `agent_sdk.call_id`, `agent_sdk.channel`
88
+
89
+ Resource defaults: `service.name=cursor`, `cursor.entrypoint=sdk_ts`,
90
+ `cursor.surface=unspecified`.
91
+
92
+ Inbound HTTP extracts W3C `traceparent`, so a channel request parents
93
+ the session span when the turn starts in that request.
94
+
95
+ If another TracerProvider already owns the process (CLI / IDE), Agent
96
+ SDK reuses it. Run `serve` as its own process when Agent SDK should
97
+ own the destination. Conflicting `agent/otel.ts` files across mounts
98
+ fail at serve start.
@@ -100,7 +100,7 @@ Usage:
100
100
  ${CLI} trajectory --events <file.ndjson> [--text]
101
101
  ${CLI} call <tool> [--input <json>] [--dir <path> | --url <baseUrl> | --prod]
102
102
  [--session <id>] [--slug <slug>] [--team <id>]
103
- ${CLI} init [dir] [--json]
103
+ ${CLI} init [dir] [--template <name>] [--json]
104
104
  ${CLI} convert-automation <url> [--dir <path>] [--json]
105
105
  ${CLI} install-skills [--print] [--json]
106
106
  ${CLI} mcp --prod [--slug <slug>] [--team <id>] [--dir <path>]
@@ -467,6 +467,7 @@ async function main(argv: string[]): Promise<number> {
467
467
  allowPositionals: true,
468
468
  options: {
469
469
  dir: { type: "string", default: "." },
470
+ template: { type: "string" },
470
471
  port: { type: "string" },
471
472
  host: { type: "string" },
472
473
  mode: { type: "string" },
@@ -624,6 +625,7 @@ async function main(argv: string[]): Promise<number> {
624
625
  return cmdInit({
625
626
  dir,
626
627
  initTarget: positionals[0],
628
+ template: values.template,
627
629
  json: values.json,
628
630
  });
629
631
  }
@@ -258,6 +258,28 @@ export async function createGitHubIssueComment(
258
258
  }
259
259
  }
260
260
 
261
+ /** Update an issue or PR timeline comment by id. */
262
+ export async function updateGitHubIssueComment(
263
+ input: GitHubResourceInput & { body: string; commentId: number }
264
+ ): Promise<GitHubPostedComment> {
265
+ const octokit = await createGitHubOctokit(input);
266
+ try {
267
+ const response = await octokit.rest.issues.updateComment({
268
+ owner: input.owner,
269
+ repo: input.repo,
270
+ comment_id: input.commentId,
271
+ body: input.body,
272
+ });
273
+ return toPostedComment(response.data);
274
+ } catch (error) {
275
+ throw wrapOctokitError(
276
+ error,
277
+ "PATCH",
278
+ `/repos/${input.owner}/${input.repo}/issues/comments/${input.commentId}`
279
+ );
280
+ }
281
+ }
282
+
261
283
  /** Reply to an inline pull-request review comment thread. */
262
284
  export async function createGitHubReviewCommentReply(
263
285
  input: GitHubResourceInput & {
@@ -5,14 +5,11 @@
5
5
  import type { ChannelEventHandlers } from "../../types.js";
6
6
  import type { GitHubBindingConfig } from "./binding.js";
7
7
  import { buildGitHubBinding, formatGitHubOutboundComment } from "./binding.js";
8
+ import { applyGitHubProgress, type GitHubProgressConfig } from "./progress.js";
8
9
  import type { GitHubChannelState } from "./state.js";
9
10
 
10
- export interface GitHubProgressConfig {
11
- /** When false, skip the eyes reaction on turn.started. Defaults to true. */
12
- reactions?: boolean;
13
- }
14
-
15
11
  export interface BuildDefaultGitHubEventsOptions extends GitHubBindingConfig {
12
+ botName?: string;
16
13
  progress?: GitHubProgressConfig;
17
14
  /**
18
15
  * When false, skip posting completed assistant messages back to GitHub.
@@ -22,7 +19,8 @@ export interface BuildDefaultGitHubEventsOptions extends GitHubBindingConfig {
22
19
  }
23
20
 
24
21
  /**
25
- * Built-in delivery: eyes reaction on turn start, post assistant text on
22
+ * Built-in delivery: eyes reaction on turn start, optional commit status /
23
+ * sticky banner via {@link GitHubProgressConfig}, post assistant text on
26
24
  * `message.completed`, and a short error comment on turn/session failure.
27
25
  */
28
26
  export function buildDefaultGitHubEvents(
@@ -32,6 +30,11 @@ export function buildDefaultGitHubEvents(
32
30
 
33
31
  return {
34
32
  async "turn.started"(_event, channel) {
33
+ await applyGitHubProgress({
34
+ phase: "pending",
35
+ channel,
36
+ options,
37
+ });
35
38
  if (options.progress?.reactions === false) {
36
39
  return;
37
40
  }
@@ -49,6 +52,14 @@ export function buildDefaultGitHubEvents(
49
52
  }
50
53
  },
51
54
 
55
+ async "turn.completed"(_event, channel) {
56
+ await applyGitHubProgress({
57
+ phase: "success",
58
+ channel,
59
+ options,
60
+ });
61
+ },
62
+
52
63
  async "message.completed"(event, channel) {
53
64
  if (!deliverReplies) {
54
65
  return;
@@ -71,10 +82,20 @@ export function buildDefaultGitHubEvents(
71
82
  },
72
83
 
73
84
  async "turn.failed"(event, channel) {
85
+ await applyGitHubProgress({
86
+ phase: "failure",
87
+ channel,
88
+ options,
89
+ });
74
90
  await postFailure(channel, options, event.data.message);
75
91
  },
76
92
 
77
93
  async "session.failed"(event, channel) {
94
+ await applyGitHubProgress({
95
+ phase: "failure",
96
+ channel,
97
+ options,
98
+ });
78
99
  await postFailure(channel, options, event.data.message);
79
100
  },
80
101
  };
@@ -137,6 +137,12 @@ const githubPullRequestPayloadSchema: z.ZodType<GitHubPullRequestPayload> =
137
137
  }),
138
138
  sender: senderSchema,
139
139
  installation: installationSchema,
140
+ label: z
141
+ .object({
142
+ name: z.string().min(1),
143
+ })
144
+ .nullable()
145
+ .optional(),
140
146
  });
141
147
 
142
148
  /**
@@ -336,6 +342,9 @@ export function parseGitHubPullRequestEvent(args: {
336
342
  ...(payload.pull_request.user?.login === undefined
337
343
  ? {}
338
344
  : { authorLogin: payload.pull_request.user.login }),
345
+ ...(payload.label?.name === undefined
346
+ ? {}
347
+ : { label: { name: payload.label.name } }),
339
348
  };
340
349
  return { ctx, pullRequest };
341
350
  }
@@ -958,6 +967,9 @@ async function handleReviewComment(input: {
958
967
  binding,
959
968
  deliveryId: ctx.deliveryId,
960
969
  eventName: ctx.eventName,
970
+ headSha: parsed.headSha,
971
+ headRef: parsed.headRef,
972
+ baseRef: parsed.baseRef,
961
973
  }),
962
974
  });
963
975
  }
@@ -1459,6 +1471,8 @@ async function startTurn(input: {
1459
1471
  title: input.dispatch.title ?? defaultGitHubTitle(input.ctx),
1460
1472
  ...(input.cloud === undefined ? {} : { cloud: input.cloud }),
1461
1473
  state: input.state as unknown as JsonValue,
1474
+ // Resume must refresh headSha / refs without wiping sticky banner id.
1475
+ refreshState: input.state as unknown as JsonValue,
1462
1476
  });
1463
1477
  return Response.json({
1464
1478
  ok: true,
@@ -1612,6 +1626,9 @@ function parseReviewCommentEvent(args: {
1612
1626
  action: string;
1613
1627
  ctx: GitHubParsedContext;
1614
1628
  comment: GitHubComment;
1629
+ headSha?: string;
1630
+ headRef?: string;
1631
+ baseRef?: string;
1615
1632
  } | null {
1616
1633
  const schema = z.object({
1617
1634
  action: z.string().min(1),
@@ -1619,6 +1636,17 @@ function parseReviewCommentEvent(args: {
1619
1636
  pull_request: z.object({
1620
1637
  number: z.number().int().positive(),
1621
1638
  html_url: z.string().url(),
1639
+ head: z
1640
+ .object({
1641
+ sha: z.string().min(1).optional(),
1642
+ ref: z.string().min(1).optional(),
1643
+ })
1644
+ .optional(),
1645
+ base: z
1646
+ .object({
1647
+ ref: z.string().min(1).optional(),
1648
+ })
1649
+ .optional(),
1622
1650
  }),
1623
1651
  comment: z.object({
1624
1652
  id: z.number(),
@@ -1679,7 +1707,14 @@ function parseReviewCommentEvent(args: {
1679
1707
  ? {}
1680
1708
  : { inReplyToId: payload.comment.in_reply_to_id }),
1681
1709
  };
1682
- return { action: payload.action, ctx, comment };
1710
+ return {
1711
+ action: payload.action,
1712
+ ctx,
1713
+ comment,
1714
+ headSha: payload.pull_request.head?.sha,
1715
+ headRef: payload.pull_request.head?.ref,
1716
+ baseRef: payload.pull_request.base?.ref,
1717
+ };
1683
1718
  }
1684
1719
 
1685
1720
  function parseIssueEvent(args: {
@@ -47,6 +47,7 @@ export * from "./defaults.js";
47
47
  export * from "./events.js";
48
48
  export * from "./forward.js";
49
49
  export * from "./github-channel.js";
50
+ export * from "./progress.js";
50
51
  export * from "./replay.js";
51
52
  export * from "./state.js";
52
53
  export * from "./types.js";