系列「企业级 AI Agent 实现拆解」E16 篇。上一篇 E15 讲了 Multi-Agent 基础模式------Host-Worker 和 Plan-Execute-Replan。这篇看一个更完整的实战案例:Manus Agent。先从单个全能 AI 出发,再拆解 deer-go 研究团队,搞清楚"什么时候用一个 AI,什么时候用一支团队"。
读完这篇你会知道
- OpenManus 是什么:全能 AI 的系统 Prompt 和图结构
- 五节点图怎么跑:ChatModel → 分支 → ToolsNode / Human
- Human-in-the-Loop:为什么让 AI 在中途等人是好设计
- 研究团队的五个角色:Coordinator / Planner / Researcher / Coder / Reporter
- Router 路由器:怎么用共享状态决定"下一个叫谁"
- Researcher 的 ReAct 内循环:一个研究员自己也有 40 步
- 单 Agent vs. 团队:怎么选
一、先说一个具体任务
假设你给 AI 下了这样一个指令:
"帮我调研 2025 年国内大模型市场格局,分析前五名产品的技术路线差异,写一份 3000 字竞品分析报告。"
这个任务需要:上网搜索 → 整理数据 → 写代码分析 → 汇总成文。每步的专业要求不同,搜索靠耐心翻页,数据分析要写代码,写报告要语言组织。
把这一切压给一个 AI,效率差,容易出错。Eino 给出了两个答案:单 Agent 全能模式(OpenManus 的 Go 复刻版),和多 Agent 团队模式(deer-go)。
二、OpenManus:全能 AI 是什么样的
先说清楚一件事:OpenManus 有两个版本,本文分析的是哪个。
FoundationAgents/OpenManus 是原版开源项目,Python 写的,有自己的 agent 框架和工具链,是国内较早开源的全能 Agent 实现之一。
本文分析的是 Eino 框架对 OpenManus 设计理念的 Go 语言复刻,源码在:
bash
eino-examples/flow/agent/manus/
两者关系:CloudWeGo 团队用 Eino 的 Graph 编排能力重新实现了同样的设计------全能单 Agent、工具调用循环、浏览器 + 代码执行 + 搜索三件套。系统 prompt 里直接用了 "You are OpenManus" 作为 Agent 的身份定义,说明它在明确致敬原版的设计理念,但底层实现语言和框架完全不同。
如果你想研究原版 Python 实现,去 FoundationAgents/OpenManus;如果你的项目用 Go + Eino,就看这里的复刻版。下面分析的是 Eino 版本。
prompt.go 第一行写清楚了这个 Go 版 OpenManus 的自我定位:
go
systemPrompt = `
You are OpenManus, an all-capable AI assistant, aimed at solving any
task presented by the user. You have various tools at your disposal...
`
为了成为"全能助手",它配备了三类工具:
- 浏览器 (
browseruse.Tool):打开网页、点击、截图、提取内容 - 命令行 + Python (
commandline):在 Docker 沙箱里跑代码 - 网页搜索 (
duckduckgo):主动搜索
三、五节点图:OpenManus 怎么跑
OpenManus 的运行逻辑是一张图,五个节点用箭头连起来:
css
[用户提问]
↓
[InputConverter] ← 把输入转成 AI 可读的消息格式
↓
[ChatModel] ← AI 大脑,思考下一步
↓
↙ ↘
[ToolsNode] [Human] ← 执行工具 OR 暂停等人
↓ ↓
└──→ [ChatModel] ← 循环
↓(无更多工具调用)
[OutputConverter] ← 输出最终结果
ChatModel 之后有个关键分支(源码 manus.go:251):
go
g.AddBranch(NodeKeyChatModel, compose.NewGraphBranch(
func(ctx context.Context, in *schema.Message) (endNode string, err error) {
if len(in.ToolCalls) > 0 {
return NodeKeyToolsNode, nil // AI 还需要用工具 → 去执行
}
return NodeKeyHuman, nil // AI 想停下来 → 等人确认
},
...
))
白话:AI 每次想完一轮,判断"还需要用工具吗"。需要就执行,不需要就停下来让用户看。
四、Human-in-the-Loop:为什么让 AI 等人
"停下来等人"叫 Human-in-the-Loop(人在环中),不是技术缺陷,是刻意设计。
AI 完成每个阶段就给人一次确认机会,防止"方向跑偏了还不停"。manus.go 里在 Human 节点前设了断点:
go
runner, err := g.Compile(ctx,
compose.WithCheckPointStore(newInMemoryStore()),
compose.WithInterruptBeforeNodes([]string{NodeKeyHuman}), // Human 节点前暂停
)
暂停后,用户可以输入新指令,也可以直接按 y 继续:
go
fmt.Print("Do you want to continue? (y/n): ")
// 读取用户输入,注入下一轮 state.UserInput
五、OpenManus 的极限
OpenManus 本质上还是一个 AI 排队做所有事:搜索完再分析,分析完再写作。面对"调研 10 个竞品"这种任务,只能一个个来。
而且一个 AI 扮演所有角色容易"乱了自己"------系统 prompt 越来越长,AI 需要同时记住"我是搜索员"和"我是报告写手",前后容易矛盾。
这就是为什么需要团队。
六、研究团队:deer-go 的设计
源码:eino-examples/flow/agent/deer-go/
deer-go 是一个专职分工的多 Agent 研究团队。五个角色,各司其职:
| 角色 | 代号 | 职责 |
|---|---|---|
| 协调员 | Coordinator |
接收需求,判断语言,移交给规划师 |
| 规划师 | Planner |
把任务拆成步骤,标注每步类型 |
| 研究员 | Researcher |
执行需要联网搜索的步骤 |
| 程序员 | Coder |
执行需要数据处理的步骤 |
| 报告员 | Reporter |
汇总研究结果,输出最终报告 |
用上班比喻:Coordinator 是前台,Planner 是项目经理,Researcher 和 Coder 是执行员工,Reporter 是写总结汇报的人。
七、Coordinator:不干活,只分活
coordinator.go 里的 Coordinator 只做一件事------判断用户语言,然后移交给规划师:
go
// coordinator.go:84
hand_to_planner := &schema.ToolInfo{
Name: "hand_to_planner",
Desc: "Handoff to planner agent to do plan.",
ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
"task_title": {Type: schema.String, Desc: "任务标题"},
"locale": {Type: schema.String, Desc: "用户语言,如 zh-CN"},
}),
}
它给自己配备了唯一一个"工具"------hand_to_planner(交接给规划师)。从不自己去搜索或分析,只确认需求、判断语言、完成移交。职责单一,不越权。
八、Router:团队的调度员
整个团队能运转,靠一个 Router(路由器)。它读取当前任务状态,决定"下一个叫谁"。
research_team.go 的逻辑清晰(源码 71 行):
go
func routerResearchTeam(ctx context.Context, input string, opts ...any) (string, error) {
err = compose.ProcessState[*model.State](ctx, func(_ context.Context, state *model.State) error {
state.Goto = consts.Planner // 默认:回到规划师
if state.CurrentPlan == nil {
return nil // 还没有计划 → 去找规划师
}
// 找第一个还没执行完的步骤
for i, step := range state.CurrentPlan.Steps {
if step.ExecutionRes != nil {
continue // 已完成,跳过
}
switch step.StepType {
case model.Research:
state.Goto = consts.Researcher // 需要搜索 → 派给研究员
return nil
case model.Processing:
state.Goto = consts.Coder // 需要处理 → 派给程序员
return nil
}
}
// 所有步骤完成,或超出迭代次数 → 叫报告员
if state.PlanIterations >= state.MaxPlanIterations {
state.Goto = consts.Reporter
}
return nil
})
return output, nil
}
白话 :路由器每次检查当前计划,找"还没结果"的第一个步骤。需要搜索叫研究员,需要代码叫程序员,全完成了叫报告员。这是状态机思路------不预先排顺序,每次根据进度动态决定。
九、共享状态:团队的"公共白板"
团队成员通过共享 State 传递信息。可以把它想象成一块大家都能看的白板:规划师写下任务清单,研究员查完写上结论,下一个人进来先看白板,再继续。
go
type State struct {
Messages []*schema.Message // 对话历史
CurrentPlan *Plan // 当前任务计划(含各步骤状态)
PlanIterations int // 已迭代次数
MaxPlanIterations int // 上限
Locale string // 用户语言
Goto string // Router 写在这里:下一步去哪
}
每个 Agent 执行完,把结果写进 State,路由器读 State 决定谁来接班。没有 Agent 是孤岛,所有人共享同一份上下文。
十、Researcher 的内循环:自己也有 40 步
研究员不是简单的"搜一下返回结果"。它内部是完整的 ReAct Agent (源码 researcher.go:153):
go
agent, err := react.NewAgent(ctx, &react.AgentConfig{
MaxStep: 40, // 最多循环 40 步
ToolCallingModel: infra.ChatModel,
ToolsConfig: compose.ToolsNodeConfig{
Tools: researchTools, // MCP 工具集(搜索、抓取等)
},
MessageModifier: modifyInputfunc, // 截断超长输入,防超 token 限制
})
MaxStep: 40------一个研究员在执行单个步骤时,可以独立循环 40 次:反复搜索、验证、补充,直到信息足够,才把结论写回公共 State。
这是嵌套结构:外层是团队工作流,内层每个 Researcher 是独立的 ReAct 循环。就像团队里每个成员自己也有工作节奏,不需要主管盯着每一步。
十一、完整流程一张图
css
用户
↓
Coordinator(确认语言)
↓
Planner(生成计划:[步骤1:研究, 步骤2:处理, 步骤3:研究])
↓
Router(循环判断当前步骤类型)
├──→ Researcher(执行步骤1,内部 ReAct×40,结果写入 State)
├──→ Coder (执行步骤2,代码处理,结果写入 State)
├──→ Researcher(执行步骤3,再次搜索,结果写入 State)
└──→ Reporter (所有步骤完成,汇总生成最终报告)
↓
最终报告 → 用户
注意:Researcher 和 Coder 是按步骤顺序执行,不是真正同时并行------因为后面的步骤可能依赖前面的结果(先搜论文,再用代码分析搜到的数据)。
Eino 支持通过 Parallel 或 GraphMultiBranch 实现真正的并行,适合步骤之间没有依赖关系的场景。
十二、单 Agent vs. 团队:怎么选
| 场景 | 推荐 |
|---|---|
| 任务 5 步以内,流程清晰 | OpenManus 单 Agent,简单直接 |
| 需要人工在中途确认方向 | OpenManus,Human-in-the-Loop |
| 任务可拆成"搜索/处理/汇总"明确步骤 | deer-go 多 Agent 团队 |
| 多个独立子任务可以并行 | 多 Agent + Parallel 分支 |
| 出错需要知道哪个环节有问题 | 多 Agent,每节点独立可追踪 |
两个方案不是竞争关系,是不同复杂度任务的对口配置。
理解了这两个,你就理解了 Eino 里两个核心概念:
- 单 Agent = 有记忆的工具调用循环
- 多 Agent = 专职 Agent 的有状态协作图
小结
OpenManus 用一个 AI + 工具调用循环处理任务,适合中等复杂度;deer-go 团队用五个专职 Agent + 共享状态 + 路由器处理研究类复杂任务。核心差异不是"工具多少",而是职责分工 和状态是否可追踪。
下篇继续。