# Agent mode (ACP) and IDE integration 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 ``` 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). --- ## What is ACP? The [Agent Client Protocol (ACP)](https://agentclientprotocol.com) defines how clients talk to coding agents over JSON-RPC. With Grok it covers: - Sessions (create, load, resume) - Prompts and streamed replies - Tool call updates - Reasoning / thought streams - Permission prompts when the session is not always-approve --- ## stdio transport stdio is the common local integration path. The agent speaks JSON-RPC on stdin and stdout: ```bash grok agent --always-approve stdio ``` Typical clients: IDE extensions (Zed, Neovim, Emacs), custom tools, and ACP SDKs. ### Options 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 ``` | Flag | Description | | ---- | ----------- | | `-m, --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 ` | Load an agent profile from a file. | | `--leader` / `--no-leader` | Connect to a shared leader process, or force a local agent. | --- ## Server mode ```bash grok agent --always-approve serve --bind 127.0.0.1:2419 --secret ``` 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). --- ## WebSocket relay To reach the agent over the internet, connect the agent to a relay and point browsers at the same relay: ```bash grok agent --always-approve headless --grok-ws-url wss://your-relay.example.com/ws ``` --- ## 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 5. **Handle permissions** -- agent may request tool execution approval (or allow or deny based on permission mode) ### 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 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 } } ``` --- ## 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() { this.proc = spawn("grok", ["agent", "--always-approve", "stdio"]); 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: [], _meta: { yoloMode: true }, }); this.sessionId = sessionId; return this; } private async request(method: string, params: any): Promise { 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)