Output formats¶
Machine output is available for one-shot runs and the bounded session operations below.
The current default is schema v5. A client that pins the retained v4 contract passes
--output-schema-version 4 together with --output-format json or stream-json. On one-shot
task, continue, and resume operations this projects every stdout record onto the frozen v4 shape;
in particular, the v5-only kernel_tax terminal field and input_attachment stream record are
not emitted. Unsupported selectors fail before a rollout is opened.
iteron --machine-contract is a provider-free capability query. Its JSON reports
cli_stream_versions, default_cli_stream_version, and resident_protocol_version as distinct
values; a launcher must not infer the CLI stream version from the resident SQ/EQ protocol.
Session operations¶
Schema-selected session operations use direct argv and emit one typed object:
--sessions [--session-limit N] [--session-cursor TOKEN] [--agent-definition-tag TAG]emitssession_list_page { sessions, next_cursor };--transcript RUN_ID [--transcript-cursor TOKEN]emitssession_transcript_page { run_id, events, older_cursor };--fork RUN_IDemitssession_fork_result { parent_run_id, child_run_id, fork_point, status: "created" }.
Cursors are opaque and bounded. List cursors are tied to their tenant and tag filter; transcript cursors are tied to their run. A transcript is read newest-page first while events within each page remain chronological. A stale, modified, or cross-query cursor is rejected rather than returning a page with silent gaps or duplicates.
--agent-definition-tag is immutable grouping metadata: at most 128 UTF-8 bytes, non-blank,
control-free, and rejected when it resembles a credential. A fresh run records it, resume may
only repeat the recorded value, forks inherit it, and legacy untagged sessions remain readable.
Final result¶
Both json and stream-json end with an authoritative result object:
{
"schema_version": 5,
"type": "result",
"outcome": "done",
"reason": null,
"success": true,
"assistant_text": "...",
"run_id": "...",
"cost_usd": null,
"cost_status": "...",
"cost_reason": null,
"turns": 1,
"kernel_tax": {
"admission_latency_us": 0,
"broker_latency_us": 0,
"record_fsync_latency_us": 0,
"estimated_tokens": 0,
"failed_runs": 0
},
"exit_code": 0,
"error": null
}
The example shows shape, not guaranteed values. cost_usd can be null or unknown
when no authoritative price evidence exists. Schema v5 requires the typed
kernel_tax object; its latency values are measured in microseconds and all five
fields are non-negative integers.
Schema v4 introduced the terminal outcome value drained, which schema v5
retains: it means the runtime stopped cleanly after quiescing admitted work and
durably checkpointing the workspace. It has success: true and exit code 0,
but remains distinct from ordinary done.
Stream event vocabulary¶
stream-json may emit:
assistant_textandthinkingdeltas;input_attachmentmetadata before a multimodal SQ submission;phaseandturn_endlifecycle events;tool_start,tool_end, andapproval_request;notice,steer_applied, andrun_done;workflow_start,workflow_plan,workflow_phase;workflow_agent_start,workflow_agent_activity,workflow_agent_end;workflow_end;- the terminal
result.
Every event carries schema_version. Consumers should ignore unknown event types
they do not need and use the final result as the authoritative terminal outcome.
input_attachment carries only ordinal, media_type, and encoded_bytes; it
never carries image bytes, a filename, or a path. Historical v4 event fixtures
and their terminal result remain unchanged; consumers should skip this v5 tag
when they do not need attachment metadata.
Run-declared artifacts¶
A run can declare a product it made: a report, a table, a diff. Before this existed the only way to learn that a run had produced something was to parse the assistant's prose, so every consumer invented its own convention and none of them could be verified.
The declaration is a handle, never inline content, because the evolution registry has to be able to verify what it holds. The handle carries everything a consumer needs to store, list and reopen the product later:
| what | where it comes from |
|---|---|
| the ref and its content address | artifact.hash |
| its kind | artifact.schema |
| its producing turn | the enclosing event's turn |
| the tool or effect that made it | artifact.producer, artifact.provenance.effect_id |
| where it lives | artifact.locator |
Two rules the producer path enforces rather than documents.
The content lands before the event does. Admission takes a durability witness and refuses without one, so a handle never names content that is not yet readable. An event that preceded its write would hand a consumer a handle to nothing.
Exceeding the per-run ceiling is counted, never silently dropped. A run may declare at most 256 artifacts; beyond that a declaration is refused and tallied, because a product stream that quietly stops is indistinguishable from a run that stopped producing. A duplicate content address is refused the same way, so a product gets exactly one event.
On the durable record this is artifact_produced, appended under abi.md
§4.3(b)2: every byte already on disk decodes unchanged, so PROTOCOL_VERSION
does not bump for it. The content address is preserved through redaction —
masking it would make the product unfindable — while the locator, being a path,
is scrubbed.
Stdout and stderr¶
For machine formats, stdout remains JSON or JSONL; diagnostics are written to stderr. Do not merge the two streams before parsing.
Model and tool text passes through output-boundary redaction. Streaming deltas use a stateful scrubber so a credential-shaped token split across transport chunks is not exposed merely because each chunk looked incomplete. This is defense in depth, not permission to send secrets to a model or tool.