Skip to content

OpenHands:为什么先记录动作,再执行工具?

返回系统目录 · 跟读代码 · 图的文字版

固定研究版本:Agent 内核以官方 OpenHands/software-agent-sdk@6ebd820d10794f1b52bb06ef6c19512888a1401b 为准;仓库分工以官方 OpenHands/OpenHands@928873b4c2efb5a17ffa93eb541c78bb43a109f3 为准,核对日期 2026-09-23。本篇是源码静态阅读,只讨论 SDK 内 LocalConversation.run() + 默认 Agent.step() 的一条局部路径,不是 Agent Canvas、远程 Agent Server 或所有 Agent 后端的实测。

30 秒读懂

在这条实现路径里,模型的工具调用先被转换并发出 ActionEvent,再检查是否需要用户确认。若需要,LocalConversation 进入 WAITING_FOR_CONFIRMATION,本次 run() 在工具执行前退出。下一次获准 run()Agent.step() 从当前分支找没有对应结果的动作,先执行这些动作,再考虑向模型采样新动作。工具返回 Observation 后,由 Agent 包装成 ObservationEvent(或错误事件),经会话回调记录进事件历史。因此“模型提出动作”“动作已记录”“工具实际做了事”是三个可区分的时刻。生成并发出 ActionEvent · 确认闸门 · 下轮先处理未匹配动作

OpenHands ActionEvent 与 ObservationEvent 的泳道时序图

查看原尺寸 SVG(可缩放)

可编辑图源 · PNG 预览 · 不看图的说明

这个边界有什么价值

事件不只是 UI 聊天记录。LocalConversation 的默认回调先 append_event(),再运行外部回调;当前分支中的 ActionEventObservationEvent / UserRejectObservation / AgentErrorEvent 可以按 ID 配对,找出尚未完成的动作。回调顺序 · 匹配规则。“入账”只表示进入 EventLog:未配置持久化目录时可使用 InMemoryFileStore,不能理解成每次都已写到磁盘。存储回退

这是基于源码的工程解读:把意图、效果和确认状态分离,为暂停、拒绝和恢复提供了明确的状态边界。它不是“恰好执行一次”的保证,也不能证明所有工具都可靠隔离。以 TerminalTool 为例,执行器的工作目录取自 conv_state.workspace.working_dir;实际隔离取决于选择的 workspace/部署模式,不能把工作目录等同于沙箱。TerminalTool 初始化 · Canvas 对无沙箱本地模式的警告

仓库边界

当前 OpenHands/OpenHands 是 Agent Canvas 前端与本地栈编排;Agent、工具、会话、workspace 和事件的权威实现已在 software-agent-sdk。本文故意不把 Canvas 的事件展示组件画成执行内核。官方仓库分工

下一步可读关键代码路径;后续再分别研究 Agent Server 的远程生命周期、工具/插件装配,以及 workspace 的隔离模型。

图的文字说明 · openhands-action-events

四条泳道从左到右是 LocalConversationAgentToolEventLog,时间从上往下。用户消息先成为 MessageEventrun() 调用 Agent.step();模型产生工具调用后,Agent 先发 ActionEvent 进入事件历史。若需确认,本次运行停在 WAITING_FOR_CONFIRMATION。再次获准运行时,Agent 找到当前分支上未匹配的动作,再交给工具执行;无须确认的动作则在同一次 step 中直接进入工具。工具把 Observation 返回给 Agent;Agent 包装成 ObservationEvent 或错误事件,经会话回调写入事件历史。

图中“再次运行”和“直接执行”是条件路径,不表示一个工具调用总要经历两次 run()。用户拒绝会产生 UserRejectObservation,不会调用工具。完整来源和例外见关键代码路径

图下的拒绝分支与主路径互斥。图内省去了长注释:结果事件的记录顺序不能推断并行工具副作用的发生顺序;图只描述同步 LocalConversation 的局部路径。

本图映射官方 SDK 的固定提交 6ebd820d10794f1b52bb06ef6c19512888a1401b 中同步 LocalConversation + 默认 Agent 的静态源码路径,不是运行轨迹;不覆盖 Agent Server、ACP 后端或工具沙箱实现。


在线预览稿:书稿仍在校稿,系统篇以文内固定源码版本为准;静态阅读不等于运行验收。