# 深度拆解 OpenManus 技术框架：与 Manus 的差距分析

> 作者：晨旭｜发布：2025-11-15｜系列：AI技术理解
> 来源：https://chenxu.xin/writing/openmanus-teardown

从代码层拆解 OpenManus 的四层架构与 ReAct 骨架，用一次真实的旅游规划任务暴露它的僵尸 Agent 和内存污染缺陷，再对照官方 Manus 与 Anthropic，看清开源框架和商业产品之间那道叫上下文工程的鸿沟。

---

MetaGPT 团队开源了 OpenManus，一个通用的 AI Agent 框架。它的目标是提供一套强大的架构，让 Agent 能够执行浏览器操作、代码执行、文件操作等复杂任务。

那么，这个框架是怎么搭建的？它和我们熟知的 Manus 有什么异同呢？

## PM 视角：为什么要扒开源代码？

现在 AI 几乎可以秒懂任何代码库，程序员的技术黑盒在逐渐白盒化，看代码就像是看文档。产品经理可以，也应该，深入前沿技术，进行「黑客级竞品调研」。

它不是简单地罗列功能，而是建立一个交叉验证的闭环：

- **实测体验**：从用户视角，感知竞品（如商业版 Manus）的效果。
- **技术解密**：深入挖掘竞品的技术博客、论文、访谈，理解其技术原理。
- **开源复现**：找到一个业界最接近的开源项目（如 OpenManus），在内部跑起来，观察其实现过程，哪怕这个开源项目只有商业 Manus 效果的 50%。

那为什么要复现一个可能落后的开源项目？因为没有对比，就没有分析。通过复现 OpenManus，我们是作为开发者的角度，能看到 Agent 所有的思考日志。这让我们能精准定位到它技术架构的优劣势，并看到它和真 Manus 的差距。

看到差的，才能真正理解好的牛在何处，才有要优化的方向。

## 整体技术架构概览

从代码和设计来看，OpenManus 采用了经典的分层设计，可以概括为四个核心层次：

- **基础设施层**：最底层，提供 LLM 抽象、沙箱环境、配置管理和日志。
- **工具层**：中间层，提供 Agent 动手的能力，如浏览器、代码执行、文件操作、搜索等。
- **Agent 层**：核心控制层，负责思考，决定何时调用什么工具。
- **应用入口层**：最上层，负责接收用户指令，启动 Agent。

简化的流程是：用户指令 → Manus Agent（Agent 层）→ LLM（基础设施层）思考并决定调用工具 → 工具集合（工具层）↔ 沙箱 / 浏览器 / 外部系统。

### 1、统一的 LLM 抽象层（`app/llm.py`）

这是 Agent 的大脑中枢。框架没有锁定单一模型：

- **兼容多家模型**：OpenAI、Azure、Ollama（本地模型）、AWS Bedrock 都可以通过 `config.toml` 无缝切换。
- **统一 API**：封装了统一的 `ask` 和 `ask_tool` 接口。
- **内置健壮性**：自带 `tenacity` 重试策略，能处理常见的速率限制和 API 错误。
- **成本控制**：内置 Token 统计，包括图片 Token 估算，能有效防止上下文超限。

### 2、强大的工具集合（`app/tool/`）

这是 Agent 的双手，内置了极为丰富的工具集：

- **环境控制**：`BrowserUseTool`（基于 Playwright 和 BrowserGym 的浏览器自动化）、`ComputerUseTool`（配合 Daytona Sandbox 实现 GUI 层面的电脑控制）。
- **代码与文件**：`PythonExecute` / `Bash`（在沙箱中安全执行代码和 Shell 命令）、`FileOperators` / `StrReplaceEditor`（文件读写、列举、编辑）。
- **信息获取**：`WebSearch`（封装 Google / Bing / Baidu）、`Crawl4ai`（结构化抓取网页内容）。
- **其他能力**：`DataAnalysis` + `ChartVisualization`（数据分析与图表可视化）、`AskHuman`（在关键节点引入人类确认）。

### 3、隔离的沙箱环境（`app/sandbox/`）

