diff --git a/docs/cli/acp.md b/docs/cli/acp.md index 429862407c2..7dba803f1bc 100644 --- a/docs/cli/acp.md +++ b/docs/cli/acp.md @@ -21,6 +21,24 @@ If you want an external MCP client to talk directly to OpenClaw channel conversations instead of hosting an ACP harness session, use [`openclaw mcp serve`](/cli/mcp) instead. +## What this is not + +This page is often confused with ACP harness sessions. + +`openclaw acp` means: + +- OpenClaw acts as an ACP server +- an IDE or ACP client connects to OpenClaw +- OpenClaw forwards that work into a Gateway session + +This is different from [ACP Agents](/tools/acp-agents), where OpenClaw runs an +external harness such as Codex or Claude Code through `acpx`. + +Quick rule: + +- editor/client wants to talk ACP to OpenClaw: use `openclaw acp` +- OpenClaw should launch Codex/Claude/Gemini as an ACP harness: use `/acp spawn` and [ACP Agents](/tools/acp-agents) + ## Compatibility Matrix | ACP area | Status | Notes | diff --git a/docs/gateway/cli-backends.md b/docs/gateway/cli-backends.md index 6877daab490..fb3b8c96e6d 100644 --- a/docs/gateway/cli-backends.md +++ b/docs/gateway/cli-backends.md @@ -20,6 +20,10 @@ rate-limited, or temporarily misbehaving. This is intentionally conservative: This is designed as a **safety net** rather than a primary path. Use it when you want “always works” text responses without relying on external APIs. +If you want a full harness runtime with ACP session controls, background tasks, +thread/conversation binding, and persistent external coding sessions, use +[ACP Agents](/tools/acp-agents) instead. CLI backends are not ACP. + ## Beginner-friendly quick start You can use Claude Code CLI **without any config** (the bundled Anthropic plugin diff --git a/docs/tools/acp-agents.md b/docs/tools/acp-agents.md index ae987cd24db..5c5ffebdda4 100644 --- a/docs/tools/acp-agents.md +++ b/docs/tools/acp-agents.md @@ -19,6 +19,36 @@ If you want Codex or Claude Code to connect as an external MCP client directly to existing OpenClaw channel conversations, use [`openclaw mcp serve`](/cli/mcp) instead of ACP. +## Which page do I want? + +There are three nearby surfaces that are easy to confuse: + +| You want to... | Use this | Notes | +| ---------------------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| Run Codex, Claude Code, Gemini CLI, or another external harness _through_ OpenClaw | This page: ACP agents | Chat-bound sessions, `/acp spawn`, `sessions_spawn({ runtime: "acp" })`, background tasks, runtime controls | +| Expose an OpenClaw Gateway session _as_ an ACP server for an editor or client | [`openclaw acp`](/cli/acp) | Bridge mode. IDE/client talks ACP to OpenClaw over stdio/WebSocket | +| Reuse a local AI CLI as a text-only fallback model | [CLI Backends](/gateway/cli-backends) | Not ACP. No OpenClaw tools, no ACP controls, no harness runtime | + +## Does this work out of the box? + +Usually, yes. + +- Fresh installs now ship the bundled `acpx` runtime plugin enabled by default. +- The bundled `acpx` plugin prefers its plugin-local pinned `acpx` binary. +- On startup, OpenClaw probes that binary and self-repairs it if needed. +- Start with `/acp doctor` if you want a fast readiness check. + +What can still happen on first use: + +- A target harness adapter may be fetched on demand with `npx` the first time you use that harness. +- Vendor auth still has to exist on the host for that harness. +- If the host has no npm/network access, first-run adapter fetches can fail until caches are pre-warmed or the adapter is installed another way. + +Examples: + +- `/acp spawn codex`: OpenClaw should be ready to bootstrap `acpx`, but the Codex ACP adapter may still need a first-run fetch. +- `/acp spawn claude`: same story for the Claude ACP adapter, plus Claude-side auth on that host. + ## Fast operator flow Use this when you want a practical `/acp` runbook: @@ -70,6 +100,26 @@ Use ACP when you want an external harness runtime. Use sub-agents when you want See also [Sub-agents](/tools/subagents). +## How ACP runs Claude Code + +For Claude Code through ACP, the stack is: + +1. OpenClaw ACP session control plane +2. bundled `acpx` runtime plugin +3. Claude ACP adapter +4. Claude-side runtime/session machinery + +Important distinction: + +- ACP Claude is not the same thing as the direct `claude-cli/...` fallback runtime. +- ACP Claude is a harness session with ACP controls, session resume, background-task tracking, and optional conversation/thread binding. +- `claude-cli/...` is a text-only local CLI backend. See [CLI Backends](/gateway/cli-backends). + +For operators, the practical rule is: + +- want `/acp spawn`, bindable sessions, runtime controls, or persistent harness work: use ACP +- want simple local text fallback through the raw CLI: use CLI backends + ## Bound sessions ### Current-conversation binds @@ -614,7 +664,17 @@ See [Configuration Reference](/gateway/configuration-reference). ## Plugin setup for acpx backend -Install and enable plugin: +Fresh installs ship the bundled `acpx` runtime plugin enabled by default, so ACP +usually works without a manual plugin install step. + +Start with: + +```text +/acp doctor +``` + +If you disabled `acpx`, denied it via `plugins.allow` / `plugins.deny`, or want +to switch to a local development checkout, use the explicit plugin path: ```bash openclaw plugins install acpx diff --git a/extensions/acpx/openclaw.plugin.json b/extensions/acpx/openclaw.plugin.json index 8029c1fd0dc..922e997c63e 100644 --- a/extensions/acpx/openclaw.plugin.json +++ b/extensions/acpx/openclaw.plugin.json @@ -1,5 +1,6 @@ { "id": "acpx", + "enabledByDefault": true, "name": "ACPX Runtime", "description": "ACP runtime backend powered by acpx with configurable command path and version policy.", "skills": ["./skills"], diff --git a/src/secrets/runtime-config-collectors-plugins.test.ts b/src/secrets/runtime-config-collectors-plugins.test.ts index d3040a62e06..4c6ba71aeb9 100644 --- a/src/secrets/runtime-config-collectors-plugins.test.ts +++ b/src/secrets/runtime-config-collectors-plugins.test.ts @@ -250,7 +250,7 @@ describe("collectPluginConfigAssignments", () => { ); }); - it("keeps bundled acpx inactive unless explicitly enabled", () => { + it("treats bundled acpx as active by default", () => { const config = asConfig({ plugins: { enabled: true, @@ -274,9 +274,11 @@ describe("collectPluginConfigAssignments", () => { loadablePluginOrigins: loadablePluginOrigins([["acpx", "bundled"]]), }); - expect(context.assignments).toHaveLength(0); + expect(context.assignments).toHaveLength(1); + expect(context.assignments[0]?.path).toBe("plugins.entries.acpx.config.mcpServers.s1.env.K"); + expect(context.assignments[0]?.ref.id).toBe("K"); expect(context.warnings.some((w) => w.code === "SECRETS_REF_IGNORED_INACTIVE_SURFACE")).toBe( - true, + false, ); }); diff --git a/src/secrets/runtime-config-collectors-plugins.ts b/src/secrets/runtime-config-collectors-plugins.ts index 66d374a3c55..01c5d5c5acb 100644 --- a/src/secrets/runtime-config-collectors-plugins.ts +++ b/src/secrets/runtime-config-collectors-plugins.ts @@ -9,6 +9,7 @@ import { import { isRecord } from "./shared.js"; const ACPX_PLUGIN_ID = "acpx"; +const ACPX_ENABLED_BY_DEFAULT = true; /** * Walk plugin config entries and collect SecretRef assignments for MCP server @@ -63,7 +64,14 @@ export function collectPluginConfigAssignments(params: { continue; } - const enableState = resolveEnableState(pluginId, pluginOrigin ?? "config", normalizedConfig); + const enableState = resolveEnableState( + pluginId, + pluginOrigin ?? "config", + normalizedConfig, + pluginId === ACPX_PLUGIN_ID && pluginOrigin === "bundled" + ? ACPX_ENABLED_BY_DEFAULT + : undefined, + ); collectMcpServerEnvAssignments({ pluginId, pluginConfig,