THE INCIDENT · CHAPTER 12
An editor team wants Grok Build inside its own interface. Reimplementing the agent loop would fork behavior and safety policy. They need a protocol that lets the editor remain the client while Grok Build remains the runtime.
The question: How can another application drive an agent without becoming that agent?
Start from first principles
ACP is like a standardized cockpit connection. The client owns buttons and displays; the runtime owns the engine and flight logic; messages define what can cross between them.
An agent becomes infrastructure when editors, CI, and custom applications can drive it without scraping terminal output.
The Agent Client Protocol supplies that boundary. The shell hosts sessions; clients initialize, authenticate, create/load, prompt, render, and answer permissions.
Embedding transfers authority to the client. A caller choosing cwd, plugins, metadata, and approvals belongs in the trusted computing base.
Build the smallest useful mental model
ACP is a control-plane protocol around the turn loop. It carries lifecycle and notifications; it does not itself execute tools.
Keep base methods separate from x.ai/ extensions. Portable clients feature-detect extras.
Stdio, server, and relay change connectivity and auth exposure but should preserve session semantics.
Fig 12.1 — ACP decouples clients from the shared shell, tool, and workspace runtime.
Now open the hood
Only after the idea is clear does Mira open the source. She ignores most of the workspace and follows the few boundaries that must exist for this part of the story to work.
1. The next clue — Run persistent stdio
Mira now needs one small mechanism: Exchange JSON-RPC over stdin/stdout across turns.
She follows that responsibility into the repository. The guide documents grok agent stdio as primary integration. The important point is not the Rust syntax. It is ownership: this is where the system decides what crosses the boundary.
Then she tests the unhappy path: Stray stdout logging corrupts framing; use stderr. If the model, operator, and saved session do not receive the same honest outcome, the mechanism is not yet trustworthy.
Source: User guide15-agent-mode.md. Verified against Grok Buildc68e39f60462f28d9be5e683d9cbe2c57b1a5027.
2. The next clue — Negotiate capabilities
Mira now needs one small mechanism: Initialize version/features before session work.
She follows that responsibility into the repository. The client example sends initialize data and lists SDKs. The important point is not the Rust syntax. It is ownership: this is where the system decides what crosses the boundary.
Then she tests the unhappy path: Ignoring response yields malformed calls or missing UI behavior. If the model, operator, and saved session do not receive the same honest outcome, the mechanism is not yet trustworthy.
Source: ACP basics/example. Verified against Grok Build c68e39f60462f28d9be5e683d9cbe2c57b1a5027.
3. The next clue — Authenticate before prompt
Mira now needs one small mechanism: Complete supported auth lifecycle outside model reasoning.
She follows that responsibility into the repository. The headless client sends initialize/auth before session materialization. The important point is not the Rust syntax. It is ownership: this is where the system decides what crosses the boundary.
Then she tests the unhappy path: Do not leak long-lived secrets to prompt/tool environments. If the model, operator, and saved session do not receive the same honest outcome, the mechanism is not yet trustworthy.
Source:headless.rs::run_single_turn. Verified against Grok Buildc68e39f60462f28d9be5e683d9cbe2c57b1a5027.
4. The next clue — Create or load explicit sessions
Mira now needs one small mechanism: Choose validated cwd and lifecycle around a concrete ID.
She follows that responsibility into the repository. ACP session/new/load flows and metadata configure session behavior. The important point is not the Rust syntax. It is ownership: this is where the system decides what crosses the boundary.
Then she tests the unhappy path: Prevent cross-tenant session IDs and path traversal. If the model, operator, and saved session do not receive the same honest outcome, the mechanism is not yet trustworthy.
Source: Agent-mode guide and ACP implementation. Verified against Grok Build c68e39f60462f28d9be5e683d9cbe2c57b1a5027.
5. The next clue — Stream typed updates
Mira now needs one small mechanism: Text, thought, tool, plan, permission, and terminal events remain structured.
She follows that responsibility into the repository. The guide lists session/update variants and notifications. The important point is not the Rust syntax. It is ownership: this is where the system decides what crosses the boundary.
Then she tests the unhappy path: Tolerate unknown variants and preserve ordering/correlation. If the model, operator, and saved session do not receive the same honest outcome, the mechanism is not yet trustworthy.
Source: Agent-mode streaming section. Verified against Grok Build c68e39f60462f28d9be5e683d9cbe2c57b1a5027.
6. The next clue — Route permission through client
Mira now needs one small mechanism: Interactive clients display/answer requests while hard policy remains server-side.
She follows that responsibility into the repository. ACP carries permission interaction and the shell uses shared permission manager. The important point is not the Rust syntax. It is ownership: this is where the system decides what crosses the boundary.
Then she tests the unhappy path: A malicious client can auto-approve; rules and sandbox enforce hard limits. If the model, operator, and saved session do not receive the same honest outcome, the mechanism is not yet trustworthy.
Source: ACP session and permissions code. Verified against Grok Build c68e39f60462f28d9be5e683d9cbe2c57b1a5027.
7. The next clue — Feature-detect x.ai extensions
Mira now needs one small mechanism: Vendor methods remain namespaced and optional.
She follows that responsibility into the repository. The guide lists methods/notifications under x.ai/. The important point is not the Rust syntax. It is ownership: this is where the system decides what crosses the boundary.
Then she tests the unhappy path: Hard dependency makes a client Grok-specific and should be declared. If the model, operator, and saved session do not receive the same honest outcome, the mechanism is not yet trustworthy.
Source: Agent-mode extensions section. Verified against Grok Build c68e39f60462f28d9be5e683d9cbe2c57b1a5027.
8. The next clue — Study headless as reference client
Mira now needs one small mechanism: A real in-repo client should exercise lifecycle and projection.
She follows that responsibility into the repository. headless.rs starts the shell in-process and drives ACP to completion. The important point is not the Rust syntax. It is ownership: this is where the system decides what crosses the boundary.
Then she tests the unhappy path: External clients must not assume internal in-process shortcuts. If the model, operator, and saved session do not receive the same honest outcome, the mechanism is not yet trustworthy.
Source:xai-grok-pager/src/headless.rs. Verified against Grok Buildc68e39f60462f28d9be5e683d9cbe2c57b1a5027.
Mira runs the experiment — minimal read-only review client
Reading source gives her a hypothesis. A small experiment tells her whether that hypothesis survives contact with a real workspace. Open Grok over stdio, create a repository session, stream findings, and refuse mutation permissions.
- Spawn stdio with stderr separate.
- Initialize and inspect capabilities.
- Authenticate.
- Create session for validated path.
- Send correlated review prompt.
- Render/log typed updates.
- Deny mutation permissions.
- Wait for terminal event and clean up.
// Pseudocode; verify current ACP SDK types.
const proc = spawn("grok", ["agent", "stdio"]);
await client.initialize({ protocolVersion: 1 });
const session = await client.newSession({ cwd: checkedPath });
await client.prompt(session.id, [{ type: "text", text: reviewPrompt }]);
What she learns. Illustrative pseudocode based on the guide, not a copy-paste SDK program.
That last check matters. Grok Build can expose a mechanism and report an observation; the repository, operating system, CI platform, and reviewer decide whether those observations prove the actual task succeeded.
The whiteboard test
Before Mira explains the chapter to her team, she reduces it to three questions: what owns the decision, what evidence comes back, and what changes when the mechanism fails?
| Review question | Source-backed answer | Operational consequence |
|---|---|---|
| Portable? | Base ACP lifecycle. | Feature-detect. |
| Grok-specific? | x.ai methods. | Declare dependency. |
| Who owns UI? | Client. | Render state accurately. |
| Who owns effects? | Shell/tools/workspace. | Transport is not sandbox. |
This is not a feature scorecard. A mechanism can work exactly as implemented and still be the wrong control for a particular threat. Defaults also change, so recheck the pinned source path before copying configuration into production.
Signals Mira keeps
- Versions, negotiated capabilities, connection identity.
- Session/cwd identity, metadata, auth method without secrets.
- Request/call/update correlation, ordering, cancellation.
- Permission answer, stop reason, cleanup and orphan state.
Together, those signals tell a complete story: the model proposed an action, the harness admitted and routed it, the environment performed something, and a verifier measured the result.
Limits and uncertainty
The public repository is unusually detailed, but it is not the complete deployed product. The snapshot has one visible public commit, so it cannot support a rich historical explanation of why every boundary evolved. Hosted xAI model serving, account systems, and production topology remain outside this study. Where code and guide differ, this series gives the pinned implementation priority and marks documentation-only behavior instead of silently merging versions.
FAQ
ACP versus MCP?
ACP connects client to agent; MCP connects agent to tool servers.
Why not headless JSON?
Headless suits one-shot automation; ACP suits persistent interactive clients.
Can client enforce read-only?
It can deny, but hard policy also belongs in rules/tools/sandbox.
Can stdio hold sessions?
Use documented persistent process and session lifecycle.
Can I use base ACP only?
Yes for supported base capabilities; extras require x.ai extensions.
What changed for Mira
Mira sees ACP as a boundary between presentation and agent semantics, not merely another transport flag.
Next: With the architecture understood, she can finally compare Grok Build with Pi Agent and Hermes fairly.
Key takeaways
- ACP separates UI and runtime.
- Transports wrap shared session semantics.
- Headless is an in-repo ACP client.
- Hard policy must not trust client approval alone.
- Negotiate versions and isolate extensions.
References & source notes
- Pinned Grok Build repository — default branch snapshot researched July 16, 2026.
- Grok Build README — first-party overview and source-build entry points.
- Agent mode guide — ACP transports and updates.
- ACP specification — protocol reference.
Freshness boundary. Grok Build claims in this article are pinned to c68e39f60462f28d9be5e683d9cbe2c57b1a5027. Pi comparison claims, where present, are pinned to 97f9978fa66685f78d2da19ae22e20c46d125f74; Hermes claims are pinned to c9c9bb33fcc6ab479846a1c496a6e9efe2c1c7d4. Recheck paths, symbols, commands, and defaults if those branches advance.