For the overview, operator runbook, and concepts, see ACP agents.
This page covers acpx harness config, plugin setup for the MCP bridges, and permission configuration.
Use this page only when you are setting up the ACP/acpx route. For native Codex app-server runtime config, use Codex harness. For OpenAI API keys or Codex OAuth model-provider config, use OpenAI.
Codex has two Apus routes:
| Route | Config/command | Setup page |
|---|---|---|
| Native Codex app-server | /codex ..., openai/gpt-* agent refs |
Codex harness |
| Explicit Codex ACP adapter | /acp spawn codex, runtime: "acp", agentId: "codex" |
This page |
Prefer the native route unless you explicitly need ACP/acpx behavior.
acpx harness support (current)
Built-in acpx harness aliases (from the pinned acpx dependency):
| Alias | Wraps |
|---|---|
claude |
Claude Code |
codex |
Codex CLI |
copilot |
GitHub Copilot CLI |
cursor |
Cursor CLI (cursor-agent acp) |
droid |
Factory Droid |
fast-agent |
fast-agent |
gemini |
Gemini CLI |
grok-build |
Grok Build (grok agent stdio) |
iflow |
iFlow CLI |
kilocode |
Kilocode |
kimi |
Kimi CLI |
kiro |
Kiro CLI |
mcode |
MiniMax Code (mcode acp; install and authenticate its CLI on the Gateway host) |
mux |
Mux |
opencode |
OpenCode |
apus |
Apus ACP bridge (native apus acp) |
pi |
Pi Coding Agent |
pool |
Pool (pool acp) |
qoder |
Qoder CLI |
qwen |
Qwen Code |
trae |
Trae CLI |
zeroclaw |
ZeroClaw (zeroclaw acp) |
factory-droid and factorydroid also resolve to the built-in droid adapter.
When Apus uses the acpx backend, prefer these values for agentId unless your acpx config defines custom agent aliases.
If your local Cursor install still exposes ACP as agent acp, override the cursor agent command in your acpx config instead of changing the built-in default.
Direct acpx CLI usage can also target arbitrary adapters via --agent <command>, but that raw escape hatch is an acpx CLI feature (not the normal Apus agentId path).
Model control is adapter-capability dependent. Codex ACP model refs are
normalized by Apus before startup. Other harnesses need an advertised model
config option with session/set_config_option, or legacy ACP models with
session/set_model. Without supported ACP model control or an adapter-specific
startup model flag, Apus/acpx cannot force a model selection.
GitHub Copilot CLI in native chat
GitHub Copilot CLI can serve ordinary Apus chat through the installed-agent
model picker, including web chat and channels. This route uses the local
copilot --acp --stdio process, not an Apus API-provider credential.
Install an ACP-capable CLI and sign in under the same OS account that runs the Gateway. Copilot CLI 1.0.86 supports model discovery and selection over ACP:
npm install -g @github/copilot
copilot --version
copilot login
Refresh the model catalog, then choose an acp-copilot/<model-id> entry. Apus
uses only the models advertised by that CLI; it does not supply a static model
list. Installation detection alone does not prove authentication or model access.
To prevent new native Copilot turns and catalog discovery, set
plugins.entries.acpx.config.nativeAgents.copilot to false. Classic
/acp spawn copilot sessions and acp.allowedAgents are separate.
Copilot owns authentication and billing:
- Native GitHub authentication uses the CLI's OAuth login or its supported GitHub
token routes, including an authenticated
ghfallback. Environment tokens (COPILOT_GITHUB_TOKEN,GH_TOKEN,GITHUB_TOKEN) can override a stored login. - Copilot model usage consumes the account's plan allowance. Do not assume a model is free because its catalog entry is available; check the account's included usage and additional-usage budget.
- Explicit CLI BYOK configuration (
COPILOT_PROVIDER_*,COPILOT_PROVIDERS_CONFIG, or the CLI'sproviders.json) can route model requests to a separately billed provider even when GitHub login is available. Configure that route deliberately. Apus does not choose it or copy an Apus API credential into the native harness.
See GitHub's CLI authentication guide and Copilot billing guide for account and plan requirements. Native chat permission and sandbox boundaries below still apply.
Installed native agents keep their own sign-in. During discovery, /models can
report Checking native agent without requiring an Apus API key. If
availability is unconfirmed, check the native app on the Gateway host and run
/models again.
Permissions for native chat runtimes
When a native runtime cannot enforce the chat's optional Apus tool, sandbox, or workspace restrictions, the Control UI offers Continue for this chat to an administrator. The same confirmation applies when selecting the runtime or sending a message with an existing selection.
Confirming selects Full access, turns off optional sandboxing for that chat, and records consent for the exact native runtime. The native agent then uses its own permissions on the Gateway host. Apus does not claim to enforce its optional tool restrictions inside that agent. Other chats and global settings stay unchanged, and tools hosted by Apus retain their existing policy.
Declining leaves permissions unchanged and keeps the message unsent. A first send can create an empty chat so confirmation is bound to that chat, but no message is saved or run before you confirm. Confirmation saves the permissions and retries that message once, including a chat's first message, without pinning its default model. Selection-only confirmation does not send the draft. Consent is not inherited by another chat and is cleared when the session resets or the selected runtime changes. Older hosts that do not recognize consent retain their previous restriction checks.
Required sandboxes, required workspace boundaries, and incompatible remote execution placement cannot be waived by this confirmation. A restricted user must ask an administrator or choose a compatible runtime.
Required config
Core ACP baseline:
{
acp: {
enabled: true,
// Optional. Default is true; set false to pause ACP dispatch while keeping /acp controls.
dispatch: { enabled: true },
backend: "acpx",
defaultAgent: "codex",
allowedAgents: [
"claude",
"codex",
"copilot",
"cursor",
"droid",
"gemini",
"iflow",
"kilocode",
"kimi",
"kiro",
"apus",
"opencode",
"qwen",
],
stream: {
deliveryMode: "live",
},
},
}
Thread binding config is shared across supported channel adapters:
{
session: {
threadBindings: {
enabled: true,
idleHours: 24,
maxAgeHours: 0,
spawnSessions: true,
},
},
}
If thread-bound ACP spawn does not work, verify the adapter feature flag first:
- Discord:
session.threadBindings.spawnSessions=true
Current-conversation binds do not require child-thread creation. They require an active conversation context and a channel adapter that exposes ACP conversation bindings.
Repair existing bare-session histories
ACPX isolates bare session names by Apus owner. If a session reports
SESSION_OWNER_MIGRATION_REQUIRED, stop the Gateway and run
apus doctor --fix, then restart. Doctor uses the same service workspace
as the Gateway; ACPX's default state directory is <service workspace>/state.
The repair requires one current, unambiguous canonical owner claim with matching backend identifiers. It preserves the raw history, event-log references, upstream session IDs, timestamps, options, and usage. Persistent record names move to an owner-qualified resource; existing oneshot physical IDs and histories remain intact. Ambiguous, stale, conflicting, unreadable, or live records remain in place with a diagnostic. Resolve the reported evidence problem before retrying; resetting the session does not bypass this repair.
This is an offline, crash-recoverable migration with atomic destination-file publication. Files and SQLite are not one atomic transaction. Interrupted repairs can be rerun: Doctor checks the existing destination and canonical claim before finishing the metadata update and archiving the old persistent record.
Plugin setup for acpx backend
Packaged installs use the official @openclaw/acpx runtime plugin for ACP.
Install and enable it before using ACP harness sessions:
apus plugins install @openclaw/acpx
apus config set plugins.entries.acpx.enabled true
Source checkouts can also use the local workspace plugin after pnpm install.
Start with:
/acp doctor
If you disabled acpx, denied it via plugins.allow / plugins.deny, or want
to switch back to the packaged plugin, use the explicit package path:
apus plugins install @openclaw/acpx
apus config set plugins.entries.acpx.enabled true
Local workspace install during development:
apus plugins install ./path/to/local/acpx-plugin
Then verify backend health:
/acp doctor
acpx runtime startup check
The acpx plugin embeds the ACP runtime directly (no separate acpx binary or
version to configure). By default it registers the embedded backend during
Gateway startup and waits for one health check before the gateway ready
signal. That check also supplies failure diagnostics and is bounded by
plugins.entries.acpx.config.timeoutSeconds; an unhealthy result does not
launch a second check. Set APUS_ACPX_RUNTIME_STARTUP_PROBE=0 or
APUS_SKIP_ACPX_RUNTIME_PROBE=1 only for scripts or environments that
intentionally keep the startup check disabled.
Health checks run from the plugin-owned <state>/acpx directory, which the
service creates before probing. They do not require the default agent workspace
to exist. Sessions still launch in their requested cwd, falling back to the
configured plugin or service workspace when no session directory is supplied.
A failed check makes the backend unavailable for ACP spawns across the Gateway.
After correcting the cause, run /acp doctor to check again; a successful check
restores availability without restarting. Spawn attempts do not automatically
retry the health check.
Override an individual ACP agent command with structured arguments when a path or flag value should remain one argv token:
{
"plugins": {
"entries": {
"acpx": {
"enabled": true,
"config": {
"agents": {
"claude": {
"command": "node",
"args": ["/path/to/custom adapter.mjs", "--verbose"]
}
}
}
}
}
}
}
agents.<id>.commandis the executable or existing command string for that ACP agent. An existing absolute executable path stays one argument even when it contains spaces.agents.<id>.argsis optional. Each item is passed unchanged, including empty strings, spaces, quotes, and backslashes. Do not add shell quoting inside the array.
On Windows, put the executable path in command and its flags in args.
Quote relative executable paths containing spaces when using a command string.
Generated adapter wrappers also use argv arrays. Reconnecting an unchanged
session preserves its saved command representation and conversation history.
See Plugins.
Automatic adapter download
acpx auto-downloads ACP adapters (for example the Claude and Codex ACP
bridges) via npx on first use. You do not need to install adapter packages
manually, and there is no separate postinstall step for Apus itself. If an
adapter download or spawn fails, /acp doctor reports the failure.
Plugin tools MCP bridge
By default, ACPX sessions do not expose Apus plugin-registered tools to the ACP harness.
If you want ACP agents such as Codex or Claude Code to call installed Apus plugin tools such as memory recall/store, enable the dedicated bridge:
apus config set plugins.entries.acpx.config.pluginToolsMcpBridge true
What this does:
- Injects a built-in MCP server named
apus-plugin-toolsinto ACPX session bootstrap. - Exposes plugin tools already registered by installed and enabled Apus plugins.
- Passes the active ACP session identity to plugin tool factories, so agent-scoped tools stay in that agent's namespace.
- Keeps the feature explicit and default-off.
Security and trust notes:
- This expands the ACP harness tool surface.
- ACP agents get access only to plugin tools already active in the gateway.
- Treat this as the same trust boundary as letting those plugins execute in Apus itself.
- Review installed plugins before enabling it.
Custom mcpServers still work as before. The built-in plugin-tools bridge is an
additional opt-in convenience, not a replacement for generic MCP server config.
Apus tools MCP bridge
By default, ACPX sessions also do not expose built-in Apus tools through
MCP. Enable the separate core-tools bridge when an ACP agent needs selected
built-in tools such as cron:
apus config set plugins.entries.acpx.config.apusToolsMcpBridge true
What this does:
- Injects a built-in MCP server named
apus-toolsinto ACPX session bootstrap. - Exposes selected built-in Apus tools. The initial server exposes
cron. - Keeps core-tool exposure explicit and default-off.
Runtime operation timeout configuration
The acpx plugin gives embedded runtime startup and control operations 120
seconds by default. This gives slower harnesses such as Gemini CLI enough time
to complete ACP startup and initialization. Override it if your host needs a
different operation limit:
apus config set plugins.entries.acpx.config.timeoutSeconds 180
Runtime turns use Apus agent/run timeouts, including /acp timeout.
An interactive turn can continue beyond the plugin operation limit until its
turn budget expires, the harness finishes, or you cancel it.
sessions_spawn does not accept per-call timeout overrides; the operator path
is agents.defaults.subagents.runTimeoutSeconds. With the default hybrid reload
mode, changing timeoutSeconds automatically reloads the plugin. See
Config hot reload.
Health check agent configuration
When /acp doctor or the startup check verifies the backend, the bundled acpx
plugin checks one harness agent. If acp.allowedAgents is set, it defaults to
the first allowed agent; otherwise it defaults to codex. If your deployment
needs a different ACP agent for health checks, set the check agent explicitly:
apus config set plugins.entries.acpx.config.probeAgent claude
With the default hybrid reload mode, this change automatically reloads the plugin.
Run /acp doctor to check the updated backend.
Permission configuration
ACP sessions run without an interactive TTY for file-write and shell-exec
permission prompts. This does not disable ACP form or URL elicitation during a
channel-delivered turn: those requests use transient Gateway questions instead.
The acpx plugin provides two config keys that control harness permissions,
permissionMode and nonInteractivePermissions, both described below.
These ACPX harness permissions are separate from Apus exec approvals and separate from CLI-backend vendor bypass flags such as Claude CLI --permission-mode bypassPermissions. ACPX approve-all is the harness-level break-glass switch for ACP sessions.
For the broader comparison between Apus tools.exec.mode, Codex Guardian
approvals, and ACPX harness permissions, see
Permission modes.
permissionMode
Controls which operations the harness agent can perform without prompting.
| Value | Behavior |
|---|---|
approve-all |
Auto-approve all file writes and shell commands. |
approve-reads |
Auto-approve reads only; writes and exec require prompts. |
deny-all |
Deny all permission prompts. |
nonInteractivePermissions
Controls what happens when a permission prompt would be shown but no interactive TTY is available (which is always the case for ACP sessions).
| Value | Behavior |
|---|---|
fail |
Abort the session with PermissionPromptUnavailableError. (default) |
deny |
Silently deny the permission and continue (graceful degradation). |
Configuration
Set via plugin config:
apus config set plugins.entries.acpx.config.permissionMode approve-all
apus config set plugins.entries.acpx.config.nonInteractivePermissions fail
With the default hybrid reload mode, these changes automatically reload the plugin. See Config hot reload for other reload modes.
Apus defaults to permissionMode=approve-reads and nonInteractivePermissions=fail. In non-interactive ACP sessions, any write or exec that triggers a permission prompt can fail with PermissionPromptUnavailableError: Permission prompt unavailable in non-interactive mode.
If you need to restrict permissions, set nonInteractivePermissions to deny so sessions degrade gracefully instead of crashing.
Related
- ACP agents — overview, operator runbook, concepts
- Sub-agents
- Multi-agent routing
- ACPx plugin reference — the acpx runtime plugin's manifest and config, including the Pi session catalog