安全是 Agent 框架的重中之重。默认使用 `DockerSandbox`，将代码执行和 Shell 命令限制在隔离的 Docker 容器中，可以配置 CPU 和内存限制防止资源滥用，也支持连接 Daytona 远程开发环境实现更复杂的 GUI 控制。

### 4、独特的能力：环境感知与协议支持

**浏览器环境感知**：在 Agent 操作浏览器时，这个模块会自动将当前页面的 DOM 摘要、页面信息等上下文喂给 LLM，极大提升了模型对当前环境的感知力。

**A2A / MCP 协议支持**：`MCPClientTool` 支持模型上下文协议，允许 Agent 动态地从外部服务加载和调用工具；`protocol/a2a` 支持将 Manus Agent 整体封装成一个 A2A 服务，让其他系统远程调用它的能力。

## 核心工作流拆解：Agent 如何思考与行动

OpenManus 的核心是一套基于 ReAct 模式的 Agent 引擎。无论上层是哪种 Agent，它们几乎都共享同一套骨架。

### 1、通用骨架：BaseAgent → ReAct → ToolCall

**`BaseAgent`** 定义了 Agent 的通用生命周期：`run(request)` 是总入口，负责管理状态（IDLE → RUNNING）、初始化 `memory`、启动多步循环；`step()` 是循环中的核心，每一步都会调用一次，直到达到 `max_steps` 或状态变为 FINISHED；`cleanup()` 在任务结束时清理资源。

**`ReActAgent`** 继承 `BaseAgent`，注入 ReAct 思想，把 `step()` 拆分成了 `think()`（思考）和 `act()`（行动）两个方法。

**`ToolCallAgent`** 继承 `ReActAgent`，是最关键的实现层：

- `think()` 负责调用 LLM。它打包好 `memory` 中的历史消息和 `available_tools` 的工具列表，调用 `llm.ask_tool(...)`，等待 LLM 返回思考文本和工具调用计划。
- `act()` 负责执行工具。它解析 `think()` 阶段拿到的 `tool_calls`，通过 `execute_tool()` 真正去调用工具，并拿到执行结果。

总结成一个闭环就是：`think` → `act` → 把 `ToolResult` 写回 `memory` → 进入下一步循环。

### 2、单 Agent 流程：各司其职

基于上述骨架，OpenManus 派生出了多种专职 Agent，共享骨架但拥有不同的工具集：

- **通用 Manus Agent**：默认的全能型 Agent，工具集包括浏览器、代码、文件、AskHuman、Terminate，以及动态加载的 MCP 工具。`create()` 时会根据配置初始化 MCP 客户端；`think()` 之前会检查是否需要注入浏览器上下文。
- **SandboxManus Agent**：Computer Use 专家，专为 Daytona 等远程 GUI 沙箱设计，工具是沙箱特供版，能力更强。`create()` 时创建远程沙箱，`cleanup()` 时销毁。
- **DataAnalysis Agent**：数据分析师，工具是跑分析脚本、生成图表配置、调用服务绘图。
- **SWEAgent**：程序员，工具集极简，只有 `Bash` 和 `StrReplaceEditor`，专注于「运行测试 → 发现错误 → 修改代码」的循环。

### 3、多 Agent 编排

当任务复杂需要多种 Agent 协作时，`PlanningFlow` 出场：

1. **创建 Flow**：注册多个 Agent，例如 `{"manus": Manus(), "data_analysis": DataAnalysis()}`。
2. **生成计划**：先用 `PlanningTool`（内部调用 LLM）根据用户输入生成一个包含多个步骤的任务计划。
3. **分发执行**：循环遍历步骤，检查 `Step` 的 `type` 字段，调用 `get_executor(step_type)` 找到最合适的 Agent；没有匹配的就用默认的 `manus` 兜底。
4. **执行并更新**：把当前步骤的 `step_prompt` 交给选定的 Agent 运行，完成后标记为 COMPLETED。
5. **汇总**：所有步骤完成后返回结果。

## 以旅游规划为例：一次真实的协作流

为了测试协作能力，我用 `run_flow.py` 的多 Agent 模式下达了一个典型的复杂指令：

