In
practice.
Twelve demonstrations of Machine Mode on the wire. The standard, made concrete.
Each demonstration shows a real conforming tool — call it outline — exercising one piece of the standard. The first arrives as a streamed JSONL output, one line at a time, the way a consumer actually reads it. The rest are static for scanning.
Discover what a tool can do.
A consumer can learn what a tool exposes without invoking it, without credentials, and without network access. The schema and capability commands return one JSON object — discovery metadata, not a JSONL stream.
$ outline schema --output json --command search{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"Outline search event","type":"object","required":["type"],"properties":{"type":{"enum":["meta","hit","warning","error","summary"]}}}$$ outline capabilities --output json{"tool":"outline","tool_version":"1.8.2","aoi_versions":["0.2"],"schemas":[{"name":"com.example.outline.events","versions":["1.0.0"],"default":"1.0.0"}],"commands":[{"name":"search","read_only":true,"bounded":true,"supports_cursor":true,"event_types":["meta","hit","summary"]},{"name":"delete","read_only":false,"destructive":true,"requires_confirm":true,"supports_dry_run":true,"supports_idempotency_key":true}]}
- No credentials. No network. No business query.
- capabilities is one JSON object so it can be parsed in a single read.
- The destructive flag on delete tells a planner this command demands extra ceremony.
Bounded, streamed search.
Every read declares its appetite. Results arrive incrementally as the tool produces them. When more exists, the terminal summary says so — and hands back a cursor so the consumer can continue.
$ outline search "agent operable" --output jsonl --limit 50{"type":"meta","tool":"outline","tool_version":"1.8.2","aoi_version":"0.2","schema_name":"com.example.outline.events","schema_version":"1.0.0","command":"search"}{"type":"hit","rank":1,"id":"doc_91","title":"Agent-operable interfaces","snippet":"A conforming tool exposes…"}{"type":"hit","rank":2,"id":"doc_177","title":"Why machine mode","snippet":"Today's tools were built for humans…"}…{"type":"hit","rank":50,"id":"doc_2041","title":"Adopt AOI-CLI","snippet":"The conformance contract is small…"}{"type":"summary","ok":true,"count":50,"truncated":true,"next_cursor":"opaque-token-abc123","elapsed_ms":612}
- The consumer chose the limit; the tool honored it.
- truncated:true means more results exist beyond this page.
- next_cursor is opaque — the tool defines it.
Continue from a cursor.
Pagination is part of the contract, not a per-tool ad-hoc. The cursor you got from one call goes back as the cursor on the next call. The state lives with the consumer.
$ outline search "agent operable" --output jsonl --limit 50 --cursor opaque-token-abc123{"type":"meta","tool":"outline","aoi_version":"0.2","schema_version":"1.0.0","command":"search"}{"type":"hit","rank":51,"id":"doc_2110","title":"…"}…{"type":"hit","rank":83,"id":"doc_3441","title":"…"}{"type":"summary","ok":true,"count":33,"truncated":false,"next_cursor":null,"elapsed_ms":410}
- truncated:false + next_cursor:null marks the end of the result set.
- A consumer never needs to invent its own pagination.
Dry-run before any write.
Before a destructive operation runs, --dry-run emits plan events: this is what would happen. Zero side effects. The plan is the contract.
$ outline delete --where "stale=true" --dry-run --output jsonl{"type":"meta","tool":"outline","command":"delete","dry_run":true}{"type":"plan","action":"delete","target":"doc_44","title":"Old onboarding draft"}{"type":"plan","action":"delete","target":"doc_91","title":"2024-Q4 plan archive"}{"type":"plan","action":"delete","target":"doc_133","title":"Deprecated docs index"}{"type":"summary","ok":true,"would_affect":3,"executed":false}
- executed:false makes the no-op explicit; a wrapper can assert on it.
- Plan events are typed the same way the real apply events would be.
Confirmed destructive apply.
The real run requires --confirm. Bulk operations demand --confirm-count N as a guard against an unexpected blast radius. Every actual side effect produces a structured record.
$ outline delete --where "stale=true" --output jsonl --confirm --confirm-count 3{"type":"meta","tool":"outline","command":"delete"}{"type":"deleted","target":"doc_44","at":"2026-05-24T17:42:11Z","actor":"kevin"}{"type":"deleted","target":"doc_91","at":"2026-05-24T17:42:11Z","actor":"kevin"}{"type":"deleted","target":"doc_133","at":"2026-05-24T17:42:11Z","actor":"kevin"}{"type":"summary","ok":true,"count":3,"executed":true,"elapsed_ms":204}
- If --confirm-count had been 4, the tool would have refused without touching anything.
- deleted events carry stable IDs — a downstream audit log can ingest them as-is.
Idempotent writes.
The same write attempted twice — same outcome, no duplicate. The idempotency key lets the tool recognize a retry and return the prior result instead of doubling the effect.
$ outline create-doc --title "Release notes" --idempotency-key rel-2026-05 --output jsonl{"type":"meta","command":"create-doc"}{"type":"created","id":"doc_9001","title":"Release notes","idempotency_key":"rel-2026-05","duplicate":false}{"type":"summary","ok":true,"count":1,"executed":true}$$ outline create-doc --title "Release notes" --idempotency-key rel-2026-05 --output jsonl{"type":"meta","command":"create-doc"}{"type":"created","id":"doc_9001","title":"Release notes","idempotency_key":"rel-2026-05","duplicate":true}{"type":"summary","ok":true,"count":1,"executed":false}
- Both runs return the same id and exit 0.
- duplicate:true on the second is the explicit signal — the consumer can rely on the field, not infer from elapsed time.
Doctor — readiness as a stream.
Tools surface their own health: config, dependencies, credentials, connectivity. Each check is a typed event. The summary aggregates.
$ outline doctor --output jsonl{"type":"meta","tool":"outline","command":"doctor"}{"type":"check","name":"config_file","ok":true,"severity":"info","detail":"~/.outline.toml"}{"type":"check","name":"api_token","ok":true,"severity":"info","detail":"sourced from OUTLINE_TOKEN"}{"type":"check","name":"endpoint_reachable","ok":false,"severity":"error","detail":"connect ETIMEDOUT api.outline.example"}{"type":"summary","ok":false,"count":3,"error_count":1}
- Each check has the same envelope — easy for a monitoring agent to roll up.
- summary.ok=false with non-zero exit makes the failure unambiguous.
Watch — an unbounded stream.
Some operations don't have a natural end. The tool documents that the stream is unbounded, optionally emits heartbeats so a consumer can distinguish quiet from dead, and produces a summary only on cancellation.
$ outline watch --output jsonl{"type":"meta","tool":"outline","command":"watch","unbounded":true}{"type":"entry","change":"created","id":"doc_42","at":"2026-05-24T17:48:10Z"}{"type":"entry","change":"updated","id":"doc_42","at":"2026-05-24T17:49:23Z"}{"type":"heartbeat","at":"2026-05-24T17:50:00Z"}{"type":"heartbeat","at":"2026-05-24T17:51:00Z"}{"type":"entry","change":"deleted","id":"doc_19","at":"2026-05-24T17:51:42Z"}⌃C{"type":"summary","ok":false,"reason":"interrupted","partial":true,"count":3}
- unbounded:true on meta tells the consumer not to wait for natural completion.
- Heartbeats let a supervisor distinguish a quiet stream from a dead one without TCP keepalive.
- A graceful interrupt still produces a structured summary.
Compose tools in a pipeline.
The output of one Machine Mode tool is the input of the next, by construction. Each tool emits its own meta and summary; consumers ignore unknown event types unless explicitly configured to fail.
$ outline search "agent" --output jsonl --limit 20 \$ | summarize --input-jsonl - --output jsonl \$ | tee run.jsonl \$ | jq -e 'select(.type=="summary") | .ok == true'{"type":"meta","tool":"outline","command":"search"}{"type":"meta","tool":"summarize","input_schemas":["com.example.outline.events@1.0.0"]}{"type":"abstract","source_id":"doc_91","text":"A typed interface…"}…{"type":"summary","ok":true,"tool":"outline","count":20}{"type":"summary","ok":true,"tool":"summarize","count":20}
- Both producer and consumer emit their own summary — no information is lost in the pipe.
- jq -e on the terminal summary turns Machine Mode into a shell-level boolean.
- With set -o pipefail, an upstream failure short-circuits the whole pipeline.
Negotiate a schema version.
A tool can ship more than one version of its event schema from a single binary. Consumers pin to what they support; the tool honors and reports.
$ outline search "agent" --output jsonl --schema-version 1 --limit 1{"type":"meta","tool":"outline","schema_name":"com.example.outline.events","schema_version":"1.0.0"}{"type":"hit","rank":1,"id":"doc_91","title":"Agent-operable"}{"type":"summary","ok":true,"count":1}$$ outline search "agent" --output jsonl --schema-version 2 --limit 1{"type":"meta","tool":"outline","schema_name":"com.example.outline.events","schema_version":"2.0.0"}{"type":"hit","rank":1,"document":{"id":"doc_91","title":"Agent-operable","mime":"text/markdown"}}{"type":"summary","ok":true,"count":1}
- v2 nested the result in a document object — a breaking shape change, so it got a major bump.
- A consumer that depends on v1 keeps working; one that wants v2 opts in explicitly.
Errors carry their own retry semantics.
An error event includes category and retryable as portable fields. A consumer can build retry logic that works across every conforming tool without learning each tool's bespoke codes.
$ outline create-doc --title "…" --output jsonl{"type":"meta","command":"create-doc"}{"type":"error","code":"RATE_LIMITED","category":"rate_limited","message":"60 writes per minute exceeded","retryable":true,"retry_after_ms":7200}{"type":"summary","ok":false,"error_count":1,"executed":false}
- category=rate_limited is from the standard taxonomy; the consumer's retry policy knows what to do without reading docs.
- retry_after_ms is the tool's hint — the consumer is free to use it or implement its own backoff.
The terminal summary is the success signal.
Exit 0 means "the process finished." Success means "the work completed and was reported." Without the terminal summary, EOF is the cross-language crash signal — even when exit code is 0.
$ # Healthy run — exit 0, summary present, ok=true{"type":"meta","command":"search"}{"type":"hit","rank":1,"id":"doc_1"}{"type":"summary","ok":true,"count":1}echo $? # 0$$ # Crash mid-stream — exit 0 because Bun's default handler swallowed it{"type":"meta","command":"search"}{"type":"hit","rank":1,"id":"doc_1"}# <EOF, no summary, exit 0>echo $? # 0 — but consumer MUST treat this as failure
- A consumer that trusts exit code alone will silently accept the truncated stream as success.
- The terminal summary is the only honest success signal — and its absence is the only honest crash signal.
Build a tool that does this.
The conformance contract is small. Emit JSONL. Expose a schema. Terminate on a summary. Handle pipes cleanly. Redact secrets. The full checklist lives in the specification.
Read §18 · conformance