Skip to content

ACP Protocol Integration ​

ACP (Agent Client Protocol) is a universal agent protocol introduced by the Zed editor that decouples the core functionality (server) from the user interface (client) of agents, allowing users to freely combine different agent servers and clients.

CodeBuddy Code natively supports the ACP protocol and can seamlessly integrate as an agent server with ACP-compatible editors.

Quick Start ​

Starting ACP Mode ​

Use the --acp parameter to start the CodeBuddy Code ACP server:

bash
codebuddy --acp

Zed Editor Integration ​

Configuration Steps ​

Open the Zed configuration file (~/.config/zed/settings.json) and add the following configuration:

json
{
  "agent_servers": {
    "CodeBuddy Code": {
      "command": "codebuddy",
      "args": ["--acp"],
      "env": {}
    }
  }
}

You can then create a CodeBuddy Code Thread in the Zed sidebar and start using it.

Configuration Details ​

  • command: Specify the CodeBuddy Code command path (ensure codebuddy is available in PATH)

  • args: Use ["--acp"] to enable ACP protocol mode

  • env: Optional environment variable configuration, for example:

    json
    {
      "env": {
        "CODEBUDDY_API_KEY": "your-api-key",
        "CODEBUDDY_INTERNET_ENVIRONMENT": "internal"
      }
    }

    Note: When using CODEBUDDY_API_KEY, you must correctly configure CODEBUDDY_INTERNET_ENVIRONMENT based on your version:

    • International version: Do not set (default)
    • China version: internal
    • iOA version: ioa

    See Identity and Access Management documentation for details.

ACP Protocol Features ​

Client Turn ID ​

Clients can provide a conversationRequestId for the current turn in the _meta field of a session/prompt request:

json
{
  "_meta": {
    "codebuddy.ai/conversationRequestId": "0198a1b2c3d47e5f8a9b0c1d2e3f4a5b"
  }
}

The value must be a lowercase, hyphen-free, 32-character UUIDv7 hexadecimal string. If omitted, the CLI generates one. The CLI does not scan session history for collisions, so callers are responsible for ensuring uniqueness. After a regular prompt is actually added to history, the same value is written to the turn's PromptResponse._meta, semantic messages' SessionUpdate._meta, JSONL providerData.conversationRequestId, and the X-Conversation-Request-ID model request header. Short-circuit commands such as /clear and /compact, or prompts rejected before being added to history, are not guaranteed to produce these outputs. The existing semantics of _meta['codebuddy.ai/requestId'] remain unchanged.

Authentication Information Extension ​

CodeBuddy Code returns user information in the _meta field of the authenticate response:

json
{
  "_meta": {
    "codebuddy.ai/userinfo": {
      "userId": "User ID",
      "userName": "Username",
      "userNickname": "User Nickname"
    }
  }
}

Clients can use this information to provide a better user experience, such as displaying the currently logged-in user or personalizing the interface.

Tool Proxy Mechanism ​

The ACP protocol supports client-side proxying of certain tool operations, improving performance and security:

  • File Operation Proxy: Based on the client's fs.readTextFile and fs.writeTextFile capabilities
  • Terminal Operation Proxy: Based on the client's terminal capability

When a client declares support for these capabilities, CodeBuddy Code will automatically proxy related tool calls to the client for execution.

Command List Push ​

CodeBuddy Code automatically pushes the available slash command list (available_commands_update) to the client when creating a new session, enabling the client to:

  • Provide command auto-completion functionality
  • Display command hints and help information
  • Dynamically update available commands

The command list includes currently callable project-level, user-level, and plugin Skills, and refreshes automatically after Skills finish loading or visibility settings change. It filters out client-specific commands (such as /theme, /config) and terminal-panel-specific commands (such as /stats, /rewind), pushing only commands applicable to ACP mode. Session control commands such as /clear and /compact are pushed; they are triggered by the ACP client and executed by the server.

Context Window Tier Configuration ​

