-
Notifications
You must be signed in to change notification settings - Fork 18
feat(onboarding): collect Gemini ACP credentials + ACP agents docs #972
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
simonrosenberg
wants to merge
12
commits into
main
Choose a base branch
from
docs-acp-agents
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
4eecf0e
docs: add ACP agents onboarding & configuration guide
242efc4
docs(acp): clarify the two local auth methods and their precedence
d8ab1d1
feat(onboarding): collect Gemini ACP credentials (GEMINI_API_KEY + GE…
1cb9c3c
docs(acp): Gemini is no longer a special case in onboarding
101bf7f
docs(acp): flag that Claude Code's CLAUDE_CONFIG_DIR is not auto-dete…
12979e9
Merge branch 'main' into docs-acp-agents
simonrosenberg 8e24ff8
chore: address PR review feedback (#972)
ef039a3
chore: clarify skipStep2 comment so it doesn't read as dead code (#972)
b1c1af4
feat(onboarding): note that a subscription/login means no API key is …
5dabfe4
refactor(onboarding): derive ACP credential fields from the SDK registry
849663e
docs(acp): correct how Claude Code's subscription login is stored/det…
438bdcc
docs(acp): trim the ACP agents guide
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| # Using ACP agents | ||
|
|
||
| Agent Canvas can drive your conversations with the built-in **OpenHands** agent or | ||
| with an external **ACP agent** — Claude Code, Codex, or Gemini CLI. This guide | ||
| explains what ACP agents are, how to onboard one, and how to switch agents or | ||
| models later. | ||
|
|
||
| ## What is an ACP agent? | ||
|
|
||
| The [Agent Client Protocol (ACP)](https://agentclientprotocol.com/protocol/overview) | ||
| is a standard for talking to coding agents over JSON-RPC on stdio. Instead of | ||
| Agent Canvas calling an LLM directly, the Agent Server spawns the agent's own CLI | ||
| as a subprocess and relays each turn to it. The external agent manages its own | ||
| LLM, tools, and execution; Agent Canvas sends messages and renders what comes | ||
| back. | ||
|
|
||
| ```mermaid | ||
| flowchart LR | ||
| canvas["Agent Canvas<br/>(this UI)"] | ||
| server["Agent Server"] | ||
| acp["ACP subprocess<br/>(e.g. claude-agent-acp)"] | ||
| llm["LLM provider<br/>(Anthropic / OpenAI / Google)"] | ||
| canvas -- "PATCH /api/settings<br/>(agent_kind, acp_*)" --> server | ||
| server -- "spawn + JSON-RPC over stdio" --> acp | ||
| acp -- "API calls" --> llm | ||
| ``` | ||
|
|
||
| The Agent Server owns the subprocess and the credentials; Agent Canvas only | ||
| records *which* agent to run and surfaces a form for the secrets it needs. The | ||
| agent choice is stored per backend, so switching backends can switch agents. | ||
|
|
||
| ## Supported providers | ||
|
|
||
| The provider list is sourced from the SDK registry | ||
| (`openhands.sdk.settings.acp_providers`, mirrored into | ||
| `@openhands/typescript-client`) and enriched with Canvas UI metadata in | ||
| [`src/constants/acp-providers.ts`](../src/constants/acp-providers.ts). Adding or | ||
| changing a provider happens upstream in the SDK, not here. | ||
|
|
||
| | Provider | Default command | | ||
| |---|---| | ||
| | **Claude Code** | `npx -y @agentclientprotocol/claude-agent-acp` | | ||
| | **Codex** | `npx -y @zed-industries/codex-acp` | | ||
| | **Gemini CLI** | `npx -y @google/gemini-cli --acp` | | ||
|
|
||
| See [Authentication](#authentication) for how each one authenticates. | ||
|
|
||
| ## Authentication | ||
|
|
||
| > [!IMPORTANT] | ||
| > ACP agents authenticate **two ways: a subscription login, or an API key** — and | ||
| > the onboarding fields are optional. If you're already signed in to the | ||
| > provider's CLI on the machine the agent runs on, it reuses that login | ||
| > automatically, so locally you often don't need a key at all. | ||
|
|
||
| A "subscription login" is the credential the provider's own CLI stores when you | ||
| sign in once — a file in your home directory, or, for Claude Code on macOS, the | ||
| system **Keychain**. When the Agent Server runs **on that same machine** (a local | ||
| or self-hosted backend), the provider CLI finds that login automatically — no API | ||
| key required. On a clean cloud sandbox there's no stored login, so an API key is | ||
| needed instead. | ||
|
|
||
| | Provider | Subscription login (auto-detected) | API key | | ||
| |---|---|---| | ||
| | **Claude Code** | A Claude Code login (Pro/Max), from Claude Code's own credential store: the **macOS Keychain**, or `~/.claude/.credentials.json` on Linux | `ANTHROPIC_API_KEY` *(onboarding)* | | ||
| | **Codex** | A ChatGPT login (`codex login`) cached at `~/.codex/auth.json` | `OPENAI_API_KEY` *(onboarding)* | | ||
| | **Gemini CLI** | Your Google login (`gemini`/`gemini --acp`) cached at `~/.gemini/oauth_creds.json` | `GEMINI_API_KEY` *(onboarding)* | | ||
|
|
||
| All three collect an *optional* API key (+ base URL) in onboarding — leave them | ||
| blank to rely on a subscription login. A few provider-specific notes: | ||
|
|
||
| - **Codex and Gemini CLI** — the SDK detects the cached login file and **prefers | ||
| it over an API key**. Gemini's free Google login is the common no-key path | ||
| locally: sign in once and it **just works**, no key required. | ||
| - **Claude Code** — the login is auto-detected too (the macOS Keychain, or | ||
| `~/.claude/.credentials.json` on Linux); `CLAUDE_CONFIG_DIR` is **not** required | ||
| for it. `CLAUDE_CONFIG_DIR` only relocates Claude Code's config directory | ||
| (default `~/.claude`, which holds settings and session history, not the token) — | ||
| e.g. for containers or multiple accounts. The one difference from the others: if | ||
| `ANTHROPIC_API_KEY` is set, Claude Code uses it **instead of** the login. A | ||
| headless setup that wants to force the login despite a key in the environment | ||
| sets `CLAUDE_CONFIG_DIR`, which signals the SDK to strip a conflicting | ||
| `ANTHROPIC_API_KEY` / `ANTHROPIC_BASE_URL`. | ||
| - **Gemini base URL caveat:** `GEMINI_BASE_URL` only takes effect on the API-key | ||
| path (it's passed as the ACP gateway endpoint); under the Google login it's | ||
| ignored. | ||
|
|
||
| ## Onboarding an ACP agent | ||
|
|
||
| First-time users get a four-step onboarding modal. To onboard an ACP agent: | ||
|
|
||
| 1. **Choose agent** — pick Claude Code, Codex, or Gemini CLI instead of | ||
| OpenHands. The choice is saved immediately to your backend's settings. | ||
| 2. **Check backend** — confirms Agent Canvas can reach the Agent Server. | ||
| 3. **Set up credentials** — enter the provider's API key (and, optionally, a | ||
| custom base URL for a proxy or gateway). All three providers — Claude Code, | ||
| Codex, and Gemini CLI — collect these here, and every field is optional. | ||
| 4. **Say hello** — creates your first conversation and closes the modal. | ||
|
|
||
| > [!NOTE] | ||
| > Every credential field is optional and the step is skippable. Leave a field | ||
| > blank to reuse a key already set on the backend, or to authenticate the agent | ||
| > through a subscription / OAuth login instead. | ||
|
|
||
| ### How credentials reach the agent | ||
|
|
||
| Each credential you enter is saved as a **global secret** whose name is exactly | ||
| the environment variable the Agent Server exports into the ACP subprocess (e.g. | ||
| `ANTHROPIC_API_KEY`). Saving in onboarding is identical to adding the secret | ||
| under **Settings → Secrets**, where you can edit or remove it anytime. Keeping | ||
| the secret name equal to the env var is what makes a saved key actually reach the | ||
| provider CLI. | ||
|
|
||
| ## Switching agent or model later | ||
|
|
||
| Open **Settings → Agent** at any time: | ||
|
|
||
| - **Agent** — switch between **OpenHands** and **ACP**. | ||
| - **Preset** — pick a built-in provider (Claude Code, Codex, Gemini CLI) or | ||
| **Custom** to point at any other ACP server. | ||
| - **Command** — the command line used to spawn the subprocess. Selecting a preset | ||
| fills this in; editing it to match another preset re-detects that provider. | ||
| API keys are *not* entered here — they live in the Secrets panel. | ||
| - **Model** — choose a suggested model for the provider or enter a custom model | ||
| override. Built-in providers save a concrete model rather than leaving it | ||
| blank. | ||
|
|
||
| Saving writes an `agent_settings_diff` (`agent_kind`, `acp_server`, | ||
| `acp_command`, `acp_model`) to `PATCH /api/settings`. A running conversation | ||
| keeps the agent it started with; the new choice applies to conversations you | ||
| start afterward. | ||
|
|
||
| ## Custom ACP servers | ||
|
|
||
| Any stdio ACP server works: choose **Custom** in Settings → Agent and enter its | ||
| launch command. Custom servers have no curated model list, so enter the model ID | ||
| the server expects (if any) as a custom model. Pass credentials by adding the | ||
| env vars the server reads as global secrets under **Settings → Secrets**. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.