Agent-Native Interfaces

Agent-Native Interfaces

The 2024–2026 dimension of client-agnostic core thinking: designing software interfaces specifically so AI agents (LLMs invoking tools, MCP servers, Claude Code, Cursor agents) can drive them effectively. Not by retrofitting an "AI mode" onto existing UIs, but by treating agents as a first-class consumer of the API/CLI from day one.

The core insight: good design for agents is also good design for shell pipelines and other programs. Agents are simply the most demanding consumer of the contract Doug McIlroy described in 1978 ("write programs to handle text streams").

What makes an interface agent-native

Six properties accumulated from ~2024–2026 practice:

1. Structured outputs always available

JSON output is a first-class flag, not an afterthought. --format json (or auto-detected from non-TTY stdout). Stable schemas. Breaking the schema breaks downstream agents silently.

Example: gh (GitHub CLI) ships JSON output for almost everything. aws does too. kubectl get -o json is universal. mxr and lazydap inherit this.

2. Idempotency and dry-run as first-class

Agents will retry. They'll re-issue the same command after a network blip. Mutating endpoints need idempotency keys (Stripe-style) or --dry-run previews so the agent can verify intent.

Both Mxr and Lazydap enforce: every mutation has --dry-run. Selection logic in dry-run matches the real mutation. Same code, same outcome.

3. Predictable schemas

Type definitions are the contract. Optional fields, error shapes, nested structures — all documented. Schema files (JSON Schema, OpenAPI, gRPC .proto) help agents validate inputs before sending.

Modern best practice: ship schemas alongside the API. MCP servers expose tools/list returning each tool's input schema. CLI tools should expose --schema or similar.

4. Semantic identifiers, not opaque pointers

Agents reason about entities by their identifiers. customer_acct_01ABC (semantic) vs f3xz9q (opaque) — the first lets an agent understand "this is a customer account"; the second forces every reference to be looked up.

Rule of thumb: prefix IDs with their type. UUIDv7 plus a type prefix is a popular shape. msg_01HXYZ, bp_01ABC (from lazydap's breakpoint IDs).

5. Capability discovery

Agents need to ask "what can I do here?" without reading documentation. APIs that don't expose their own surface programmatically force agents to be hand-tuned per integration.

Mechanisms:

CLIWatch's "Designing a CLI Skills Protocol for AI Agents" (2025) argues for a standard skills subcommand. Worth watching.

6. Self-contained, non-overlapping tool surface

Two tools that do nearly the same thing confuse LLMs at tool selection. A clean surface has each operation in exactly one place. Anthropic's Writing tools for agents emphasises this:

"Every tool must justify its existence."

Reduce surface area; consolidate similar operations; document each tool's distinct purpose.

Design rules from Anthropic's "Writing tools for agents"

Anthropic's engineering post is the closest thing to a canonical guide for this:

These rules apply equally to JSON CLIs, REST APIs, and MCP tools.

Two emerging "best practice" articles worth reading

Both crystallise patterns that mxr and lazydap arrived at independently.

Why this is newly important

Pre-LLM, "agent-friendly CLI" was a niche concern (cron jobs, CI scripts). Post-LLM, every popular CLI is being driven by agents in some capacity. Tools that don't ship structured output, idempotency, dry-run, and discovery are increasingly invisible to LLM-based development.

This isn't a marketing observation. It's a structural one: agents are doing real work in 2026, and the tools they reach for are the ones that are easy to reach for.

Simon Willison's framing

Simon Willison is the most-cited voice on agent-CLI design. Two posts to read:

Willison explicitly prefers shell commands over MCP for coding agents: "coding agents are really good at running shell commands… create an AGENTS.md with examples." This is exactly the Mxr / Lazydap design intuition, articulated.

Native vs retrofitted

Two approaches to "AI-friendliness":

  1. Retrofit. Existing tool, add an "AI mode" or MCP wrapper later. Hard; the original surface wasn't designed for this.
  2. Native. Design the tool such that the AI usage is the same as the human usage (with maybe a --format json flag). Easier; the discipline that makes humans' lives easier (composable, scriptable, predictable) makes agents' lives easier too.

mxr and lazydap take approach 2. The CLI is one consumer. The agent skill is another. Both speak the same protocol. No special "AI mode."

The 2026 mxr v1 pass added a sharper rule: MCP is a peer client, not a bypass.
mxr mcp serve exposes typed tools over stdio, but each tool calls the daemon
with origin mcp. That means account scope, send/destructive gates, dry-run
previews, and activity logging stay in the daemon instead of being reimplemented
in the MCP wrapper. If an MCP server talks directly to provider internals, it is
not first-class. It is a second authority path.

The CLI as the agent's test harness

An agent-native CLI is also the test harness an agent should use to debug the product.

Spotuify makes this explicit: every TUI, MCP, and daemon capability must be available through spotuify <subcommand>, with JSON output where useful. That lets an agent reproduce a runtime bug by starting the daemon, reading status, listing devices, pressing the same playback path through CLI commands, and checking logs without asking a human to screenshot the TUI.

The discipline cuts both ways. If an agent cannot verify a feature through the public CLI, either the feature is not truly agent-native or the CLI contract has a gap. Hidden internal hooks are easier for tests, but they weaken the product surface.

Fault injection must stay inside the product boundary

Offline recovery tests need a deterministic way to make product requests fail. That failure must not escape into the host running the test.

On 1 September 2026, a Recto verification task disabled the host Mac's Wi-Fi and monitor Ethernet while testing offline recovery. The test affected unrelated work because it changed the machine instead of the product's view of the network.

Simulate the failure at the app's network seam, through a proxy, in an isolated virtual machine or container, or against a development backend. Do not disable host network services. The public CLI can be the agent's test harness, but destructive fault injection still needs an isolated scope and postcondition checks. Otherwise a realistic test becomes the incident it was meant to model.

This is the same boundary behind Tests Fail on Realistic Bugs: test the real behavior without making the surrounding machine part of the fixture.

Source: Recto offline-recovery incident, 2026-09-01. The exact local session pointer is retained in Dream Log.

What sufficient agent-nativity looks like

A checklist for new tools:

Hit 8 of 10 and your tool is in the top decile of agent-friendliness. Hit all 10 and agents will reach for it before alternatives.

See also