Stream Events Reference
orchcore normalizes the JSONL output of five agent CLI formats into one event model. This page lists the event types, the StreamEvent fields, and the related monitoring and result models.
StreamFormat
Identifies the JSONL output format of an agent CLI.
| Value | Agent CLI |
|---|---|
claude |
Claude Code |
codex |
Codex |
opencode |
OpenCode |
antigravity |
Antigravity CLI (agy) |
copilot |
Copilot CLI |
from orchcore.stream import StreamFormat
format = StreamFormat.CLAUDE # "claude"
StreamEventType
The category of a StreamEvent, covering the agent lifecycle from launch to result.
| Value | Description |
|---|---|
init |
Agent process started |
state |
Agent state changed (see AgentState) |
heartbeat |
Keep-alive signal from the agent |
tool_start |
Agent began executing a tool |
tool_exec |
Tool execution in progress (intermediate update) |
tool_done |
Tool execution completed |
text |
Agent emitted text output |
subagent |
Agent spawned a sub-agent |
result |
Agent completed with final result |
error |
Agent encountered an error |
cancelled |
Agent was cancelled (e.g., via SIGINT) |
retry |
Agent is being retried after failure |
rate_limit |
Agent hit a rate limit |
stall |
Agent stalled (no activity for timeout period) |
StreamEvent
The normalized event model. A JSONL line from any agent format yields zero, one, or
several StreamEvent instances, depending on the line's content.
from orchcore.stream import StreamEvent, StreamEventType
Fields
| Field | Type | Default | Description |
|---|---|---|---|
event_type |
StreamEventType |
(required) | Event category |
timestamp |
datetime |
now(UTC) |
When the event occurred (timezone-aware) |
tool_id |
str \| None |
None |
Unique identifier for a tool invocation |
tool_name |
str \| None |
None |
Tool name (e.g., "Read", "Bash", "Write") |
tool_detail |
str \| None |
None |
Tool-specific detail (file path, command, etc.) |
tool_status |
"running" \| "done" \| "error" \| None |
None |
Current tool execution status |
tool_duration_ms |
int \| None |
None |
Tool execution duration in milliseconds |
text_preview |
str \| None |
None |
Truncated text content for display |
text_full |
str \| None |
None |
Complete text content |
cost_usd |
Decimal \| None |
None |
Cumulative cost in USD |
duration_ms |
int \| None |
None |
Total agent execution duration |
exit_code |
int \| None |
None |
Process exit code (on result events) |
num_turns |
int \| None |
None |
Number of conversation turns |
session_id |
str \| None |
None |
Agent session identifier |
token_usage |
dict[str, int] \| None |
None |
Token counts (e.g., {"input": 1000, "output": 500}) |
error |
str \| None |
None |
Error message (on error events) |
retry_attempt |
int \| None |
None |
Current retry attempt number |
retry_max |
int \| None |
None |
Maximum retry attempts |
retry_delay_ms |
int \| None |
None |
Delay before next retry |
error_category |
str \| None |
None |
Error classification |
idle_seconds |
float \| None |
None |
Seconds since last activity (on stall events) |
raw |
dict \| None |
None |
Original parsed JSON for debugging |
StreamEvent is a frozen Pydantic model, so instances cannot be changed after creation.
AgentState
The state machine AgentMonitor uses to track an agent's lifecycle. It has nine states:
STARTING → THINKING → WRITING
↓ ↓
TOOL_RUNNING ───┘
↓
STALLED / RATE_LIMITED
↓
COMPLETED / FAILED / CANCELLED
| State | Description |
|---|---|
starting |
Agent subprocess has been launched |
thinking |
Agent is processing (no tool active) |
writing |
Agent is emitting text output |
tool_running |
Agent is executing a tool |
stalled |
No activity detected for timeout period |
rate_limited |
Agent hit a rate limit |
completed |
Agent finished successfully |
failed |
Agent exited with an error |
cancelled |
Agent was terminated by signal |
ToolExecution
Tracks a single tool invocation through its lifecycle.
| Field | Type | Description |
|---|---|---|
tool_id |
str |
Unique invocation identifier |
name |
str |
Raw tool name |
friendly_name |
str |
Human-readable name (e.g., "Read" → "Read file") |
detail |
str \| None |
Tool-specific detail (file path, command) |
started_at |
datetime |
When the tool started |
completed_at |
datetime \| None |
When the tool finished |
status |
"running" \| "done" \| "error" |
Current status |
duration |
timedelta \| None |
Execution time |
ToolCounters
Aggregated tool execution statistics.
| Field | Type | Description |
|---|---|---|
total |
int |
Total tool invocations |
succeeded |
int |
Successfully completed |
failed |
int |
Failed with error |
running |
int |
Currently in progress |
AgentMonitorSnapshot
Point-in-time state of a monitored agent, returned by AgentMonitor.snapshot() for dashboards and status displays.
| Field | Type | Description |
|---|---|---|
agent_name |
str |
Agent identifier |
state |
AgentState |
Current state |
elapsed |
timedelta |
Time since agent started |
counters |
ToolCounters |
Aggregated tool stats |
active_tools |
list[ToolExecution] |
Currently running tools |
recent_tools |
list[ToolExecution] |
Recently completed tools (max 20) |
last_tool |
str \| None |
Name of most recent tool |
last_tool_detail |
str \| None |
Detail of most recent tool |
cost_usd |
Decimal \| None |
Cumulative cost |
token_usage |
dict[str, int] \| None |
Token consumption |
text_count |
int |
Number of text events |
subagent_count |
int |
Number of sub-agent spawns |
idle_seconds |
float |
Seconds since last activity |
AgentResult
Return type of AgentRunner.run(). It holds the outputs and diagnostics of a single agent execution.
| Field | Type | Default | Description |
|---|---|---|---|
agent_name |
str |
"" |
Agent identifier |
output_path |
Path \| None |
None |
Path to extracted output file |
stream_path |
Path \| None |
None |
Path to raw JSONL stream |
log_path |
Path \| None |
None |
Path to log file |
exit_code |
int |
0 |
Process exit code |
duration |
timedelta \| None |
None |
Execution duration |
cost_usd |
Decimal \| None |
None |
Total cost |
token_usage |
dict[str, int] \| None |
None |
Token counts |
num_turns |
int \| None |
None |
Conversation turns |
session_id |
str \| None |
None |
Session identifier |
output_empty |
bool |
False |
Whether output file was empty |
error |
str \| None |
None |
Human-readable error message if the run failed, kept in full |
error_category |
AgentErrorCategory \| None |
None |
Typed failure classification (see below) |
rate_limit_reset_seconds |
int \| None |
None |
Reset wait parsed from the rate-limit message, once, at the source |
json_parse_error_count |
int |
0 |
Malformed JSONL lines the stream parser skipped |
wire_validation_error_count |
int |
0 |
Well-formed JSONL lines that failed the selected wire-format schema |
agent_version |
str \| None |
None |
CLI version detected by the advisory version check; None when detection is disabled or fails |
AgentResult.error is set from the final stream state as well as the process exit code. A subprocess that exits 0 but emits a result with error, an error event, or an unrecovered rate_limit event returns a result with error set, and phase aggregation treats it as failed.
AgentErrorCategory
error_category lets consumers, and the engine's retry loop, branch on the kind of
failure without matching error messages. The category is set where the failure is
first observed:
| Population site | Category |
|---|---|
Runner sees a typed rate_limit stream event |
rate_limit (reset parsed once into rate_limit_reset_seconds) |
Runner sees error or result(error=...) with exit 0 |
stream_error |
| Runner: exit code != 0, no stream category | nonzero_exit, upgraded to rate_limit when the fallback RateLimitDetector matches the stderr tail (for CLIs that never emit typed events) |
| Runner: empty output file on an otherwise clean run | empty_output |
Runner: max_runtime exceeded / kill_on_stall fired |
timeout / stall_timeout |
Engine: agent binary missing (FileNotFoundError) |
binary_not_found |
Engine: other OSError at launch |
os_error |
| Engine: shutdown or fail-fast sibling cancellation | cancelled |
Related
- Stream Pipeline architecture: how the four stages process the stream
- ADR-004: Composable stream processing pipeline
- ADR-006: Pydantic for all data models