Synced from monorepo Changes: - Refresh tool search when the managed MCP catalog is re-fetched - Prevent duplicate leader process spawn and startup hang from stale leaders - Document marketplaces, plugins, and organization controls - Stamp session ID on image generation direct-to-API requests - Fix auto mode blocked documentation - Auto mode considers recent user intent - Expose deploy archive, taken-down, limit, and in-progress reasons on the chat API - Fail-closed auth refresh contract for shell clients - Emit a chat-supplied per-session turn index in turn hooks - Show bash mode chrome in minimal mode - Add metrics for true-noop and stationarity stops - Include voice interim text on prompt submit - Silently end turn on true-noop thrash - Quiet copy toast when clipboard delivery is confirmed - Fix session fork truncating at the wrong prompt in rewound sessions - Make the idle "still running" watcher cue clickable to open the tasks pane - Default web search model to grok-4.5 - Let plugin subagents inherit parent MCP servers - Gate no-op end-turn reminder on system reminders - Add gateway bridge lifecycle telemetry - Allow editing finalized text while voice is open - Relocate token carrier to turn-commit events and plumb per-turn origin context - Raise workflow scratch quotas and make failed runs resumable - Workflows overlay: auto-progress phases, live agent status, and drop budget meter Source-Revision: 9b8d35b46d959c042ea9aa31cbbebbd1f0c5c527
11 KiB
Agent mode (ACP) and IDE integration
Agent mode runs Grok as a long-lived server that clients talk to over ACP (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).
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.
# 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:
{
"cwd": "/path/to/project",
"mcpServers": [],
"_meta": { "yoloMode": true }
}
Interactive TUI users typically leave the default ask mode (or use auto). See Permissions and safety.
What is ACP?
The Agent Client Protocol (ACP) 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:
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).
grok agent --always-approve --model grok-build stdio
grok agent --always-approve serve --bind 127.0.0.1:2419 --secret <token>
| 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. |
--leader / --no-leader |
Connect to a shared leader process, or force a local agent. |
Server mode
grok agent --always-approve serve --bind 127.0.0.1:2419 --secret <token>
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.
WebSocket relay
To reach the agent over the internet, connect the agent to a relay and point browsers at the same relay:
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:
- Initialize -- client sends
initializewith capabilities - Create session -- client sends
session/newwith working directory - Send prompts -- client sends
session/promptwith user messages - Receive updates -- agent sends
session/updatenotifications with streamed content - 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. |
{
"cwd": "/path/to/project",
"mcpServers": [],
"_meta": { "yoloMode": true }
}
ACP SDKs
Official SDK libraries are available for multiple languages:
| Language | Package |
|---|---|
| TypeScript | @agentclientprotocol/sdk |
| Rust | agent-client-protocol |
| Python | agent-client-protocol-python |
| Go | acp-go-sdk |
| Kotlin | acp |
Compatible clients
| Client | Status |
|---|---|
| Zed | Supported |
| Neovim (CodeCompanion, avante.nvim) | Supported |
| Emacs | Supported |
| marimo notebook | Supported |
| JetBrains | Coming soon |
Integration example: a TypeScript ACP client
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<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;
}
}