Eino学习笔记 —— 附录1 - MuxiaoWF跳到主要内容

Eino学习笔记 —— 附录1

Eino学习笔记 —— 附录一:Flow 流程模块 , ReAct Agent 与 MultiAgent

周一 7月 20 2026
2362 字 · 14 分钟

本笔记通过ai辅助生成,但对于代码阅读顺序应当没有问题(均使用eino官方的例子进行,个人认为官方的教程感觉有点太难懂了)

理论上个人感觉附录只做了解即可,需要时可进行查询

附录一:Flow 流程模块 — ReAct Agent 与 MultiAgent

📂 源码仓库github.com/cloudwego/eino-examples

📖 系列文档入门笔记 | Agentic 进阶 | 附录一 Flow | 附录二 组件 | 附录三 工具

📁 代码根目录:flow/agent/

📖 前置知识:本附录假设你已掌握 入门笔记(一~七节)和 Agentic 进阶 的内容。


速览:Flow vs ADK — 两套体系

Eino 提供了两套并行的 Agent 构建方式

维度ADK(入门笔记 / Agentic 进阶Flow(本附录)
入口adk.NewChatModelAgent / adk.NewTypedChatModelAgentreact.NewAgent / host.NewMultiAgent / Compose Graph
抽象层级高层封装,开箱即用中低层,精细控制每个节点
编排方式Agent + Runner + Middleware(声明式)Graph + Node + Branch + State(命令式)
适用场景快速构建标准 Agent 应用自定义控制流、多 Agent 协作、精细状态管理

🧠 怎么选:ADK 能覆盖的场景优先用 ADK。需要自定义 ReAct 循环行为、运行时动态修改模型参数、多 Agent 状态图流转时用 Flow。


技术选型决策树

graph TD
    Q["你要做什么?"] --> Q1{"标准单 Agent
问答+工具+记忆?"} Q1 -->|是| ADK["用 ADK
入门笔记 §3 / Agentic 进阶 §3"] Q1 -->|否| Q2{"需要自定义
ReAct 循环行为?"} Q2 -->|是| REACT["用 react.NewAgent
本附录 §1/§2/§4"] Q2 -->|否| Q3{"需要多 Agent 协作?"} Q3 -->|调度模式| SUP["快速: ADK Supervisor
精细: Host MultiAgent
本附录 §6"] Q3 -->|流水线| PE["Plan-Execute
本附录 §7"] Q3 -->|复杂状态图| CUSTOM["自定义 Graph+State
本附录 §9"] Q3 -->|否| Q4{"需要浏览器/沙箱工具?"} Q4 -->|是| MANUS["参考 Manus Agent
本附录 §8"]

📇 本附录速记卡片

react.NewAgent({ToolCallingModel, ToolsConfig}) → Stream/Generate
react.WithMessageFuture() → 观察中间步骤(无需 Callback)
host.NewMultiAgent({Host, Specialists}) → 调度型多 Agent
自定义 Graph + State → Plan-Execute / Deer-Go

一、ReAct Agent 基础

📁 flow/agent/react/

📖 官方文档:https://www.cloudwego.io/zh/docs/eino/core_modules/flow_integration_components/react_agent_manual/

1.1 ReAct 是什么

ReAct(Reasoning + Acting)是 Agent 的核心循环模式:

用户输入 → ChatModel 思考 → 需要调 Tool?
├─ 是 → 执行 Tool → Tool 结果交还 ChatModel → 继续思考
└─ 否 → 输出最终答案

Eino 将这套循环封装为 react.NewAgent,一行创建,开箱即用。

1.2 最简示例:餐厅推荐

import (
"github.com/cloudwego/eino/flow/agent/react"
"github.com/cloudwego/eino/compose"
)
rAgent, err := react.NewAgent(ctx, &react.AgentConfig{
ToolCallingModel: arkModel,
ToolsConfig: compose.ToolsNodeConfig{
Tools: []tool.BaseTool{restaurantTool, dishTool},
},
})
// 流式调用(与 ChatModel.Stream 一样的 Recv+EOF 模式)
sr, _ := rAgent.Stream(ctx, []*schema.Message{
schema.SystemMessage("你是一个帮助用户推荐餐厅的助手..."),
schema.UserMessage("我在北京,推荐口味辣的菜,至少2家餐厅"),
})
defer sr.Close()
for {
msg, err := sr.Recv()
if errors.Is(err, io.EOF) { break }
fmt.Print(msg.Content)
}

💡 这与 入门笔记 第三节的 ChatModelAgent + Runner 功能等效,但 react.NewAgent 暴露了更多底层控制点。

1.3 两个重要扩展点

MessageModifier:在每轮 ReAct 循环中注入 System Prompt:

react.NewAgent(ctx, &react.AgentConfig{
MessageModifier: func(_ context.Context, input []*schema.Message) []*schema.Message {
return append([]*schema.Message{schema.SystemMessage(sys)}, input...)
},
})

StreamToolCallChecker:自定义 Tool 调用判断(某些模型不在第一个 chunk 返回 ToolCall):

toolCallChecker := func(ctx context.Context, sr *schema.StreamReader[*schema.Message]) (bool, error) {
defer sr.Close()
for {
msg, err := sr.Recv()
if errors.Is(err, io.EOF) { break }
if len(msg.ToolCalls) > 0 { return true, nil }
}
return false, nil
}

1.4 可视化调试:ExportGraph + Mermaid

anyG, opts := rAgent.ExportGraph()
gen := visualize.NewMermaidGenerator("flow/agent/react")
g := compose.NewGraph[[]*schema.Message, *schema.Message]()
g.AddGraphNode("react_agent", anyG, opts...)
g.AddEdge(compose.START, "react_agent")
g.AddEdge("react_agent", compose.END)
g.Compile(context.Background(), compose.WithGraphCompileCallbacks(gen))

二、Agentic ReAct Agent(Responses API 版)

📁 flow/agent/react/agentic/

2.1 核心差异点

维度基础 ReActAgentic ReAct
模型model.BaseChatModelmodel.AgenticModel
消息*schema.Message*schema.AgenticMessage
工具节点compose.NewToolNodecompose.NewAgenticToolsNode
分支判断检查 ToolCalls检查 ContentBlocks 中的 FunctionToolCall
服务端工具

2.2 关键创新:ToolReturnDirectly

config := &AgentConfig{
Model: am,
ToolsConfig: compose.ToolsNodeConfig{
Tools: []tool.BaseTool{summarizeTool, locationTool},
},
ToolReturnDirectly: map[string]struct{}{
"summarize_news": {}, // ← summarize_news 执行完直接结束
},
}

2.3 按 ContentBlock 类型分别处理

msg, _ := schema.ConcatAgenticMessages(msgs)
for _, block := range msg.ContentBlocks {
switch block.Type {
case schema.ContentBlockTypeReasoning:
fmt.Printf("[推理] %s\n", block.Reasoning.Text)
case schema.ContentBlockTypeServerToolCall:
fmt.Printf("[服务端工具] %s\n", block.ServerToolCall.Name)
case schema.ContentBlockTypeAssistantGenText:
fmt.Printf("[输出] %s\n", block.AssistantGenText.Text)
}
}

三、短期记忆(Memory)

📁 flow/agent/react/memory_example/

3.1 MemoryStore 接口

type MemoryStore interface {
Write(ctx, sessionID string, msgs []*schema.Message) error
Read(ctx, sessionID string) ([]*schema.Message, error)
Query(ctx, sessionID, text string, limit int) ([]*schema.Message, error)
}
实现存储介质适用场景
InMemoryStore进程内存开发/测试
RedisStoreRedis生产环境

3.2 多轮对话模式

store := memory.NewInMemoryStore()
sessionID := "session:demo"
// 每轮对话
prev, _ := store.Read(ctx, sessionID) // 恢复历史
eff := append(prev, schema.UserMessage(turn)) // 拼接新输入
sr, _ := agent.Stream(ctx, eff, msgFutureOpt) // 执行
_ = store.Write(ctx, sessionID, append(eff, produced...)) // 持久化

3.3 用 MessageFuture 观察中间步骤

msgFutureOpt, msgFuture := react.WithMessageFuture()
// 消费中间消息流
iter := msgFuture.GetMessageStreams()
for {
sr, ok, _ := iter.Next()
if !ok { break }
full, _ := schema.ConcatMessages(readAllChunks(sr))
fmt.Printf("中间消息: role=%s content=%s\n", full.Role, full.Content)
}

四、动态选项(Dynamic Option)

📁 flow/agent/react/dynamic_option_example/

4.1 痛点

ReAct Agent 在每轮迭代中使用相同的模型参数。但你可能希望第一轮开启思考模式,后续轮关闭思考。

4.2 核心机制:包装 ChatModel + ProcessState

type ChatModel struct {
Model model.BaseChatModel
GetOptionFunc OptionFunc // ← 根据 State 返回动态选项
}
func (d *ChatModel) Generate(ctx context.Context, input []*schema.Message, opts ...model.Option) (*schema.Message, error) {
var dynamicOpts []model.Option
compose.ProcessState[*State](ctx, func(_ context.Context, state *State) error {
dynamicOpts = d.GetOptionFunc(ctx, input, state)
state.Iteration++
return nil
})
return d.Model.Generate(ctx, input, append(dynamicOpts, opts...)...)
}

4.3 动态选项函数示例

func getDynamicOptions(ctx context.Context, input []*schema.Message, state *State) []model.Option {
if state.Iteration >= 1 {
// 第二轮开始:关闭思考,禁止 Tool 调用
return []model.Option{
ark.WithThinking(&arkModel.Thinking{Type: arkModel.ThinkingTypeDisabled}),
model.WithToolChoice(schema.ToolChoiceForbidden),
}
}
// 第一轮:允许 Tool 调用
return []model.Option{
model.WithToolChoice(schema.ToolChoiceAllowed),
model.WithTools(toolInfos),
}
}

五、未知工具处理(Unknown Tool Handler)

📁 flow/agent/react/unknown_tool_handler_example/

rAgent, _ := react.NewAgent(ctx, &react.AgentConfig{
ToolsConfig: compose.ToolsNodeConfig{
Tools: []tool.BaseTool{sumTool},
UnknownToolsHandler: func(ctx context.Context, name, input string) (string, error) {
return fmt.Sprintf(
"unknown tool: %s; try again with the correct tool name", name,
), nil
},
},
})

模型幻觉调用不存在的工具 → 不崩溃,返回提示 → 模型自纠错。


六、Multi-Agent:Host 模式

📁 flow/agent/multiagent/host/journal/

📖 官方文档:https://www.cloudwego.io/zh/docs/eino/core_modules/flow_integration_components/multi_agent_hosting/

6.1 概念

一个 Host(调度者) + 多个 Specialist(专家)

用户 → Host(分析意图)
├─ "写日记" → WriteJournalSpecialist
├─ "读日记" → ReadJournalSpecialist
└─ "查日记" → AnswerWithJournalSpecialist

6.2 完整实现

import "github.com/cloudwego/eino/flow/agent/multiagent/host"
h := &host.Host{ChatModel: chatModel, SystemPrompt: "..."}
hostMA, _ := host.NewMultiAgent(ctx, &host.MultiAgentConfig{
Host: *h,
Specialists: []*host.Specialist{writer, reader, answerer},
})
// 多轮对话
out, _ := hostMA.Stream(ctx, []*schema.Message{schema.UserMessage(input)},
host.WithAgentCallbacks(cb), // 可监听 HandOff 事件
)

6.3 与 ADK Supervisor 的对比

维度Host MultiAgent(Flow)Supervisor(ADK)
位置flow/agent/multiagent/hostadk/prebuilt/supervisor
调度方式Host ChatModel 决定派给谁Supervisor Agent 决定派给谁
抽象层级中低层(Compose Graph)高层(ADK 封装)
适用需要自定义 Specialist 结构快速构建多 Agent 系统

七、Multi-Agent:Plan-Execute 模式

📁 flow/agent/multiagent/plan_execute/

7.1 概念

三阶段协作模式:

Planner(规划者)→ Executor(执行者)⇄ Reviser(审查者)
输出"最终答案" → END

7.2 核心配置

config := &Config{
PlannerModel: deepSeekModel, // 规划者模型
ExecutorModel: arkModel, // 执行者模型(需支持 ToolCalling)
ReviserModel: deepSeekModel, // 审查者模型
ToolsConfig: compose.ToolsNodeConfig{Tools: toolsConfig},
MaxStep: 100,
}

💡 不同角色可以用不同的模型——Planner/Reviser 用便宜的推理模型,Executor 用支持 Tool Calling 的模型。


八、完整应用:Manus Agent

📁 flow/agent/manus/

8.1 概述

Manus Agent 展示了如何用 Compose Graph API 构建一个具备以下能力的 Agent:

  • 🖥️ 命令行执行:Docker 沙箱中运行 Python 代码
  • 🌐 浏览器操作:基于 Playwright 的网页浏览和交互
  • 🔍 搜索引擎:DuckDuckGo 集成
  • 👤 人类反馈:执行中断,等待用户确认后继续
  • 📊 可观测性:Langfuse + CozeLoop 双追踪

8.2 Interrupt 驱动的人类反馈循环

for {
result, err := agent.Invoke(ctx, input,
compose.WithCheckPointID("1"),
compose.WithRuntimeMaxSteps(20),
)
info, ok := compose.ExtractInterruptInfo(err)
if ok {
// 中断了——展示结果,等待用户确认
fmt.Print("Do you want to continue? (y/n): ")
// ... 读用户输入 ...
continue // 自动 Resume
}
fmt.Printf("[FinalResult]: %s", result)
break
}

8.3 工具生态

// 命令行工具(Docker 沙箱)
sandbox.NewDockerSandbox(ctx, &sandbox.Config{...})
// 浏览器工具
browseruse.NewBrowserUseTool(ctx, &browseruse.Config{...})
// 搜索引擎
duckduckgo.NewSearch(ctx, &duckduckgo.Config{...})

九、完整应用:Deer-Go(研究团队协作)

📁 flow/agent/deer-go/

参考:https://github.com/bytedance/deer-flow

9.1 概述

Deer-Go 是一个基于状态图的多 Agent 研究团队,模拟真实的研究协作流程。

9.2 核心机制:State 驱动的子图流转

每个子图执行完毕后,改写 state.Goto 指定下一个要执行的 Agent:

func agentHandOff(ctx context.Context, input string) (next string, err error) {
compose.ProcessState[*model.State](ctx, func(_ context.Context, state *model.State) error {
next = state.Goto
return nil
})
return next, nil
}
// 所有 Agent 节点共享同一个 Branch 函数
g.AddBranch(consts.Coordinator, compose.NewGraphBranch(agentHandOff, outMap))
g.AddBranch(consts.Planner, compose.NewGraphBranch(agentHandOff, outMap))

9.3 团队组成

Coordinator → BackgroundInvestigator → Planner → ResearchTeam
├─→ Researcher
├─→ Coder
└─→ Planner(迭代)
└─→ Reporter → Human → Coordinator

十、示例导航

目录主题核心知识点复杂度
react/ReAct Agent 基础react.NewAgent, Stream, ExportGraph
react/agentic/Agentic ReActGraph 自定义 ReAct, ToolReturnDirectly⭐⭐⭐
react/memory_example/短期记忆MemoryStore 接口, MessageFuture⭐⭐
react/dynamic_option_example/动态选项ChatModel 包装, ProcessState⭐⭐⭐
react/unknown_tool_handler_example/未知工具UnknownToolsHandler
multiagent/host/journal/Host Multi-AgentHost + Specialist, HandOff 回调⭐⭐
multiagent/plan_execute/Plan-ExecutePlanner→Executor⇄Reviser⭐⭐⭐
manus/Manus AgentDocker 沙箱, 浏览器, Interrupt+Resume⭐⭐⭐⭐
deer-go/Deer-Go 研究团队状态图流转, 多子图协作, Goto 驱动⭐⭐⭐⭐

常用 import 路径

// ReAct Agent
"github.com/cloudwego/eino/flow/agent/react" // react.NewAgent, WithMessageFuture
// Multi-Agent
"github.com/cloudwego/eino/flow/agent/multiagent/host" // host.NewMultiAgent, Host, Specialist
// Compose 底层
"github.com/cloudwego/eino/compose" // Graph, Branch, ProcessState, ToolNode
"github.com/cloudwego/eino/schema" // Message, AgenticMessage, ToolInfo
// Callbacks
"github.com/cloudwego/eino/callbacks" // Handler, HandlerBuilder
"github.com/cloudwego/eino/utils/callbacks" // NewHandlerHelper

📇 本附录速记卡片

Flow 模块核心方法:
react.NewAgent({ToolCallingModel, ToolsConfig})
host.NewMultiAgent({Host, Specialists})
compose.NewGraphBranch(fn, outMap)
compose.ProcessState[T](ctx, fn) — 读写 Graph State
选型:标准→ADK | 自定义循环→react | 多Agent调度→host | 状态图→Graph+State

📂 源码仓库github.com/cloudwego/eino-examples

📖 继续阅读


感谢您的阅读!如果可以,给俺点些关注吧~

Eino学习笔记 —— 附录1

周一 7月 20 2026
2362 · 14 分钟
封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00