@senad-d/observme 0.1.0

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 (111) hide show
  1. package/.env.example +57 -0
  2. package/CHANGELOG.md +52 -0
  3. package/LICENSE +21 -0
  4. package/ObservMe-Production-Docs/00-README.md +79 -0
  5. package/ObservMe-Production-Docs/01-requirements-and-scope.md +207 -0
  6. package/ObservMe-Production-Docs/02-reference-architecture.md +306 -0
  7. package/ObservMe-Production-Docs/03-pi-event-and-session-model.md +266 -0
  8. package/ObservMe-Production-Docs/04-telemetry-semantic-conventions.md +722 -0
  9. package/ObservMe-Production-Docs/05-otel-pipeline-and-collector.md +355 -0
  10. package/ObservMe-Production-Docs/06-security-privacy-redaction.md +294 -0
  11. package/ObservMe-Production-Docs/07-extension-implementation-blueprint.md +447 -0
  12. package/ObservMe-Production-Docs/08-query-grafana-integration.md +276 -0
  13. package/ObservMe-Production-Docs/09-dashboards-alerts-slos.md +640 -0
  14. package/ObservMe-Production-Docs/10-testing-release-operations.md +319 -0
  15. package/ObservMe-Production-Docs/11-deployment-runbooks.md +203 -0
  16. package/ObservMe-Production-Docs/12-configuration-reference.md +337 -0
  17. package/ObservMe-Production-Docs/13-source-notes.md +33 -0
  18. package/ObservMe-Production-Docs/pi-session-format.md +427 -0
  19. package/README.md +356 -0
  20. package/SECURITY.md +45 -0
  21. package/dashboards/observme-agent-node-graphs.json +250 -0
  22. package/dashboards/observme-agents.json +1880 -0
  23. package/dashboards/observme-alerts.yaml +113 -0
  24. package/dashboards/observme-branches-compactions.json +1042 -0
  25. package/dashboards/observme-cost.json +1254 -0
  26. package/dashboards/observme-errors.json +1659 -0
  27. package/dashboards/observme-export-health.json +1802 -0
  28. package/dashboards/observme-latency.json +1494 -0
  29. package/dashboards/observme-llm-conversations.json +730 -0
  30. package/dashboards/observme-logs-llm.json +644 -0
  31. package/dashboards/observme-models.json +933 -0
  32. package/dashboards/observme-overview.json +2129 -0
  33. package/dashboards/observme-slo-health.json +737 -0
  34. package/dashboards/observme-slos.yaml +56 -0
  35. package/dashboards/observme-tools.json +902 -0
  36. package/dashboards/observme-trace-journey.json +1793 -0
  37. package/docs/STRUCTURE.md +49 -0
  38. package/docs/agent-subagent-observability-requirements.md +997 -0
  39. package/docs/compatibility-matrix.md +39 -0
  40. package/docs/configuration-tui-design-standard.md +767 -0
  41. package/docs/configuration.md +38 -0
  42. package/docs/review-validation.md +115 -0
  43. package/docs/validation-flow.md +117 -0
  44. package/examples/collector.yaml +123 -0
  45. package/examples/observme.yaml +131 -0
  46. package/img/demo.gif +0 -0
  47. package/img/icon.svg +47 -0
  48. package/package.json +103 -0
  49. package/src/commands/obs-agents-runtime.ts +150 -0
  50. package/src/commands/obs-agents.ts +491 -0
  51. package/src/commands/obs-args.ts +63 -0
  52. package/src/commands/obs-backfill.ts +1334 -0
  53. package/src/commands/obs-command-support.ts +43 -0
  54. package/src/commands/obs-cost.ts +228 -0
  55. package/src/commands/obs-diagnostics.ts +22 -0
  56. package/src/commands/obs-errors.ts +156 -0
  57. package/src/commands/obs-health.ts +301 -0
  58. package/src/commands/obs-link.ts +90 -0
  59. package/src/commands/obs-logs.ts +194 -0
  60. package/src/commands/obs-loki-summary.ts +184 -0
  61. package/src/commands/obs-session.ts +259 -0
  62. package/src/commands/obs-status.ts +359 -0
  63. package/src/commands/obs-tools.ts +274 -0
  64. package/src/commands/obs-trace.ts +411 -0
  65. package/src/commands/obs.ts +211 -0
  66. package/src/config/bootstrap-project-config.ts +300 -0
  67. package/src/config/defaults.ts +143 -0
  68. package/src/config/load-config.ts +631 -0
  69. package/src/config/project-paths.ts +61 -0
  70. package/src/config/schema.ts +405 -0
  71. package/src/config/validate.ts +456 -0
  72. package/src/constants.ts +4 -0
  73. package/src/diagnostics/sanitize.ts +6 -0
  74. package/src/extension.ts +38 -0
  75. package/src/otel/logs.ts +160 -0
  76. package/src/otel/metrics.ts +165 -0
  77. package/src/otel/otlp-endpoint.ts +10 -0
  78. package/src/otel/sdk.ts +114 -0
  79. package/src/otel/shutdown.ts +102 -0
  80. package/src/otel/traces.ts +166 -0
  81. package/src/pi/agent-lineage.ts +378 -0
  82. package/src/pi/agent-tree-tracker.ts +258 -0
  83. package/src/pi/event-handlers/agent-turn.ts +155 -0
  84. package/src/pi/event-handlers/lifecycle.ts +642 -0
  85. package/src/pi/event-handlers/llm.ts +115 -0
  86. package/src/pi/event-handlers/session-events.ts +159 -0
  87. package/src/pi/event-handlers/tool-bash.ts +275 -0
  88. package/src/pi/handler-internals.ts +2154 -0
  89. package/src/pi/handler-runtime.ts +633 -0
  90. package/src/pi/handler-types.ts +261 -0
  91. package/src/pi/handlers.ts +75 -0
  92. package/src/pi/subagent-spawn.ts +975 -0
  93. package/src/pi/subagent-types.ts +29 -0
  94. package/src/privacy/content-capture.ts +104 -0
  95. package/src/privacy/hash.ts +93 -0
  96. package/src/privacy/redact.ts +619 -0
  97. package/src/privacy/secret-patterns.ts +185 -0
  98. package/src/privacy/truncate.ts +69 -0
  99. package/src/query/grafana-readiness.ts +164 -0
  100. package/src/query/grafana-transport.ts +481 -0
  101. package/src/query/grafana.ts +371 -0
  102. package/src/query/loki.ts +332 -0
  103. package/src/query/prometheus.ts +388 -0
  104. package/src/query/tempo.ts +332 -0
  105. package/src/safety/sensitive-input.ts +208 -0
  106. package/src/semconv/attributes.ts +279 -0
  107. package/src/semconv/metrics.ts +146 -0
  108. package/src/semconv/spans.ts +19 -0
  109. package/src/semconv/values.ts +13 -0
  110. package/src/util/bounded-map.ts +97 -0
  111. package/tsconfig.json +15 -0