CodeBuddy Code supports session-level context budget tier selection (such as 200K / 1M) through the context_window configuration option in getConfigOptions / setSessionConfigOption:

  • Availability: getConfigOptions returns this option only when the current model has multiple configured context budget tiers (contextWindow.supportedLengths contains at least 2 tiers). Models with a single tier or no configuration do not display the selector.
  • Tier validation: setSessionConfigOption('context_window', value) accepts only tiers declared by the current model and rejects invalid values.
  • Scope: The tier is temporary session-level configuration that remains effective within the process and persists when switching sessions. It falls back to the model's default tier after the process restarts.
  • Denominator synchronization: After a tier is selected, both the context ring (usage_update.size) and compaction threshold are calculated according to that tier.
  • Subagent inheritance: After the main Agent switches tiers, newly created/resumed subagents (including Agent Team members) automatically inherit the main session's current explicit tier selection. When the main session has no explicit tier, subagents fall back to their own model's default tier and do not inherit the effective budget computed from the main session's model. If the inherited tier is not in the set of tiers supported by the subagent's actual model, it fails closed to the model's default/minimum valid tier (#133811).

Agent Teams Protocol Extension ​

CodeBuddy Code extends the ACP protocol through the _meta field of session_info_update to support real-time status push for Agent Teams multi-agent collaboration.

Team Status Events ​

The following event types are pushed via _meta['codebuddy.ai/teamUpdate']:

Member Status Change (member_status_change):

json
{
  "sessionUpdate": "session_info_update",
  "_meta": {
    "codebuddy.ai/teamUpdate": {
      "type": "member_status_change",
      "teamName": "my-team",
      "isAutoTeam": false,
      "members": [
        {
          "name": "ux-designer",
          "color": "blue",
          "description": "UX design analysis",
          "status": "running",
          "taskId": "agent-abc123",
          "sessionId": "session-xyz",
          "tokenUsage": { "inputTokens": 1000, "outputTokens": 500, "lastContextWindow": 42000 },
          "toolCallCount": 5
        }
      ]
    }
  }
}

Team Created (team_created) / Deleted (team_deleted):

json
{
  "sessionUpdate": "session_info_update",
  "_meta": {
    "codebuddy.ai/teamUpdate": {
      "type": "team_created",
      "teamName": "my-team"
    }
  }
}

Member Streaming Messages ​

Real-time messages from members (text, tool calls) are pushed through standard ACP events, with the _meta['codebuddy.ai/memberEvent'] tag added to identify the message source:

json
{
  "sessionUpdate": "agent_message_chunk",
  "content": { "type": "text", "text": "Analyzing architecture proposal..." },
  "_meta": {
    "codebuddy.ai/memberEvent": "tech-architect"
  }
}

Upon receiving events with the memberEvent tag, clients should route them to the corresponding member's conversation timeline rather than the main conversation area.

Page Refresh Recovery ​

After a page refresh, once loadSession's replayHistory is complete, the current Team status is automatically pushed (member_status_change event), so clients do not need to make a separate request. When AcpTeamBridge subscribes to a member session, it automatically replays the complete history, so member conversation data is also fully restored via ACP SSE without requiring additional HTTP APIs.

Other Editor Support ​

ACP is an open protocol, so theoretically any editor supporting ACP can integrate with CodeBuddy Code. Configuration is similar to Zed:

json
{
  "agent_servers": {
    "CodeBuddy": {
      "command": "codebuddy",
      "args": ["--acp"]
    }
  }
}

Multitask Coordinator ​

Do not pass --agent multitask or --multitask to ACP / --serve (the entry guard rejects the process with a non-zero exit). Multitask is a session-level overlay, not a Scene Mode or permissionMode. Applying the stamp does not change agentName / permissionMode and does not use session/set_mode. It is independent of mainAgentSupport: hosts that have not opted in can still discover and write this standard boolean configuration.

1. Discover the Capability ​

initialize response:

