Observability
Follow ArmorCodex turns from policy checks through tool results and model usage in the ArmorIQ dashboard.
ArmorCodex Observability
ArmorCodex records one trace for each Codex turn. Use these traces to see what Codex planned, which tools it attempted, why a policy allowed or denied an action, whether the tool succeeded, and how many model tokens the turn used.
Observability is enabled automatically when ArmorCodex has an ArmorIQ API key. It is separate from enforcement: a telemetry failure does not change the hook's policy result.
What a Turn Records
ArmorCodex session
└── Turn trace
├── Plan start
├── Tool check
│ └── Policy decision
├── Tool result
└── Model generation usageThe trace can include:
- a bounded preview of the turn prompt;
allowordenypolicy decisions and their reasons;- tool names, bounded inputs, results, and error status;
- input, output, and cache-read token totals derived from the turn transcript;
- trace duration, agent identity, tags, and an output summary.
See the shared observability data model for field definitions and span kinds.
Why ArmorCodex Uses Disk Buffering
Codex starts a new short-lived process for every hook. An in-memory recorder created during UserPromptSubmit would be gone before PreToolUse or Stop runs, so ArmorCodex accumulates the turn as append-only NDJSON.
Each hook writes one self-contained line with O_APPEND. This avoids concurrent hook processes overwriting one another through a read-modify-write race. Attribute objects and line sizes are capped so each append remains bounded.
The session ID is hashed before it is used in a buffer filename. The raw ID is sent as an observability session ID only when it is a valid UUID.
Turn Lifecycle
| Hook | Observability action |
|---|---|
SessionStart | Removes abandoned observability files older than six hours |
UserPromptSubmit | Writes turn metadata and the plan-start span |
PreToolUse or PermissionRequest | Appends a tool-check span and nested policy decision |
PostToolUse | Appends a tool-result span with ok or error status |
Stop | Claims the file, assembles the trace, adds token usage, ships it, and removes the file |
At Stop, ArmorCodex atomically renames the live file before reading it. The Stop process then creates a fresh SDK recorder, replays all complete spans, ends the trace, and explicitly waits for POST /observability/spans to finish.
ArmorCodex cannot rely on the SDK's periodic timer because the hook process exits immediately after Stop. The awaited flush makes delivery possible, but an unavailable endpoint can add retry latency to the end of the turn.
Delivery and Failure Behavior
Shipping is best-effort and fail-open:
- telemetry exceptions are caught and do not replace the policy decision;
- malformed or incomplete NDJSON lines are skipped without discarding other complete records;
- network and server failures are retried by the SDK shipper;
- an exhausted batch is dropped rather than blocking the agent indefinitely;
- a turn that never reaches
Stopis not shipped, and its file is removed after six hours during a laterSessionStart.
The disk file is a cross-hook assembly buffer, not a durable retry queue. If delivery exhausts its retries, ArmorCodex does not keep the claimed trace for later replay.
Enable or Disable Observability
Observability is on when an API key is configured. It uses the same ArmorIQ backend selected by the plugin and reports product armorcodex.
The configuration bridge also honors a forwarded disable_observability plugin option, although the current packaged plugin metadata may not expose it in a configuration UI. Use the environment variable below as the reliable customer-facing opt-out.
To opt out, set the variable before starting Codex:
export ARMORCODEX_OBSERVABILITY_DISABLED=trueAccepted true values are true, 1, yes, y, and on. Without an API key, ArmorCodex does not create or ship observability records.
When Traces Appear
ArmorCodex does not stream an active turn. The trace is assembled and sent during Stop, and the ArmorIQ dashboard polls for updates every 30 seconds. It is normal for the response to finish before the trace appears.
Use the observability dashboard guide to understand refresh behavior. If a turn remains missing, check the observability troubleshooting guide.
Privacy Boundary
Observability can contain prompt previews, policy inputs, tool inputs, tool outputs, and model usage. ArmorCodex applies bounded depth, item-count, string-length, and attribute-size limits. It also redacts a defined set of sensitive field names and known secret patterns.
These controls are not general-purpose data-loss prevention and cannot guarantee that every credential or personal value is removed. Keep secrets out of prompts and tool arguments, use synthetic values when debugging, and limit dashboard access to the appropriate organization members.
For the end-to-end producer, backend, and dashboard flow, see the observability overview.