数据STUDIO

号称比 Claude 更好的 AI Coding -- OpenHands 拆解

Image

全文速览

  • OpenHands 用 Event Stream 把 AI 编程变成可审计可回放的工程流水线——不是又一个代码补全工具
  • Agent 循环核心仅 35 行,但周围 8 万行代码解决安全隔离 / 卡住检测 / 多模型适配 / 错误恢复
  • 同款 Claude Opus 4.7,换 OpenHands 架子 SWE-Bench 多拿 12%——scaffolding 比模型值钱

0178k Star 的 AI 程序员,到底在"自动"什么?

OpenHands 在 GitHub 上拿了 78.3k Star,910k Fork,103 个 release——最新 v1.30.0 昨天刚发(2026-06-24)。

Image

如果你稍微关注 AI coding 赛道,这是绕不开的名字。但我对它的第一反应是警惕:又一个"AI 自动写代码"的工具?和 Claude Code、Cursor、Copilot 有什么区别?

跑了一圈之后我发现:OpenHands 不是在做一个更强的 AI 程序员。它在做一件更底层的事——把"AI 编程"从一次性黑箱输出,变成一套可审计、可回放、可中断的工程流水线。

看一个数字你就知道差距:SWE-Bench Verified 排行榜上,同样用 Claude Opus 4.7,OpenHands scaffolding 拿 76.8%,naive loop(直接让模型写完整答案)只有 65% 左右。同样的模型,换个 Agent 架子就差了近 12 个百分点。

这个"架子"是什么?往下拆。

Image

02为什么"AI 自动写代码"听起来很酷,用起来却心虚?

用过 Cursor 或 Copilot 你应该有这种体验:补全很爽,但你没把握它写的逻辑对不对。因为它们的流程是这个形状:

你描述需求 → AI 给出代码 → 你人肉验证

AI 只负责"输出",不负责"验证"。test 要你自己跑,错误要你自己看,修正要你自己改。出问题时你只能猜:是 prompt 没说清楚?模型幻觉了?还是你代码环境有问题?

OpenHands 把流程翻了个面:

你描述需求 → Agent 思考 → Agent 执行(bash/Python) → 读取 stdout/stderr/exit code → Agent 验证 → 不通过就回到"思考"那步重来

这个差别不是功能多少的区别,是架构的区别。Cursor/Copilot 本质是编辑器插件——它们"建议"。OpenHands 本质是执行引擎——它"做完并验证"。

做到这一点的核心,是两样东西:Event Stream 和 Agent Loop。


03Event Stream + Agent Loop:把 AI 编程变成可回放的日志

Image

Event Stream:不可修改的"Git commit log"

OpenHands 最底层的设计只有一个:一切状态变更都是 Event。

Agent 下了一个 shell 命令:
ActionEvent(CmdRunAction(command="pytest -x"))

沙箱返回了执行结果:
ObservationEvent(CmdOutputObservation(exit_code=1, stderr="..."))

Agent 据此决定修改某个文件:
ActionEvent(FileEditAction(path="auth.py", ...))

每个 Event 一个 JSON 文件,追加(append)到事件流里,从不修改历史。这件事听起来像废话,但它的含义很深——和 Git commit log 一样:你可以 blame 任何一步,可以 replay 从第一步到最后一步的完整过程,可以在任何一步中断、检查、重来。

传统的 Agent 实现怎么做?扔一个 state = {} dict,每个 loop 往里写。出 bug 了你想知道"第 37 步 Agent 为什么做了那个决策"——对不起,state 已经被第 38 步覆写了。

OpenHands 用 Event Sourcing 解决:当前状态 = 从第一个 Event 回放到最后一个。删掉第 37 个 Event 之后的全部事件,你可以让 Agent 从那个分叉点重新来。

Agent Loop:5 阶段的执行引擎

Image

Event Stream 负责"记录",Agent Loop 负责"决策"。核心在 codeact_agent.py 的 step() 方法——核心逻辑约 35 行:

def step(self, state: State) -> Action:
# Phase 1: 排空待执行动作队列
if pending_actions := self._get_pending_actions():
return self._execute_next(pending_actions)

# Phase 2: 检查用户消息是否被 hook 拦截
if blocked_reason := self._check_blocking_hooks(state):
return AgentFinishAction(reason=blocked_reason)