> 我想要 11.15-11.20 去北京游玩，我和我妈妈两个人，请你帮我制定一下旅游规划，预算一万五左右

### 一、启动 PlanningFlow

Agent 接收到指令后，第一件事不是动手，而是启动规划流程。规划器调用 LLM，把模糊指令分解为一份清晰有序的行动计划，几秒钟后生成了 7 步：

```text
Plan: 北京5日游规划（11.15-11.20，2人预算一万五左右）
0. [ ] 前期准备：预订机票/高铁票、酒店、景点门票
1. [ ] Day 1 (11.15)：抵达北京，入住酒店，游览天安门广场、前门大街
2. [ ] Day 2 (11.16)：故宫博物院深度游，景山公园俯瞰全景
3. [ ] Day 3 (11.17)：八达岭长城一日游
4. [ ] Day 4 (11.18)：颐和园游览，圆明园遗址参观
5. [ ] Day 5 (11.19)：天坛公园，王府井购物，品尝北京烤鸭
6. [ ] Day 6 (11.20)：自由活动，整理行李，返程
```

### 二、调度执行者：从在线预订到被迫放弃

计划制定后，`PlanningFlow` 开始调度默认的 Manus Agent 完成第 0 步「前期准备」，Agent 获得了 20 步的执行权限。接下来是一场教科书式的挣扎与妥协。

**尝试 1（Web 搜索）**：调用 `browser_use (action: "web_search")`，报错 `Cannot navigate to invalid URL`。

**尝试 2（访问携程）**：Agent 自救，改为 `go_to_url` 直接访问携程，报错 `Timeout 30000ms exceeded`。

**关键缺陷（幻觉）**：下一步的思考日志写着「Great! I can see we've successfully navigated to Ctrip」。这是最致命的一点——尽管上一步明确超时失败，Agent 却幻觉自己成功了，并基于这个错误状态继续执行 `extract_content`、`click_element`，结果自然是连续失败。

**最后的妥协**：在连续 18 步失败后，Agent 似乎意识到浏览器工具不可靠，日志写着「The website seems to be having navigation issues. Let me try a different approach」，转而调用文件编辑工具，成功创建了《北京5日游预订规划.md》和《北京5日游预算计算器.py》。

最终 Agent 耗尽了 20 步，`PlanningFlow` 把第 0 步标记为完成。

### 三、关键缺陷：僵尸 Agent 与健忘的 Planner

前期准备完成后，`PlanningFlow` 指派**同一个** Manus Agent 实例去执行第 1 步。Agent 重复了「挣扎—妥协」循环，最后用文件工具产出了《Day1详细行程.md》，并成功调用 `terminate` 结束任务。

但从第 2 步开始，系统暴露了严重的设计缺陷。

**状态管理缺陷**：调度第 2 步「Day 2 故宫」时，日志显示 `Executing step 11/20`。注意，这是一个新任务，但 Agent 的 `current_step` 计数器却从 11 开始——`PlanningFlow` 复用了 Agent 实例，却没有重置它的内部状态。

**内存管理缺陷（致命）**：Agent 成功创建了《Day2故宫深度游.md》后，执行第二项操作时系统崩溃：

```text
ERROR | app.llm:ask_tool - OpenAI API error: Error code: 400
{'error': {'message': "Messages with role 'tool' must be a response to
a preceding message with 'tool_calls'"}}
```

这个 400 错误是 Agent 开发中最经典的错误：消息历史被污染了。上一个任务的最后一条消息是一条 `tool` 结果，而新任务没有正确清空历史，导致 `think()` 时发送了一个无效的消息序列。

**错误处理缺陷**：此时 Agent 实例已经僵尸化，`think()` 会永远 400 报错。而 `PlanningFlow` 捕获了错误之后……继续调度第 3 步。接下来的日志就是这个僵尸循环的不断重复：调度 Day 3 → Agent 成功写一个文件 → `think()` 时 400 报错 → Planner 捕获错误，继续调度 Day 4。

**小结**：

优点是规划能力清晰（成功把复杂任务分解成逻辑清晰的步骤）、实现了指挥家—执行者的调度模式、有一定弹性（浏览器工具连续失败时能妥协转向文件工具，曲线救国）。

