Direction.
Where AOI‑CLI is going beyond v0.2, and how it sits next to adjacent standards.
Nothing on this page is normative in the current specification. This is committed direction — design that the v0.3 work will build on. The AOI‑CLI v0.2 spec is what conforming tools should implement today.
Modes.
Everything in the current specification defines Batch Mode — one process invocation per operation, JSONL on stdout, terminal summary, clean exit. Batch Mode covers the vast majority of agent‑tool interactions today and is the only normative mode in v0.2.
Session Mode is the next mode under design — a long‑lived process that accepts a sequence of requests over stdin and emits responses and server‑initiated notifications over stdout. This is the LSP / MCP shape, generalized for any agent‑operable CLI: JSON‑RPC 2.0 messages, one per line (NDJSON framing), with id correlation for multiple in‑flight requests and $/event notifications for server pushes.
$ outline --mode session{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocol_version":"0.3","client":{"name":"my-agent","version":"1.0.0"}}}{"jsonrpc":"2.0","id":1,"result":{"tool":"outline","tool_version":"1.8.2","capabilities":{"commands":["search","watch"],"wire_formats":["jsonl","cbor"],"push_notifications":true}}}{"jsonrpc":"2.0","id":2,"method":"search","params":{"query":"agent operable","limit":2}}{"jsonrpc":"2.0","method":"$/event","params":{"type":"hit","rank":1,"id":"doc_91"}}{"jsonrpc":"2.0","method":"$/event","params":{"type":"hit","rank":2,"id":"doc_177"}}{"jsonrpc":"2.0","id":2,"result":{"type":"summary","ok":true,"count":2,"truncated":false}}
- NDJSON framing (one JSON message per line) rather than LSP's
Content-Lengthheaders — same choice MCP made, simpler to implement, and means the transport is shared across both AOI Session Mode tools and MCP servers. - Each event from the Batch Mode vocabulary (
hit,match,warning, …) is delivered as a$/eventnotification with the event object asparams. The terminalsummaryis delivered as the JSON‑RPCresult. Same vocabulary, different transport. - Multiplexing is inherited from JSON‑RPC
idcorrelation — multiple in‑flight requests, responses interleave as they complete. No separate spec needed.
Wire formats.
JSONL is the only normative wire format in v0.2 and will remain the required baseline for every conforming tool. Human inspectability of the wire is a feature, not a compromise.
A tool may additionally offer compact binary encodings, advertised in capabilities and selected via HTTP‑style content negotiation:
| Format | Status | When it earns the complexity | Reference |
|---|---|---|---|
| JSON / JSONL | baseline · required | always | RFC 8259 |
| CBOR | optional | high‑rate telemetry · constrained bandwidth · large binary payloads | RFC 8949 |
| MessagePack | optional | same as CBOR, with broader language coverage | msgpack.org |
| Protobuf / Cap’n Proto | out of scope | would force every tool to ship .proto / .capnp files; not justified at v0.x | — |
Negotiation example (HTTP‑style Accept header in spirit):
outline search "x" --output jsonl --accept "application/cbor, application/x-ndjson;q=0.5"
When negotiation produces no overlap, the tool must fall back to the baseline (JSON / JSONL) rather than fail.
Until you are credibly emitting thousands of events per second, or shipping large binary payloads, JSONL is the right answer.
Other profiles.
AOI‑CLI is the first formal profile of the Machine Mode standard. Different interface surfaces have different operational primitives — process boundaries, HTTP connections, message queues, physical actuators don't share I/O, framing, error, or cancellation models. Each surface gets its own profile.
| Surface | Profile | Status |
|---|---|---|
| Command‑line tools (local process) | AOI‑CLI | v0.2 draft · shipping |
| HTTP services (remote endpoint) | OpenAPI + AOI HTTP supplement | OpenAPI de facto · supplement planned |
| Message queues / event streams | AOI‑Queue | future |
| Embedded devices / sensors / actuators | AOI‑Device | future |
The ten characteristics are normative across every profile. What changes per profile is how each characteristic gets expressed at that surface's operational layer.
On OpenAPI.
OpenAPI is the existing, mature, overwhelmingly adopted standard for describing HTTP service interfaces. The Machine Mode HTTP profile, when authored, will not reinvent OpenAPI — it will reference OpenAPI as the wire format and add the remaining characteristics (idempotency keys, terminal completion signals, dry‑run plans, structured error retryability) as a profile / style guide on top, likely as OpenAPI vendor extensions (x-aoi-*) plus a conformance document.
A well‑designed OpenAPI service already satisfies most of the ten characteristics implicitly. AOI‑CLI exists because no equivalent standard exists for the command‑line surface — and the characteristics that apply to OpenAPI apply to CLIs too, but the expression of those characteristics is operationally different at the process boundary.
The detailed argument for why CLIs need their own profile rather than just becoming HTTP services lives in § 05 of the essay.
On MCP.
The Model Context Protocol standardizes how an agent discovers and invokes tools. MCP is a transport and invocation layer. AOI is an operating contract— what a tool does once invoked. They compose: AOI Session Mode (§ 01 above) uses the same transport MCP uses. A conforming AOI‑CLI tool can be exposed as an MCP server with a thin adapter, and an MCP server that follows the AOI characteristics is, by construction, an AOI‑conforming tool.
Authentication is deliberately out of scope
AOI does not standardize authentication. This is a feature, not a gap. A CLI runs as the invoking user, with the user's existing credential ecosystem already in place — keychain, AWS credential chain, kubeconfig, ssh agent, gpg keyring, Vault token, gh PAT, corporate SSO session. Decades of investment in MFA, role assumption, certificate pinning, browser‑based flows, and credential renewal lives in those ecosystems. AOI tools inherit all of it by inheriting the process environment.
Protocols that try to centralize auth at the wire layer — MCP's evolving OAuth profile included — keep running into real‑world federated identity. AOI sidesteps that by not solving it. Authentication happens beneath the AOI invocation, not at it. What AOI does specify is how a tool reports auth state — via the standard error categories authn and authz, and via check events from doctor.
Lineage.
AOI is not the first standard to formalize typed event streams between processes. It sits in a long lineage of stream‑processing systems — Kafka, Flink, Spark Streaming, Apache Beam, materialized views, the whole data‑engineering layer — and it deliberately occupies the smallest, simplest slice of that lineage.
The conceptual parallels are direct:
| AOI concept | Stream-processing analogue |
|---|---|
| source (emits JSONL) | Kafka producer / Flink source |
| sink (reads --input-jsonl) | Kafka consumer / Flink sink |
| transformer (reads + emits) | Flink operator / Kafka Streams app |
| shell pipe | inter-operator channel |
| schema_name@schema_version in meta | Confluent Schema Registry subjects + versions |
| --idempotency-key | Kafka idempotent producer / exactly-once writes |
| summary.next_cursor | consumer offsets |
| summary.truncated:true + cursor | consumer pagination |
| SIGPIPE / clean pipe-close handling | backpressure propagation |
| terminal summary | end-of-stream / watermark |
| malformed-input handling modes | dead-letter queue patterns |
What AOI borrows from the lineage
The producer / consumer / transformer / sink vocabulary, used consistently throughout the spec. The schema‑registry concept, long‑term — eventually a centralized index of schema names so a consumer can fetch the schema for a tool it doesn't have installed. Idempotent‑write semantics via --idempotency-key. Explicit truncation and cursor patterns. Backpressure via clean pipe‑close handling. Dead‑letter patterns for malformed input.
What AOI deliberately doesn't
Distributed runtime semantics — event time vs processing time, watermark generation, state backends, exactly‑once‑across‑failures — stay out. Operator DAGs and query planners stay out; shell pipes already compose at AOI's scale and they do it naively well. Stateful operators (windowing, joins, aggregations) stay out — a single AOI invocation is the state lifecycle. Cluster topology, broker coordination, and query languages on top all stay out. AOI is a contract at a single process boundary, not a runtime system that manages clusters of them.
The relationship is composition, not competition
AOI is the Unix‑pipe‑shaped version of the same idea — same vocabulary about streams, radically smaller operational scope. AOI tools compose with stream processors. You can pipe AOI output into a Flink job that ingests JSONL. You can write a Kafka consumer that feeds an AOI sink over stdin. The contracts bridge cleanly, and the same schema discipline applies on both sides.
Open questions.
- Should Session Mode use NDJSON (MCP‑compatible) or
Content-Lengthframing (LSP‑compatible) as default? Currently leaning NDJSON. - Should the AOI‑HTTP profile, when authored, define its own conformance lint or extend
aoi-lintto drive OpenAPI documents through the same characteristic checks? - Should AOI‑Queue (when designed) inherit Session Mode framing over a different transport, or define its own?
- Should the per‑characteristic conformance reporting from
aoi-lintfollow a standard JSON Schema so consumers can ingest lint reports as data? - What's the right cadence for promoting a forthcoming mode (e.g. Session) from "design committed" to "normative in next minor version" without forcing existing tools to immediately add support?