# Phase 3: 构建 LLM prompt(可能触发 condensation 压缩)
    messages = self.condenser.prepare(state.events)

# Phase 4: 调用 LLM with retry
    response = self.llm.completion(messages, tools=self.tools)

# Phase 5: 分类并分发 LLM 响应
match self._classify(response):
case "tool_calls":  return self._parse_actions(response)
case "content":     return MessageAction(response.content)
case "empty":       return self._request_retry()

15 行伪代码就把核心决策讲完了。但"简单"≠"简陋"——五个阶段每一段都有工程深意:

  1. 待办优先:Agent 可以一次生成多个 Action,逐个执行——减少等待 LLM 响应的延迟
  2. Hook 拦截:如果用户中途说"停"或改了需求,Agent 不继续执行——尊重人的判断
  3. Condensation 压缩:跑几百步后 context window 会爆,LLMSummarizingCondenser 自动压缩历史事件——保持关键信息,丢弃冗余
  4. LLM 重试:API 出错或 context window 溢出时,自动重试或触发 Condensation——不丢上下文
  5. 响应分类:tool_call / 纯文本 / 空响应 三种情况有明确处理路径——不会出现"LLM 没调用 tool,loop 卡住了"

而周围的 8 万行代码,解决的是"这 35 行逻辑在真实世界里怎么跑得稳":Docker 沙箱管理、Stuck 检测(检测重复相同 action 死循环,stuck.py ~489 行)、多模型适配(LiteLLM 统一调用层,~3282 行)、错误恢复和降级策略。

Image


04Sandbox + CodeAct:为什么让 Agent 写代码比给它 20 个 tool schema 聪明

三层沙箱:安全的地方快跑,危险的地方隔离

OpenHands 不强制所有代码都在沙箱跑。它有三种 WorkSpace,同一套 Agent 代码无缝切换:

类型
隔离级别
速度
适用场景
LocalWorkspace
进程级
快(3x Docker)
dev / 单测
DockerWorkspace
容器隔离
正常
生产、不可信代码
RemoteAPIWorkspace
网络隔离
取决于远程
云 / 多租户

DockerWorkspace 里是一个完整的开发环境:

  • tmux bash session(保留 shell 历史,Agent 可以执行复杂 shell 命令链)
  • 持久化 IPython kernel(可以跑数据分析、重构脚本)
  • Playwright Chromium(可以打开网页看文档、抓取 API 响应)
  • str_replace 文件编辑器(带 undo,编辑源码用)

Agent 和沙箱通过 REST API 通信:POST /execute_action 发送 Action,返回 Observation。

CodeAct:一把刀替代 20 个模具

大部分 Agent 框架的做法是:定义一堆 tool,每个 tool 一个 JSON schema——read_file、write_file、search_code、run_test、list_directory...十几个甚至几十个。

OpenHands 问了一个更根本的问题:LLM 最擅长什么?写代码。那为什么要让它用 JSON 结构来表达动作?

CodeAct 的答案:只给 Agent 三样东西——

1. Bash(shell 命令:文件操作 / git / 运行工具 / 启动服务)
2. Python via Jupyter(数据分析 / 重构 / 批量操作)
3. 浏览器 DSL(网页抓取 / 查阅文档 / UI 测试)

LLM 用自己最擅长的 Python/bash 来表达"我要做什么",而不是填一个它不擅长的 JSON schema。16 种 Action 类型映射到统一的 Action/Observation 配对——你不需要"写文件这个 tool 的 schema 里 path 字段是 required 还是 optional"这种维护噩梦。

举个具体例子:Agent 要修一个 pytest 失败的 bug——

# Agent 的思考(内部,不落地沙箱)
# "这个测试失败了,先看报错信息"

# → 生成 Action: CmdRunAction(command="pytest tests/test_auth.py -x")
# → 沙箱返回 Observation: CmdOutputObservation(exit_code=1, stderr="AssertionError: ...")
# → Agent 读报错,定位到 auth.py:42

# → 生成 Action: FileEditAction(path="src/auth.py", old_str="...", new_str="...")
# → 沙箱返回 Observation: FileEditObservation(diff="+2 -1")

# → 生成 Action: CmdRunAction(command="pytest tests/test_auth.py -x")  
# → 沙箱返回 Observation: CmdOutputObservation(exit_code=0)
# → 验证通过!生成 Action: AgentFinishAction()