json
{ "agentCapabilities": { "multitaskSupport": true } }

Recognize only multitaskSupport === true. If the field is missing or false, do not render the toggle (for example, when CODEBUDDY_CODE_DISABLE_BACKGROUND_TASKS is set). Helper: isMultitaskSupportAdvertised.

2. Discover the Configuration Option ​

In the configOptions returned by session/new, session/load, and session/resume, look for id === 'multitask'. category is metadata (currently _codebuddy.ai/multitask), not the primary key.

json
{
  "type": "boolean",
  "id": "multitask",
  "name": "Multitask",
  "description": "Coordinate detached workers while keeping the current agent mode",
  "category": "_codebuddy.ai/multitask",
  "currentValue": false
}

If this option is absent, Multitask cannot be enabled for the session (minimal standing sessions, workers / child sessions, or disabled background tasks). Clients must tolerate unknown categories; correctness depends only on id, type, and currentValue.

session/set_config_option
json
{
  "sessionId": "<id>",
  "configId": "multitask",
  "type": "boolean",
  "value": true
}

value must be a JSON boolean. "true" / 1 are rejected rather than silently toggling the setting. A successful call returns the updated { "configOptions": [...] }; use this response and the subsequent session/update (sessionUpdate: config_option_update, with the full configOptions array) as the source of truth for currentValue. Both write paths share live-session resolution, connection ownership checks, persistence, and config_option_update. Business-rule rejections (Minimal / worker / background tasks disabled) use JSON-RPC -32602; the detailed reason is in error.data.details, so do not read only error.message (which is often Invalid params).

ts
const response = await connection.setSessionConfigOption({
    sessionId,
    configId: 'multitask',
    type: 'boolean',
    value: true,
});

const option = response.configOptions.find(item => item.id === 'multitask');
const enabled = option?.type === 'boolean' && option.currentValue === true;

Only the current connection's acpConnectionId is accepted. Calls without an ID fail closed; an identified connection may claim a session with no owner; all other owners are rejected.

4. CodeBuddy Dialect: session/set_multitask (Compatibility) ​

Existing clients can continue to use it through extMethod. New clients should use the standard write path in the previous section. The dialect retains toggle behavior and the structured { ok, on, already, agentName, message } response.

Namesession/set_multitask (ACP_METHOD_SESSION_SET_MULTITASK)
Params{ sessionId, enabled?: boolean }: true enters, false exits, omit to toggle
Response{ ok, on, already, agentName, message }
ConstraintsNon-empty sessions may switch; worker / child session / minimal standing session / background-disabled returns ok: false
Ownership / validationSame as the standard write path; if enabled is present and not a boolean → invalidParams
ts
import {
    ACP_METHOD_SESSION_SET_MULTITASK,
    buildSetMultitaskParams,
    isMultitaskSupportAdvertised,
} from '@genie/agent-client-protocol';

if (isMultitaskSupportAdvertised(init.agentCapabilities)) {
    await conn.extMethod(ACP_METHOD_SESSION_SET_MULTITASK, buildSetMultitaskParams(sessionId, true));
}

The TUI /multitask command reuses the same stamping semantics.

5. Unsolicited Drain Turns ​

After a worker completes, the coordinator runs another summary turn when the parent session is idle and the client has not sent another session/prompt. This turn has no user bubble, and the CLI assigns its requestId.

At the start of the turn, the CLI first sends a standard session_info_update, followed by content frames. The existing session_end still closes the turn:

json
{
  "sessionUpdate": "session_info_update",
  "_meta": {
    "codebuddy.ai/unsolicitedTurn": {
      "requestId": "cli-hex-request-id",
      "reason": "background_drain"
    },
    "codebuddy.ai/requestId": "cli-hex-request-id"
  }
}

Clients should immediately open a Request with no user message for this requestId. Do not wait for user_message_chunk, and do not discard an unfamiliar requestId after idle as a stale frame. Subsequent tool_call / agent_message_chunk events with the same requestId belong to this turn; session_end closes it.

