资讯动态

16|从流程到 Agent:理解 ChatModelAgent 与 ReAct - eino教程

发布时间:2026/10/20 11:57:54 来源:尧图企业网站定制
16从流程到 Agent理解 ChatModelAgent 与 ReAct《Eino 实战用 Go 构建 AI 应用与智能体》· 第 16 篇关键词ADK、ChatModelAgent、ReAct、Runner、AgentEvent、工具反馈前置条件已完成 11Tool 与 ToolsNode 与 07Graph 实战。第 11 篇提到过一个麻烦要让模型“先查工具、看结果、再决定下一步”用 Graph 手写这个循环很啰嗦——需要模型节点、工具节点、分支回退还得处理边界情况。这类“模型反复决策”的场景正是 ADKAgent Development Kit要解决的。它把 ReAct 循环封装起来你只需要描述用什么模型、给什么工具、说什么规则。一、Agent 与 Graph 的区别先回到第一篇的区分现在可以讲得更具体了GraphAgent谁决定下一步开发者分支函数、边模型路径编译期可枚举运行时不可预测交付物最终结果全过程事件适合固定流程开放式任务一个系统有聊天框不代表它是 Agent。判据是下一步行动由谁决定。如果是你在代码里写死的那就是 Graph。二、ChatModelAgent 的四个要素官方文档给出的定义很精炼ChatModelAgent 以 ChatModel 作为决策器、以 Tools 作为行动空间、以工具反馈和历史记录作为下一轮决策上下文的 ReAct Agent。拆开看四个要素缺一不可要素作用缺失的后果ChatModel决策器每轮判断下一步做什么无法推理Tools行动空间定义能采取的行动只能空谈无法执行反馈工具结果把执行结果送回上下文无法根据真实结果修正历史累积上下文保留推理轨迹与工具结果每轮都从零开始关键特征是累积上下文驱动的渐进式决策每一轮模型看到的不是孤立问题而是从开始到现在的完整求解过程。注意ChatModelAgent 不是一次模型调用而是一次可持续推进的求解过程。这句话决定了它的成本模型——一次Run可能触发多次模型调用。三、最小可用配置agent,err:adk.NewChatModelAgent(ctx,adk.ChatModelAgentConfig{Name:ticket-assistant,Description:查询工单状态的助手,Instruction:你是工单助手需要时调用工具查询。,Model:chatModel,ToolsConfig:adk.ToolsConfig{ToolsNodeConfig:compose.ToolsNodeConfig{Tools:[]tool.BaseTool{ticketTool},},},})字段含义字段说明NameAgent 名称。作为子 Agent 被调用时必填Description能力描述帮助其他 Agent 判断是否该转交任务Instruction系统提示词。支持用会话变量填充占位符Model决策模型。使用工具时模型必须支持model.WithToolsToolsConfig工具配置复用compose.ToolsNodeConfigMaxIterations默认20。超过上限时 Agent 会以 error 结束而不是无限循环下去——这是保护机制也是排查“为什么突然报错”时该先看的地方。四、Runner执行入口构建好 Agent 后通过 Runner 运行runner:adk.NewRunner(ctx,adk.RunnerConfig{Agent:agent,EnableStreaming:false,})iter:runner.Query(ctx,工单 T-1001 现在是什么状态)for{event,ok:iter.Next()if!ok{break}// 处理 event}只有经过 Runner才能获得事件流、检查点与中断恢复等运行期能力。直接调用 Agent 的Run拿不到这些更准确地说Run也返回AsyncIterator但EnableStreaming、CheckPointStore等运行配置由 Runner 统一管理。Query是Run的便捷方法把单个字符串包装成用户消息。Run接受完整的消息列表。五、完整示例看清 ReAct 循环下面这段程序用一个模拟模型跑通完整的“模型 → 工具 → 模型”循环不访问网络packagemainimport(contextfmtloggithub.com/cloudwego/eino/adkgithub.com/cloudwego/eino/components/modelgithub.com/cloudwego/eino/components/toolgithub.com/cloudwego/eino/components/tool/utilsgithub.com/cloudwego/eino/composegithub.com/cloudwego/eino/schema)typeTicketReqstruct{TicketIDstringjson:ticket_id jsonschema:description工单编号}// mockModel 模拟两轮决策先请求调用工具看到工具结果后给出最终回答。typemockModelstruct{}func(m*mockModel)Generate(_context.Context,in[]*schema.Message,_...model.Option)(*schema.Message,error){for_,msg:rangein{ifmsg.Roleschema.Tool{returnschema.AssistantMessage(工单 T-1001 已分派给网络支持组。,nil),nil}}returnschema.AssistantMessage(,[]schema.ToolCall{{ID:call_1,Type:function,Function:schema.FunctionCall{Name:get_ticket,Arguments:{ticket_id:T-1001},},}}),nil}func(m*mockModel)Stream(ctx context.Context,in[]*schema.Message,opts...model.Option)(*schema.StreamReader[*schema.Message],error){msg,err:m.Generate(ctx,in,opts...)iferr!nil{returnnil,err}sr,sw:schema.Pipe[*schema.Message](1)gofunc(){defersw.Close()sw.Send(msg,nil)}()returnsr,nil}func(m*mockModel)WithTools([]*schema.ToolInfo)(model.ToolCallingChatModel,error){returnm,nil}funcmain(){iferr:run();err!nil{log.Fatal(err)}}funcrun()error{ctx:context.Background()ticketTool,err:utils.InferTool[*TicketReq,string](get_ticket,查询工单状态,func(_context.Context,req*TicketReq)(string,error){return工单 req.TicketID 状态已分派处理人网络支持组,nil})iferr!nil{returnerr}agent,err:adk.NewChatModelAgent(ctx,adk.ChatModelAgentConfig{Name:ticket-assistant,Description:查询工单状态的助手,Instruction:你是工单助手需要时调用工具查询。,Model:mockModel{},ToolsConfig:adk.ToolsConfig{ToolsNodeConfig:compose.ToolsNodeConfig{Tools:[]tool.BaseTool{ticketTool},},},})iferr!nil{returnfmt.Errorf(创建 Agent 失败: %w,err)}runner:adk.NewRunner(ctx,adk.RunnerConfig{Agent:agent,EnableStreaming:false})iter:runner.Query(ctx,工单 T-1001 现在是什么状态)n:0for{event,ok:iter.Next()if!ok{break}nifevent.Err!nil{fmt.Printf(event %d: ERR%v\n,n,event.Err)continue}ifmv:event.Output.MessageOutput;mv!nilmv.Message!nil{// mv.Role 表示这条消息来自模型还是工具mv.ToolName 在工具结果时非空。fmt.Printf(event %d: role%-9s tool%-10s content%q tool_calls%d\n,n,mv.Role,mv.ToolName,mv.Message.Content,len(mv.Message.ToolCalls))}ifevent.Action!nilevent.Action.Exit{fmt.Printf(event %d: 动作退出\n,n)}}fmt.Println(事件总数:,n)returnnil}实机输出event 1: roleassistant tool content tool_calls1 event 2: roletool toolget_ticket content工单 T-1001 状态已分派处理人网络支持组 tool_calls0 event 3: roleassistant tool content工单 T-1001 已分派给网络支持组。 tool_calls0 事件总数: 3这三行就是 ReAct 循环的完整形状事件 1模型输出为空、tool_calls1——它没有直接回答而是请求调用get_ticket。事件 2角色是tooltool_name是get_ticket——工具执行结果回到流程。事件 3模型基于工具结果给出最终回答没有新的工具调用循环结束。对照第 11 篇手写 Graph 的版本可以看出这套循环现在由框架管理模型决策、工具执行、结果回填、再次决策都不需要你写分支逻辑。你要做的只是定义工具和规则。六、AgentEvent 里有什么每次iter.Next()拿到一个AgentEvent字段含义AgentName产生事件的 Agent 名称Output.MessageOutput消息输出模型输出或工具结果Action动作如退出、中断、转交Err错误RunPath从根 Agent 到当前事件的执行路径MessageOutput上有几个字段很关键字段用法Message非流式时的完整消息MessageStream流式时的读取器Role这条消息来自模型assistant还是工具toolToolName工具结果时非空流式下这是识别来源的唯一方式务必处理event.Err。事件流可能在中途携带错误忽略它会让失败看起来像“正常结束但没输出”。七、关于事件流的两个常见误解误解一事件流等于模型的完整思维链。不是。事件反映的是执行步骤——模型输出、工具调用、工具结果、动作。模型内部如何得出这个结果内部的推理 token事件流并不展示。支持深度思考的模型会把推理内容放在消息的ReasoningContent字段那是另一回事。误解二事件流越长说明 Agent 越聪明。恰恰相反。事件多意味着多轮往返直接对应更多的模型调用、更长的耗时和更高的成本。事件数量是成本指标不是能力指标。八、什么时候该用 Agent场景建议步骤固定、可提前枚举Graph / Chain步骤依赖运行时结果无法提前写死ChatModelAgent需要多轮试错、根据反馈修正ChatModelAgent单次生成、无需外部调用直接用 ChatModel判断标准很简单如果你能用一段流程图把步骤画完就不需要 Agent。只有当“下一步做什么”真的取决于运行结果时自主决策才带来价值。反过来说用了 Agent 并不意味着放弃控制关键业务操作仍应通过工具内部鉴权第 11 篇。不可逆操作可以要求人工确认第 20 篇。迭代次数有上限MaxIterations不会无限跑下去。九、常见问题Agent 不调用工具直接回答检查Instruction是否说明了工具的使用时机以及模型是否支持WithTools。工具描述含糊时第 11 篇模型难以判断何时使用。报错说迭代次数超限默认上限 20。可能是模型陷入循环也可能是工具持续返回让模型“还想再查”的结果。先用事件流看清发生了什么再决定是放宽上限还是修正工具。event.Output为空指针不同事件类型携带的内容不同。访问前先判空特别是Output、MessageOutput和Message三层。流式下拿不到内容流式事件的内容在MessageStream里需要Recv读取。另外要先SetAutomaticClose或自行Close避免泄漏。同样的问题每次工具调用次数不同这是自主决策的正常表现。用事件流观察典型路径并关注成本上限。想让 Agent 记住上一次对话Agent 自身不维护跨请求记忆。需要把历史消息传给Run或使用会话机制第 18 篇。十、小结Agent 与 Graph 的分界在于下一步由谁决定模型还是开发者。ChatModelAgent四要素决策器、行动空间、反馈、累积上下文缺一不可。它是一次可持续推进的求解过程一次运行可能触发多次模型调用。Runner是执行入口只有经过它才能获得事件流与运行期能力。事件流展示的是执行步骤不等于模型的完整思维链。MaxIterations默认 20是防失控的保护不是可忽略的配置。下一篇《Runner 与事件流看见 Agent 的执行过程》我们系统地消费事件为交互界面和诊断提供依据。参考资料与版本说明资料核对日期为2026 年 10 月 9 日五分钟上手 Eino ADKEino ADK 概述Agent 还是 GraphAI 应用路线辨析Eino 主仓库本文示例按Eino v0.9.21编写使用模拟模型不访问网络已实机运行正文事件流为真实输出。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