@@ -0,0 +1,997 @@
1
+ # Agent and Subagent Orchestration Observability Requirements
2
+
3
+ ## Purpose
4
+
5
+ This document explains what ObservMe and a future Pi agent-orchestration extension need in order to run, manage, and observe root agents and subagents correctly.
6
+
7
+ The target runtime model is explicit: subagents are isolated Pi processes, often started inside dedicated `tmux` sessions, and every child/subagent Pi process is expected to load the ObservMe extension too. Tmux isolation is compatible with ObservMe, but tmux does not create lineage by itself. The orchestration extension must launch tmux with ObservMe lineage and trace-context environment variables, then record spawn, wait, join, status, and cleanup telemetry.
8
+
9
+ It is documentation-only. It does not change runtime behavior.
10
+
11
+ ## Sources reviewed
12
+
13
+ Project sources:
14
+
15
+ - `README.md`
16
+ - `ObservMe-Production-Docs/01-requirements-and-scope.md`
17
+ - `ObservMe-Production-Docs/02-reference-architecture.md`
18
+ - `ObservMe-Production-Docs/03-pi-event-and-session-model.md`
19
+ - `ObservMe-Production-Docs/04-telemetry-semantic-conventions.md`
20
+ - `ObservMe-Production-Docs/06-security-privacy-redaction.md`
21
+ - `ObservMe-Production-Docs/07-extension-implementation-blueprint.md`
22
+ - `ObservMe-Production-Docs/09-dashboards-alerts-slos.md`
23
+ - `ObservMe-Production-Docs/10-testing-release-operations.md`
24
+ - `ObservMe-Production-Docs/12-configuration-reference.md`
25
+ - `src/pi/agent-lineage.ts`
26
+ - `src/pi/agent-tree-tracker.ts`
27
+ - `src/pi/subagent-spawn.ts`
28
+ - `src/pi/handlers.ts`
29
+ - `src/pi/handler-internals.ts`
30
+ - `src/commands/obs-agents.ts`
31
+ - `src/commands/obs-agents-runtime.ts`
32
+ - `src/config/defaults.ts`
33
+ - `src/config/schema.ts`
34
+ - `src/config/validate.ts`
35
+ - `src/semconv/attributes.ts`
36
+ - `src/semconv/metrics.ts`
37
+ - `dashboards/observme-agents.json`
38
+ - `dashboards/observme-overview.json`
39
+ - `dashboards/observme-trace-journey.json`
40
+ - `dashboards/observme-alerts.yaml`
41
+ - `dashboards/observme-slos.yaml`
42
+ - `examples/observme.yaml`
43
+ - `examples/collector.yaml`
44
+ - `test/agent-lineage.test.ts`
45
+ - `test/subagent-spawn.test.mjs`
46
+
47
+ Pi documentation and examples:
48
+
49
+ - Pi `README.md`
50
+ - Pi `docs/extensions.md`
51
+ - Pi `docs/session-format.md`
52
+ - Pi `docs/sessions.md`
53
+ - Pi `docs/packages.md`
54
+ - Pi `examples/extensions/subagent/README.md`
55
+ - Pi `examples/extensions/subagent/index.ts`
56
+ - Pi `examples/extensions/subagent/agents.ts`
57
+
58
+ ## Target outcome for the orchestration extension
59
+
60
+ The future orchestration extension should provide the complete control plane for agent and subagent work:
61
+
62
+ - discover and validate agent definitions
63
+ - start root-like managed agents and child subagents
64
+ - launch isolated subagent Pi processes inside tmux sessions
65
+ - ensure every child Pi process loads ObservMe
66
+ - propagate ObservMe workflow, parent/root agent lineage, spawn id, session id, and W3C trace context into the child process
67
+ - distinguish root agents, subagents, and orphan agents deterministically
68
+ - list, inspect, attach to, detach from, stop, and clean up tmux-backed agents
69
+ - send tasks or follow-up messages to running child agents when the selected execution mode supports it
70
+ - record spawn, wait, join, cancellation, timeout, child failure, and recovery telemetry
71
+ - keep high-cardinality identifiers out of Prometheus metric labels
72
+ - expose enough local state for `/obs agents` and enough exported telemetry for Grafana dashboards
73
+
74
+ Current state: ObservMe already has lineage, agent-tree, spawn, wait/join, dashboard, and `/obs agents` building blocks, but subagent dashboards are not fully automatic for arbitrary child Pi processes or tmux sessions. Full dashboard behavior requires an ObservMe-aware orchestration launcher.
75
+
76
+ ## 1. Terminology
77
+
78
+ ### Pi agent runtime
79
+
80
+ A Pi agent runtime is one running Pi process/session that emits Pi lifecycle events such as:
81
+
82
+ - `session_start`
83
+ - `agent_start`
84
+ - `turn_start`
85
+ - `before_provider_request`
86
+ - `tool_execution_start`
87
+ - `tool_call`
88
+ - `tool_result`
89
+ - `turn_end`
90
+ - `agent_end`
91
+ - `session_shutdown`
92
+
93
+ In ObservMe, this runtime gets a logical identity:
94
+
95
+ - `pi.agent.id`
96
+ - `pi.agent.root_id`
97
+ - `pi.agent.parent_id` when it is a child
98
+ - `pi.agent.depth`
99
+ - `pi.agent.role`
100
+
101
+ ### Agent run
102
+
103
+ A Pi `agent_start` / `agent_end` pair is one user-prompt lifecycle inside a Pi runtime. ObservMe represents this as a `pi.agent.run` span.
104
+
105
+ Important distinction:
106
+
107
+ - `pi.agent.id` identifies the logical runtime.
108
+ - `pi.agent.run.id` identifies one prompt lifecycle inside that runtime.
109
+
110
+ Dashboard panels such as `observme_agent_runs_total` count `agent_start` / `agent_end` lifecycles, not process spawns.
111
+
112
+ ### Pi subagent
113
+
114
+ Pi core does not have built-in subagents. The Pi docs state that subagents are created by extensions or packages. The official example subagent extension launches separate `pi` subprocesses in JSON/print mode so each delegated agent has an isolated context window.
115
+
116
+ In ObservMe, a subagent is a separate Pi runtime that has trusted parent lineage:
117
+
118
+ - `pi.agent.parent_id` is set.
119
+ - `pi.agent.root_id` is inherited from the original root agent.
120
+ - `pi.workflow.id` is inherited from the original workflow.
121
+ - `pi.agent.depth` is parent depth plus one.
122
+ - `pi.agent.role` is usually `subagent` unless explicitly set to a bounded role such as `worker` or `reviewer`.
123
+
124
+ ### Pi subagent agent definitions
125
+
126
+ The Pi subagent example uses markdown agent definitions such as:
127
+
128
+ - `~/.pi/agent/agents/*.md`
129
+ - `.pi/agents/*.md`
130
+
131
+ Each definition has frontmatter like `name`, `description`, `tools`, and `model`, plus a system prompt body.
132
+
133
+ These markdown agent names are not automatically the same thing as ObservMe `pi.agent.id` or `pi.agent.role`. For observability they should be treated as safe capability/role metadata only if mapped intentionally, for example:
134
+
135
+ - `OBSERVME_AGENT_CAPABILITY=scout`
136
+ - `agent_capability="scout"`
137
+ - `agent_role="worker"` or `agent_role="reviewer"`
138
+
139
+ Do not use markdown agent names as high-cardinality identifiers.
140
+
141
+ ### Tmux-managed subagent
142
+
143
+ A tmux-managed subagent is a child Pi process started in its own tmux session or pane. It is still just a Pi subagent from ObservMe's perspective. Tmux provides process isolation, attach/detach behavior, and operator control, but it does not provide ObservMe lineage.
144
+
145
+ Required tmux-managed subagent properties:
146
+
147
+ - It runs a normal Pi command inside tmux.
148
+ - It loads ObservMe through an installed package, project/user extension discovery, or an explicit `-e` extension source.
149
+ - It receives ObservMe lineage and trace env from the parent launcher.
150
+ - It exports telemetry to the same or compatible OTLP backend as the parent.
151
+ - It has a predictable tmux session/window/pane name so the orchestration extension can list, attach, stop, and clean it up.
152
+
153
+ Recommended naming pattern:
154
+
155
+ ```text
156
+ observme-<workflow-short>-<agent-name>-<spawn-short>
157
+ ```
158
+
159
+ The full workflow id, agent id, spawn id, and session id remain trace/log attributes only. Do not use them as Prometheus labels.
160
+
161
+ ## 2. How to know root agent vs subagent
162
+
163
+ ObservMe decides agent lineage from trusted propagated context.
164
+
165
+ ### Root-like agent
166
+
167
+ A runtime is root-like when no trusted parent context is accepted.
168
+
169
+ Expected fields:
170
+
171
+ ```text
172
+ pi.agent.role = root
173
+ pi.agent.depth = 0
174
+ pi.agent.parent_id is absent
175
+ pi.agent.root_id = pi.agent.id
176
+ pi.workflow.root_agent_id = pi.agent.id
177
+ ```
178
+
179
+ ### Subagent
180
+
181
+ A runtime is a subagent when it accepts trusted parent lineage.
182
+
183
+ Expected fields:
184
+
185
+ ```text
186
+ pi.agent.role = subagent
187
+ pi.agent.parent_id = <parent pi.agent.id>
188
+ pi.agent.root_id = <root pi.agent.id>
189
+ pi.workflow.id = <parent workflow id>
190
+ pi.workflow.root_agent_id = <root pi.agent.id>
191
+ pi.agent.depth = <parent depth> + 1
192
+ ```
193
+
194
+ ### Orphan subagent
195
+
196
+ A runtime is orphaned when some parent lineage is present but the root/parent linkage is incomplete or cannot be connected to a known parent.
197
+
198
+ Expected behavior:
199
+
200
+ - Emit `agent.orphaned` log/event.
201
+ - Increment `observme_orphan_agents_total`.
202
+ - Keep Pi running fail-open.
203
+ - Do not place raw environment values or raw command lines into telemetry.
204
+
205
+ ### Current production rule
206
+
207
+ The shipped extension registers session handlers with `trustedParentContext: true`, making the Pi process environment eligible for launcher-provided lineage. Trusted project `.env` values are loaded into ObservMe configuration but are not copied into this lineage input, so a project file cannot establish parent provenance.
208
+
209
+ Eligibility is not blind acceptance. When any propagation value is present, `src/pi/agent-lineage.ts` requires a complete validated workflow, parent agent, root agent, parent depth, and spawn envelope. Trace-enabled propagation also requires valid W3C `traceparent`; optional `tracestate` and duplicate parent trace/span metadata must validate and agree. A stale inherited child agent id is rejected. Partial, malformed, oversized, or stale envelopes fail open to root/orphan lineage with bounded diagnostics that never include raw inherited values.
210
+
211
+ ObservMe validates the process envelope but does not cryptographically authenticate the launcher. An ObservMe-aware launcher remains responsible for constructing the envelope immediately before child startup and clearing stale propagation variables. Explicit runtime lineage options remain available to tests and embedders.
212
+
213
+ For tmux orchestration this is the critical distinction:
214
+
215
+ - **Child Pi with ObservMe but no propagation envelope:** telemetry exists and the child starts as a root-like runtime.
216
+ - **Child Pi with a complete validated process envelope:** telemetry joins the parent workflow and continues the propagated W3C trace.
217
+ - **Child Pi with a partial/broken/stale envelope:** Pi keeps running with root/orphan fallback and one bounded propagation-failure signal.
218
+
219
+ ## 3. What ObservMe must do at a subagent spawn point
220
+
221
+ Pi does not emit a dedicated `subagent_spawned` event. ObservMe must instrument the exact code path that launches or waits for another Pi process.
222
+
223
+ The required parent-side flow is:
224
+
225
+ 1. Parent is already inside an ObservMe session.
226
+ 2. Parent extension/tool decides to launch a child Pi process.
227
+ 3. ObservMe starts a `pi.agent.spawn` span.
228
+ 4. ObservMe creates a spawn id: `pi.agent.spawn.id`.
229
+ 5. ObservMe builds child environment variables containing workflow, parent/root agent, depth, spawn, session, and trace context.
230
+ 6. The subagent launcher must pass that environment to `child_process.spawn` or an equivalent process runner.
231
+ 7. Parent records spawn completion or failure.
232
+ 8. Parent records `pi.agent.wait` when it waits for the child.
233
+ 9. Parent records `pi.agent.join` when it receives the child result/status.
234
+ 10. Parent updates the in-memory agent tree and `/obs agents` runtime state.
235
+
236
+ The existing helper module for this is `src/pi/subagent-spawn.ts`:
237
+
238
+ - `startSubagentSpawn(...)`
239
+ - `completeSubagentSpawn(...)`
240
+ - `failSubagentSpawn(...)`
241
+ - `runSubagentWithObservability(...)`
242
+ - `startAgentWait(...)` / `endAgentWait(...)`
243
+ - `startAgentJoin(...)` / `endAgentJoin(...)`
244
+ - `recordAgentWait(...)` / `recordAgentJoin(...)`
245
+ - `observeTrustedSubagentLineage(...)`
246
+
247
+ If a subagent extension launches `pi` without using these helpers, ObservMe can still observe the launcher as a normal tool call, but the agent/subagent dashboards will not get the full spawn/depth/fan-out/wait/join contract.
248
+
249
+ ### Tmux-specific spawn requirements
250
+
251
+ When the child is launched through tmux, the orchestration extension must still treat tmux as the process runner around a child Pi process.
252
+
253
+ Required flow:
254
+
255
+ 1. Start `pi.agent.spawn` before creating the tmux session.
256
+ 2. Build the child environment from the started spawn state.
257
+ 3. Start tmux with an explicit command that injects that environment into the child Pi process.
258
+ 4. Do not rely on the tmux server's cached global environment; it may be stale if the tmux server was started earlier.
259
+ 5. Store the tmux session/window/pane identifiers in local orchestration state and in safe span/log attributes when low-cardinality or hashed.
260
+ 6. Mark spawn `completed` only when the tmux session/pane and child command were created successfully.
261
+ 7. Mark spawn `failed` if tmux cannot be started, the pane exits before Pi starts, or the command cannot be delivered.
262
+ 8. Record `wait` while the orchestrator is waiting for child completion or a child status signal.
263
+ 9. Record `join` when the orchestrator collects a child result, sees a terminal child status, or times out.
264
+
265
+ Conceptual command shape:
266
+
267
+ ```text
268
+ tmux new-session -d -s <safe-session-name> \
269
+ 'env OBSERVME_WORKFLOW_ID=... OBSERVME_PARENT_AGENT_ID=... traceparent=... pi ...'
270
+ ```
271
+
272
+ The command above is illustrative only. The implementation must avoid logging the raw command because it contains environment values and user task text.
273
+
274
+ ## 4. Environment propagation contract
275
+
276
+ When propagation is enabled, parent-to-child environment must include safe generated lineage values.
277
+
278
+ Configured default env names:
279
+
280
+ ```text
281
+ OBSERVME_WORKFLOW_ID
282
+ OBSERVME_PARENT_AGENT_ID
283
+ OBSERVME_ROOT_AGENT_ID
284
+ OBSERVME_PARENT_SESSION_ID
285
+ OBSERVME_PARENT_TRACE_ID
286
+ OBSERVME_PARENT_SPAN_ID
287
+ OBSERVME_AGENT_DEPTH
288
+ OBSERVME_SPAWN_ID
289
+ OBSERVME_AGENT_CAPABILITY
290
+ traceparent
291
+ tracestate
292
+ ```
293
+
294
+ Important details:
295
+
296
+ - `OBSERVME_AGENT_ID` is not normally propagated from parent to child; the child should generate its own `pi.agent.id`.
297
+ - Inherited ObservMe and W3C propagation variables are cleared before current child lineage is written, so stale agent IDs, spawn IDs, parent trace/span IDs, `traceparent`, or `tracestate` never leak into a new child environment.
298
+ - `OBSERVME_AGENT_DEPTH` carries the parent depth. The child increments it when creating its own lineage.
299
+ - `traceparent` and `tracestate` let the child continue the same distributed trace when possible.
300
+ - If W3C trace context cannot be propagated, ObservMe must still propagate workflow/parent/root ids and emit fallback telemetry.
301
+ - Raw commands, prompts, cwd, usernames, hostnames, PIDs, and inherited environment values must not be used to derive lineage ids.
302
+ - In tmux mode, env propagation must be explicit per child command or per tmux session. Do not assume the parent process environment reaches a pane through an already-running tmux server.
303
+ - If the orchestrator stores tmux metadata, store only safe names, hashed values, or bounded status enums in telemetry.
304
+
305
+ Config gates:
306
+
307
+ ```yaml
308
+ workflow:
309
+ enabled: true
310
+ agent:
311
+ propagateTraceContext: true
312
+ propagateToSubagents: true
313
+ ```
314
+
315
+ Validation gates:
316
+
317
+ - Workflow, parent-agent, root-agent, depth, and spawn values must be present together when any propagated value is supplied.
318
+ - Lineage env values must be short and match the safe character pattern.
319
+ - Trace-enabled propagation must include a valid W3C `traceparent`; optional `tracestate` is bounded and structurally validated.
320
+ - Parent trace id must be 32 hex characters and parent span id must be 16 hex characters when duplicate metadata is supplied; both must match `traceparent`.
321
+ - Depth must be an integer between 0 and 64.
322
+ - A stale inherited child agent id or uppercase W3C propagation variable invalidates the envelope.
323
+
324
+ ## 5. Child runtime contract
325
+
326
+ For child subagent telemetry to appear correctly:
327
+
328
+ 1. The child process must load the ObservMe extension.
329
+ 2. The child process must inherit the ObservMe propagation env from the parent wrapper.
330
+ 3. The child ObservMe runtime must treat that env as trusted parent context.
331
+ 4. The child must export traces, metrics, and logs to the same or compatible OTLP backend.
332
+ 5. The Collector must preserve lineage attributes on traces/logs and drop high-cardinality lineage attributes from metric labels.
333
+
334
+ If the child process runs `pi --no-session`, it can still emit runtime telemetry, but durable Pi session-file recovery is not available. ObservMe should rely on live events and propagated lineage in that case.
335
+
336
+ ## 5.1 Tmux-based orchestration extension requirements
337
+
338
+ This section is the implementation brief for the future Pi extension that manages agent orchestration.
339
+
340
+ ### Responsibilities
341
+
342
+ The orchestration extension is responsible for:
343
+
344
+ - agent discovery and validation
345
+ - tmux session creation and naming
346
+ - ObservMe lineage and trace propagation
347
+ - child Pi command construction
348
+ - child ObservMe loading guarantees
349
+ - child task delivery
350
+ - child lifecycle/status tracking
351
+ - parent wait/join accounting
352
+ - cancellation/timeout handling
353
+ - attach/detach user workflows
354
+ - safe cleanup of completed or failed tmux sessions
355
+ - local `/obs agents` state updates and exported telemetry
356
+
357
+ The ObservMe telemetry layer is responsible for:
358
+
359
+ - spans, metrics, logs, and dashboards
360
+ - redaction and high-cardinality protection
361
+ - fail-open export behavior
362
+ - agent-tree and lineage semantics
363
+
364
+ Do not mix these responsibilities by putting orchestration secrets or raw commands into telemetry.
365
+
366
+ ### Required execution modes
367
+
368
+ The extension should support at least these modes:
369
+
370
+ | Mode | Description | Best for | Join source |
371
+ |---|---|---|---|
372
+ | `tmux-interactive` | Start a normal interactive Pi TUI in tmux. Operators can attach and watch or steer. | Long-running isolated work. | tmux pane status, explicit completion marker, or operator action. |
373
+ | `tmux-print-json` | Start `pi --mode json -p` in tmux and capture stdout/stderr to files or pipes. | Automated delegated tasks with structured output. | process exit plus parsed JSON events. |
374
+ | `tmux-rpc` | Start Pi RPC mode in tmux or a supervised process and communicate through explicit pipes. | Long-lived managed agents. | RPC response/status protocol. |
375
+
376
+ For all modes, ObservMe lineage propagation is mandatory.
377
+
378
+ ### Agent definition contract
379
+
380
+ Each manageable agent should have a bounded definition:
381
+
382
+ ```yaml
383
+ name: scout
384
+ role: worker # root|subagent|orchestrator|worker|reviewer|unknown
385
+ capability: scout # bounded low-cardinality value
386
+ description: Fast codebase recon
387
+ model: claude-haiku-4-5
388
+ tools: read, grep, find, ls, bash
389
+ mode: tmux-print-json # tmux-interactive|tmux-print-json|tmux-rpc
390
+ cwdPolicy: parent # parent|explicit|project-root
391
+ maxRuntimeMs: 1800000
392
+ maxConcurrent: 4
393
+ ```
394
+
395
+ Rules:
396
+
397
+ - `name`, `role`, and `capability` must be normalized to bounded safe strings before use in telemetry.
398
+ - `name` may be shown in UI and tmux names, but it must not replace `pi.agent.id`.
399
+ - `role` and `capability` may become metric labels only if bounded by config validation.
400
+ - Project-local agent definitions require project trust and, in interactive mode, confirmation before execution.
401
+
402
+ ### Child Pi command requirements
403
+
404
+ The child command must guarantee ObservMe loads in the child runtime.
405
+
406
+ Acceptable approaches:
407
+
408
+ - ObservMe is installed globally as a Pi package and extension discovery is enabled.
409
+ - ObservMe is installed project-locally and the project is trusted.
410
+ - The orchestrator explicitly passes `-e <observme-extension-source>` to the child Pi command.
411
+
412
+ The child command must not use `--no-extensions` unless it also explicitly loads ObservMe. If a mode requires `--no-extensions` for isolation, the command must add ObservMe back explicitly.
413
+
414
+ Recommended child command inputs:
415
+
416
+ ```text
417
+ pi [observme-load-options] [mode-options] [model/tools options] [task]
418
+ ```
419
+
420
+ Examples of mode options:
421
+
422
+ ```text
423
+ --mode json -p --no-session
424
+ --mode rpc
425
+ # or normal interactive mode inside tmux
426
+ ```
427
+
428
+ Do not include raw prompt/task text in exported telemetry. Use hashes, lengths, bounded status, or redacted content only when capture is explicitly enabled.
429
+
430
+ ### Tmux session lifecycle
431
+
432
+ The orchestration extension should maintain a bounded in-memory registry for active tmux agents:
433
+
434
+ ```text
435
+ spawn_id
436
+ workflow_id
437
+ parent_agent_id
438
+ child_agent_id when known
439
+ agent_name
440
+ agent_role
441
+ agent_capability
442
+ tmux_session_name
443
+ tmux_window_id / pane_id when available
444
+ status: starting|active|completed|failed|cancelled|timeout|orphaned
445
+ started_at
446
+ last_status_at
447
+ ```
448
+
449
+ Telemetry rules:
450
+
451
+ - `spawn_id`, `workflow_id`, `parent_agent_id`, `child_agent_id`, and session ids are span/log attributes only.
452
+ - `agent_role`, `agent_capability`, `subagent_depth`, `spawn_type`, `spawn_reason`, `status`, and `reason` may be metric labels when bounded.
453
+ - Tmux pane ids and raw session names should be treated as operational metadata; prefer span/log attributes or hashed values, not metric labels.
454
+
455
+ Lifecycle operations:
456
+
457
+ 1. **Create**: validate agent definition, build lineage env, create tmux session, start child Pi.
458
+ 2. **Activate**: mark child status active after tmux and Pi startup are confirmed.
459
+ 3. **Wait**: record `pi.agent.wait` while parent waits for child output, exit, or status marker.
460
+ 4. **Join**: record `pi.agent.join` with terminal status and result summary.
461
+ 5. **Attach**: open or report the tmux attach command without exposing secrets.
462
+ 6. **Detach**: leave child running and keep status active.
463
+ 7. **Stop**: request graceful Pi shutdown first, then terminate tmux session after timeout.
464
+ 8. **Cleanup**: remove completed tmux sessions according to retention policy.
465
+
466
+ ### Management command surface
467
+
468
+ The future extension should expose commands or tools equivalent to:
469
+
470
+ ```text
471
+ /agents list
472
+ /agents start <agent> [task]
473
+ /agents status [agent|spawn]
474
+ /agents attach <agent|spawn>
475
+ /agents send <agent|spawn> <message>
476
+ /agents wait <agent|spawn>
477
+ /agents join <agent|spawn>
478
+ /agents stop <agent|spawn>
479
+ /agents cleanup
480
+ ```
481
+
482
+ If this is folded under ObservMe commands, use `/obs agents` only for observability and add a separate orchestration namespace for mutations. `/obs` query commands should remain read-only.
483
+
484
+ LLM-facing tools should be separate from user commands and must have clear schemas, prompt snippets, and prompt guidelines. Tool names must explicitly identify the tool in every guideline.
485
+
486
+ ### Result and status collection
487
+
488
+ The extension must define how a parent knows a tmux subagent has completed.
489
+
490
+ Allowed approaches:
491
+
492
+ - child process exits and the orchestrator captures exit status
493
+ - child writes a small status/result file with redacted/structured summary
494
+ - child emits JSON events that the orchestrator reads from a pipe/log
495
+ - child is controlled through RPC and returns an explicit response
496
+ - operator marks a tmux-interactive child as joined/cancelled
497
+ - backend query confirms terminal telemetry, with timeout fallback
498
+
499
+ The parent `join` record should include:
500
+
501
+ ```text
502
+ child status: ok|error|cancelled|timeout|partial|unknown
503
+ failure propagated: true|false
504
+ active children count
505
+ child count / fan-out count
506
+ safe result summary hash/length when available
507
+ ```
508
+
509
+ ### Trust model for propagated lineage
510
+
511
+ The implemented trust boundary is the child Pi process environment plus a complete generated spawn envelope:
512
+
513
+ 1. The parent creates a fresh `OBSERVME_SPAWN_ID` and validated workflow/parent/root/depth values around the `pi.agent.spawn` span.
514
+ 2. The launcher passes those values and W3C context directly to the child process after clearing stale ObservMe and W3C variables.
515
+ 3. The shipped child extension makes only the Pi process environment eligible for lineage; trusted project `.env` remains configuration-only.
516
+ 4. The child accepts the envelope only when every required value validates and the W3C and duplicate trace metadata agree.
517
+ 5. Invalid envelopes fail open without raw-value diagnostics. Explicit runtime overrides are reserved for controlled embedders and tests.
518
+
519
+ This is process-boundary validation, not a cryptographic launcher signature. A future orchestration extension may add signing if it needs stronger provenance against other code running as the same local user, but it must preserve the current bounded validation and fail-open behavior.
520
+
521
+ ### Isolation and safety
522
+
523
+ Tmux isolation does not sandbox filesystem or network access. A tmux child Pi process has the permissions of the user account.
524
+
525
+ Requirements:
526
+
527
+ - confirm project-local agents before running them unless the project is already trusted and policy disables confirmation
528
+ - do not pass secrets through command strings when a safer env/pipe path is available
529
+ - do not log raw env, raw task prompts, raw command lines, or full paths by default
530
+ - support cancellation and timeout for spawned children
531
+ - avoid unbounded local registries, output buffers, and result files
532
+ - clean up temporary files containing prompts or status details
533
+ - fail open for ObservMe export failures, but fail safely for orchestration control errors
534
+
535
+ ## 6. Spans and logs required for dashboards
536
+
537
+ ### Spans
538
+
539
+ Required span names:
540
+
541
+ ```text
542
+ pi.session
543
+ pi.agent.run
544
+ pi.turn
545
+ pi.llm.request
546
+ pi.tool.call
547
+ pi.agent.spawn
548
+ pi.agent.wait
549
+ pi.agent.join
550
+ pi.bash.execution
551
+ pi.compaction
552
+ pi.branch
553
+ ```
554
+
555
+ Agent/subagent-specific spans:
556
+
557
+ - `pi.agent.run`: one prompt lifecycle in current agent runtime.
558
+ - `pi.agent.spawn`: parent operation that launches a child Pi process.
559
+ - `pi.agent.wait`: parent waiting for child progress/completion.
560
+ - `pi.agent.join`: parent collecting child result/status.
561
+
562
+ ### Logs
563
+
564
+ Agent-tree log events expected by Loki dashboards:
565
+
566
+ ```text
567
+ agent.run.started
568
+ agent.run.completed
569
+ agent.run.failed
570
+ agent.spawn.started
571
+ agent.spawn.completed
572
+ agent.spawn.failed
573
+ agent.wait.started
574
+ agent.wait.completed
575
+ agent.join.started
576
+ agent.join.completed
577
+ agent.orphaned
578
+ trace_context.propagation_failed
579
+ ```
580
+
581
+ Agent-tree logs use:
582
+
583
+ ```text
584
+ event.category = agent-tree
585
+ ```
586
+
587
+ Loki normalizes dotted OTEL names, so Grafana queries use labels such as:
588
+
589
+ ```text
590
+ event_name
591
+ pi_agent_id
592
+ pi_agent_parent_id
593
+ pi_agent_root_id
594
+ pi_workflow_id
595
+ pi_agent_spawn_id
596
+ ```
597
+
598
+ ## 7. Metrics required by the dashboards
599
+
600
+ Prometheus metrics must use only low-cardinality labels.
601
+
602
+ ### Agent run metrics
603
+
604
+ ```text
605
+ observme_agent_runs_total
606
+ observme_agent_run_errors_total
607
+ observme_agent_run_duration_ms
608
+ ```
609
+
610
+ Expected labels:
611
+
612
+ ```text
613
+ agent_role
614
+ environment
615
+ provider/model only for LLM metrics, not agent-run metrics
616
+ ```
617
+
618
+ Dashboard examples:
619
+
620
+ ```promql
621
+ sum(rate(observme_agent_runs_total[$__rate_interval])) by (agent_role)
622
+ histogram_quantile(0.95, sum(rate(observme_agent_run_duration_ms_bucket[$__rate_interval])) by (agent_role, le))
623
+ ```
624
+
625
+ ### Subagent spawn metrics
626
+
627
+ ```text
628
+ observme_subagents_spawned_total
629
+ observme_subagent_spawn_failures_total
630
+ observme_subagent_spawn_duration_ms
631
+ ```
632
+
633
+ Expected labels:
634
+
635
+ ```text
636
+ agent_role
637
+ subagent_depth
638
+ spawn_type
639
+ spawn_reason
640
+ error_class only on failures
641
+ ```
642
+
643
+ Dashboard examples:
644
+
645
+ ```promql
646
+ sum(rate(observme_subagents_spawned_total[$__rate_interval])) by (subagent_depth, spawn_type, spawn_reason)
647
+ sum(rate(observme_subagent_spawn_failures_total[$__rate_interval])) by (subagent_depth, spawn_type, spawn_reason, error_class)
648
+ histogram_quantile(0.95, sum(rate(observme_subagent_spawn_duration_ms_bucket[$__rate_interval])) by (agent_role, spawn_type, spawn_reason, le))
649
+ ```
650
+
651
+ ### Agent tree metrics
652
+
653
+ ```text
654
+ observme_active_agents
655
+ observme_agent_tree_depth
656
+ observme_agent_tree_width
657
+ observme_agent_fanout_count
658
+ ```
659
+
660
+ Expected labels:
661
+
662
+ ```text
663
+ agent_role
664
+ subagent_depth
665
+ ```
666
+
667
+ Dashboard examples:
668
+
669
+ ```promql
670
+ sum(observme_active_agents) by (agent_role, subagent_depth)
671
+ histogram_quantile(0.95, sum(rate(observme_agent_tree_depth_bucket[$__rate_interval])) by (subagent_depth, le))
672
+ histogram_quantile(0.95, sum(rate(observme_agent_tree_width_bucket[$__rate_interval])) by (subagent_depth, le))
673
+ histogram_quantile(0.95, sum(rate(observme_agent_fanout_count_bucket[$__rate_interval])) by (subagent_depth, le))
674
+ ```
675
+
676
+ ### Lineage health metrics
677
+
678
+ ```text
679
+ observme_orphan_agents_total
680
+ observme_trace_context_propagation_failures_total
681
+ ```
682
+
683
+ Expected labels:
684
+
685
+ ```text
686
+ agent_role
687
+ subagent_depth
688
+ reason/status as bounded enums
689
+ ```
690
+
691
+ Dashboard examples:
692
+
693
+ ```promql
694
+ sum(rate(observme_orphan_agents_total[$__rate_interval])) by (agent_role, subagent_depth)
695
+ sum(rate(observme_trace_context_propagation_failures_total[$__rate_interval])) by (agent_role, subagent_depth)
696
+ ```
697
+
698
+ ### Wait/join and child failure metrics
699
+
700
+ ```text
701
+ observme_agent_wait_duration_ms
702
+ observme_agent_join_duration_ms
703
+ observme_child_agent_failures_total
704
+ observme_parent_recovered_from_child_failure_total
705
+ ```
706
+
707
+ Expected labels:
708
+
709
+ ```text
710
+ agent_role
711
+ subagent_depth
712
+ status/reason as bounded enums when needed
713
+ ```
714
+
715
+ Dashboard examples:
716
+
717
+ ```promql
718
+ histogram_quantile(0.95, sum(rate(observme_agent_wait_duration_ms_bucket[$__rate_interval])) by (agent_role, le))
719
+ histogram_quantile(0.95, sum(rate(observme_agent_join_duration_ms_bucket[$__rate_interval])) by (agent_role, le))
720
+ sum(rate(observme_child_agent_failures_total[$__rate_interval])) by (agent_role, subagent_depth)
721
+ sum(rate(observme_parent_recovered_from_child_failure_total[$__rate_interval])) by (agent_role, subagent_depth)
722
+ ```
723
+
724
+ ## 8. Labels that are allowed vs forbidden
725
+
726
+ ### Allowed metric labels
727
+
728
+ Low-cardinality labels allowed for aggregates:
729
+
730
+ ```text
731
+ agent_role
732
+ agent_capability
733
+ subagent_depth
734
+ spawn_type
735
+ spawn_reason
736
+ status
737
+ reason
738
+ error_class
739
+ environment
740
+ provider
741
+ model
742
+ tool_name
743
+ tool_category
744
+ operation
745
+ ```
746
+
747
+ ### Forbidden metric labels
748
+
749
+ These may appear on traces/logs, but must not be Prometheus labels:
750
+
751
+ ```text
752
+ session_id
753
+ workflow_id
754
+ workflow_root_agent_id
755
+ agent_id
756
+ parent_agent_id
757
+ child_agent_id
758
+ agent_run_id
759
+ spawn_id
760
+ spawn_tool_call_id
761
+ trace_id
762
+ span_id
763
+ entry_id
764
+ tool_call_id
765
+ raw_command
766
+ raw_prompt
767
+ raw_path
768
+ raw_error_message
769
+ ```
770
+
771
+ The production Collector config reinforces this by deleting high-cardinality metric resource attributes such as `pi.workflow.id`, `pi.agent.id`, `pi.agent.parent_id`, `pi.agent.root_id`, `pi.agent.spawn.id`, `pi.agent.child.id`, and `pi.session.id` from the metrics pipeline.
772
+
773
+ ## 9. What `/obs agents` needs
774
+
775
+ `/obs agents` combines:
776
+
777
+ 1. In-memory runtime state from the current Pi process.
778
+ 2. Prometheus aggregate queries.
779
+ 3. Tempo trace search by safe lineage attributes.
780
+
781
+ It renders:
782
+
783
+ - workflow id and root id
784
+ - current agent id, role, and depth
785
+ - current session id
786
+ - fan-out count in current trace
787
+ - tree depth/width/active/orphan counts
788
+ - recent children
789
+ - wait/join hints
790
+ - aggregate series counts
791
+ - Tempo drill-down attributes and latest trace id
792
+
793
+ Current PromQL used by `/obs agents`:
794
+
795
+ ```promql
796
+ sum(rate(observme_subagents_spawned_total[1h])) by (agent_role, subagent_depth, spawn_type, spawn_reason)
797
+ histogram_quantile(0.95, sum(rate(observme_agent_fanout_count_bucket[1h])) by (subagent_depth, le))
798
+ sum(rate(observme_orphan_agents_total[1h])) by (agent_role, subagent_depth)
799
+ ```
800
+
801
+ Tempo drill-down uses span attributes:
802
+
803
+ ```text
804
+ pi.agent.id
805
+ pi.workflow.id
806
+ ```
807
+
808
+ These are query attributes, not metric labels.
809
+
810
+ ## 10. Pi subagent example and tmux compatibility
811
+
812
+ The Pi example subagent extension:
813
+
814
+ - registers a `subagent` tool
815
+ - supports single, parallel, and chain modes
816
+ - discovers user agents from `~/.pi/agent/agents/*.md`
817
+ - optionally discovers project agents from `.pi/agents/*.md`
818
+ - spawns child `pi` processes with `child_process.spawn(...)`
819
+ - runs children with `--mode json -p --no-session`
820
+ - reads child JSON events from stdout
821
+ - collects child assistant messages, tool results, token usage, cost, and final output
822
+ - supports Ctrl+C abort by killing child processes
823
+
824
+ By default, the example spawn call does not pass ObservMe propagation env and does not call ObservMe's `startSubagentSpawn` / `completeSubagentSpawn` / `failSubagentSpawn` helpers.
825
+
826
+ Therefore, to use that style of subagent and still populate ObservMe dashboards, an ObservMe-aware adapter must wrap the child process spawn and pass the returned env to the child process.
827
+
828
+ Minimum adapter behavior:
829
+
830
+ 1. Before spawning child Pi, call `startSubagentSpawn` with spawn type/reason and safe command metadata.
831
+ 2. Pass `started.env` into `child_process.spawn`.
832
+ 3. On child process close success, call `completeSubagentSpawn`.
833
+ 4. On child process error/abort/failure, call `failSubagentSpawn` or complete with cancelled/failed status.
834
+ 5. Around blocking waits, record `pi.agent.wait`.
835
+ 6. When child output is collected, record `pi.agent.join` with child status.
836
+ 7. Ensure the child command loads ObservMe as an extension/package.
837
+ 8. Ensure the child ObservMe runtime accepts the propagated parent context as trusted.
838
+
839
+ Without that adapter, parent tool metrics may show a `subagent` tool call, but the agent-tree dashboard will not have reliable spawn/depth/fan-out/wait/join lineage.
840
+
841
+ ### Tmux compatibility conclusion
842
+
843
+ Running subagents in tmux is supported by the requirements, but tmux must be integrated as an ObservMe-aware runner.
844
+
845
+ The correct mental model is:
846
+
847
+ ```text
848
+ parent Pi + ObservMe
849
+ -> orchestration extension starts pi.agent.spawn
850
+ -> orchestration extension starts tmux with explicit ObservMe env
851
+ -> child Pi starts inside tmux and loads ObservMe
852
+ -> child ObservMe accepts trusted parent lineage
853
+ -> parent records wait/join based on tmux/process/result status
854
+ -> Grafana correlates parent and child by workflow/agent lineage
855
+ ```
856
+
857
+ If the child loads ObservMe but does not receive or trust parent lineage, the child is observable but not connected as a subagent.
858
+
859
+ ## 11. Dashboard readiness checklist
860
+
861
+ Use this checklist before expecting subagents to appear correctly in Grafana.
862
+
863
+ ### Parent process
864
+
865
+ - [ ] ObservMe extension is loaded in the parent Pi process.
866
+ - [ ] Parent has emitted `session_start`.
867
+ - [ ] Parent has a current `pi.workflow.id` and `pi.agent.id`.
868
+ - [ ] `workflow.enabled=true`.
869
+ - [ ] `agent.propagateToSubagents=true`.
870
+ - [ ] Parent subagent launcher uses ObservMe spawn helpers.
871
+ - [ ] Parent passes returned env into the child Pi process.
872
+ - [ ] In tmux mode, parent injects env explicitly into the tmux child command and does not rely on stale tmux server env.
873
+ - [ ] Parent records tmux session/pane status in a bounded local registry.
874
+ - [ ] Parent records spawn completion/failure.
875
+ - [ ] Parent records wait/join if it waits for child output, process exit, status marker, or operator action.
876
+
877
+ ### Child process
878
+
879
+ - [ ] Child Pi process loads ObservMe.
880
+ - [ ] Child command does not use `--no-extensions` unless ObservMe is explicitly re-added.
881
+ - [ ] Child receives `OBSERVME_WORKFLOW_ID`, `OBSERVME_PARENT_AGENT_ID`, `OBSERVME_ROOT_AGENT_ID`, `OBSERVME_AGENT_DEPTH`, and `OBSERVME_SPAWN_ID`.
882
+ - [ ] Child receives `traceparent` when trace propagation is enabled and possible.
883
+ - [ ] Child accepts propagated ObservMe env as trusted parent context.
884
+ - [ ] Child exports OTLP to the configured Collector/backend.
885
+ - [ ] In tmux-interactive mode, operators can attach/detach without changing lineage or losing telemetry.
886
+
887
+ ### Collector/backend
888
+
889
+ - [ ] Traces pipeline preserves `pi.workflow.*` and `pi.agent.*` attributes.
890
+ - [ ] Logs pipeline preserves normalized event labels/metadata needed by Loki dashboards.
891
+ - [ ] Metrics pipeline drops high-cardinality lineage attributes but preserves safe labels.
892
+ - [ ] Prometheus contains `observme_subagents_spawned_total` after a subagent run.
893
+ - [ ] Loki contains `event_category="agent-tree"` logs.
894
+ - [ ] Tempo can search by `pi.workflow.id` or `pi.agent.id`.
895
+
896
+ ### Quick checks
897
+
898
+ Prometheus:
899
+
900
+ ```promql
901
+ sum(rate(observme_subagents_spawned_total[5m])) by (agent_role, subagent_depth, spawn_type, spawn_reason)
902
+ sum(rate(observme_orphan_agents_total[5m])) by (agent_role, subagent_depth)
903
+ sum(rate(observme_trace_context_propagation_failures_total[5m])) by (agent_role, subagent_depth)
904
+ ```
905
+
906
+ Loki:
907
+
908
+ ```logql
909
+ {service_name="observme-pi-extension", event_category="agent-tree"}
910
+ {service_name="observme-pi-extension", event_name="agent.spawn.completed"}
911
+ {service_name="observme-pi-extension", event_name="agent.orphaned"}
912
+ {service_name="observme-pi-extension", event_name="trace_context.propagation_failed"}
913
+ ```
914
+
915
+ Pi command:
916
+
917
+ ```text
918
+ /obs agents
919
+ ```
920
+
921
+ ### Dashboard navigation note
922
+
923
+ Use the improved dashboards in this order when validating a root-agent/subagent scenario:
924
+
925
+ 1. Start in **ObservMe Overview** and confirm the `Agent lineage` and `Health` rows are green or intentionally idle.
926
+ 2. Open **Trace Journey** with the same time range and apply Loki/Tempo-only `session_id`, `workflow_id`, `agent_id`, or `agent_run_id` filters to follow one execution.
927
+ 3. Open **Agents and Subagents** for spawn failure, orphan, propagation, child recovery, wait/join, fan-out, and depth ratios, then use the handoff rows to jump back to Trace Journey or Tempo.
928
+ 4. Open **Agent Node Graphs** only for aggregate topology; it shows selected-range counts and red health nodes/edges, not a single trace tree.
929
+ 5. Open **SLO Health** or **Export Health** when lineage panels look empty or stale, because healthy idle ranges, missing optional child telemetry, and export failures have different meanings.
930
+
931
+ High-cardinality identifiers remain log/trace filters only. Prometheus panels should continue to use bounded labels such as `agent_role`, `subagent_depth`, `spawn_type`, `spawn_reason`, `status`, `reason`, and `error_class`.
932
+
933
+ ### Dashboard implementation note
934
+
935
+ The Agents and Agent Node Graphs dashboards now surface the main operator questions directly: spawn failure ratio, orphan pressure, trace-context propagation failure ratio, child recovery ratio, depth/fan-out alert references, slow/failing/orphan/high-fan-out top tables, and Loki handoff rows with Trace Journey/Tempo drill-down links. The node graphs also include red health nodes/edges for failed spawns, orphan lineage, and propagation failures alongside selected-range counts.
936
+
937
+ `agent_capability` remains deliberately absent from dashboard filters until a launcher emits a bounded capability label consistently. Keep capability detail in Loki/Tempo or orchestration-local state unless the launcher maps names into a documented low-cardinality enum.
938
+
939
+ ## 12. Current implementation checkpoints and gaps
940
+
941
+ These checkpoints reflect the current code and dashboards after source-review remediation.
942
+
943
+ ### Present pieces
944
+
945
+ - Agent lineage generation and complete propagated-envelope validation exist in `src/pi/agent-lineage.ts`.
946
+ - The production extension enables process-environment lineage eligibility while keeping trusted project `.env` outside the provenance boundary.
947
+ - Valid W3C context explicitly parents the child `pi.session`; unavailable continuation uses a validated span link or bounded propagation-failure fallback.
948
+ - Bounded agent-tree tracking exists in `src/pi/agent-tree-tracker.ts`.
949
+ - Spawn/wait/join helper functions exist in `src/pi/subagent-spawn.ts`.
950
+ - Spawn duration is recorded on completion and launcher failure. Child completion/join records child failure and confirmed parent recovery once through bounded deduplication state.
951
+ - Session, agent-run/turn, LLM, tool/bash, and session metadata/tree handlers are split under `src/pi/event-handlers/` behind the stable `src/pi/handlers.ts` facade.
952
+ - Root workflow duration is recorded at shutdown, and failed agent runs increment `observme_agent_run_errors_total`.
953
+ - `/obs agents` is implemented and uses local runtime state, Prometheus aggregates, and Tempo drill-down attributes.
954
+ - Grafana dashboards include agent/subagent panels and alert/SLO rules.
955
+ - Tests cover child trace parenting, sanitized propagation fallback, spawn duration, child failure/recovery deduplication, wait/join spans, and low-cardinality metric labels.
956
+
957
+ ### Remaining integration gaps before relying on full subagent dashboards
958
+
959
+ 1. **External and tmux subagent launchers are not automatically wrapped.**
960
+ - `src/pi/subagent-spawn.ts` exposes helpers, but arbitrary extensions that call `child_process.spawn` or `tmux new-session` will not be detected automatically.
961
+ - The Pi example subagent extension currently spawns child Pi processes without ObservMe env propagation.
962
+ - A future tmux orchestration extension must own this wrapping and lifecycle tracking.
963
+
964
+ 2. **Some dashboard label expectations remain broader than current emitted labels.**
965
+ - `observme_active_agents` currently carries `environment` and `agent_role`, not `subagent_depth`.
966
+ - `observme_subagent_spawn_failures_total` carries `spawn_type` and `error_class`, while some dashboard queries also group by depth/reason.
967
+ - Orphan signals emitted by tracker and session-propagation paths do not yet share one identical label set.
968
+ - These missing dimensions do not introduce high cardinality, but affected grouped panels may show blank label values until the metric contract is aligned.
969
+
970
+ 3. **Agent capability is not automatically derived from Pi markdown agent definitions.**
971
+ - If dashboards should show `agent_capability`, the subagent launcher must map agent names/capabilities into a documented bounded enum before metrics use them.
972
+
973
+ 4. **Tmux management state does not exist yet.**
974
+ - ObservMe has bounded in-memory telemetry agent-tree state, but not a tmux orchestration registry for session names, panes, attach commands, stop/cleanup state, or result collection.
975
+ - A future extension must add that management layer while keeping telemetry privacy and cardinality boundaries intact.
976
+
977
+ ## 13. Decision summary
978
+
979
+ To use subagents and have them appear in ObservMe dashboards, the extension must treat subagent support as explicit instrumentation, not passive observation.
980
+
981
+ Required decisions:
982
+
983
+ 1. **Subagent spawn point:** choose the exact launcher(s) to wrap, including tmux session creation and any direct `child_process.spawn` paths.
984
+ 2. **Tmux control model:** decide supported modes (`tmux-interactive`, `tmux-print-json`, `tmux-rpc`), session naming, attach/detach behavior, status detection, and cleanup policy.
985
+ 3. **Trust model:** use the implemented complete process-envelope boundary; decide whether a future orchestrator also needs cryptographic signing against same-user processes.
986
+ 4. **Child ObservMe loading:** decide whether child Pi commands rely on installed ObservMe packages or receive explicit `-e` extension loading.
987
+ 5. **Capability mapping:** decide whether Pi markdown agent names map to `agent_capability`, `agent_role`, both, or neither.
988
+ 6. **Metric label contract:** align the remaining active-agent, spawn-failure, and orphan dashboard dimensions while keeping high-cardinality ids out of labels.
989
+ 7. **Duration/failure accounting:** use the implemented elapsed spawn duration and deduplicated child failure/recovery counters at completion/join transitions.
990
+ 8. **Packaging:** ensure both parent and child Pi processes load ObservMe and share compatible config/export endpoints.
991
+ 9. **Management command surface:** define commands/tools for list, start, status, attach, send, wait, join, stop, and cleanup.
992
+
993
+ Once those decisions are implemented, root agents and subagents can be distinguished as follows:
994
+
995
+ - Root agent: no parent id, depth `0`, role `root` or `orchestrator`.
996
+ - Subagent: has parent id, inherited workflow/root id, depth `1+`, role `subagent` or a bounded worker role.
997
+ - Orphan: has incomplete/broken parent lineage or parent cannot be linked, with orphan logs/metrics emitted.