Binary interface

2026-07-23 · 5 min read essay textserve

An agent needs something to grip. A command, an endpoint, an operation with a defined surface and a predictable output. The handle has to be narrow enough that there aren't many ways to hold it wrong. And when you look at what that requires, it turns out to be the same thing a human needs at 9am when they're switching context and don't want to think: one command, one input, one observable effect.

This convergence is not obvious. The instinct is to design differently for the two audiences. Humans get ergonomic CLIs with friendly flags. Agents get JSON payloads and programmatic APIs, because agents are code, and code speaks JSON. But that instinct is wrong, and Microsoft measured it.

The numbers

Their test was straightforward: the same task, the same five models, two interface shapes. One was a conventional flat-args CLI. One was a JSON-payload API. On the flat CLI, every model hit perfect correctness, including the weakest one tested (Haiku 4.5). On the JSON interface, only the three strongest models matched that. Haiku 4.5 got two out of five right.

The cost difference was larger than the correctness difference. JSON ran 4 to 11 times more expensive per task, almost entirely from retries: 7 to 14 times more output tokens. Add a shell-escaping tax on top, 9 times the cost premium on PowerShell, 1.5 times on Bash, same model and task. The JSON interface wasn't just harder to call correctly. It was dramatically more expensive to fail at.

Narrowing the valid input space compensates for gaps in model capability.

That's their summary. It's also a precise description of what a well-designed human interface does. You narrow the input space so the user doesn't have to hold the full schema in their head. The model and the human are hitting the same constraint from different directions: the model has capability gaps under pressure, the human has attention gaps under pressure. A narrow interface compensates for both.

Same constraint, same shape

The Paperworlds tools were not designed with agents in mind. textaccounts switch work was built for a human who switches contexts several times a day and can't afford to remember the exact flag names. One positional argument. One observable effect: CLAUDE_CONFIG_DIR set, shell environment updated, done. textserve bundle use work is the same shape: one operation, one surface, one thing that changes. You can call either from a script, from a Makefile, from an agent loop, without touching a schema or constructing a payload. That's not an accident of design. It's the consequence of designing for a human who doesn't want to think.

JSON APIs feel more agent-native because they're programmatic. Structured. Parseable. But structured and narrow are different things. A JSON payload can be wide: optional fields, nested objects, multiple valid orderings, enum values that require checking the docs. Each degree of freedom is another way the agent can be wrong and another retry it has to make. The flat CLI compresses all of that. The binary has one calling convention. You can't pass the arguments in the wrong order. You can't accidentally omit a required field from a nested object. The surface is the constraint.

Building for both

The design discipline is the same whether you're optimizing for a human or an agent: reduce the number of ways to be wrong. Single operation. Explicit positional arguments over optional flags where possible. One success state, one failure mode, one output format. The agent benefits from this because its error budget is small and retries are expensive. The human benefits from this because their attention is finite and documentation is a tax.

What this rules out is the "programmable surface" instinct: expose everything, let the caller compose what they need. That instinct makes sense for a library used by developers who will read the source and build against it deliberately. It doesn't make sense for a CLI that needs to be called correctly by something that isn't reading the source. The handle has to fit the hand. For an agent, the hand is the model's prior, shaped by training on a distribution of valid commands. For a human, the hand is memory under interruption. Both get the same handle: short, unambiguous, impossible to hold upside down.

Protobuf in disguise

The parallel to data serialization is exact. JSON became the lingua franca of APIs because it's human-readable: you can inspect a payload in your terminal, fix a field without regenerating a schema, reason about a response without a decoder. Protobuf is binary and opaque, but it wins on reliability: every field has a declared type, every message has an enforced shape, and there's no way to send a payload that violates the contract. Service-to-service communication migrated toward protobuf not because machines prefer binary, but because constraint is reliable. The wider the valid input space, the more ways to be wrong.

The CLI does the same thing at the interface layer. It looks like something a person typed. It reads as human-native. But the argument parser is the schema: positional arguments enforce ordering, required flags surface immediately as errors, types are validated before the first line of business logic runs. You can't pass a string where an integer is expected. You can't omit a required argument silently. The surface is enforced by the tool itself, not by a contract the caller has to read and remember. The CLI is the protobuf of interfaces: readable like JSON, constrained like a binary format.

This reframes the surprise in the Microsoft numbers. JSON APIs feel more agent-native because they're programmatic. But programmatic and constrained are different things. JSON is flexible by design, and that flexibility is precisely the failure surface: optional fields, nested structures, multiple valid orderings, enum values that require checking the docs. Each degree of freedom is another way the agent can be wrong and another retry it has to buy. The flat CLI compresses all of that. The shape is the constraint. And the constraint is what makes it work for both callers: the agent that can't afford ambiguity, and the human who won't read the schema at 9am.

The inversion

There is a version of this argument that sounds like it's about making things simple for less capable systems. Dumb down the interface so the weaker model can handle it. That reading inverts the point. The flat CLI isn't simpler. It's more constrained. Constraint is a design choice, not a concession. The narrow surface isn't there because the agent can't handle complexity: it's there because complexity in a calling interface adds cost that accrues on every call, for every caller, forever. Narrowing isn't a workaround. It's the correct shape for anything that needs to be called reliably at scale.

The models that failed the JSON test weren't failing because they were incapable. They were failing because the interface gave them room to fail. Remove the room and the failure rate drops to zero. That's not a capability story. It's a surface area story.

Build the handle. Make it narrow. The agent and the human will grip it the same way, for the same reason: there's only one way to hold it.

References

Pairs with: Bricks that become a building · Accountability debt