# OpenHands Agent Canvas: o que é e como rodar Claude Code e outros agentes self-hosted

> O Agent Canvas, do repositório OpenHands, é um painel self-hosted para conversar com agentes de código (OpenHands, Claude Code, Codex) e criar automações em local, Docker ou VM.

Por Lucas Roberto · Open source · publicado em 2026-10-13 · 10 min de leitura
Versão web: https://lucasroberto.com/blog/openhands-agent-canvas-o-que-e-e-como-rodar-claude-code-e-outros-agentes-self-hosted

O OpenHands Agent Canvas é um painel self-hosted, distribuído como o pacote npm `@openhands/agent-canvas` e como imagem Docker, que centraliza conversas com agentes de código e automações agendadas ou disparadas por webhook. Ele roda o agente open source OpenHands por padrão, mas também conduz Claude Code, Codex, Gemini CLI, Pi, OpenCode ou qualquer agente compatível com ACP. Serve para quem quer tirar o agente do terminal do laptop e rodá-lo num container, numa VM ou num cluster, alternando entre esses ambientes por uma única interface.

Este texto se baseia na leitura do código e da documentação do [repositório OpenHands/OpenHands](https://github.com/OpenHands/OpenHands). Não executei a ferramenta. Na data deste post, o repositório tem 90744 estrelas e licença MIT. O próprio README marca o projeto como beta.

## O que é o OpenHands Agent Canvas?

O nome do repositório é OpenHands, mas o produto descrito no README é o **Agent Canvas**, definido como "o centro de controle self-hosted para agentes de código e automações". Na prática, é um frontend em React e TypeScript que conversa com um ou mais **Agent Servers**, além de um launcher que sobe o stack local completo.

O repositório deixa claro o que fica de fora dele:

| Repositório | Responsabilidade |
|---|---|
| `OpenHands/OpenHands` | Interface do Agent Canvas, seleção de backend e orquestração do stack local |
| `OpenHands/software-agent-sdk` | SDK Python, Agent Server, agentes, ferramentas e API canônica |
| `OpenHands/typescript-client` | Cliente TypeScript da API do Agent Server |
| `OpenHands/automation` | Definição de automações, agendamento, webhooks e histórico de execuções |

O agente não executa nada dentro do Canvas. Quem executa é o Agent Server. O Canvas registra o que você quer, mostra eventos, terminal, arquivos e diffs, e manda as ações para o backend escolhido.

## Como o Agent Canvas funciona por dentro?

O comando `agent-canvas` sobe quatro processos atrás de um **ingress proxy**, um proxy reverso que expõe uma única porta e roteia por caminho. A documentação de self-hosting descreve o layout padrão:

| Serviço | Porta | Rotas |
|---|---|---|
| Ingress proxy | `127.0.0.1:8000` | ponto de entrada único |
| Static server (frontend) | `3001` | `/*` |
| Agent Server | `18000` | `/api/*`, `/sockets` |
| Automation backend | `18001` | `/api/automation/*` |

O Dockerfile em `docker/Dockerfile` faz o mesmo numa imagem só. Parte da imagem oficial do Agent Server, instala `openhands-automation` via `uv pip`, copia o build estático do frontend e usa `docker/entrypoint.sh` como entrypoint, com `tini` na frente.

Algumas peças que valem conhecer:

1. **Versões pinadas em `config/defaults.json`.** O Agent Server e o automation rodam via `uvx` com a versão de `versions.agentServer` e `versions.automation`. O campo `compatibility.minimumAgentServer` define o Agent Server mais antigo que o frontend aceita, verificado em runtime por `assertAgentServerVersionIsSupported()`. Dá para trocar o backend com `OH_AGENT_SERVER_VERSION`, `OH_AGENT_SERVER_GIT_REF` ou `OH_AGENT_SERVER_LOCAL_PATH`.
2. **Cliente tipado obrigatório.** O frontend só fala com o Agent Server pelo `@openhands/typescript-client`. Existe um teste (`src/api/no-direct-agent-server-calls.test.ts`) que barra `fetch` ou `axios` direto para esses endpoints.
3. **ACP como ponte para agentes de terceiros.** O ACP (Agent Client Protocol) é um padrão de comunicação com agentes de código via JSON-RPC sobre stdio. Quando você escolhe Claude Code, o Agent Server sobe a CLI do agente como subprocesso (por padrão `npx -y @agentclientprotocol/claude-agent-acp`) e repassa cada turno. O LLM, as ferramentas e a execução ficam com o agente externo.
4. **Segredos viram variáveis de ambiente.** Cada credencial cadastrada é salva como "global secret" com o nome exato da variável que o Agent Server exporta para o subprocesso ACP, por exemplo `ANTHROPIC_API_KEY`.
5. **Contexto de runtime injetado.** O launcher expõe `/server_info.runtime_services`, e o frontend repassa esse bloco para novas conversas, para o agente usar as URLs corretas em vez de chutar portas.

## Como instalar o Agent Canvas?

O README traz quatro caminhos. Os pré-requisitos comuns são Node.js 24 ou superior e `uv`. Para os modos com container, também Docker.

**Opção 1, sem sandbox** (o agente tem acesso total ao seu filesystem):

```sh
npm install -g @openhands/agent-canvas
agent-canvas
```

Dá para separar as partes com `agent-canvas --frontend-only` ou `agent-canvas --backend-only`.

**Opção 2, com sandbox Docker.** O agente só enxerga o que estiver em `PROJECTS_PATH`:

```sh
export PROJECTS_PATH="$HOME/projects"
mkdir -p "$PROJECTS_PATH" "$HOME/.openhands"

docker run -it --rm \
  -p 127.0.0.1:8000:8000 \
  -e AGENT_CANVAS_ALLOW_LAN_SESSION_KEY=true \
  -v "$HOME/.openhands:/home/openhands/.openhands" \
  -v "${PROJECTS_PATH}:/projects" \
  ghcr.io/openhands/agent-canvas:1.27.1
```

Nesse modo a interface fica em `http://localhost:8000/canvas`.

**Opção 3, um container por conversa.** Útil para rodar vários agentes em paralelo:

```sh
npm install -g @openhands/agent-canvas
OH_CONVERSATION_RUNTIME=docker agent-canvas
```

Cada conversa ganha seu próprio Agent Server num container. O Canvas e o serviço de automação continuam no host. No Windows, esse modo só funciona dentro do WSL 2.

**Opção 4, a partir do código-fonte:** `git clone`, `npm install` e `npm run dev`.

Também existe um chart Helm em `helm/agent-canvas`, que a própria documentação chama de experimental, e um app desktop em Electron.

## Como usar o Claude Code dentro do Agent Canvas?

Este é o fluxo que mais interessa a quem já usa Claude Code no terminal. Se você já configurou o Claude Code no projeto, com o que descrevi em [como configurar o Claude Code em projetos Laravel com CLAUDE.md, hooks e comandos](/blog/como-configurar-o-claude-code-em-projetos-laravel-claudemd-hooks-e-comandos), o Canvas reaproveita a CLI em vez de substituí-la.

O onboarding tem quatro passos:

1. **Choose agent:** escolha Claude Code em vez de OpenHands.
2. **Check backend:** confirma que o Agent Server responde.
3. **Set up credentials:** em backend local, é opcional. Se você já fez login no Claude Code na mesma máquina (Keychain no macOS, `~/.claude/.credentials.json` no Linux), o login de assinatura é detectado e **tem prioridade sobre a API key**. Em backend Docker ou cloud, o passo é obrigatório, porque o container não tem login do host. Nesse caso você informa `CLAUDE_CODE_OAUTH_TOKEN` ou `ANTHROPIC_API_KEY`.
4. **Say hello:** cria a primeira conversa.

Depois, em **Settings → Agent**, dá para trocar entre OpenHands e ACP, escolher outro preset ou usar **Custom** com o comando de qualquer servidor ACP via stdio. Uma conversa em andamento mantém o agente com que começou. A mudança só vale para as próximas.

A documentação traz um alerta específico: não defina `ANTHROPIC_BASE_URL` junto com o token OAuth do Claude. Uma base URL herdada de um LiteLLM, por exemplo, quebra a autenticação bearer sem erro claro.

Para deixar os agentes rodando com o laptop fechado, o guia `docs/SELF_HOSTING.md` propõe uma VM:

```bash
export LOCAL_BACKEND_API_KEY=$(openssl rand -base64 32)
npx @openhands/agent-canvas --public
```

Com `--public`, a chave não é injetada no HTML. Quem abrir a interface precisa colar o valor de `LOCAL_BACKEND_API_KEY`, e toda chamada `/api/*` exige o header `X-Session-API-Key`. O guia inclui uma unit systemd, a configuração do nginx com suporte a WebSocket e o passo a passo do Let's Encrypt. Depois, no Canvas local, você adiciona a VM em **Manage backends → Add a backend** e alterna entre os dois pelo seletor.

## Quando vale a pena usar o Agent Canvas e quando não?

Vale a pena quando:

1. Você mantém vários projetos e quer agentes trabalhando fora do horário, por exemplo gerando relatórios ou quebrando issues do GitHub em tarefas. Para quem toca vários produtos sozinho, como discuti em [como manter vários SaaS em produção sendo dev solo](/blog/como-manter-varios-saas-em-producao-sendo-dev-solo-sem-virar-refem-do-on-call), automatizar esse tipo de rotina libera tempo de verdade.
2. Você quer compartilhar um Agent Server com o time para code review e atualização de dependências, e manter agentes pessoais no laptop. O README cita esse cenário explicitamente.
3. Você usa mais de um agente (Claude Code para uma coisa, Codex para outra) e quer uma interface só, com histórico, terminal, diff e segredos no mesmo lugar.
4. Você precisa de isolamento por conversa sem montar a infraestrutura na mão (Opção 3).

Não vale a pena quando:

1. Você usa um agente só, num repositório só, pelo terminal. O stack (Agent Server, automation, ingress, frontend) é peso extra para pouco ganho.
2. Você precisa de multiusuário com autenticação e isolamento entre times. O chart Helm diz que o Agent Canvas é "não autenticado e single-tenant" e aponta o produto Enterprise para esse caso.
3. O ambiente é Windows nativo e você quer containers por conversa.
4. Você não tolera mudanças frequentes. O projeto está em beta e depende de quatro repositórios versionados de forma independente.

## Quais cuidados tomar antes de rodar o Agent Canvas?

Tudo aqui roda com as permissões de quem instala. A documentação é bem honesta sobre isso, e vale levar a sério:

1. **Filesystem e shell.** Nas opções 1 e 4, o Agent Server roda direto no host e o agente lê e escreve qualquer arquivo do seu usuário, executa comandos e acessa a rede. A skill `verify-openhands`, do próprio repositório, registra que, com prompts vagos, um modelo leu o diretório de execução, o checkout, arquivos de outras sessões em `/tmp` e a saída de `env`. Tudo o que o agente lê vai para o provedor do LLM. Num ambiente de fintech, isso basta para nunca rodar o modo sem sandbox numa máquina que tenha `.env` de produção ou credenciais de gateway.
2. **Variáveis de ambiente e segredos.** As credenciais viram variáveis de ambiente do subprocesso do agente. Um agente que roda `env` vê todas elas. Os riscos de prompt injection levando a vazamento são os mesmos que descrevi em [prompt injection e LGPD em agentes de IA](/blog/prompt-injection-e-lgpd-em-agentes-de-ia-no-laravel-como-proteger-dados-e-acoes).
3. **Chave de sessão no navegador.** O `SELF_HOSTING.md` avisa que o editor OpenVSCode embutido compartilha a origem do Canvas. Um script nessa origem pode ler o `localStorage`, onde ficam as chaves de sessão de *todos* os backends cadastrados naquele navegador. O problema está rastreado na issue #16492.
4. **Bind de rede.** O launcher npm escuta só em `127.0.0.1`. Se você passar `--host 0.0.0.0` ou publicar o Docker numa interface de LAN, remova `AGENT_CANVAS_ALLOW_LAN_SESSION_KEY` e defina uma `LOCAL_BACKEND_API_KEY` forte. Para exposição na internet, siga o roteiro de firewall do guia antes de subir o serviço.
5. **Download de código em runtime.** Os agentes ACP Pi e OpenCode não vêm na imagem: a primeira conversa baixa a CLI via `npx`. O Agent Server e o automation também são baixados via `uvx` no primeiro start. Fixe versões se isso importar para a sua cadeia de suprimentos.
6. **Telemetria.** O frontend inclui `posthog-js`, a imagem Docker recebe `VITE_POSTHOG_API_KEY` no build e há um banner de consentimento de telemetria. Revise essa configuração se o ambiente for sensível.
7. **Workspace compartilhado.** Mesmo com um container por conversa, conversas que apontam para o mesmo diretório do host compartilham arquivos. A documentação recomenda diretórios ou worktrees separados.
8. **Kubernetes.** No chart Helm, `rbac.clusterAdmin=true` dá `cluster-admin` ao agente. Prefira restringir por `rbac.namespaces` e coloque um ingress autenticado na frente.

## Por onde começar com o Agent Canvas

Se eu fosse avaliar o Agent Canvas num contexto de back-end com dados financeiros, começaria pela Opção 2. O `PROJECTS_PATH` apontaria para uma pasta só com clones de trabalho, sem `.env` real, e as credenciais de LLM ficariam numa conta com limite de gasto. Com isso estável, o passo seguinte é uma VM com `--public`, firewall fechado e acesso via túnel SSH, cadastrada como segundo backend no Canvas local. Só depois disso eu criaria automações que tocam GitHub ou Slack, sempre lembrando que quem fala com o Agent Server tem, na prática, um shell na máquina.

---

Lucas Roberto é desenvolvedor back-end e fundador da Granpag. Mais textos: https://lucasroberto.com/blog