# 整个过程 5 个 Action,每一次都有 Observation 验证

这就是 Event Stream 里记录的"think → act → observe → verify"完整链条。不是"AI 写了一段代码"就完了。


05与 Claude Code / Devin / Cursor 比,到底怎么选?

工具
定位
自主性
可审计性
部署成本
OpenHands
自托管 Agent 平台
✅ 自主执行+验证
✅ Event Stream 全链路可回放
需要 Docker + API key
Claude Code
Anthropic 官方 CLI Agent
✅ 终端内自主
⚠️ 无 Event Stream
一条命令启动
Devin
商业全自主 Agent
✅ 全自主+Slack 集成
❌ 黑箱执行
月费 $500+
Cursor/Copilot
IDE 内嵌辅助
❌ 不能自主执行
❌ 无执行日志
几乎为零

一句话选型:

  • 团队要可审计的自主 Agent,能控制模型和沙箱 → OpenHands
  • 个人快速编码,终端内和 Claude 对话写代码 → Claude Code
  • 有钱没时间,想要开箱即用的全自主程序员 → Devin(但准备好接受黑箱)
  • 日常写代码要智能补全和对话 → Cursor / Copilot

而且 OpenHands 和 Claude Code 不是互斥的——OpenHands 支持 ACP(Agent-Client Protocol),你可以把 Claude Code 挂进 OpenHands Agent Canvas 当其中一个 Agent。(当然,Codex 也是同理)


06OpenHands 的三个硬伤和一个关键优势

踩了几天坑,诚实说三个问题:

1. 部署门槛不低。 Docker + 模型 API key + config 文件 + 理解 Event Stream 和 Agent Loop 的概念。对"只想试试AI能不能帮我写代码"的人不友好。

2. Token 烧钱。 因为每一步都带全量事件历史进 prompt,一个复杂任务吃掉几百万 token 很正常。用 Opus 4.7 跑 SWE-Bench 每个任务平均 $0.42——修一个 bug 四毛二,批量修 100 个就是 $42。

3. 长任务不稳定。 Context window 溢出的风险真实存在。Condensation 可以压缩,但压缩过程本身可能丢失关键信息——Agent 在"记忆不全"的状态下做决策,效果打折扣。

但关键优势盖过了这些:它开源。stuck.py 里的检测逻辑你可以改,condenser 的压缩策略你可以换,甚至 Agent 循环的 5 个 Phase 你可以重写。商业工具给你一个黑箱,OpenHands 给你一张可修改的工程蓝图。


07这套架构不只给 AI 编程用——你的 Agent 项目也能复用

Event Stream + Agent Loop 的设计,是 OpenHands 最有价值的贡献——不局限于"AI 辅助编码"赛道。

Event Sourcing 在金融和 DevOps 是成熟范式——银行用 append-only transaction log 保证账目可审计,Kafka 用 append-only message queue 保证消息可回放。OpenHands 是第一个把它系统性地用在 AI Agent 上的项目。

如果你在写自己的 Agent,一个可以用今天就开始的改进:把 state dict 换成 append-only event log。好处立竿见影:

  • 出 bug 时你能 blame 每一步决策
  • 你可以从任意中间步骤重放(replay)
  • 你可以并行跑多个分支(从同一个分叉点)

CI/CD 给了我们 build → test → deploy → monitor 的可审计管道,OpenHands 给了 Agent think → act → observe → verify 的同等东西。


08跑起来:一段代码 + 一张架构图

Image
# 1. 装 Docker(略,去 docker.com 下载)

# 2. 拉 OpenHands
docker pull docker.all-hands.dev/all-hands-ai/openhands:1.8.0

# 3. 设置 API key
export LLM_API_KEY="sk-your-key"
export LLM_MODEL="anthropic/claude-sonnet-4-5"

# 4. 启动
docker run -d --rm \
  -e LLM_API_KEY \
  -e LLM_MODEL \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -p 3000:3000 \
  docker.all-hands.dev/all-hands-ai/openhands:1.8.0

# 5. 打开 http://localhost:3000 ,告诉它你要做什么
# 比如:"在这个 Python 项目里修所有 pytest 失败的测试,修完后跑一遍确认"

Image