Manus Agent:一个全能 AI,和一支研究团队

系列「企业级 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):打开网页、点击、截图、提取内容
  • 命令行 + Pythoncommandline):在 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 支持通过 ParallelGraphMultiBranch 实现真正的并行,适合步骤之间没有依赖关系的场景。


十二、单 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 + 共享状态 + 路由器处理研究类复杂任务。核心差异不是"工具多少",而是职责分工状态是否可追踪

下篇继续。


代码来源:cloudwego/eino-examples

相关推荐
东坡白菜2 小时前
破局全栈:前端开发的Java入门实战记录—JPA(2)
java·后端
代码丰2 小时前
RAG 系统如何实现全链路追踪:AOP 埋点与流式调用追踪实践
后端
小码编匠2 小时前
C# 工控上位机必备:数据转换工具类与十个核心模块
后端·c#·.net
神奇小汤圆3 小时前
一文读懂 OpenAI Codex 源码的原理、架构与未来
后端
道友可好3 小时前
AI 是最好的混乱放大器:代码熵管理实战
前端·人工智能·后端
掘金者阿豪4 小时前
写了很多内容后,我还是决定给自己搭一个Typecho博客
后端
Younglina5 小时前
打了3年羽毛球球才发现:我对自己的装备和胜率一无所知
前端·后端
牧艺5 小时前
用 Next.js 搭建 AI Agent 前端编排:从 Plan 到 SSE Trace 的完整实践
前端·agent
刘棕霆5 小时前
18—sentry-static 入口收敛:从多能力检查到 1 个静态分析入口
aigc·测试