缺陷是工具脆弱（`browser_use` 和 `python_execute` 高频超时）、状态管理有漏洞（复用实例不重置）、内存管理有漏洞（切任务不清空 memory）、错误处理缺乏健壮机制（不重试也不重新规划，只是记录后继续）。

## 与 Manus 的差距，以及 MCP 的演进

Manus 官方博客揭示了这套朴素流程在真实复杂任务（平均 50 次工具调用）中会遇到的核心瓶颈——上下文管理。这正是最大的差距所在，官方 Manus 的核心护城河就是上下文工程。

### 差距一：上下文管理

**OpenManus 的做法**非常朴素：把每一步的观察完整地、只增不减地追加到 `memory` 列表，累积到 Token 上限时 LLM 就报错，任务失败。

**官方 Manus 的做法**是把上下文当作成本最高昂的资源来管理，其策略不是存储，而是调度。核心理念是——文件系统才是真正的上下文：

- **上下文卸载**：LLM 的上下文窗口只是一个短暂的暂存器，Manus 被训练成按需读写文件，将文件系统用作结构化的外部记忆。
- **上下文缩减**：不存储完整结果，而是区分 Full 和 Compact。一个工具调用的原始结果（Full）可能非常长，Manus 会把它存入文件系统，只在 `memory` 中保留一个文件路径（Compact）。

### 差距二：工具调用与 KV 缓存成本

**OpenManus 的做法**：`think()` 阶段每次都把 `available_tools` 里的所有工具都塞给 LLM。

**官方 Manus 的做法**围绕 KV 缓存命中率来设计：

- **问题**：如果在循环中动态添加或删除工具，会导致 LLM 的 KV 缓存失效，推理成本和延迟飙升十倍。
- **方案：遮蔽，而非移除**。Manus 的工具列表是固定的，它不会移除工具，而是在解码时通过遮蔽或预填充的方式，强制 LLM 只能从一个特定子集（比如 `browser_*`）中选择。
- **卸载到沙箱**：Manus 只保留极少数（不到 20 个）原子工具，其他所有复杂功能都被卸载到沙箱中，通过 `Bash` 以命令行方式调用。这极大简化了工具集，进一步保证了 KV 缓存的稳定。

### 差距三：多 Agent 编排

**OpenManus 的做法**：`PlanningFlow` 先让 LLM 生成计划，然后按步骤为每个步骤选择执行者，把 `step_prompt` 传过去。

**官方 Manus 的做法**：多 Agent 的首要目标是上下文隔离，而不是模仿人类角色，因为 LLM 没有人类的认知局限。它的情景式上下文共享比简单的 `step_prompt` 传递灵活得多：

- **简单任务**：Planner 只传递指令，子 Agent 在干净的上下文中执行后返回结果。
- **复杂任务**：例如子 Agent 需要读写 Planner 正在操作的文件，Planner 会把完整上下文加共享文件系统一起传过去，确保子 Agent 在需要时拥有完整记忆，同时又能在自己的隔离环境中思考。

小结一下：OpenManus 提供了一个功能完整、模块清晰的 Agent 骨架，让我们看清了 Agent 是如何基于 think → act → observe 循环工作的。但官方 Manus 展示了，从一个「能跑」的开源框架到一个「好用」的商业产品，中间隔着一条由上下文工程组成的深深护城河。

### 作为服务：Agent 能力的 API 化

OpenManus 提供了两种把能力暴露给外部的方式：A2A 协议把整个 Agent 封装成一个标准服务，让外部系统远程调用它作为黑盒执行者；MCP 服务器则把工具层打包成 MCP 服务器，实现 Tools-as-a-Service。

但用 Anthropic 提出的 Agent Skills 和 MCP Code Execution 来审视，会发现两者在设计哲学上的巨大差异。OpenManus 实现了「API 化」，而 Anthropic 正在构建一个「可扩展的能力生态」。

**概念辨析：接口 vs 技能包**

OpenManus 的 AgentSkill 在 A2A 协议中仅仅是一个可远程调用的能力接口。它告诉外部系统「我有一个叫 `python_execute` 的功能」，但并不包含如何用好这个功能的知识。

