@nifrajs/agent-telemetry 3.1.0 → 3.3.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.
package/README.md CHANGED
@@ -16,6 +16,35 @@ Requests under `/_nifra/tool/*` and requests to `/mcp` receive tool-name, input-
16
16
  duration, and status observations. When `@nifrajs/otel` owns the request observation, tool spans are
17
17
  attached as children; otherwise the plugin creates a standalone observation. Other routes pass through.
18
18
 
19
+ ## Tracing agent runs
20
+
21
+ `traceAgentRun` turns a `@nifrajs/agent` run's step evidence into an OpenTelemetry trace: one
22
+ `nifra.agent.run` span per run, one child span per evidence item, with tool names, effect ids, error
23
+ codes, and effect-ledger heads carried as span attributes. Only the runner's constrained evidence
24
+ fields are exported - prompts, tool inputs, and outputs cannot enter a trace.
25
+
26
+ Orchestration correlation is opt-in and cardinality-bounded. Allowed attributes are run, plan, node,
27
+ attempt, evidence, replay, and trace coordinates plus bounded status/error codes. Content-bearing or
28
+ unbounded attributes are rejected; the exporter is not a payload retention sink.
29
+
30
+ ```ts
31
+ import { traceAgentRun } from "@nifrajs/agent-telemetry"
32
+ import { combineAgentTelemetry, runAgent } from "@nifrajs/agent"
33
+
34
+ const trace = traceAgentRun({ agent: agent.name, turnId, exporter })
35
+ const result = await runAgent(agent, input, {
36
+ ...ports,
37
+ telemetry: combineAgentTelemetry(ports.telemetry, trace.telemetry),
38
+ })
39
+ trace.end(result)
40
+ ```
41
+
42
+ Model evidence arrives as a started/terminal pair and becomes one timed `nifra.agent.model` span;
43
+ tool, approval, budget, and state evidence are terminal-only and become instant children. Pass
44
+ `parent` (for example the enclosing request observation's `context`) to nest runs under the HTTP
45
+ span, or `traceparent` to continue an inbound W3C trace; `trace.context` is the run span's identity,
46
+ forwardable with `traceHeaders`. Telemetry is fail-open: a throwing exporter never fails the turn.
47
+
19
48
  ## For AI agents
20
49
 
21
50
  Start with [`LLM.md`](./LLM.md) - this package's contract card (the exports you call + its footguns),
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@
9
9
  * routes on the sync fast path unless hooks are present at registration time.
10
10
  */
11
11
  import { type ActiveObservation, type ObservationAdapter } from "@nifrajs/otel";
12
+ export { type AgentRunEvidence, type AgentRunOutcome, type AgentRunTrace, type TraceAgentRunOptions, traceAgentRun, } from "./run.js";
12
13
  export interface AgentTelemetryOptions {
13
14
  /** Exporter that receives completed tool-call spans. */
14
15
  readonly exporter: ObservationAdapter;
@@ -50,5 +51,35 @@ export declare function agentTelemetry(options: AgentTelemetryOptions): {
50
51
  * ```
51
52
  */
52
53
  export declare function consoleAgentExporter(log?: (line: string) => void): ObservationAdapter;
53
- export {};
54
+ /** Content-free lifecycle kinds emitted by run dispatch and recovery. */
55
+ export type OrchestrationTelemetryKind = "started" | "checkpointed" | "retrying" | "recovered" | "cancelled" | "completed" | "failed" | "dead-lettered";
56
+ /** Allowlisted correlation fields. No index signature is intentional: arbitrary attributes are rejected. */
57
+ export interface OrchestrationTelemetryEvent {
58
+ readonly kind: OrchestrationTelemetryKind;
59
+ readonly runId: string;
60
+ readonly planDigest: string;
61
+ readonly nodeId: string;
62
+ readonly attempt: number;
63
+ readonly evidenceSeq: number;
64
+ readonly at: number;
65
+ readonly evidenceId?: string;
66
+ readonly replayId?: string;
67
+ readonly traceRef?: string;
68
+ readonly scheduleToken?: string;
69
+ readonly statusCode?: string;
70
+ }
71
+ export interface OrchestrationTelemetryOptions {
72
+ /** No exporter means disabled telemetry and zero spans. */
73
+ readonly exporter?: ObservationAdapter;
74
+ readonly adapters?: readonly ObservationAdapter[];
75
+ readonly maxDistinctValues?: number;
76
+ }
77
+ export interface OrchestrationTelemetry {
78
+ readonly enabled: boolean;
79
+ readonly dropped: number;
80
+ record(event: OrchestrationTelemetryEvent | unknown): boolean;
81
+ close(): void;
82
+ }
83
+ /** Create an opt-in, bounded telemetry bridge for run/retry/recovery correlation. */
84
+ export declare function orchestrationTelemetry(options?: OrchestrationTelemetryOptions): OrchestrationTelemetry;
54
85
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,KAAK,iBAAiB,EAEtB,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAA;AAMtB,MAAM,WAAW,qBAAqB;IACpC,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAA;IACrC,qEAAqE;IACrE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C,oDAAoD;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACtC;AAED,gEAAgE;AAChE,UAAU,WAAW;IACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE;QACf,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;QACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAC1B,CAAA;IACD,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAA;CACzC;AAMD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB;;0BAUnC,WAAW;mBAiClB,OAAO,WAAW,WAAW;yBAMvB,QAAQ,WAAW,OAAO;EAqDlD;AAMD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAEtB,GACA,kBAAkB,CAWpB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,KAAK,iBAAiB,EAEtB,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAA;AAEtB,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,aAAa,GACd,MAAM,UAAU,CAAA;AAMjB,MAAM,WAAW,qBAAqB;IACpC,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAA;IACrC,qEAAqE;IACrE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5C,oDAAoD;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACtC;AAED,gEAAgE;AAChE,UAAU,WAAW;IACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE;QACf,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;QACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAC1B,CAAA;IACD,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAA;CACzC;AAMD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB;;0BAUnC,WAAW;mBAiClB,OAAO,WAAW,WAAW;yBAMvB,QAAQ,WAAW,OAAO;EAqDlD;AAMD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAEtB,GACA,kBAAkB,CAWpB;AAMD,yEAAyE;AACzE,MAAM,MAAM,0BAA0B,GAClC,SAAS,GACT,cAAc,GACd,UAAU,GACV,WAAW,GACX,WAAW,GACX,WAAW,GACX,QAAQ,GACR,eAAe,CAAA;AAEnB,4GAA4G;AAC5G,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAA;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,6BAA6B;IAC5C,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACjD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,MAAM,CAAC,KAAK,EAAE,2BAA2B,GAAG,OAAO,GAAG,OAAO,CAAA;IAC7D,KAAK,IAAI,IAAI,CAAA;CACd;AAiID,qFAAqF;AACrF,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,6BAAkC,GAC1C,sBAAsB,CA0DxB"}
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@
9
9
  * routes on the sync fast path unless hooks are present at registration time.
10
10
  */
11
11
  import { createObservationLifecycle, } from "@nifrajs/otel";
12
+ export { traceAgentRun, } from "./run.js";
12
13
  // ---------------------------------------------------------------------------
13
14
  // Middleware
14
15
  // ---------------------------------------------------------------------------
@@ -135,4 +136,186 @@ export function consoleAgentExporter(log = (line) => {
135
136
  },
136
137
  };
137
138
  }
139
+ const ORCHESTRATION_TOKEN = /^[A-Za-z0-9._:-]{1,128}$/;
140
+ const ORCHESTRATION_DIGEST = /^[0-9a-f]{64}$/;
141
+ const ORCHESTRATION_KINDS = new Set([
142
+ "started",
143
+ "checkpointed",
144
+ "retrying",
145
+ "recovered",
146
+ "cancelled",
147
+ "completed",
148
+ "failed",
149
+ "dead-lettered",
150
+ ]);
151
+ const ORCHESTRATION_FIELDS = new Set([
152
+ "kind",
153
+ "runId",
154
+ "planDigest",
155
+ "nodeId",
156
+ "attempt",
157
+ "evidenceSeq",
158
+ "at",
159
+ "evidenceId",
160
+ "replayId",
161
+ "traceRef",
162
+ "scheduleToken",
163
+ "statusCode",
164
+ ]);
165
+ const ORCHESTRATION_FORBIDDEN = new Set([
166
+ "prompt",
167
+ "message",
168
+ "text",
169
+ "input",
170
+ "output",
171
+ "arguments",
172
+ "body",
173
+ "response",
174
+ "secret",
175
+ "credential",
176
+ "diagnostic",
177
+ "stack",
178
+ "content",
179
+ "transcript",
180
+ "artifact",
181
+ "path",
182
+ ]);
183
+ function orchestrationRecord(value) {
184
+ return typeof value === "object" && value !== null && !Array.isArray(value);
185
+ }
186
+ function boundedTelemetryToken(value) {
187
+ return typeof value === "string" && ORCHESTRATION_TOKEN.test(value);
188
+ }
189
+ function parseOrchestrationEvent(value) {
190
+ if (!orchestrationRecord(value))
191
+ return undefined;
192
+ for (const key of Object.keys(value)) {
193
+ if (ORCHESTRATION_FORBIDDEN.has(key.toLowerCase()) || !ORCHESTRATION_FIELDS.has(key))
194
+ return undefined;
195
+ }
196
+ if (typeof value.kind !== "string" ||
197
+ !ORCHESTRATION_KINDS.has(value.kind) ||
198
+ !boundedTelemetryToken(value.runId) ||
199
+ !boundedTelemetryToken(value.nodeId) ||
200
+ typeof value.planDigest !== "string" ||
201
+ !ORCHESTRATION_DIGEST.test(value.planDigest) ||
202
+ typeof value.at !== "number" ||
203
+ !Number.isSafeInteger(value.at) ||
204
+ value.at < 0 ||
205
+ typeof value.attempt !== "number" ||
206
+ !Number.isSafeInteger(value.attempt) ||
207
+ value.attempt < 1 ||
208
+ typeof value.evidenceSeq !== "number" ||
209
+ !Number.isSafeInteger(value.evidenceSeq) ||
210
+ value.evidenceSeq < 0)
211
+ return undefined;
212
+ for (const key of [
213
+ "evidenceId",
214
+ "replayId",
215
+ "traceRef",
216
+ "scheduleToken",
217
+ "statusCode",
218
+ ]) {
219
+ const candidate = value[key];
220
+ if (candidate !== undefined && !boundedTelemetryToken(candidate))
221
+ return undefined;
222
+ }
223
+ return Object.freeze({
224
+ kind: value.kind,
225
+ runId: value.runId,
226
+ planDigest: value.planDigest,
227
+ nodeId: value.nodeId,
228
+ attempt: value.attempt,
229
+ evidenceSeq: value.evidenceSeq,
230
+ at: value.at,
231
+ ...(value.evidenceId === undefined ? {} : { evidenceId: value.evidenceId }),
232
+ ...(value.replayId === undefined ? {} : { replayId: value.replayId }),
233
+ ...(value.traceRef === undefined ? {} : { traceRef: value.traceRef }),
234
+ ...(value.scheduleToken === undefined ? {} : { scheduleToken: value.scheduleToken }),
235
+ ...(value.statusCode === undefined ? {} : { statusCode: value.statusCode }),
236
+ });
237
+ }
238
+ function orchestrationAttributes(event) {
239
+ return {
240
+ "nifra.orchestration.run_id": event.runId,
241
+ "nifra.orchestration.plan_digest": event.planDigest,
242
+ "nifra.orchestration.node_id": event.nodeId,
243
+ "nifra.orchestration.attempt": event.attempt,
244
+ "nifra.orchestration.evidence_seq": event.evidenceSeq,
245
+ "nifra.orchestration.at": event.at,
246
+ ...(event.evidenceId === undefined
247
+ ? {}
248
+ : { "nifra.orchestration.evidence_id": event.evidenceId }),
249
+ ...(event.replayId === undefined ? {} : { "nifra.orchestration.replay_id": event.replayId }),
250
+ ...(event.traceRef === undefined ? {} : { "nifra.orchestration.trace_ref": event.traceRef }),
251
+ ...(event.scheduleToken === undefined
252
+ ? {}
253
+ : { "nifra.orchestration.schedule": event.scheduleToken }),
254
+ ...(event.statusCode === undefined
255
+ ? {}
256
+ : { "nifra.orchestration.status_code": event.statusCode }),
257
+ };
258
+ }
259
+ /** Create an opt-in, bounded telemetry bridge for run/retry/recovery correlation. */
260
+ export function orchestrationTelemetry(options = {}) {
261
+ const adapters = [
262
+ ...(options.exporter === undefined ? [] : [options.exporter]),
263
+ ...(options.adapters ?? []),
264
+ ];
265
+ const enabled = adapters.length > 0;
266
+ const maxDistinct = options.maxDistinctValues ?? 512;
267
+ if (!Number.isSafeInteger(maxDistinct) || maxDistinct < 1 || maxDistinct > 10_000)
268
+ throw new RangeError("orchestration telemetry maxDistinctValues is invalid");
269
+ if (!enabled)
270
+ return {
271
+ enabled: false,
272
+ get dropped() {
273
+ return 0;
274
+ },
275
+ record: () => false,
276
+ close: () => undefined,
277
+ };
278
+ const lifecycle = createObservationLifecycle({ adapters });
279
+ const run = lifecycle.start({ name: "nifra.orchestration.run", attributes: {} });
280
+ const distinct = new Map();
281
+ let droppedCount = 0;
282
+ let closed = false;
283
+ const record = (raw) => {
284
+ if (closed)
285
+ return false;
286
+ const event = parseOrchestrationEvent(raw);
287
+ if (event === undefined) {
288
+ droppedCount = Math.min(1_000_000, droppedCount + 1);
289
+ return false;
290
+ }
291
+ const attrs = orchestrationAttributes(event);
292
+ for (const [key, value] of Object.entries(attrs)) {
293
+ if (typeof value !== "string")
294
+ continue;
295
+ const values = distinct.get(key) ?? new Set();
296
+ if (!values.has(value) && values.size >= maxDistinct) {
297
+ droppedCount = Math.min(1_000_000, droppedCount + 1);
298
+ return false;
299
+ }
300
+ values.add(value);
301
+ distinct.set(key, values);
302
+ }
303
+ const status = event.kind === "failed" || event.kind === "dead-lettered" ? "error" : "ok";
304
+ run.startChild({ name: `nifra.orchestration.${event.kind}`, attributes: attrs }).end({ status });
305
+ return true;
306
+ };
307
+ return {
308
+ enabled: true,
309
+ get dropped() {
310
+ return droppedCount;
311
+ },
312
+ record,
313
+ close() {
314
+ if (closed)
315
+ return;
316
+ closed = true;
317
+ run.end({ status: "ok" });
318
+ },
319
+ };
320
+ }
138
321
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/run.d.ts ADDED
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Agent-run tracing - one OpenTelemetry span per bounded agent run, one child span per step
3
+ * evidence item, effect ledger heads carried as span attributes.
4
+ *
5
+ * The bridge consumes only the runner's constrained step-evidence contract (`seq`, `kind`,
6
+ * `outcome`, tool name, effect id, error code, ledger head): prompts, tool inputs, and outputs
7
+ * cannot enter an export. The evidence shape is declared structurally so the package stays
8
+ * dependency-free on `@nifrajs/agent`; the returned `telemetry` object satisfies its
9
+ * `AgentTelemetryPort` as-is.
10
+ */
11
+ import { type ObservationAdapter, type ObservationContext, type ObservationParent } from "@nifrajs/otel";
12
+ /** Structural twin of `@nifrajs/agent`'s `AgentStepEvidence`. */
13
+ export interface AgentRunEvidence {
14
+ readonly seq: number;
15
+ readonly at: number;
16
+ readonly kind: "model" | "tool" | "approval" | "budget" | "state";
17
+ readonly outcome: "started" | "passed" | "failed" | "denied" | "suspended" | "committed";
18
+ readonly name?: string;
19
+ readonly effectId?: string;
20
+ readonly code?: string;
21
+ readonly ledgerHead?: string;
22
+ }
23
+ /** Structural slice of the runner's `AgentRunResult` that `end()` reads. */
24
+ export interface AgentRunOutcome {
25
+ readonly status: "completed" | "suspended" | "continue";
26
+ readonly error?: {
27
+ readonly code: string;
28
+ };
29
+ readonly reason?: string;
30
+ }
31
+ export interface TraceAgentRunOptions {
32
+ /** Agent name, recorded as `nifra.agent.name`. */
33
+ readonly agent: string;
34
+ /** Turn id, recorded as `nifra.agent.turn_id`. */
35
+ readonly turnId: string;
36
+ /** Exporter that receives the run span and its evidence child spans. */
37
+ readonly exporter?: ObservationAdapter;
38
+ readonly adapters?: readonly ObservationAdapter[];
39
+ /**
40
+ * Parent span for the run - pass the enclosing request observation's `context` to nest agent
41
+ * runs under the HTTP span. `null` forces a root span; `undefined` falls back to `traceparent`.
42
+ */
43
+ readonly parent?: ObservationParent | null;
44
+ /** Inbound W3C header used when `parent` is undefined. */
45
+ readonly traceparent?: string | null;
46
+ }
47
+ export interface AgentRunTrace {
48
+ /** Pass as (or combine into) `ports.telemetry`. Never throws; a failing adapter cannot fail the turn. */
49
+ readonly telemetry: {
50
+ step(evidence: AgentRunEvidence): void;
51
+ };
52
+ /** The run span's trace identity, forwardable with `traceHeaders`. */
53
+ readonly context: ObservationContext;
54
+ /**
55
+ * End the run span. Pass the runner's result to record the final status
56
+ * (`nifra.agent.status`, pending reason, error code); omit it when the run threw.
57
+ * Exactly-once: repeated calls are ignored.
58
+ */
59
+ end(result?: AgentRunOutcome): void;
60
+ }
61
+ /**
62
+ * Open a run span and adapt the runner's step evidence into child spans.
63
+ *
64
+ * const trace = traceAgentRun({ agent: agent.name, turnId, exporter, parent: c.observation?.context })
65
+ * const result = await runAgent(agent, input, { ...ports, telemetry: trace.telemetry }, options)
66
+ * trace.end(result)
67
+ *
68
+ * Model evidence arrives as a started/terminal pair and becomes one timed `nifra.agent.model`
69
+ * span; every other evidence item is terminal-only and becomes an instant child span.
70
+ */
71
+ export declare function traceAgentRun(options: TraceAgentRunOptions): AgentRunTrace;
72
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,eAAe,CAAA;AAEtB,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAA;IACjE,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAA;IACxF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,UAAU,CAAA;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACjD;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAC1C,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B,yGAAyG;IACzG,QAAQ,CAAC,SAAS,EAAE;QAAE,IAAI,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAA;KAAE,CAAA;IAC9D,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;IACpC;;;;OAIG;IACH,GAAG,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;CACpC;AAcD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAmE1E"}
package/dist/run.js ADDED
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Agent-run tracing - one OpenTelemetry span per bounded agent run, one child span per step
3
+ * evidence item, effect ledger heads carried as span attributes.
4
+ *
5
+ * The bridge consumes only the runner's constrained step-evidence contract (`seq`, `kind`,
6
+ * `outcome`, tool name, effect id, error code, ledger head): prompts, tool inputs, and outputs
7
+ * cannot enter an export. The evidence shape is declared structurally so the package stays
8
+ * dependency-free on `@nifrajs/agent`; the returned `telemetry` object satisfies its
9
+ * `AgentTelemetryPort` as-is.
10
+ */
11
+ import { createObservationLifecycle, } from "@nifrajs/otel";
12
+ function evidenceAttributes(evidence) {
13
+ const attributes = {
14
+ "nifra.agent.evidence.seq": evidence.seq,
15
+ "nifra.agent.evidence.outcome": evidence.outcome,
16
+ };
17
+ if (evidence.name !== undefined)
18
+ attributes["tool.name"] = evidence.name;
19
+ if (evidence.effectId !== undefined)
20
+ attributes["nifra.effect.id"] = evidence.effectId;
21
+ if (evidence.code !== undefined)
22
+ attributes["nifra.agent.error_code"] = evidence.code;
23
+ if (evidence.ledgerHead !== undefined)
24
+ attributes["nifra.ledger.head"] = evidence.ledgerHead;
25
+ return attributes;
26
+ }
27
+ /**
28
+ * Open a run span and adapt the runner's step evidence into child spans.
29
+ *
30
+ * const trace = traceAgentRun({ agent: agent.name, turnId, exporter, parent: c.observation?.context })
31
+ * const result = await runAgent(agent, input, { ...ports, telemetry: trace.telemetry }, options)
32
+ * trace.end(result)
33
+ *
34
+ * Model evidence arrives as a started/terminal pair and becomes one timed `nifra.agent.model`
35
+ * span; every other evidence item is terminal-only and becomes an instant child span.
36
+ */
37
+ export function traceAgentRun(options) {
38
+ const adapters = [
39
+ ...(options.exporter === undefined ? [] : [options.exporter]),
40
+ ...(options.adapters ?? []),
41
+ ];
42
+ const lifecycle = createObservationLifecycle({ adapters });
43
+ const run = lifecycle.start({
44
+ name: "nifra.agent.run",
45
+ ...(options.parent === undefined ? {} : { parent: options.parent }),
46
+ ...(options.traceparent === undefined ? {} : { traceparent: options.traceparent }),
47
+ attributes: {
48
+ "nifra.agent.name": options.agent,
49
+ "nifra.agent.turn_id": options.turnId,
50
+ },
51
+ });
52
+ // The runner is sequential - at most one model call is in flight, so a single slot pairs the
53
+ // `started` item with its terminal twin. Kinds other than "model" emit terminal items only.
54
+ let openModel;
55
+ const step = (evidence) => {
56
+ try {
57
+ if (evidence.kind === "model" && evidence.outcome === "started") {
58
+ openModel?.end({ status: "error", attributes: { "nifra.agent.error_code": "unpaired" } });
59
+ openModel = run.startChild({
60
+ name: "nifra.agent.model",
61
+ attributes: evidenceAttributes(evidence),
62
+ });
63
+ return;
64
+ }
65
+ const failed = evidence.outcome === "failed" || evidence.outcome === "denied";
66
+ const status = failed ? "error" : "ok";
67
+ if (evidence.kind === "model" && openModel !== undefined) {
68
+ const span = openModel;
69
+ openModel = undefined;
70
+ span.setAttributes(evidenceAttributes(evidence));
71
+ span.end({ status });
72
+ return;
73
+ }
74
+ run
75
+ .startChild({
76
+ name: `nifra.agent.${evidence.kind}`,
77
+ attributes: evidenceAttributes(evidence),
78
+ })
79
+ .end({ status });
80
+ }
81
+ catch {
82
+ // Telemetry must never fail the turn it observes.
83
+ }
84
+ };
85
+ const end = (result) => {
86
+ try {
87
+ openModel?.end({ status: "error", attributes: { "nifra.agent.error_code": "run_ended" } });
88
+ openModel = undefined;
89
+ if (result === undefined) {
90
+ run.end({ status: "error", attributes: { "nifra.agent.status": "threw" } });
91
+ return;
92
+ }
93
+ const attributes = { "nifra.agent.status": result.status };
94
+ if (result.reason !== undefined)
95
+ attributes["nifra.agent.pending_reason"] = result.reason;
96
+ if (result.error !== undefined)
97
+ attributes["nifra.agent.error_code"] = result.error.code;
98
+ run.end({ status: result.error === undefined ? "ok" : "error", attributes });
99
+ }
100
+ catch {
101
+ // Same fail-open rule as step().
102
+ }
103
+ };
104
+ return Object.freeze({ telemetry: Object.freeze({ step }), context: run.context, end });
105
+ }
106
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nifrajs/agent-telemetry",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "Agent telemetry plugin - child spans for AI tool calls on /_nifra/tool/* and MCP endpoints.",
5
5
  "keywords": [
6
6
  "bun",
@@ -38,10 +38,10 @@
38
38
  "access": "public"
39
39
  },
40
40
  "dependencies": {
41
- "@nifrajs/otel": "3.1.0"
41
+ "@nifrajs/otel": "3.3.0"
42
42
  },
43
43
  "peerDependencies": {
44
- "@nifrajs/core": "^3.1.0"
44
+ "@nifrajs/core": "^3.3.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@nifrajs/core": "workspace:*"
package/src/index.ts CHANGED
@@ -15,6 +15,14 @@ import {
15
15
  type ObservationAdapter,
16
16
  } from "@nifrajs/otel"
17
17
 
18
+ export {
19
+ type AgentRunEvidence,
20
+ type AgentRunOutcome,
21
+ type AgentRunTrace,
22
+ type TraceAgentRunOptions,
23
+ traceAgentRun,
24
+ } from "./run.ts"
25
+
18
26
  // ---------------------------------------------------------------------------
19
27
  // Types
20
28
  // ---------------------------------------------------------------------------
@@ -183,3 +191,238 @@ export function consoleAgentExporter(
183
191
  },
184
192
  }
185
193
  }
194
+
195
+ // ---------------------------------------------------------------------------
196
+ // Orchestration correlation
197
+ // ---------------------------------------------------------------------------
198
+
199
+ /** Content-free lifecycle kinds emitted by run dispatch and recovery. */
200
+ export type OrchestrationTelemetryKind =
201
+ | "started"
202
+ | "checkpointed"
203
+ | "retrying"
204
+ | "recovered"
205
+ | "cancelled"
206
+ | "completed"
207
+ | "failed"
208
+ | "dead-lettered"
209
+
210
+ /** Allowlisted correlation fields. No index signature is intentional: arbitrary attributes are rejected. */
211
+ export interface OrchestrationTelemetryEvent {
212
+ readonly kind: OrchestrationTelemetryKind
213
+ readonly runId: string
214
+ readonly planDigest: string
215
+ readonly nodeId: string
216
+ readonly attempt: number
217
+ readonly evidenceSeq: number
218
+ readonly at: number
219
+ readonly evidenceId?: string
220
+ readonly replayId?: string
221
+ readonly traceRef?: string
222
+ readonly scheduleToken?: string
223
+ readonly statusCode?: string
224
+ }
225
+
226
+ export interface OrchestrationTelemetryOptions {
227
+ /** No exporter means disabled telemetry and zero spans. */
228
+ readonly exporter?: ObservationAdapter
229
+ readonly adapters?: readonly ObservationAdapter[]
230
+ readonly maxDistinctValues?: number
231
+ }
232
+
233
+ export interface OrchestrationTelemetry {
234
+ readonly enabled: boolean
235
+ readonly dropped: number
236
+ record(event: OrchestrationTelemetryEvent | unknown): boolean
237
+ close(): void
238
+ }
239
+
240
+ const ORCHESTRATION_TOKEN = /^[A-Za-z0-9._:-]{1,128}$/
241
+ const ORCHESTRATION_DIGEST = /^[0-9a-f]{64}$/
242
+ const ORCHESTRATION_KINDS: ReadonlySet<string> = new Set([
243
+ "started",
244
+ "checkpointed",
245
+ "retrying",
246
+ "recovered",
247
+ "cancelled",
248
+ "completed",
249
+ "failed",
250
+ "dead-lettered",
251
+ ])
252
+ const ORCHESTRATION_FIELDS = new Set([
253
+ "kind",
254
+ "runId",
255
+ "planDigest",
256
+ "nodeId",
257
+ "attempt",
258
+ "evidenceSeq",
259
+ "at",
260
+ "evidenceId",
261
+ "replayId",
262
+ "traceRef",
263
+ "scheduleToken",
264
+ "statusCode",
265
+ ])
266
+ const ORCHESTRATION_FORBIDDEN = new Set([
267
+ "prompt",
268
+ "message",
269
+ "text",
270
+ "input",
271
+ "output",
272
+ "arguments",
273
+ "body",
274
+ "response",
275
+ "secret",
276
+ "credential",
277
+ "diagnostic",
278
+ "stack",
279
+ "content",
280
+ "transcript",
281
+ "artifact",
282
+ "path",
283
+ ])
284
+
285
+ function orchestrationRecord(value: unknown): value is Record<string, unknown> {
286
+ return typeof value === "object" && value !== null && !Array.isArray(value)
287
+ }
288
+
289
+ function boundedTelemetryToken(value: unknown): value is string {
290
+ return typeof value === "string" && ORCHESTRATION_TOKEN.test(value)
291
+ }
292
+
293
+ function parseOrchestrationEvent(value: unknown): OrchestrationTelemetryEvent | undefined {
294
+ if (!orchestrationRecord(value)) return undefined
295
+ for (const key of Object.keys(value)) {
296
+ if (ORCHESTRATION_FORBIDDEN.has(key.toLowerCase()) || !ORCHESTRATION_FIELDS.has(key))
297
+ return undefined
298
+ }
299
+ if (
300
+ typeof value.kind !== "string" ||
301
+ !ORCHESTRATION_KINDS.has(value.kind) ||
302
+ !boundedTelemetryToken(value.runId) ||
303
+ !boundedTelemetryToken(value.nodeId) ||
304
+ typeof value.planDigest !== "string" ||
305
+ !ORCHESTRATION_DIGEST.test(value.planDigest) ||
306
+ typeof value.at !== "number" ||
307
+ !Number.isSafeInteger(value.at) ||
308
+ value.at < 0 ||
309
+ typeof value.attempt !== "number" ||
310
+ !Number.isSafeInteger(value.attempt) ||
311
+ value.attempt < 1 ||
312
+ typeof value.evidenceSeq !== "number" ||
313
+ !Number.isSafeInteger(value.evidenceSeq) ||
314
+ value.evidenceSeq < 0
315
+ )
316
+ return undefined
317
+ for (const key of [
318
+ "evidenceId",
319
+ "replayId",
320
+ "traceRef",
321
+ "scheduleToken",
322
+ "statusCode",
323
+ ] as const) {
324
+ const candidate = value[key]
325
+ if (candidate !== undefined && !boundedTelemetryToken(candidate)) return undefined
326
+ }
327
+ return Object.freeze({
328
+ kind: value.kind as OrchestrationTelemetryKind,
329
+ runId: value.runId,
330
+ planDigest: value.planDigest,
331
+ nodeId: value.nodeId,
332
+ attempt: value.attempt,
333
+ evidenceSeq: value.evidenceSeq,
334
+ at: value.at,
335
+ ...(value.evidenceId === undefined ? {} : { evidenceId: value.evidenceId as string }),
336
+ ...(value.replayId === undefined ? {} : { replayId: value.replayId as string }),
337
+ ...(value.traceRef === undefined ? {} : { traceRef: value.traceRef as string }),
338
+ ...(value.scheduleToken === undefined ? {} : { scheduleToken: value.scheduleToken as string }),
339
+ ...(value.statusCode === undefined ? {} : { statusCode: value.statusCode as string }),
340
+ })
341
+ }
342
+
343
+ function orchestrationAttributes(
344
+ event: OrchestrationTelemetryEvent,
345
+ ): Record<string, string | number> {
346
+ return {
347
+ "nifra.orchestration.run_id": event.runId,
348
+ "nifra.orchestration.plan_digest": event.planDigest,
349
+ "nifra.orchestration.node_id": event.nodeId,
350
+ "nifra.orchestration.attempt": event.attempt,
351
+ "nifra.orchestration.evidence_seq": event.evidenceSeq,
352
+ "nifra.orchestration.at": event.at,
353
+ ...(event.evidenceId === undefined
354
+ ? {}
355
+ : { "nifra.orchestration.evidence_id": event.evidenceId }),
356
+ ...(event.replayId === undefined ? {} : { "nifra.orchestration.replay_id": event.replayId }),
357
+ ...(event.traceRef === undefined ? {} : { "nifra.orchestration.trace_ref": event.traceRef }),
358
+ ...(event.scheduleToken === undefined
359
+ ? {}
360
+ : { "nifra.orchestration.schedule": event.scheduleToken }),
361
+ ...(event.statusCode === undefined
362
+ ? {}
363
+ : { "nifra.orchestration.status_code": event.statusCode }),
364
+ }
365
+ }
366
+
367
+ /** Create an opt-in, bounded telemetry bridge for run/retry/recovery correlation. */
368
+ export function orchestrationTelemetry(
369
+ options: OrchestrationTelemetryOptions = {},
370
+ ): OrchestrationTelemetry {
371
+ const adapters = [
372
+ ...(options.exporter === undefined ? [] : [options.exporter]),
373
+ ...(options.adapters ?? []),
374
+ ]
375
+ const enabled = adapters.length > 0
376
+ const maxDistinct = options.maxDistinctValues ?? 512
377
+ if (!Number.isSafeInteger(maxDistinct) || maxDistinct < 1 || maxDistinct > 10_000)
378
+ throw new RangeError("orchestration telemetry maxDistinctValues is invalid")
379
+ if (!enabled)
380
+ return {
381
+ enabled: false,
382
+ get dropped() {
383
+ return 0
384
+ },
385
+ record: () => false,
386
+ close: () => undefined,
387
+ }
388
+
389
+ const lifecycle = createObservationLifecycle({ adapters })
390
+ const run = lifecycle.start({ name: "nifra.orchestration.run", attributes: {} })
391
+ const distinct = new Map<string, Set<string>>()
392
+ let droppedCount = 0
393
+ let closed = false
394
+ const record = (raw: OrchestrationTelemetryEvent | unknown): boolean => {
395
+ if (closed) return false
396
+ const event = parseOrchestrationEvent(raw)
397
+ if (event === undefined) {
398
+ droppedCount = Math.min(1_000_000, droppedCount + 1)
399
+ return false
400
+ }
401
+ const attrs = orchestrationAttributes(event)
402
+ for (const [key, value] of Object.entries(attrs)) {
403
+ if (typeof value !== "string") continue
404
+ const values = distinct.get(key) ?? new Set<string>()
405
+ if (!values.has(value) && values.size >= maxDistinct) {
406
+ droppedCount = Math.min(1_000_000, droppedCount + 1)
407
+ return false
408
+ }
409
+ values.add(value)
410
+ distinct.set(key, values)
411
+ }
412
+ const status = event.kind === "failed" || event.kind === "dead-lettered" ? "error" : "ok"
413
+ run.startChild({ name: `nifra.orchestration.${event.kind}`, attributes: attrs }).end({ status })
414
+ return true
415
+ }
416
+ return {
417
+ enabled: true,
418
+ get dropped() {
419
+ return droppedCount
420
+ },
421
+ record,
422
+ close() {
423
+ if (closed) return
424
+ closed = true
425
+ run.end({ status: "ok" })
426
+ },
427
+ }
428
+ }
package/src/run.ts ADDED
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Agent-run tracing - one OpenTelemetry span per bounded agent run, one child span per step
3
+ * evidence item, effect ledger heads carried as span attributes.
4
+ *
5
+ * The bridge consumes only the runner's constrained step-evidence contract (`seq`, `kind`,
6
+ * `outcome`, tool name, effect id, error code, ledger head): prompts, tool inputs, and outputs
7
+ * cannot enter an export. The evidence shape is declared structurally so the package stays
8
+ * dependency-free on `@nifrajs/agent`; the returned `telemetry` object satisfies its
9
+ * `AgentTelemetryPort` as-is.
10
+ */
11
+
12
+ import {
13
+ type ActiveObservation,
14
+ type AttributeValue,
15
+ createObservationLifecycle,
16
+ type ObservationAdapter,
17
+ type ObservationContext,
18
+ type ObservationParent,
19
+ } from "@nifrajs/otel"
20
+
21
+ /** Structural twin of `@nifrajs/agent`'s `AgentStepEvidence`. */
22
+ export interface AgentRunEvidence {
23
+ readonly seq: number
24
+ readonly at: number
25
+ readonly kind: "model" | "tool" | "approval" | "budget" | "state"
26
+ readonly outcome: "started" | "passed" | "failed" | "denied" | "suspended" | "committed"
27
+ readonly name?: string
28
+ readonly effectId?: string
29
+ readonly code?: string
30
+ readonly ledgerHead?: string
31
+ }
32
+
33
+ /** Structural slice of the runner's `AgentRunResult` that `end()` reads. */
34
+ export interface AgentRunOutcome {
35
+ readonly status: "completed" | "suspended" | "continue"
36
+ readonly error?: { readonly code: string }
37
+ readonly reason?: string
38
+ }
39
+
40
+ export interface TraceAgentRunOptions {
41
+ /** Agent name, recorded as `nifra.agent.name`. */
42
+ readonly agent: string
43
+ /** Turn id, recorded as `nifra.agent.turn_id`. */
44
+ readonly turnId: string
45
+ /** Exporter that receives the run span and its evidence child spans. */
46
+ readonly exporter?: ObservationAdapter
47
+ readonly adapters?: readonly ObservationAdapter[]
48
+ /**
49
+ * Parent span for the run - pass the enclosing request observation's `context` to nest agent
50
+ * runs under the HTTP span. `null` forces a root span; `undefined` falls back to `traceparent`.
51
+ */
52
+ readonly parent?: ObservationParent | null
53
+ /** Inbound W3C header used when `parent` is undefined. */
54
+ readonly traceparent?: string | null
55
+ }
56
+
57
+ export interface AgentRunTrace {
58
+ /** Pass as (or combine into) `ports.telemetry`. Never throws; a failing adapter cannot fail the turn. */
59
+ readonly telemetry: { step(evidence: AgentRunEvidence): void }
60
+ /** The run span's trace identity, forwardable with `traceHeaders`. */
61
+ readonly context: ObservationContext
62
+ /**
63
+ * End the run span. Pass the runner's result to record the final status
64
+ * (`nifra.agent.status`, pending reason, error code); omit it when the run threw.
65
+ * Exactly-once: repeated calls are ignored.
66
+ */
67
+ end(result?: AgentRunOutcome): void
68
+ }
69
+
70
+ function evidenceAttributes(evidence: AgentRunEvidence): Record<string, AttributeValue> {
71
+ const attributes: Record<string, AttributeValue> = {
72
+ "nifra.agent.evidence.seq": evidence.seq,
73
+ "nifra.agent.evidence.outcome": evidence.outcome,
74
+ }
75
+ if (evidence.name !== undefined) attributes["tool.name"] = evidence.name
76
+ if (evidence.effectId !== undefined) attributes["nifra.effect.id"] = evidence.effectId
77
+ if (evidence.code !== undefined) attributes["nifra.agent.error_code"] = evidence.code
78
+ if (evidence.ledgerHead !== undefined) attributes["nifra.ledger.head"] = evidence.ledgerHead
79
+ return attributes
80
+ }
81
+
82
+ /**
83
+ * Open a run span and adapt the runner's step evidence into child spans.
84
+ *
85
+ * const trace = traceAgentRun({ agent: agent.name, turnId, exporter, parent: c.observation?.context })
86
+ * const result = await runAgent(agent, input, { ...ports, telemetry: trace.telemetry }, options)
87
+ * trace.end(result)
88
+ *
89
+ * Model evidence arrives as a started/terminal pair and becomes one timed `nifra.agent.model`
90
+ * span; every other evidence item is terminal-only and becomes an instant child span.
91
+ */
92
+ export function traceAgentRun(options: TraceAgentRunOptions): AgentRunTrace {
93
+ const adapters = [
94
+ ...(options.exporter === undefined ? [] : [options.exporter]),
95
+ ...(options.adapters ?? []),
96
+ ]
97
+ const lifecycle = createObservationLifecycle({ adapters })
98
+ const run = lifecycle.start({
99
+ name: "nifra.agent.run",
100
+ ...(options.parent === undefined ? {} : { parent: options.parent }),
101
+ ...(options.traceparent === undefined ? {} : { traceparent: options.traceparent }),
102
+ attributes: {
103
+ "nifra.agent.name": options.agent,
104
+ "nifra.agent.turn_id": options.turnId,
105
+ },
106
+ })
107
+ // The runner is sequential - at most one model call is in flight, so a single slot pairs the
108
+ // `started` item with its terminal twin. Kinds other than "model" emit terminal items only.
109
+ let openModel: ActiveObservation | undefined
110
+
111
+ const step = (evidence: AgentRunEvidence): void => {
112
+ try {
113
+ if (evidence.kind === "model" && evidence.outcome === "started") {
114
+ openModel?.end({ status: "error", attributes: { "nifra.agent.error_code": "unpaired" } })
115
+ openModel = run.startChild({
116
+ name: "nifra.agent.model",
117
+ attributes: evidenceAttributes(evidence),
118
+ })
119
+ return
120
+ }
121
+ const failed = evidence.outcome === "failed" || evidence.outcome === "denied"
122
+ const status = failed ? "error" : "ok"
123
+ if (evidence.kind === "model" && openModel !== undefined) {
124
+ const span = openModel
125
+ openModel = undefined
126
+ span.setAttributes(evidenceAttributes(evidence))
127
+ span.end({ status })
128
+ return
129
+ }
130
+ run
131
+ .startChild({
132
+ name: `nifra.agent.${evidence.kind}`,
133
+ attributes: evidenceAttributes(evidence),
134
+ })
135
+ .end({ status })
136
+ } catch {
137
+ // Telemetry must never fail the turn it observes.
138
+ }
139
+ }
140
+
141
+ const end = (result?: AgentRunOutcome): void => {
142
+ try {
143
+ openModel?.end({ status: "error", attributes: { "nifra.agent.error_code": "run_ended" } })
144
+ openModel = undefined
145
+ if (result === undefined) {
146
+ run.end({ status: "error", attributes: { "nifra.agent.status": "threw" } })
147
+ return
148
+ }
149
+ const attributes: Record<string, AttributeValue> = { "nifra.agent.status": result.status }
150
+ if (result.reason !== undefined) attributes["nifra.agent.pending_reason"] = result.reason
151
+ if (result.error !== undefined) attributes["nifra.agent.error_code"] = result.error.code
152
+ run.end({ status: result.error === undefined ? "ok" : "error", attributes })
153
+ } catch {
154
+ // Same fail-open rule as step().
155
+ }
156
+ }
157
+
158
+ return Object.freeze({ telemetry: Object.freeze({ step }), context: run.context, end })
159
+ }