Output formats¶
Machine output is available for one-shot runs and the bounded session operations below.
The current one-shot CLI default is schema v8. A client can pin schema v4, v5, v6, or v8 with
--output-schema-version, together with --output-format json or stream-json. On one-shot task,
continue, and resume operations, each version projects every stdout record onto its published shape.
Unsupported selectors fail before a rollout is opened.
PlantCore resident runs select schema v7 through their admitted bootstrap. Schema v7 is emitted on the resident App Server event stream and is not a generic one-shot CLI projection.
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": 8,
"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. Schemas v5, v6, and v8 require 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 later schemas
retain: 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;- in v8,
approval_resolved,steer_submission_applied,control_submission_applied, andsubmission_rejectedwith exact submission IDs; 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.
The four exact submission lifecycle records are declared only for v8. When an
operator selects v4, v5, or v6, each projects to a bounded, scrubbed notice without
an ID or an Applied claim; clients needing authoritative receipts should use
v8 or the Product V1 App Server contract. An approval request is not itself an
approval resolution, and a queued submission is not proof of application.
Schema v6 adds turn_end.context.components, a non-overlapping vector of
stable_prefix_tokens, instruction_tokens, task_context_tokens, memory_tokens,
transcript_tokens, attachment_tokens, tool_schema_tokens, tool_result_tokens, and
lsp_result_tokens. These are content-free estimates from the same admission boundary as the
aggregate context estimate; evaluation uses them to attribute efficiency to general runtime
modules rather than to provider or model names.
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.