Anthropic 的 Agent Skill 则是一个「知识 + 代码」的经验包，是一个包含 `SKILL.md` 和辅助脚本的完整文件夹，核心是渐进式披露：启动时只加载元数据，Agent 认为相关时才主动读取 `SKILL.md` 学习怎么做，需要时再进一步读取其他脚本。

差距在于：OpenManus 的 Skill 是一个固定的功能点，而 Anthropic 的 Skill 是一个可被 Agent 学习和发现的知识包。

**架构对比：直接调用 vs 代码执行**

OpenManus 把自己的工具注册为 MCP 工具，任何客户端 Agent 都要在上下文中加载这些工具的完整定义，然后直接调用。

Anthropic 明确指出了直接调用的两个致命缺陷：**定义过载**（工具成百上千时，所有 schema 会塞爆上下文）和**结果过载**（工具的中间结果，比如一份两小时的会议转录稿，必须完整流入上下文再传给下一个工具）。

它的解决方案是把 MCP 工具作为代码 API 暴露在文件系统上，Agent 不再直接调用工具，而是编写代码来与 MCP 交互。这种模式的优势是压倒性的：

- **渐进式披露**：Agent 通过 `ls ./servers` 发现工具，只在需要时 `cat` 读取特定工具的代码。
- **上下文高效**：Agent 可以在沙箱中用代码处理数据（过滤、聚合），只把最终的小结果返回给 LLM。
- **能力持久化**：Agent 可以把自己写的好用代码保存为新文件，再加一个 `SKILL.md`，这就创造了一个全新的 Agent Skill。

## 最后

OpenManus 不仅仅是一个能运行的 Agent，它是一个设计清晰、高度模块化的 AI 代理框架。

但通过与官方 Manus 和 Anthropic 的深度对比，我们能更清醒地看到「能跑的开源框架」与「好用的商业产品」之间的真正鸿沟。

这正回应了开篇提到的黑客级竞品调研。拆解 OpenManus，看的不仅是它如何思考与如何行动，更是为了通过复现它的脆弱与缺陷，去反推那些商业产品到底解决了多少看不见的难题。

对于 PM 而言，这就是深入代码的价值。

## 核心结论

- 程序员的技术黑盒正在白盒化，PM 可以也应该做「黑客级竞品调研」——实测体验、技术解密、开源复现三者交叉验证。看到差的，才能真正理解好的牛在何处。（判断 · 把握较大）
  永久链接：https://chenxu.xin/writing/openmanus-teardown#read-code-as-competitive-research
- 实测中最致命的一幕：浏览器导航明确超时失败后，Agent 在下一步思考里幻觉自己成功了，并基于这个错误状态继续操作。工具失败后的状态确认是 Agent 可靠性的关键缺口。（把握较大）
  永久链接：https://chenxu.xin/writing/openmanus-teardown#agent-hallucinates-tool-success
- PlanningFlow 复用 Agent 实例时既不重置 current_step，也不清空 memory，导致新任务发出无效消息序列而 API 400 报错，Agent 从此僵尸化，而 Planner 只是记录错误继续调度下一步。（把握较大）
  永久链接：https://chenxu.xin/writing/openmanus-teardown#zombie-agent-from-memory-pollution
- OpenManus 和官方 Manus 之间最大的差距是上下文管理。OpenManus 只增不减地往 memory 里追加观察，撑到 Token 上限就失败；Manus 把上下文当最昂贵的资源来调度，文件系统才是它真正的上下文。（判断 · 把握较大）
  永久链接：https://chenxu.xin/writing/openmanus-teardown#manus-moat-is-context-engineering
- 在循环中动态增删工具会让 KV 缓存失效，推理成本和延迟可能飙升十倍。正确做法是保持工具列表固定，在解码时通过遮蔽强制模型只从特定子集中选择。
  永久链接：https://chenxu.xin/writing/openmanus-teardown#mask-tools-dont-remove-them

---

本文出自晨光里的AI（https://chenxu.xin），作者晨旭。
引用时请保留来源链接。文中标注「判断」「假设」的部分是作者的个人看法，不是事实。
