# Gemini ACP Adapter This document records the verified local behavior of `gemini --experimental-acp` and the recommended adapter design for integrating Gemini into `xworkmate-bridge` as a single-agent ACP backend. ## Goal Keep the bridge semantics unchanged: - `openclaw gateway` stays on gateway runtime forwarding - `codex ACP` stays a single-agent ACP backend - `opencode ACP` stays a single-agent ACP backend - `gemini ACP` is added as another single-agent ACP backend Gemini should therefore be integrated through an adapter layer, not through the gateway runtime path. ## Verified Local Findings The local Gemini CLI binary supports an experimental ACP stdio mode: ```bash gemini --experimental-acp ``` The bridge's current ACP RPC surface is not directly compatible with Gemini's ACP mode. The following bridge-style methods were verified to be unsupported by Gemini ACP: - `acp.capabilities` - `session.start` - `tools/list` Example response: ```json {"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"\"Method not found\": acp.capabilities","data":{"method":"acp.capabilities"}}} ``` Gemini ACP does respond to `initialize`, and `protocolVersion` is required: ```bash printf '%s\n' \ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1}}' \ | gemini --experimental-acp ``` Observed result: ```json { "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": 1, "authMethods": [ { "id": "oauth-personal", "name": "Log in with Google", "description": null }, { "id": "gemini-api-key", "name": "Use Gemini API key", "description": "Requires setting the `GEMINI_API_KEY` environment variable" }, { "id": "vertex-ai", "name": "Vertex AI", "description": null } ], "agentCapabilities": { "loadSession": false, "promptCapabilities": { "image": true, "audio": true, "embeddedContext": true }, "mcpCapabilities": { "http": true, "sse": true } } } } ``` ## Conclusion Gemini ACP is reachable over stdio JSON-RPC, but it does not expose the same RPC methods expected by `xworkmate-bridge` today. This means Gemini should be connected behind a small ACP adapter that: 1. speaks the bridge-facing ACP surface already used by `xworkmate-bridge` 2. speaks Gemini's experimental ACP surface on stdio ## Recommended Topology ```text xworkmate app / agent manager -> xworkmate-bridge -> external provider: gemini -> gemini ACP adapter -> stdio child process: gemini --experimental-acp ``` The adapter should be registered in the bridge-owned provider catalog as the `gemini` single-agent ACP backend: - `providerId: "gemini"` - `label: "Gemini"` - `endpoint: http://127.0.0.1:/acp/rpc` or `ws://127.0.0.1:/acp` - `enabled: true` In production, `xworkmate-bridge` exposes `gemini` from its built-in provider catalog rather than from app-driven sync. ## Adapter Responsibilities The Gemini ACP adapter should own all protocol translation. ### Bridge-facing side Expose the same single-agent ACP methods the bridge already forwards: - `acp.capabilities` - `session.start` - `session.message` - `session.cancel` - `session.close` ### Gemini-facing side Launch one Gemini ACP stdio child process: ```bash gemini --experimental-acp ``` Then initialize it first: ```json { "jsonrpc": "2.0", "id": "init-1", "method": "initialize", "params": { "protocolVersion": 1, "clientInfo": { "name": "xworkmate-gemini-adapter", "version": "0.1.0" } } } ``` The adapter should cache the initialization result and derive bridge-side capability information from it. ## Bridge-to-Gemini Mapping The exact post-`initialize` Gemini method surface still needs to be enumerated. Until that discovery is finished, the adapter contract should be structured as follows. ### `acp.capabilities` Return a bridge-compatible synthesized response. Suggested response: ```json { "singleAgent": true, "multiAgent": false, "providers": ["gemini"], "capabilities": { "single_agent": true, "multi_agent": false, "providers": ["gemini"] }, "upstream": { "protocolVersion": 1, "promptCapabilities": { "image": true, "audio": true, "embeddedContext": true }, "mcpCapabilities": { "http": true, "sse": true }, "authMethods": [ "oauth-personal", "gemini-api-key", "vertex-ai" ] } } ``` ### `session.start` Suggested adapter behavior: 1. Ensure Gemini stdio process is started 2. Ensure `initialize` has succeeded 3. Create adapter-local session state keyed by `sessionId` 4. Translate the bridge prompt and metadata into the Gemini request format 5. Return a bridge-compatible response envelope If Gemini requires a different request method than bridge `session.start`, the translation should remain fully internal to the adapter. ### `session.message` Suggested adapter behavior: 1. Reuse adapter-local session state 2. Translate `taskPrompt`, attachments, and working directory metadata as supported 3. Stream or collect Gemini output 4. Repackage into the bridge's current single-agent result shape ### `session.cancel` and `session.close` Because Gemini reported `loadSession: false`, the first adapter version should assume sessions are adapter-local, not durable upstream sessions. Recommended behavior: - `session.cancel`: cancel the current in-flight Gemini request or kill and restart the child process if fine-grained cancellation is unavailable - `session.close`: drop adapter-local state and optionally recycle the child process ## Startup Configuration ## Environment At minimum, support these startup modes: ### API key mode ```bash export GEMINI_API_KEY=your_api_key gemini --experimental-acp ``` ### OAuth mode Use the Gemini CLI's own authenticated environment, then run: ```bash gemini --experimental-acp ``` ### Vertex AI mode Run Gemini CLI in an environment already configured for Vertex AI auth, then launch: ```bash gemini --experimental-acp ``` ## Recommended adapter process contract Example adapter startup: ```bash ./build/bin/xworkmate-go-core gemini-acp-adapter \ --listen 127.0.0.1:8791 \ --gemini-bin /opt/homebrew/bin/gemini \ --gemini-args="--experimental-acp" ``` Recommended adapter environment: ```bash XWORKMATE_GEMINI_BIN=/opt/homebrew/bin/gemini XWORKMATE_GEMINI_ARGS=--experimental-acp XWORKMATE_GEMINI_INIT_PROTOCOL_VERSION=1 ``` The implemented adapter exposes: - `POST /acp/rpc` - `GET /acp` WebSocket ACP Supported adapter methods: - `acp.capabilities` - `session.start` - `session.message` - `session.cancel` - `session.close` - `gemini.initialize` - `gemini.raw` `session.start` and `session.message` now use a compatibility layer by default: - the adapter still initializes Gemini ACP first so `acp.capabilities` remains grounded in the real upstream ACP surface - if `GEMINI_ADAPTER_UPSTREAM_METHOD` is unset, session traffic runs through adapter-local prompt mode - the adapter keeps session-local history keyed by `sessionId` - `session.start` resets adapter-local history for that session - `session.message` replays prior user turns plus the new turn as one prompt to the Gemini CLI - the adapter returns a bridge-compatible single-agent payload with `output`, `provider`, `mode`, and `upstreamMethod: "prompt"` - `session.close` drops adapter-local state This default exists because the verified Gemini ACP upstream did not expose bridge-compatible `session.start` / `session.message` methods during testing. If Gemini ACP later gains a compatible conversation method, you can override the forwarded method name with: ```bash export GEMINI_ADAPTER_UPSTREAM_METHOD=your-discovered-gemini-method ``` ## Bridge Provider Catalog Example Once the adapter is running, expose it from the bridge-owned provider catalog as the `gemini` backend: ```json { "providerId": "gemini", "label": "Gemini", "endpoint": "http://127.0.0.1:8791/acp/rpc", "enabled": true } ``` Example local startup and sync flow: ```bash ./build/bin/xworkmate-go-core gemini-acp-adapter \ --listen 127.0.0.1:8791 \ --gemini-bin /opt/homebrew/bin/gemini \ --gemini-args="--experimental-acp" ``` Then wire the bridge startup/runtime config so the built-in `gemini` catalog entry points at this adapter endpoint: ```json { "providerId": "gemini", "label": "Gemini", "endpoint": "http://127.0.0.1:8791", "enabled": true } ``` ## Recommended First Implementation Scope The first adapter milestone should stay intentionally small: 1. Start `gemini --experimental-acp` 2. Send `initialize` 3. Expose bridge-compatible `acp.capabilities` 4. Translate one synchronous prompt path for `session.start` and `session.message` 5. Return bridge-compatible `output`, `provider`, `mode`, and `turnId` Do not block the first version on: - durable upstream session restore - multimodal attachment parity - complex streaming semantics - full cancellation fidelity ## Next Validation Tasks Before implementing the adapter, enumerate Gemini's post-`initialize` callable methods and request schema. Recommended next probes: - inspect whether Gemini sends notifications after `initialize` - test likely conversation methods after `initialize` - determine whether the protocol requires explicit auth selection or out-of-band auth only - verify whether one process supports multiple sequential requests safely - verify whether one process supports concurrent requests or must be serialized