Helpers: buildUnsolicitedTurnUpdate / readUnsolicitedTurn (ACP_META_UNSOLICITED_TURN). Unknown _meta fields must be ignored rather than treated as protocol errors.

Fake-model e2e: packages/agent-cli/src/e2e/serve/prompt/multitask-worker-wakeup.spec.ts (run pnpm run package:all first).

6. Child Worker Questions Across Parent Turns ​

After the coordinator dispatches work, end_turn and an idle parent session are expected. AskUserQuestion / ExitPlanMode requests from live detached workers still use the parent session's requestPermission. Hosts must not mark these questions as canceled merely because the parent turn emitted session_end. They close only when the user stops that worker or closes the parent session.

Code Mode (codeMode Configuration Option) ​

A session-level two-state configuration option that pins the tool-calling style within a single session (PTC evaluation: one new session per test case). It is independent of mainAgentSupport: hosts that have not opted in (such as WorkBuddy) can still discover and write it. Clients decide based on whether configOptions contains id === 'codeMode' (capability-driven, same approach as Multitask).

ValueMeaningStanding mode
offStandard mode: all tools are called directly (default, no stamp)cli
allPTC (all tools): all tools go through REPL, equivalent to standing mode ptcptc

1. Discovery ​

The initialize response includes agentCapabilities.codeModeSupport: true (auxiliary only; configOptions is authoritative). In the configOptions returned by session/new, session/load, and session/resume, look for id === 'codeMode':

json
{
  "type": "select",
  "id": "codeMode",
  "name": "Code Mode",
  "description": "Tool-calling mode for this session. Locked after the first agent reply.",
  "category": "_codebuddy.ai/codeMode",
  "currentValue": "off",
  "options": [
    { "value": "off", "name": "Standard" },
    { "value": "all", "name": "PTC (All tools)" }
  ]
}

category is metadata only, not the primary key.

2. Writing ​

Standard write; value is the string 'off' | 'all':

json
{ "sessionId": "<id>", "configId": "codeMode", "value": "all" }
  • On success, returns the updated { "configOptions": [...] } and broadcasts config_option_update.
  • Invalid value → JSON-RPC -32602, with the reason in error.data.details.
  • Locked after the first turn: once the session has main agent output (not a blank session), writing a different value is rejected (-32602, details contains codeMode locked), and the client should roll back the UI. Writing the current value is an idempotent success (hosts may replay the current value before each prompt or after reconnecting).
  • The session must belong to the current connection (same ownership check as Multitask).

3. Initial Value When Creating a Session ​

Pass 'all' in _meta['codebuddy.ai/codeMode'] of session/new ('off' is equivalent to omitting it); this only takes effect for newly created blank sessions. mcp is an invalid new value and explicitly returns -32602; mode switching has not shipped yet, so no legacy mode aliases or migrations are kept.

4. Persistence and Gate ​

all is written to session.meta['codebuddy.ai/codeMode'], and the standing key session.meta['codebuddy.ai/mainAgent'] is set to ptc at the same time. Switching back to off writes an explicit off marker and restores the PTC standing key to cli (blank sessions only), preventing historical snapshots from restoring the old state. Sessions carrying this marker light up the standing mode gate even on hosts that have not opted in (as long as the master switch is not off); sessions without the marker behave exactly as before. The marker does not unlock the agent picker / session/set_agent (which still requires mainAgentSupport).

Troubleshooting ​

Connection Failed ​

Problem: Zed cannot connect to CodeBuddy

Solution:

  1. Confirm the codebuddy command is available:

    bash
    which codebuddy
  2. Test ACP mode startup:

    bash
    codebuddy --acp
  3. Check if the configuration file JSON format is correct

Tool Call Failed ​

Problem: File operation or command execution errors

Solution:

  1. Check working directory permissions
  2. View CodeBuddy logs

Through the ACP protocol, integrate CodeBuddy Code into your favorite editor 🚀