OpenHands (Agent Canvas) — 架构与原理
30 秒导读: OpenHands 这个仓库(对外叫 Agent Canvas)是一个自托管的编码 agent 控制中心。它自己不实现 agent 的「想—调工具—观察」循环——那部分已经搬到另一个仓库
software-agent-sdk,作为 pip 包openhands-sdk/openhands-agent-server被依赖。本仓库做的是编排:开沙箱、克隆代码、装技能与 git hook、把你的一句话拼成一个会话请求,然后 HTTP 转发给沙箱里那台真正干活的 agent-server,再把事件流回前端。
1. 这是什么(零基础也能懂)
一句话定义: OpenHands 是一个控制中心(control center)——你在一个网页界面里发起「让 agent 帮我改这个 repo」,它负责把这件事安全地、可重复地在某个沙箱里跑起来,并能定时/被 Slack、GitHub 触发(自动化)。
解决谁的什么问题。 假设你想让 AI agent 帮你改一个真实代码仓库——它得能跑命令、装依赖、改文件、提 PR。直接在你的笔记本上放手让它跑很危险(它有你整个文件系统的权限)。OpenHands 把每个会话关进一个沙箱(通常是 Docker 容器),并提供一套统一界面去管理多个这样的 agent、跨多个「后端」(本地 / 远程 VM / 云)切换。
它能做什么:
- 在沙箱里起一个编码会话,自动克隆你选的 git 仓库、跑
.openhands/setup.sh、装 pre-commit hook。 - 跨后端运行:同一个前端,既能连本地容器,也能连远程 / 云上的 agent。
- 接任何 agent:自带 OpenHands agent,也能用 Claude Code、Codex、Gemini 等任何讲 ACP(Agent-Client Protocol) 的 agent。
- 自动化:把会话挂到定时任务或 webhook 上(GitHub issue 自动拆任务、生成报告发 Slack 等)。
用起来什么样(取自 README.md 的 Quickstart):
npm install -g @openhands/agent-canvas
agent-canvas # 起整套本地栈:前端 + agent-server + 自动化后端
一句话直觉 / 类比。 把它想成编码 agent 的「机场塔台」:塔台自己不开飞机(不跑 agent 循环),它负责调度跑道(沙箱)、放行航班(会话)、对接地勤(git / 技能 / 密钥)。真正开飞机的飞行员住在沙箱里,叫 agent-server(来自 openhands-sdk)。
本节不碰代码细节。 记住一个反直觉的事实就够了:这个仓库里没有 agent 的主循环。 见下一节。
2. 一个关键事实:agent 循环不在这个仓库里
这是读这份源码最容易踩的坑,先说清楚。
README.md 顶部有一条迁移说明:agent 与 agent-server 的源码已搬到 OpenHands/software-agent-sdk,Agent Canvas 的源码搬到 OpenHands/agent-canvas。在本仓库里,它们以固定版本的 pip 依赖出现:
# pyproject.toml(节选)
"openhands-agent-server==1.29.0",
"openhands-sdk==1.29.0",
"openhands-tools==1.29.0",
所以仓库里凡是 from openhands.sdk import ...、from openhands.agent_server import ... 的,都是外部包,不在 openhands/ 目录下(openhands/sdk 这个目录在本 clone 里根本不存在)。
本仓库真正的代码是 openhands/ 下的这几块:
| 目录 | 是什么 |
|---|---|
openhands/app_server/ |