Metrics — three counters and one histogram
Four instruments emitted via OTLP to <endpoint>/v1/metrics. Label keys align with matching trace span attributes (gen_ai.tool.name matches the tool span, nio.guard.* matches the OpenClaw tool-span guard attrs) so cross-signal queries use the same key names.
Instruments
| Instrument | Type | Unit | When recorded |
|---|---|---|---|
nio.tool_use.count | Counter | {invocations} | Each PreToolUse and PostToolUse (and TaskCreated / TaskCompleted if fired) |
nio.turn.count | Counter | {turns} | Each Stop / SubagentStop / SessionEnd (turn boundary) |
nio.decision.count | Counter | {decisions} | Each guard decision (allow / deny / ask) |
nio.risk.score | Histogram | {score} | Each guard evaluation; 0–1 distribution for avg / p50 / p99 |
Labels
Five label keys, used across the four instruments above. Each row below is a unique label.
| Attribute | Description | Captured at | Platforms |
|---|---|---|---|
gen_ai.tool.name | Host tool name (Bash, WebFetch, …); same key as the tool-span attribute | PreToolUse · PostToolUse · guard decision | all |
nio.event | Hook event firing this counter — PreToolUse / PostToolUse / TaskCreated / TaskCompleted | PreToolUse · PostToolUse · TaskCreated · TaskCompleted | all |
nio.platform | Source platform — claude-code / hermes / openclaw | every metric | all |
nio.guard.decision | Guard verdict — allow / deny / ask | guard decision | all |
nio.guard.risk_level | Guard risk level — low / medium / high / critical | guard decision | all |
Label sets per instrument
| Instrument | Labels |
|---|---|
nio.tool_use.count | gen_ai.tool.name · nio.event · nio.platform |
nio.turn.count | nio.platform |
nio.decision.count | nio.guard.decision · nio.guard.risk_level · gen_ai.tool.name · nio.platform |
nio.risk.score | gen_ai.tool.name · nio.platform |
The user-facing Task tool (subagent dispatch) is reported as tool_name="Agent" in Claude Code hook payloads, so PreToolUse / PostToolUse counters use Agent as the gen_ai.tool.name label. The literal value Task only appears as a counter label when TaskCreated / TaskCompleted fire (Teammates / cloud-agent flows; never fired by the regular Task tool subagent on current Claude Code builds — see e2e-test/hook-subagent-e2e-task.md). OpenClaw and Hermes use their own native tool names.
Metrics have no local file — there is no metrics.jsonl. If collector.endpoint is empty, metrics drop on the floor (the meter provider returns null).