单项目深读

OpenHands:让 agent 自主规划并提交可审查改动的编码平台

OpenHands 把 issue 交给 AI agent,由它规划、写代码、跑命令并提交可审查改动。MIT 许可,9.1 万星,支持 CLI 与 Web 界面,可接任意模型。

|INS-0029

大多数人第一次用 AI 写代码,卡住的地方不是模型不够强,而是它没有一台自己的机器。

你在聊天框里贴一段代码,它给你一段补丁;你想让它跑一遍测试、看一眼报错、再改一版,就得自己复制粘贴、自己开终端、自己判断哪一步错了。所谓「AI 编程」,本质上还是人在当执行器。

OpenHands 要拆掉的就是这个人肉环节。它给 agent 一台能跑命令的机器、一个能读写的文件系统、一套能持续多轮的执行循环,然后把 issue 丢进去,等它自己规划、自己改、自己验证。README 里对它的定位写得很直白:self-hosted developer control center for coding agents and automations——不是聊天工具,是一个控制中心。

下面按「它凭什么能让 agent 自主干活」这条线拆开讲。

一、先看它到底由什么组成

OpenHands 的 README 里,产品名其实叫 Agent Canvas。这个名字容易让人以为是画布式的 UI 玩具,但它的架构说明指向一个更工程化的结构:一个前端控制中心 + 若干个可插拔的 Agent Server + 一个自动化服务。

README 的 Architecture 段给了一句关键定义:

Agent Canvas is powered by the OpenHands Agent Server, a REST API for running multiple agents on a single machine. Each Agent Server runs on a single host/port; the Agent Canvas can connect to multiple Agent Servers and easily flip between them.

这句话把整个系统的分层说清楚了。把它展开成层:

层组件职责
控制层Agent Canvas 前端(本仓库 OpenHands/OpenHands)用户界面、会话发起、后端选择与切换、本地栈编排
执行层OpenHands Agent Server(REST API)在单机单端口上跑多个 agent,管理会话、工具、工作区、事件
自动化层Automation Server让 agent 按定时或事件/webhook触发运行
集成层Slack / GitHub / Linear / Notion 等作为自动化的输入源与输出目标
模型层任意 LLM(LLM Profiles)由用户自带,不绑定厂商

再往下是仓库边界。README 专门列了一张表,说明这套系统是多仓库的,改行为要去对的仓库改:

仓库负责什么
OpenHands/OpenHandsAgent Canvas 前端、面向用户的控制中心、后端选择、本地栈编排
OpenHands/software-agent-sdkPython SDK、Agent Server、agents、tools、conversations、workspaces、events,以及规范的 server API
OpenHands/typescript-clientTypeScript 客户端(README 在此截断)

这张表本身就是一条重要信息:OpenHands 不是一个单体应用。你在这个仓库里看到的是「壳」和「编排」,真正让 agent 跑起来的运行时(会话、工具、工作区、事件流)在 software-agent-sdk 里。所以评价它时,说「前端仓库」是准确的——它的价值在于把多个后端收敛成一个可操作的面板,而不是自己实现 agent 循环。

请求怎么流转

按 README 的描述,一次典型交互的路径是:

  1. 用户在 Canvas 里发起一个会话,选定一个后端(本地 / Docker / VM / 云)。
  2. Canvas 把请求路由到对应的 Agent Server(host:port)。
  3. Agent Server 在该环境里创建会话、挂载工作区、暴露工具,让 agent 开始多轮执行。
  4. 如果这个会话属于某个自动化,Automation Server 负责触发时机(cron 或 webhook)和结果投递(比如发到 Slack)。

关键设计点在第 1 步和第 2 步之间:Canvas 可以同时连着多个 Agent Server,并在 UI 里切换。README 举的例子很具体——团队共享一台 Agent Server 跑 code review 和依赖升级,个人的 agent 跑在自己笔记本上,同一个前端里来回切,不用换工具。

这个设计的直接后果是:agent 的执行环境与用户界面解耦。你把笔记本合上,跑在云上服务器里的 agent 不会停。README 明确说这是「最强大的运行方式」的原因:agent 能持续跑,也更容易被 Slack、GitHub、Datadog 这类外部服务触发。

它不绑定自己的 agent

这一点容易被忽略,但是架构上最值得写的一处。README 反复强调:

Agent Canvas runs the open source OpenHands agent out-of-the-box, but can use third-party agents such as Claude Code, Codex, Gemini, Pi, and OpenCode.

