Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
68e8f81
docs: add Onboarding Agent Canvas section with agent-canvas docs
openhands-agent May 28, 2026
3b4207c
docs: refine Quick Start card and move Repository Customization
openhands-agent May 28, 2026
cd4b863
docs: refine Onboarding Agent Canvas nav and content
openhands-agent May 28, 2026
93e04be
docs: add backend setup sub-pages under Connect and Manage Backends
openhands-agent May 28, 2026
23367d2
docs: merge automations into prebuilt-automations; add pre-built over…
openhands-agent May 28, 2026
ffba5d3
docs: add First Time Setup page to Onboarding Agent Canvas
openhands-agent May 28, 2026
78a81a6
Update links to pre-built automations and fill in missing guides
DevinVinson May 29, 2026
77d082b
Add first-time setup wizard docs for Agent Canvas
openhands-agent May 29, 2026
187ecef
add images
openhands-agent May 29, 2026
2f7a2da
Updates to setup and backends
openhands-agent Jun 2, 2026
d12a846
docs: add custom Agent Server image guide for Docker backend (#541)
rbren Jun 2, 2026
90bf251
Merge branch 'main' into docs/onboarding-agent-canvas
jpelletier1 Jun 2, 2026
6bfac7f
docs: update self-hosting and setup pages for --public mode
openhands-agent Jun 2, 2026
843e5c1
docs: use agent-canvas CLI command in self-hosting guide
openhands-agent Jun 2, 2026
817938d
docs: reframe "What Agent Canvas Includes" as "Why Agent Canvas"
openhands-agent Jun 2, 2026
b83b937
docs: rework Key Concepts in Agent Canvas overview
openhands-agent Jun 2, 2026
7f1e31b
docs: rename Setup link to Install in overview for consistency
openhands-agent Jun 2, 2026
edbc7bb
docs: rework product descriptions in Agent Canvas overview
openhands-agent Jun 2, 2026
a0335d0
docs: restructure Introduction page
openhands-agent Jun 2, 2026
a14d0a2
docs: add ACP Agents page to Agent Canvas onboarding
Jun 2, 2026
9dc0e71
docs: update Install page CLI flags and env vars
openhands-agent Jun 2, 2026
c3c6eb8
docs: remove redundant "Change the Port" section
openhands-agent Jun 2, 2026
04eca51
docs: replace Docker placeholder with real install instructions
openhands-agent Jun 2, 2026
447ebd4
docs: trim Docker section for conciseness
openhands-agent Jun 2, 2026
c65a188
docs: restructure Install page with npm/Docker tabs
openhands-agent Jun 2, 2026
e22b772
docs: remove auto-install note for uv prerequisite
openhands-agent Jun 2, 2026
dc7ff9d
docs: move CLI flags and env vars into install tabs
openhands-agent Jun 2, 2026
69f5ef0
docs: consolidate first-time-setup into overview carousel
openhands-agent Jun 2, 2026
90efbd4
chore: trigger Mintlify preview
openhands-agent Jun 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,41 @@
]
},
{
"group": "Onboarding OpenHands",
"group": "Onboarding Agent Canvas",
"pages": [
"openhands/usage/customization/repository",
"openhands/usage/customization/hooks"
"openhands/usage/agent-canvas/overview",
"openhands/usage/agent-canvas/setup",
{
"group": "Setup a Pre-built Automation",
"pages": [
"openhands/usage/agent-canvas/prebuilt-automations",
"openhands/usage/agent-canvas/prebuilt/github-pr-review",
"openhands/usage/agent-canvas/prebuilt/github-repo-monitor",
"openhands/usage/agent-canvas/prebuilt/slack-channel-monitor"
]
},
{
"group": "Connect and Manage Backends",
"pages": [
"openhands/usage/agent-canvas/backends",
"openhands/usage/agent-canvas/backend-setup/local",
"openhands/usage/agent-canvas/backend-setup/vm",
"openhands/usage/agent-canvas/backend-setup/docker",
"openhands/usage/agent-canvas/backend-setup/cloud"
]
},
"openhands/usage/agent-canvas/customize-and-settings",
"openhands/usage/agent-canvas/acp-agents",
"openhands/usage/agent-canvas/self-hosting",
"openhands/usage/agent-canvas/development",
"openhands/usage/agent-canvas/troubleshooting"
]
},
{
"group": "Product Guides",
"pages": [
"openhands/usage/key-features",
"openhands/usage/customization/hooks",
"overview/model-context-protocol",
{
"group": "Skills",
Expand All @@ -74,6 +99,7 @@
"openhands/usage/automations/managing-automations"
]
},
"openhands/usage/customization/repository",
{
"group": "Settings",
"pages": [
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
94 changes: 94 additions & 0 deletions openhands/usage/agent-canvas/acp-agents.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: ACP Agents
description: Drive Agent Canvas conversations with an external coding agent — Claude Code, Codex, or Gemini CLI — over the Agent Client Protocol.
---

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.

Check warning on line 10 in openhands/usage/agent-canvas/acp-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/acp-agents.mdx#L10

Did you really mean 'subprocess'?

```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
canvas -- "conversation turns" --> 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.

Check warning on line 24 in openhands/usage/agent-canvas/acp-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/acp-agents.mdx#L24

Did you really mean 'subprocess'?

## Supported providers

| 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` |

The provider list is sourced from the OpenHands SDK registry (`openhands.sdk.settings.acp_providers`, mirrored into `@openhands/typescript-client`) and enriched with Canvas UI metadata. Adding or changing a provider happens upstream in the SDK.

## Authentication

<Info>
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. **The login takes priority over an API key:** while you're signed in, a key set in the environment isn't used — so the onboarding key fields do nothing and can be left blank.
</Info>

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` |
| **Codex** | A ChatGPT login (`codex login`) cached at `~/.codex/auth.json` | `OPENAI_API_KEY` |
| **Gemini CLI** | Your Google login (`gemini`/`gemini --acp`) cached at `~/.gemini/oauth_creds.json` | `GEMINI_API_KEY` |

All three collect an *optional* API key (plus base URL) in onboarding. As noted above, a subscription / OAuth login takes priority over an API key — when the provider's CLI is signed in, a key set in the environment is not used:

- **Codex** — `codex login status` keeps reporting the ChatGPT login even with `OPENAI_API_KEY` set.
- **Gemini CLI** — uses the OAuth auth type chosen at `gemini` login; `GEMINI_API_KEY` is only consulted if you switch the auth type. The free Google login is the common no-key path locally — sign in once and it just works.
- **Claude Code** — with both present, `claude auth status` reports it is authenticated via the subscription (`claude.ai`), not the key. The login is auto-detected from the macOS Keychain (or `~/.claude/.credentials.json` on Linux); `CLAUDE_CONFIG_DIR` is **not** required for it — it only relocates Claude Code's config directory (settings/history, not the token) and signals the SDK to strip a conflicting `ANTHROPIC_API_KEY` / `ANTHROPIC_BASE_URL`.

The one exception is the **base URL** (`*_BASE_URL`): a custom value points the CLI at a different endpoint (a proxy or gateway) and *does* take effect even under a login — for Gemini it rides the ACP `gateway` param. It's an advanced override, not needed for normal use.

Check warning on line 56 in openhands/usage/agent-canvas/acp-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/acp-agents.mdx#L56

Did you really mean 'param'?

## 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.

Check warning on line 62 in openhands/usage/agent-canvas/acp-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/acp-agents.mdx#L62

Did you really mean 'backend's'?
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 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.

Check warning on line 68 in openhands/usage/agent-canvas/acp-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/acp-agents.mdx#L68

Did you really mean 'skippable'?
</Note>

### 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.

Check warning on line 73 in openhands/usage/agent-canvas/acp-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/acp-agents.mdx#L73

Did you really mean 'subprocess'?

## 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.

Check warning on line 81 in openhands/usage/agent-canvas/acp-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/acp-agents.mdx#L81

Did you really mean 'subprocess'?
- **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**.

## Related Guides

- [Customize and Settings](/openhands/usage/agent-canvas/customize-and-settings)
- [LLM Profiles and Model Configuration](/openhands/usage/agent-canvas/llm-profiles)
- [Connect and Manage Backends](/openhands/usage/agent-canvas/backends)
6 changes: 6 additions & 0 deletions openhands/usage/agent-canvas/backend-setup/cloud.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Setup an OpenHands Cloud Backend
description: Connect Agent Canvas to an OpenHands Cloud backend.
---

Coming soon.
155 changes: 155 additions & 0 deletions openhands/usage/agent-canvas/backend-setup/docker.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
---
title: Setup a Docker Backend
description: Build a custom OpenHands Agent Server image and connect Agent Canvas to it.
---

This guide walks through building a **custom Agent Server image** that layers extra tooling (for example, the JDK) on top of the official base image, running it locally with Docker, and registering it as a backend in Agent Canvas.

Use this approach when the default backend's toolchain is missing something your agent needs, such as a specific language runtime, build tool, or CLI.

Check warning on line 8 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L8

Did you really mean 'backend's'?

Check warning on line 8 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L8

Did you really mean 'toolchain'?

## Prerequisites

- Docker installed and running
- An LLM API key (Anthropic, OpenAI, etc.)
- Agent Canvas installed and running locally — see [Setup](/openhands/usage/agent-canvas/setup)

## 1. Build a Custom Image

The OpenHands Agent Server publishes a base image at `ghcr.io/openhands/agent-server`. Extend it with a small `Dockerfile` that installs whatever your agent needs.

The example below adds the JDK and a few common utilities. Save it as `Dockerfile`:

```dockerfile icon="docker"
FROM ghcr.io/openhands/agent-server:1-python

USER root

# Install Java (JDK) and common build/diagnostic utilities.
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
default-jdk \
maven \
unzip \
vim \
less \
&& rm -rf /var/lib/apt/lists/*

# Switch back to the unprivileged user that the base image runs as.
USER openhands
```

<Note>
The base image already ships with Python, Node.js, `git`, `jq`, `tmux`, build tools, and a VS Code Web + VNC stack. Only add what you actually need on top.
</Note>

<Tip>
For fully reproducible builds, pin to a more specific tag like `1.24.0-python` instead of `1-python`.
</Tip>

Build the image with a tag you can reference later:

```bash
docker build -t agent-server-java:latest .
```

<Tip>
For ARM hosts (Apple Silicon, Graviton), prefer the matching base tag (for example `latest-python` already supports multi-arch). If you need to force a platform, pass `--platform linux/amd64` to `docker build`.
</Tip>

## 2. Run the Custom Image

Start the image, expose the agent server's HTTP port, and protect it with a session API key. The agent server reads `SESSION_API_KEY` from the environment and requires the same value on the `X-Session-API-Key` header for every request.

Use the same name for the container as you'll use for the Agent Canvas backend — it makes it easy to tell which container backs which backend later.

```bash
# Pick any sufficiently random value; you'll paste it into Agent Canvas later.
export SESSION_API_KEY="$(openssl rand -hex 32)"

docker run -d \
--name agent-server-java \
-p 8001:8000 \
-e SESSION_API_KEY="$SESSION_API_KEY" \
agent-server-java:latest
```

Verify the server is reachable:

```bash
curl -H "X-Session-API-Key: $SESSION_API_KEY" http://localhost:8001/health
```

<Warning>
The agent server can execute arbitrary shell commands inside the container. Treat `SESSION_API_KEY` like a production credential and **do not expose port 8001 to the public internet** without a TLS-terminating reverse proxy in front of it.
</Warning>

To follow logs or stop the container:

```bash
docker logs -f agent-server-java
docker stop agent-server-java
```

## 3. Add the Backend in Agent Canvas

With the container running, point Agent Canvas at it:

1. Open Agent Canvas.
2. Click the backend switcher in the top bar and choose **Manage Backends**.
3. Click **Add Backend** and fill in:
- **Name** — `agent-server-java` (matching the container name)
- **Host / Base URL** — `http://localhost:8001`
- **API Key** — the `SESSION_API_KEY` value from step 2
- **Type** — `Local`
4. Save the backend and select it as the **active backend**.

Agent Canvas will run a health check against the URL. Once it passes, the backend is ready to handle conversations using the tools you baked into the image.

<Note>
See [Connect and Manage Backends](/openhands/usage/agent-canvas/backends) for what changes when you switch the active backend (settings, LLM availability, MCP servers, automations).

Check warning on line 109 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L109

Did you really mean 'automations'?
</Note>

## Running Multiple Custom Backends

You can build as many custom images as you need and run each one as its own backend in Agent Canvas. A common pattern is one image per language or repo toolchain — for example a `agent-server-java` for JVM work, a `agent-server-rust` for Cargo projects, and a `agent-server-data` image with the Python data stack pre-installed.

Check warning on line 114 in openhands/usage/agent-canvas/backend-setup/docker.mdx

View check run for this annotation

Mintlify / Mintlify Validation (allhandsai) - vale-spellcheck

openhands/usage/agent-canvas/backend-setup/docker.mdx#L114

Did you really mean 'toolchain'?

Give each container its own name, its own host port, and its own `SESSION_API_KEY`, then add a matching backend entry in Agent Canvas for each one:

```bash
# JVM toolchain on port 8001
docker run -d --name agent-server-java \
-p 8001:8000 -e SESSION_API_KEY="$JAVA_KEY" \
agent-server-java:latest

# Rust toolchain on port 8002
docker run -d --name agent-server-rust \
-p 8002:8000 -e SESSION_API_KEY="$RUST_KEY" \
agent-server-rust:latest

# Python data stack on port 8003
docker run -d --name agent-server-data \
-p 8003:8000 -e SESSION_API_KEY="$DATA_KEY" \
agent-server-data:latest
```

In **Manage Backends**, add one entry per container using the matching name, URL, and API key. You can then switch between them from the backend selector depending on what kind of task you're working on.

## Updating the Image

When you want to add more tooling or pick up a newer agent server release:

```bash
docker pull ghcr.io/openhands/agent-server:1-python
docker build -t agent-server-java:latest .
docker stop agent-server-java && docker rm agent-server-java
# then re-run the `docker run` from step 2
```

The existing backend entry in Agent Canvas keeps working as long as the host, port, and `SESSION_API_KEY` stay the same.

## Related Guides

- [Connect and Manage Backends](/openhands/usage/agent-canvas/backends)
- [Setup a Local Backend](/openhands/usage/agent-canvas/backend-setup/local)
- [Setup a VM Backend](/openhands/usage/agent-canvas/backend-setup/vm)
- [Agent Server Overview](/sdk/guides/agent-server/overview)
6 changes: 6 additions & 0 deletions openhands/usage/agent-canvas/backend-setup/local.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Setup a Local Backend
description: Run an OpenHands agent server locally and connect Agent Canvas to it.
---

Coming soon.
6 changes: 6 additions & 0 deletions openhands/usage/agent-canvas/backend-setup/vm.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Setup a VM Backend
description: Run an OpenHands agent server on a VM and connect Agent Canvas to it.
---

Coming soon.
Loading
Loading