Evidence and Exports
Take runtime evidence out of SOIT as run evidence bundles and ledger exports in a versioned contract.
Everything SOIT runs is recorded in its ledger: runs, run steps, cost entries, audit events, and outbox events. Since v1.3.0 that record leaves SOIT in one versioned shape, in two ways: ledger exports of one kind of record over a time window, and run evidence bundles that package one run for a reviewer.
When to use them
- Use ledger exports to feed a data warehouse, a SIEM, or a finance process with runs, costs, or audit events.
- Use evidence bundles when someone outside SOIT — an auditor, a customer, an incident reviewer — needs to check what one run did, without access to SOIT.
The ledger contract
server/app/kernel/specs/v1/ledger_spec.schema.json (JSON Schema 2020-12, version 1.0) defines five record types. Every exported record is wrapped in an envelope that names the contract version it was written in:
{"schema_version": "1.0", "record_type": "cost", "record": {"cost_entry_id": "ce_…", "amount": "0.0012", "currency": "USD", "created_at": "2026-09-27T10:30:15.123456Z", "…": "…"}}record_type | Source | Key fields |
|---|---|---|
run | runs | run_id, mode, kind, status, source, api_key_id, subject, timings, error |
step | run_steps | step_record_id, run_id, step_type, status, metrics, error |
cost | run_cost_entries | cost_entry_id, amount, currency, tokens, provider, model, tool |
audit | audit_events | audit_id, event_type, operation, outcome, actor, resource, payload |
event | event_outbox | event_id, event_type, subject and correlation ids, payload |
Conventions:
- Timestamps are UTC with a
Zsuffix. - Amounts and quantities are decimal strings, so no reader rounds them.
- Structured fields stay objects.
- Outbox delivery state (leases, attempts, last error) stays inside SOIT.
Adding an optional field is a minor version (1.1); removing, renaming, or retyping one is a major version. A contract test fails whenever a ledger table gains a column the contract does not account for, so every change to what leaves the runtime is a reviewed change.
Ledger exports
GET /api/v1/exports/{runs|steps|costs|audit|events}?since=…&until=…&format=jsonl|csv- Returns one kind of record created in
[since, until), oldest first, for the caller's workspace.untildefaults to now; a window covers at most 92 days. jsonlgives one envelope per line;csvgives the contract's fields as columns, in contract order, with objects as JSON cells. The contract version is in theX-SOIT-Ledger-Schemaresponse header.- Records are streamed in keyset batches, so a large window is never held in memory.
- Workspace owners and admins only. Each export is itself written to the audit ledger as
ledger.exported, with the window and format. - The audit export covers every audit event of the workspace, in a run or not: gateway requests, egress and budget refusals, policy changes, and exports.
In the console, Export on Observe › Runs and Govern › Audit downloads the current window as CSV. From a terminal, the soit CLI saves an export to a file:
soit export costs --since 2026-09-01T00:00:00Z --format csv -o costs.csvRun evidence bundles
GET /api/v1/runs/{run_id}/evidenceOne run's evidence as a zip a reviewer can take away and check without SOIT:
| File | Holds |
|---|---|
run.json, steps.jsonl, costs.jsonl, audit.jsonl | Ledger records in the contract |
tool_calls.jsonl | The run's tool calls |
approvals.jsonl | Approval requests and decisions |
citations.jsonl | Knowledge citations |
content_safety.jsonl | Content safety findings per step (categories and decisions, never the matched text) |
policy.json | The policy bundle ids the run's decisions were made under |
governance.json | The governance evidence matrix of the run detail |
manifest.json | Versions, content capture mode, child runs, and each file's SHA-256, size, and record count |
SHA256SUMS | Every file's digest, for sha256sum -c |
The bundle keeps no more content than the workspace records: under metadata_only content capture, tool arguments and results, approval details, and citation text are replaced by a length and a hash. A context that cannot tell the workspace's mode withholds content.
The archive is deterministic: an unchanged run always gives the same bytes, so the digest in the X-SOIT-Evidence-SHA256 response header identifies the evidence. Each download is written to the audit ledger as run.evidence_exported with that digest, but not attached to the run, so downloading does not change the evidence.
Evidence bundle on a run's detail page downloads it. The CLI checks the bundle against the server's digest before saving it:
soit export evidence "$RUN_ID" -o evidence.zipTo check the files, unzip the bundle and run sha256sum -c SHA256SUMS in the extracted folder.
API and UI surfaces
- API:
GET /api/v1/exports/{kind},GET /api/v1/runs/{run_id}/evidence - Console: Export on Observe › Runs and Govern › Audit; Evidence bundle on a run's detail page
- CLI:
soit export evidence,soit export runs|steps|costs|audit|events
Known limitations
- Ledger exports cover at most 92 days per request.
Related pages
- Tasks and Runs — the records being exported.
- Runtime Ledger — the invariants behind them.
- Budgets and Cost — reading spend.
soitCLI — exports from a terminal or CI.