并且给出了协议名:ACP(Agent-Client Protocol)。任何兼容 ACP 的 agent 都能接进来。这意味着 Canvas 的定位不是「OpenHands 模型的专属前端」,而是一个 agent 的通用驾驶舱——它管的是会话、后端、自动化、集成,至于里面跑的是谁的 agent,是可换的。

同理,模型层也是可换的,README 的卖点表里写的是「Use with any LLM」,配置入口在 LLM Profiles。

二、四种装法,对应四种信任级别

README 的 Quickstart 给了四条路径。它们不是简单的「安装方式不同」,而是隔离程度不同,这个差别 README 用 WARNING 标得很清楚。

方式一:直接跑,没有沙箱

前置条件:Node.js 24 或更高、uv。

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

agent-canvas 默认拉起完整的本地栈。也可以拆开跑:

sh
agent-canvas --frontend-only # static frontend + ingress only agent-canvas --backend-only # agent server + automation backend + ingress only

README 在这条路径上放了警告:agent-server 直接跑在你安装的那台机器上,agent 对你的文件系统有完全访问权限。这不是客套话,是这套架构的必然结果——agent 要能改代码、跑命令,就得有真实的文件和 shell 权限。

方式二:Docker 沙箱

前置条件是 Docker,外加一个宿主机目录 PROJECTS_PATH,里面放你想让 agent 访问的项目文件夹,启动容器前先建好。

sh
export PROJECTS_PATH="$HOME/projects" # directory containing your project folders 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 # x-release-please-version

注意端口绑定写的是 127.0.0.1:8000:8000,只发布到回环地址。agent 只能访问 PROJECTS_PATH 下的项目。

方式三:每个会话一个 Docker 容器

这条路径是为并发准备的:每个新会话跑在自己的容器里,有自己的 Agent Server 和工具。Canvas 和外层 Agent Server 跑在宿主机上,把会话请求路由进各个容器。

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

README 在这里补了两个容易被踩的细节:

  • 已有的本地会话不会被转换。
  • 每个容器挂载自己会话的工作区和持久化状态,所以文件和历史能扛住容器替换;但共用同一个宿主机工作区的会话仍然共享文件,要避免冲突编辑,得选不同目录或 worktree。

还有一句边界说明很重要:这个设置隔离的是会话执行,不是把整个 Canvas 和自动化服务也塞进沙箱。

方式四:从源码跑

前置条件多了 npm,uv 用来通过 uvx 跑 agent server。

sh
git clone https://github.com/OpenHands/OpenHands.git cd OpenHands npm install npm run dev

访问地址有两套:npm / 源码启动的走 http://localhost:8000,Docker 镜像的走 http://localhost:8000/canvas。额外后端可以直接在 UI 里加。

安全模型:会话密钥怎么注入

这段是 README 里技术含量最高、也最容易被跳过的部分,值得单独拎出来。

  • 本地(npx / npm run dev)监听器只绑回环地址(127.0.0.1),这样自动注入的 session key 不会被同网段其他机器拿到。
  • 要监听所有网卡,得传 --host 0.0.0.0 或设 OH_BIND_HOST;此时 session key 不会被注入,UI 走和 --public 一样的 API key 输入页。
  • Docker 监听所有容器网卡(否则端口发布不出去),但默认不把 session key 注入 HTML。上面的 quickstart 显式开了注入,同时把宿主机端口只发布在 127.0.0.1 上——两个条件必须同时成立才安全。
  • 如果要把 Docker 发布到 LAN 或公网,就去掉 AGENT_CANVAS_ALLOW_LAN_SESSION_KEY,在 UI 里手输 API key;LOCAL_BACKEND_API_KEY 设一个强值,或者用 docker exec <container> sh -c 'cat "$STATE_DIR/api-key.txt"' 取出自动生成的那个。
  • 面向公网的部署,README 指向 docs/SELF_HOSTING.md。

这套设计的逻辑是一致的:便利性和暴露面成反比。默认配置尽量只对本机开放,一旦你扩大监听范围,鉴权就从「自动注入」退回到「手动输入」。

三、能力清单:它到底能替你做什么

README 的卖点表列了六项,逐条对应到具体机制:

能力具体含义
Self-host your way本地、Docker、VM,或任何能跑 agent server 后端的地方
Switch between different backends本地 / 远程 / 云端 agent 之间切换,不打断当前工作
Create automations建自动化和 workflow,接 Slack、GitHub、Linear 等;按计划或 webhook 事件触发
Integrate with the tools you use自动化可连 Slack、GitHub、Notion 等第三方服务
Bring your own model配 LLM Profiles,任意 LLM
Use with any agentOpenHands、Claude Code、Codex、Gemini、Pi、OpenCode,或任何支持 ACP 的 agent

