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. 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):

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:

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:

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, 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:

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