feat: add OpenClaw as ACP backend#11
Conversation
Add OpenClaw (https://github.com/openclaw/openclaw) as a new ACP backend via the `openclaw acp` subcommand, which bridges ACP stdio to a running OpenClaw gateway over WebSocket. Unlike other backends (Kiro / Claude / Codex / Hermes / etc.) where the ACP CLI is the entire agent, OpenClaw requires a separately-running gateway service for provider routing, model selection, and agent runtime. The OpenAB container only embeds the bridge CLI. Files: - Dockerfile.openclaw — node:22-bookworm-slim + `npm i -g openclaw` - docs/openclaw.md — gateway prerequisites, auth, session/model semantics - config.toml.example — commented example agent block - .github/workflows/build.yml — matrix entries (build / merge / promote) - .github/workflows/docker-smoke-test.yml — matrix entry (falls back to --help check when gateway unreachable, same as other auth-required CLIs) - README.md — agent table row Notes: - src/acp/connection.rs intentionally unchanged — `openclaw acp` returns `authMethods: []`, so the auto-authenticate flow from openabdev#822 is a no-op - `/model` slash command does not switch LLM models for OpenClaw; routing is by `--session` key on the gateway side (documented in docs/openclaw.md) - Companion zeabur-template for `openclaw-gateway` to follow in a separate PR so users can one-click the required gateway service
|
All PRs must reference a prior Discord discussion to ensure community alignment before implementation. Please edit the PR description to include a link like: This PR will be automatically closed in 3 days if the link is not added. |
There was a problem hiding this comment.
Pull request overview
Adds OpenClaw as a new selectable ACP backend, mirroring the existing per-agent pattern (Dockerfile + docs + config example + CI matrix entries). The bridge process (openclaw acp) connects over WebSocket to a separately-deployed OpenClaw gateway — the gateway is intentionally not bundled, preserving the project's single-process-per-container model.
Changes:
- New
Dockerfile.openclaw(node:22-bookworm-slim + globally installedopenclawnpm package + gh CLI), modeled onDockerfile.opencode. - New
docs/openclaw.mdcovering architecture, gateway prerequisites, authentication, session/model semantics, capability matrix, and troubleshooting; plus README andconfig.toml.exampleentries. - Adds the
-openclawvariant to thebuild.yml(build-image, merge-manifests, promote-stable) anddocker-smoke-test.ymlmatrices.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
README.md |
Adds OpenClaw row to the supported-agents table. |
docs/openclaw.md |
New user-facing doc with architecture, helm/config examples, capability/limits matrix, and troubleshooting. |
Dockerfile.openclaw |
New runtime image installing the openclaw npm package and gh CLI on node:22-bookworm-slim. |
config.toml.example |
Adds a commented [agent] block illustrating the openclaw bridge invocation. |
.github/workflows/build.yml |
Adds -openclaw to the build/merge/promote matrices. |
.github/workflows/docker-smoke-test.yml |
Adds -openclaw smoke-test matrix entry (falls back to --help when the gateway is unreachable). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Install openclaw | ||
| # Note: openclaw does not publish SHA256 checksums for its npm releases, | ||
| # so checksum verification is not performed. | ||
| ARG OPENCLAW_VERSION=latest |
| ```bash | ||
| helm install openab openab/openab \ | ||
| --set agents.kiro.enabled=false \ | ||
| --set agents.openclaw.discord.enabled=true \ | ||
| --set agents.openclaw.discord.botToken="$DISCORD_BOT_TOKEN" \ | ||
| --set-string 'agents.openclaw.discord.allowedChannels[0]=YOUR_CHANNEL_ID' \ | ||
| --set agents.openclaw.image=ghcr.io/openabdev/openab-openclaw:latest \ | ||
| --set agents.openclaw.command=openclaw \ | ||
| --set-json 'agents.openclaw.args=["acp","--url","ws://openclaw-gateway:18789","--session","agent:main:main"]' \ | ||
| --set agents.openclaw.workingDir=/home/node \ | ||
| --set agents.openclaw.env.OPENCLAW_GATEWAY_TOKEN="$OPENCLAW_GATEWAY_TOKEN" | ||
| ``` |
| # command = "openclaw" | ||
| # args = ["acp", "--url", "ws://openclaw-gateway:18789", "--session", "agent:main:main"] | ||
| # working_dir = "/home/node" | ||
| # env = { OPENCLAW_GATEWAY_TOKEN = "${OPENCLAW_GATEWAY_TOKEN}" } |
|
🔒 Auto-closing: this PR has had the Feel free to reopen after adding the discussion link to the PR body. |
0. Discord Discussion URL
Not yet — opening this PR against the fork for internal review before
upstreaming. The architectural decision (external gateway dependency vs.
bundling) is worth a Discord discussion before the upstream PR; this PR is the
concrete artifact to anchor that conversation.
1. What problem does this solve?
Adds OpenClaw as a selectable ACP
backend, so OpenAB users get the same first-class experience for OpenClaw
that they have for Kiro / Claude / Codex / Gemini / OpenCode / Copilot /
Cursor / Hermes / Grok Build.
No related issue yet — exploratory work prompted by openabdev#828 surfacing OpenClaw's
ACP capability.
2. At a Glance
3. Prior Art & Industry Research
OpenClaw itself —
openclaw acpis registered in`src/cli/acp-cli.ts`;
declares `protocolVersion: 1`, `authMethods: []`, supports `loadSession`,
image + embeddedContext content blocks, no audio, no per-session MCP servers,
2 MB prompt cap (`src/acp/translator.ts:686-711`). The bridge requires a
running gateway daemon — `src/acp/server.ts` awaits `gatewayReady` before
serving ACP and exits otherwise.
`openclaw/acpx` — the upstream ACP
multi-agent wrapper. Its registry entry is literally
`openclaw: "openclaw acp"` (`src/agent-registry.ts`), confirming the
`openclaw acp` subcommand is the canonical stdio entry point. acpx itself
adds no useful abstraction for our use case (it expects `openclaw` already
on PATH and would just be an extra hop), so we invoke `openclaw acp`
directly — same as we do for `hermes acp`, `gemini --acp`, etc.
Hermes Agent — closest in-tree analogue for "agent with external
dependency complexity." Hermes requires out-of-band OAuth setup
(SuperGrok / xAI device flow, etc.); OpenClaw requires an out-of-band gateway
service. Both share the same Dockerfile/docs/build.yml shape — this PR
mirrors that pattern.
4. Proposed Solution
Add OpenClaw as a backend where:
openclawnpm package (Node 22.16+).openclaw acp --url ws://<gateway> --session <key>as the stdio ACP process.
(companion
openclaw-gatewayZeabur template to follow).Files:
Dockerfile.openclaw(new)node:22-bookworm-slim+npm i -g openclaw+ gh CLI, matchesDockerfile.opencodeshapedocs/openclaw.md(new)config.toml.example--urland--session.github/workflows/build.yml.github/workflows/docker-smoke-test.yml--helpcheck when gateway unreachable, same path other auth-required CLIs hitREADME.mdDeliberately unchanged:
src/acp/connection.rs. The auto-authenticateflow added in openabdev#822 triggers when
authMethodsis non-empty; OpenClaw returns[], so the existing code path is a no-op for this backend.5. Why This Approach
External gateway over in-container gateway. The alternative (Option A:
supervisord +
openclaw gateway+openclaw acpin the same container)breaks OpenAB's single-process-per-container model, adds a persistent volume
contract (
~/.openclaw/for config + sessions + transcripts), and couplesOpenAB releases to OpenClaw gateway versions. Keeping the gateway external
preserves single-process consistency with all eight existing backends and
keeps OpenClaw version bumps independent.
Known tradeoff —
/modelsemantics differ. OpenClaw routes bysession key (
agent:<name>:<thread>), not by ACPmodelfield. The/model gpt-4oslash command is a no-op for this backend; users switchmodels by editing the gateway-side agent definition or by changing
--session. Documented explicitly indocs/openclaw.md. Not introducing afake mapping layer in OpenAB — would be surprising magic and tightly couple
us to gateway-side naming conventions.
Known limitation — deployment is two pieces. Users must run an OpenClaw
gateway somewhere. Companion Zeabur template (separate PR) reduces this to a
one-click deploy.
6. Alternatives Considered
~/.openclaw/, version coupling. Higher long-term maintenance cost on OpenAB maintainers.OPENAI_BASE_URL=openclaw-gateway)/v1/chat/completions) but not Anthropic-compat (/v1/messages) — so Claude Code can't use it. Also, this isn't an OpenAB-side integration at all; it's just env-var config users can do today without our involvement. Doesn't deliver "OpenClaw as a named backend" UX.@openclaw/acp-bridgethin packageacpxopenclaw acpanyway; no value.7. Validation
cargo check— no Rust changes; existingsrc/acp/connection.rsno-op verified by inspection (OpenClaw
authMethods: []).cargo test— no behavior change in OpenAB core.cargo clippy— no new code paths.the bridge exits with
gateway closed before ready; the workflowfalls back to
openclaw --helpcheck (same path Hermes/others takewhen they need auth).
openclaw-gatewayto a test cluster, run OpenAB with this imagepointing at it, send a message in the test Discord channel
(
1493817398997029006), verify ACP round-trip + tool calls + imageattachments.
agents.openclaw.*— not added in this PRto keep diff focused; will follow once manual e2e confirms the
argument shape.
Notes
mainfor internal review.Upstream PR (against
openabdev/openab) will follow after Discorddiscussion + manual e2e validation.
openclaw-gatewayZeabur template tracked separately.