2026-07-24 16:59:42 +00:00
# Agent mode (ACP) and IDE integration
2026-07-16 06:46:02 +01:00
2026-07-24 16:59:42 +00:00
Agent mode runs Grok as a long-lived server that clients talk to over [ACP ](https://agentclientprotocol.com ) (JSON-RPC). Use it from IDEs, SDKs, eval harnesses, and custom apps. For a one-shot prompt that prints and exits, use `grok -p` instead ([headless mode ](14-headless-mode.md )).
---
## Automation and SDKs
For scripts, CI, evals, and agent servers, start with always-approve so tools run without interactive permission prompts. Deny rules and hooks still apply.
```bash
# stdio (local process / many SDKs)
grok agent --always-approve stdio
# WebSocket server
grok agent --always-approve serve --bind 127.0.0.1:2419 --secret <token>
```
You can also set always-approve per session on `session/new` :
```json
{
"cwd": "/path/to/project",
"mcpServers": [],
"_meta": { "yoloMode": true }
}
```
Interactive TUI users typically leave the default ask mode (or use auto). See [Permissions and safety ](22-permissions-and-safety.md ).
2026-07-16 06:46:02 +01:00
---
## What is ACP?
2026-07-24 16:59:42 +00:00
The [Agent Client Protocol (ACP) ](https://agentclientprotocol.com ) defines how clients talk to coding agents over JSON-RPC. With Grok it covers:
2026-07-16 06:46:02 +01:00
2026-07-24 16:59:42 +00:00
- Sessions (create, load, resume)
- Prompts and streamed replies
- Tool call updates
- Reasoning / thought streams
- Permission prompts when the session is not always-approve
2026-07-16 06:46:02 +01:00
---
## stdio transport
2026-07-24 16:59:42 +00:00
stdio is the common local integration path. The agent speaks JSON-RPC on stdin and stdout:
2026-07-16 06:46:02 +01:00
```bash
2026-07-24 16:59:42 +00:00
grok agent --always-approve stdio
2026-07-16 06:46:02 +01:00
```
2026-07-24 16:59:42 +00:00
Typical clients: IDE extensions (Zed, Neovim, Emacs), custom tools, and ACP SDKs.
2026-07-16 06:46:02 +01:00
### Options
2026-07-24 16:59:42 +00:00
Agent options apply to every transport (`stdio` , `serve` , `headless` , `leader` ). They go after `agent` and before the mode name. Mode-specific flags go after the mode (for example `serve --bind` ).
```bash
grok agent --always-approve --model grok-build stdio
grok agent --always-approve serve --bind 127.0.0.1:2419 --secret <token>
```
2026-07-16 06:46:02 +01:00
2026-07-24 16:59:42 +00:00
| Flag | Description |
| ---- | ----------- |
| `-m, --model <MODEL>` | Model ID (for example `grok-build` ). |
| `--always-approve` | Run without interactive tool-permission prompts. Alias: `--yolo` . |
| `--reauth` | Authenticate before the agent starts. |
| `--agent-profile <PATH>` | Load an agent profile from a file. |
2026-07-27 17:54:34 +00:00
| `--leader` / `--no-leader` | Connect to a shared leader process, or force a local agent. When a non-`off` sandbox profile is requested, leader mode is refused so tools stay in-process (see [Sandbox Mode ](18-sandbox.md )). |
2026-07-16 06:46:02 +01:00
---
## Server mode
```bash
2026-07-24 16:59:42 +00:00
grok agent --always-approve serve --bind 127.0.0.1:2419 --secret <token>
2026-07-16 06:46:02 +01:00
```
2026-07-24 16:59:42 +00:00
Clients connect over WebSocket and authenticate with the secret token. If you omit `--secret` , the agent prints a generated token at startup, or set `GROK_AGENT_SECRET` . The process keeps state across client reconnects. Permissions match other entry points; see [Permissions and safety ](22-permissions-and-safety.md ).
2026-07-16 06:46:02 +01:00
---
## WebSocket relay
2026-07-24 16:59:42 +00:00
To reach the agent over the internet, connect the agent to a relay and point browsers at the same relay:
2026-07-16 06:46:02 +01:00
```bash
2026-07-24 16:59:42 +00:00
grok agent --always-approve headless --grok-ws-url wss://your-relay.example.com/ws
2026-07-16 06:46:02 +01:00
```
---
## ACP protocol basics
Communication follows the JSON-RPC 2.0 format. A typical session lifecycle:
1. **Initialize ** -- client sends `initialize` with capabilities
2. **Create session ** -- client sends `session/new` with working directory
3. **Send prompts ** -- client sends `session/prompt` with user messages
4. **Receive updates ** -- agent sends `session/update` notifications with streamed content
2026-07-24 16:59:42 +00:00
5. **Handle permissions ** -- agent may request tool execution approval (or allow or deny based on permission mode)
2026-07-16 06:46:02 +01:00
### Architecture
```
+------------------------------------------+
| ACP Client |
| (IDE, Editor, Custom Application) |
+-------------------+----------------------+
| JSON-RPC over stdio
+-------------------v----------------------+
| grok agent stdio |
| |
| +---------+ +---------+ +---------+ |
| | Session | | Tools | | MCP | |
| | Manager | | Registry| | Servers | |
| +---------+ +---------+ +---------+ |
+------------------------------------------+
```
---
## Streaming updates
ACP streams structured events. Each `session/update` notification carries a `sessionUpdate` field that identifies the update type:
| `sessionUpdate` value | Description |
| --------------------- | ----------------------------------------------------- |
| `agent_message_chunk` | A chunk of the agent's response text. |
| `agent_thought_chunk` | A chunk of the agent's internal reasoning. |
| `tool_call` | A new tool invocation (title, kind, status, input). |
| `tool_call_update` | A status or result update for an in-flight tool call. |
| `plan` | The agent's execution plan. |
Each update names its type, so a client can render distinct panels for reasoning, tool calls, and response text.
---
## Extension methods
Beyond the base ACP protocol, Grok defines extension methods under the `x.ai/` prefix for SpaceXAI-specific functionality. These cover:
| Category | Prefix | Examples |
| -------------------------- | -------------------- | ------------------------------------------------ |
| **Filesystem ** | `x.ai/fs/*` | `list` , `exists` , `read_file` , `write_file` |
| **Git ** | `x.ai/git/*` | `status` , `stage` , `commit` , `diffs` , `discard` |
| **Git Worktree ** | `x.ai/git/worktree/*` | `create` , `remove` , `apply` , `list` , `gc` |
| **Search ** | `x.ai/search/*` | `fuzzy/open` , `fuzzy/change` , `content` |
| **Terminal ** | `x.ai/terminal/*` | `create` , `kill` , `output` , `wait_for_exit` |
| **Session Management ** | `x.ai/session/*` | `fork` , `resolve_local_for_worktree_resume` |
| **Conversation & History ** | `x.ai/*` | `prompt_history` , `rewind/*` , `compact_conversation` |
| **Authentication ** | `x.ai/auth/*` | `get_url` , `submit_code` |
| **Feedback & Telemetry ** | `x.ai/*` | `feedback` , `telemetry/*` |
The tables here show representative methods in each category. The `x.ai/*` set is SpaceXAI-specific and may expand across releases, so treat it as non-exhaustive and discover the available methods from the agent's `initialize` response.
### Notifications (agent to client)
The agent sends push notifications to clients for real-time updates:
| Notification | Description |
| -------------------------- | ------------------------------------ |
| `x.ai/search/fuzzy/status` | Fuzzy search results update |
| `x.ai/git/worktree/status` | Worktree creation progress |
| `x.ai/fs_notify` | Filesystem change notification |
| `x.ai/fs/index` | Full file index update |
| `x.ai/fs/index/delta` | Incremental file index update |
| `x.ai/session_notification` | Session-specific updates (diff review, retry state, auto-compact) |
| `x.ai/session/update` | Session update (tool calls, content) |
---
## Session `_meta` options
2026-07-24 16:59:42 +00:00
Optional fields on `session/new` :
| Field | Description |
| ----- | ----------- |
| `rules` | Extra rules appended to the system prompt. |
| `systemPromptOverride` | Replacement system prompt. |
| `agentProfile` | Agent profile name or JSON object. |
| `yoloMode` | When `true` , always-approve for this session. |
| `autoMode` | When `true` , auto permission mode for this session. Superseded when always-approve is already on. |
```json
{
"cwd": "/path/to/project",
"mcpServers": [],
"_meta": { "yoloMode": true }
}
```
2026-07-16 06:46:02 +01:00
---
## ACP SDKs
Official SDK libraries are available for multiple languages:
| Language | Package |
| ---------- | ---------------------------------------------------------------------------------------- |
| TypeScript | [`@agentclientprotocol/sdk` ](https://www.npmjs.com/package/@agentclientprotocol/sdk ) |
| Rust | [`agent-client-protocol` ](https://crates.io/crates/agent-client-protocol ) |
| Python | [`agent-client-protocol-python` ](https://github.com/PsiACE/agent-client-protocol-python ) |
| Go | [`acp-go-sdk` ](https://github.com/coder/acp-go-sdk ) |
| Kotlin | [`acp` ](https://github.com/agentclientprotocol/kotlin-sdk ) |
---
## Compatible clients
| Client | Status |
| -------------------------------------------------------- | ----------- |
| [Zed ](https://zed.dev/docs/ai/external-agents ) | Supported |
| [Neovim ](https://neovim.io ) (CodeCompanion, avante.nvim) | Supported |
| [Emacs ](https://github.com/xenodium/agent-shell ) | Supported |
| [marimo notebook ](https://github.com/marimo-team/marimo ) | Supported |
| JetBrains | Coming soon |
---
## Integration example: a TypeScript ACP client
```typescript
import { spawn, ChildProcess } from "child_process";
import * as readline from "readline";
class GrokACPChat {
private proc!: ChildProcess;
private sessionId!: string;
private rl!: readline.Interface;
constructor(private cwd = ".") {}
async init() {
2026-07-24 16:59:42 +00:00
this.proc = spawn("grok", ["agent", "--always-approve", "stdio"]);
2026-07-16 06:46:02 +01:00
this.rl = readline.createInterface({ input: this.proc.stdout! });
await this.request("initialize", {
protocolVersion: 1,
clientCapabilities: {
fs: { readTextFile: true, writeTextFile: true },
terminal: true,
},
});
const { sessionId } = await this.request("session/new", {
cwd: this.cwd,
mcpServers: [],
2026-07-24 16:59:42 +00:00
_meta: { yoloMode: true },
2026-07-16 06:46:02 +01:00
});
this.sessionId = sessionId;
return this;
}
private async request(method: string, params: any): Promise<any> {
return new Promise((resolve) => {
const msg = JSON.stringify({ jsonrpc: "2.0", id: 1, method, params });
this.proc.stdin!.write(msg + "\n");
this.rl.once("line", (line) => {
resolve(JSON.parse(line).result || {});
});
});
}
async *streamPrompt(text: string) {
const msg = JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "session/prompt",
params: {
sessionId: this.sessionId,
prompt: [{ type: "text", text }],
},
});
this.proc.stdin!.write(msg + "\n");
for await (const line of this.rl) {
const data = JSON.parse(line);
if (data.method === "session/update") {
const update = data.params.update;
yield update; // { sessionUpdate, content, title, ... }
} else if (data.result) {
break; // Final response
}
}
}
}
// Usage
const client = await new GrokACPChat(".").init();
for await (const update of client.streamPrompt("List the files in this project")) {
switch (update.sessionUpdate) {
case "agent_message_chunk":
process.stdout.write(update.content?.text || "");
break;
case "agent_thought_chunk":
console.log(`\n[Thinking: ${update.content?.text}]` );
break;
case "tool_call":
console.log(`\n[Tool: ${update.title}]` );
break;
}
}
```
---
## Resources
- [ACP Specification ](https://agentclientprotocol.com/protocol/prompt-turn )
- [Protocol Introduction ](https://agentclientprotocol.com/overview/introduction )