The execution graph
Every run is a graph you can open: the plan, each tool call, each decision, each latency, each result — not a chat transcript.
When an agent does something unexpected, the usual evidence is a chat transcript. That shows what the model said, not what it did, to what, with whose authority, or in what order — which is the difference between a story and evidence.
Nodes and edges
Nodes are calls and decisions; edges are causality. Fan-out, delegation, and retries are visible as structure instead of being inferred from a log.
Reading a run
run_01JQ8F2K7M agent: pr-triage duration 4.21s 14 calls 00.000 plan ── 00.118 github.pull_request.read #4821 permit 12ms 00.402 fs.read PR_review_notes.md permit 3ms 00.406 ⚠ injection score 0.91 on tool result flagged — 00.409 fs.read .env.production deny 2ms └─ policy deny-dotenv-read 00.411 agent re-planned after refusal ── 01.240 github.issues.comment #4821 permit 81ms 01.322 slack.post #eng-reviews permit 64ms ... 04.210 complete ──Opening a decision
why prints every policy considered for a call, which one matched, and what would need to change for the verdict to differ.
$ cirvix why dec_01JQ8F2K7M considered allow-workspace-read permit matched principal, action deny-dotenv-read forbid MATCHED ← decisive require-approval-secrets permit not reached (forbid wins) reason Reading .env* is denied outside an approved secrets flow.Replay against a candidate policy
Replay reconstructs a run from its recorded decisions and re-evaluates each one under a policy you're considering — see which calls would flip before you merge, not after.
Exporting to your existing stack
Traces export in OTLP to whatever you already run — Datadog, Grafana, Honeycomb, Splunk. Cirvix is a source of truth, not a place you're required to look.
Limits
- Cirvix records what crossed the boundary. Reasoning that never became a call is not in the trace, because it never reached anything Cirvix governs.