README 开头给的两个自动化例子很能说明产品意图:生成报告并发布到 Slack、自动把 GitHub issue 拆解成任务。这两个都不是「帮我写个函数」,而是「把一件周期性、有明确输入输出的工程事务交给 agent 常驻处理」。

这也解释了为什么它要把 agent 放在服务器上跑:自动化的前提是常驻。笔记本合上就停的 agent,做不了 webhook 触发的活。

四、和同主题项目比,它站在哪

用素材里的对照项目做一个横向定位。需要说明的是,这几个项目解决的问题并不完全重叠,放在一起看的是「它们各自把 AI 放在了工程流程的哪个位置」。

项目语言星标(快照)它占据的位置
OpenHandsTypeScript约 9.1 万自托管的 agent 控制中心:多后端、多 agent、自动化编排
claude-memTypeScript约 10.0 万agent 的跨会话记忆:记录操作、AI 压缩、后续会话注入上下文
strixPython约 6.8 万安全测试专用 agent:攻击模拟 + 修复建议,可进 CLI / CI
kongLua约 4.4 万API / AI Gateway:把多家模型 API 收敛到一个入口,管 key、转发、配额
AI-For-BeginnersJupyter Notebook约 7.0 万教学课程,不是工具
Deep-Live-CamPython约 9.7 万实时换脸,与编码 agent 不在同一赛道

从这张表能读出两件事。

第一,OpenHands 和 claude-mem 是互补而非竞争。 claude-mem 解决的是「每次重开对话都要重新交代背景」——它管的是上下文连续性。OpenHands 解决的是「agent 没有执行环境」——它管的是执行与编排。一个 agent 可以在 OpenHands 提供的后端里跑,同时用 claude-mem 保住跨会话记忆。两者都在 TypeScript 生态里,星标量级接近,但切入的痛点完全不同。

第二,OpenHands 和 kong 是不同层的收敛。 kong 收敛的是模型 API 的入口(key、转发、配额);OpenHands 收敛的是agent 后端的入口(本地/远程/云、不同 agent 实现)。如果你的团队既要用多家模型、又要跑多种 agent,这两个东西会同时出现在架构图里,一个在模型侧,一个在执行侧。

第三,strix 展示了另一条路:垂直化。 strix 只做渗透测试,把安全测试做成可编排的 workflow。OpenHands 走的是通用化——不限定 agent 干什么,只提供跑 agent 的基础设施和自动化框架。通用平台的代价是你要自己想清楚自动化做什么;垂直工具的代价是它只能干那一件事。

五、谁该用它,以及用之前要想清楚什么

从 README 的描述倒推,它最适合的场景有三类:

  • 想让 agent 常驻的团队。把 Canvas 装在一台服务器或 Mac Mini 上,agent 24 小时在线,Slack 里 @ 一下或者 GitHub 上开个 issue 就能触发。
  • 同时用多种 agent 的人。手上既有 OpenHands,也用 Claude Code、Codex、Gemini CLI,不想为每个工具开一个窗口、记一套用法。ACP 让它们进同一个面板。
  • 要把工程事务自动化的团队。issue 拆解、依赖升级、code review、报告生成——这些有明确触发条件和输出目标的事,适合挂到 Automation Server 上。

用之前要想清楚的是权限边界。README 在两条安装路径上都放了同一句警告:agent 会对你安装所在的机器有完全的文件系统访问权。方式二、方式三用 Docker 和目录挂载把范围收窄到 PROJECTS_PATH,方式一和方式四没有这层保护。这不是配置疏忽,而是「让 agent 真能干活」和「让它什么都碰不到」之间的取舍。

另一个要想清楚的是项目状态。README 顶部的徽章标的是 beta,并且挂在 OpenHands/incubator-program 下。同时它是 MIT 许可、9.1 万星、1.2 万 fork、仓库创建于 2024 年 3 月、最近一次推送在 2026 年 10 月——活跃度不缺,但 beta 标签意味着接口和行为还可能变。把它放进关键流程之前,值得先在自己的环境里跑通一遍。

拿到手的第一步

如果只是想看看它长什么样,最短路径是方式一,两条命令:

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

然后开 http://localhost:8000。但如果你打算让它碰真实项目,建议直接上方式二——多写几行 docker run,换来的是 agent 只能看见 PROJECTS_PATH 下面那些目录。这个交换在第一次让 agent 自主跑命令之前,值得做。