news 2026/10/24 11:08:12

21|Agent 与 Graph 结合:自主决策,确定性执行 - eino教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
21|Agent 与 Graph 结合:自主决策,确定性执行 - eino教程

21|Agent 与 Graph 结合:自主决策,确定性执行

《Eino 实战:用 Go 构建 AI 应用与智能体》· 第 21 篇
关键词:GraphTool、AgentAsTool、流程复用、职责边界、确定性
前置条件:已完成 16|从流程到 Agent 与 11|Tool 与 ToolsNode。

前几篇我们分别用 Graph 编排流程、用 Agent 做自主决策。现实项目里两者往往都要:流程需要稳定可预测,但入口又想灵活。

直觉做法是把 Agent 塞进 Graph 当节点。第一篇引用的官方辨析明确指出,这样做不优雅——Agent 需要多轮交互、长时记忆和异步输出,而 Graph 节点期待确定性的输入输出。

正确的结合方向是反过来的:把 Graph 封装成 Agent 的工具。


二、为什么不是“Agent 作为节点”

先把“反向方案”为什么不合适说清楚,这有助于理解边界。

特征Graph 节点Agent
输入上游节点的输出结构化输入加上会话历史
输出确定的结构化值异步的全过程事件
执行同步、可预期多轮、路径不定

把 Agent 当作 Graph 节点,会同时踩三个坑:

  1. 输入不完整。Agent 依赖历史,而 Graph 节点只拿到上游输出。
  2. 输出不好用。后续节点拿到的是一串事件,而不是一个确定的值。
  3. 阻塞主流程。Agent 的多轮交互会卡住本应快速推进的编排。

官方文档的结论很直接:Graph 中需要的是一个纯粹的 LLM 节点(做好意图识别或内容生成),而不是完整的 Agent。如果确实需要 Agent 的自主性,更好的做法是给 Agent 加前置/后置处理,而不是把它塞进静态图里。


三、Graph 与 Tool 的相似性

反过来看,为什么“Graph 作为工具”就自然得多?

维度GraphTool
输入结构化数据结构化数据(JSON 参数)
交付物最终结果最终结果
状态单次执行单次执行
同步性同步对模型而言是同步

两者几乎是同一个形状。因此封装起来几乎没有阻抗:Graph 负责确定性的执行,Tool 接口负责与 Agent 对接。

网上很流行的一张关系图概括了这一点:

Agent:理解目标、决定何时行动 └─ 调用 Tool └─ Tool 内部封装 Graph └─ Graph 按预定步骤确定执行 └─ 返回确定性结果给 Agent

四、完整示例

下面这段程序把一个知识问答流程封装成工具,不访问外部服务:

packagemainimport("context""encoding/json""fmt""log""strings""github.com/cloudwego/eino/components/tool""github.com/cloudwego/eino/compose""github.com/cloudwego/eino/schema")// ---- 一个确定性的知识问答流程:先整理资料,再生成回答 ----funcbuildKnowledgeGraph()(compose.Runnable[string,string],error){g:=compose.NewGraph[string,string]()// 节点 1:检索(真实项目接 Retriever,这里用固定资料模拟)。retrieve:=compose.InvokableLambda(func(_context.Context,_string)(string,error){return"资料:打印机离线时,先检查网线,再确认网段。",nil})// 节点 2:生成回答(真实项目接 ChatModel,这里用字符串处理模拟)。answer:=compose.InvokableLambda(func(_context.Context,ctxTextstring)(string,error){return"根据资料,"+strings.TrimPrefix(ctxText,"资料:"),nil})iferr:=g.AddLambdaNode("retrieve",retrieve);err!=nil{returnnil,err}iferr:=g.AddLambdaNode("answer",answer);err!=nil{returnnil,err}_=g.AddEdge(compose.START,"retrieve")_=g.AddEdge("retrieve","answer")_=g.AddEdge("answer",compose.END)returng.Compile(context.Background())}// ---- 把图封装为工具 ----typegraphToolstruct{namestringdescstringrun compose.Runnable[string,string]}func(t*graphTool)Info(_context.Context)(*schema.ToolInfo,error){return&schema.ToolInfo{Name:t.name,Desc:t.desc,ParamsOneOf:schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{"query":{Type:schema.String,Desc:"用户问题"},}),},nil}func(t*graphTool)InvokableRun(ctx context.Context,argsJSONstring,_...tool.Option)(string,error){varargsstruct{Querystring`json:"query"`}iferr:=json.Unmarshal([]byte(argsJSON),&args);err!=nil{return"",fmt.Errorf("参数解析失败: %w",err)}// 图在工具内部以确定性方式执行,输入输出都是普通值。returnt.run.Invoke(ctx,args.Query)}funcmain(){iferr:=run();err!=nil{log.Fatal(err)}}funcrun()error{ctx:=context.Background()graph,err:=buildKnowledgeGraph()iferr!=nil{returnfmt.Errorf("构建图失败: %w",err)}gt:=&graphTool{name:"knowledge_qa",desc:"基于内部知识库回答问题",run:graph}// 编译期断言:这个类型满足 Eino 的工具接口,可直接交给 Agent。var_tool.InvokableTool=gt info,err:=gt.Info(ctx)iferr!=nil{returnerr}fmt.Printf("工具名=%s 描述=%s\n",info.Name,info.Desc)out,err:=gt.InvokableRun(ctx,`{"query":"打印机离线怎么办"}`)iferr!=nil{returnerr}fmt.Println("工具输出:",out)returnnil}

实机输出:

工具名=knowledge_qa 描述=基于内部知识库回答问题 工具输出: 根据资料,打印机离线时,先检查网线,再确认网段。

关键点在于var _ tool.InvokableTool = gt这行编译期断言:只要类型满足接口,它就能像第 11 篇的任何工具一样交给ToolsNode或ChatModelAgent。对 Agent 而言,这个工具背后是图还是函数,它并不关心。


五、官方封装方式

上面手写的graphTool有教学价值,但每个项目重复写一遍并不划算。Eino 官方在示例仓库中提供了graphtool包,思路正是一样的:把任意 Graph 转成InvokableTool。

// 官方 graphtool 的签名(来自 eino-examples)funcNewInvokableGraphTool[I,O any](graph compose.Graph[I,O],name,descstring,opts...compose.GraphCompileOption,)(*InvokableGraphTool[I,O],error)

它内部处理了这几件事:

  1. 由输入类型推导工具的 JSON Schema。
  2. 把模型给的 JSON 参数反序列化成I。
  3. 编译并执行图。
  4. 处理中断(图内也可能有 HITL 点)。
  5. 把输出O序列化成字符串返回。

生产项目建议直接用官方实现,而不是自己造一遍。参考:

https://github.com/cloudwego/eino-examples/tree/main/adk/common/tool/graphtool

官方还提供了三个典型示例:Chain 文档摘要、Graph 多源研究、Workflow 订单处理——覆盖了三种编排方式封成工具的场景。


六、这套组合的价值在哪

好处说明
复用现有流程已经调好的 RAG 流程、数据处理管道,不必为 Agent 重写
保证关键步骤确定授权、计算、落库等步骤在图内按固定顺序执行
缩小暴露面Agent 只看到一个工具,而不是内部十几个节点
便于测试图可以脱离 Agent 单独测试,各测各的

一句话概括:让 Agent 决定“做什么”,让 Graph 决定“怎么做”。

这个分工也回应了第一篇的一句话:模型可以提出行动,但关键业务怎么执行,应该由可信代码控制。


七、边界与注意事项

1. 图内不要依赖对话历史。
图的输入是结构化参数。需要历史信息时,应由 Agent 在调用工具时把相关内容整理进参数,而不是让图自己去猜。

2. 输入输出要保持可序列化。
工具的入参是 JSON 字符串,出参也必须是字符串。复杂的结构要设计好序列化格式,并考虑长度限制。

3. 图内的中断需要透传。
如果图内含审批点(第 20 篇),封装时要确保中断能正确传播到外层,否则 Agent 会“卡住”而用户看不到确认提示。官方graphtool已处理这一点,自己实现时务必注意。

4. 工具描述决定 Agent 会不会选它。
和所有工具一样,描述要写清使用时机。图内部再精巧,描述含糊也会被模型忽略。

5. 鉴权仍在最内层。
图封装成工具后,权限校验依然要在图内部或具体工具内完成。“藏在图里”不是安全措施。


八、什么时候该拆、什么时候该合

情况建议
流程固定、需要复用封装为工具,交给 Agent 调用
流程需要 Agent 逐步交互不要把 Agent 塞进图;改为给 Agent 加处理逻辑
只是想做一次意图识别或生成用 LLM 节点,不需要完整 Agent
关键步骤必须按顺序且可审计放进图内,作为工具暴露

判断标准是**“这一步是否需要反复交互”**。需要交互的交给 Agent,一次完成且结果确定的封装成工具。


九、小结

  • 把 Agent 当作 Graph 节点会造成输入不完整、输出不好用、阻塞主流程三个问题。
  • Graph 与 Tool 在输入、交付物、状态、同步性上高度相似,天然适合互相封装。
  • 用Info+InvokableRun就能把图变成工具;官方graphtool包已提供成熟实现。
  • Agent 决定做什么,Graph 决定怎么做。
  • 图内不要依赖对话历史;注意序列化、长度限制和中断透传。
  • 鉴权仍须在最内层完成,封装不构成安全边界。

第四篇《Agent 开发》到此完成。下一篇进入第五篇,讨论多智能体协作。


参考资料与版本说明

资料核对日期为2026 年 10 月 9 日:

  1. Agent 还是 Graph?AI 应用路线辨析
  2. Eino 官方示例:graphtool
  3. Eino 主仓库

本文示例按Eino v0.9.21编写,图内节点使用自定义 Lambda(不访问外部服务),已实机运行,正文输出为真实结果。官方graphtool包的签名与职责依据示例仓库文档整理,未在本篇实机运行。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 11:07:44

从模糊标题到可执行方案:以rea为例的响应式、实时分析与资源预估实践

1. 从“rea”这个标题说起:一个被低估的缩写背后藏着什么第一次看到“rea”这个标题的时候,我脑子里蹦出来的第一反应是——这大概率又是一个被缩写玩坏了的项目名。做技术的人都有个毛病,喜欢把长名字砍成三四个字母,仿佛名字越短…

作者头像 李华
网站建设 2026/10/24 11:02:48

DPU方案深度拆解:从硬件规格到裸金属与虚拟化落地

简介:BlueField-2 DPU解决方案官方资料,系统性梳理了数据中心从以CPU为中心到向DPU卸载的演进路径,适合云计算、网络虚拟化、存储加速与裸金属架构的工程师快速建立整体认知。资源为单份PDF文件,共4.7MB,体量精炼便于通…

作者头像 李华
网站建设 2026/10/24 10:43:06

Matlab降维工具箱:PCA/t-SNE选型与交叉验证避坑

简介:Matlab数据降维工具箱面向科研人员、高校师生和算法开发者,适合高维数据特征压缩、可视化探索、分类聚类前处理以及多种降维方法横向对比。内容覆盖PCA、LDA、ICA、MDS等经典线性方法,也包含Isomap、LLE、Laplacian、LTSA、DiffusionMap…

作者头像 李华
网站建设 2026/10/24 10:43:03

Azure Pipelines配置全攻略:从YAML到自托管代理的CI/CD避坑实践

简介:这是一份面向 Azure DevOps 用户的 Azure Pipelines 官方文档操作手册,适合需要搭建持续集成与持续交付流程的开发、运维及 DevOps 工程师阅读。内容系统覆盖核心概念与落地操作:从代理、条件、表达式、环境、作业、阶段、任务、模板到触…

作者头像 李华
网站建设 2026/10/24 10:20:20

SylixOS深度解析:硬实时与自主可控的大型实时操作系统

干了这么多年嵌入式,接触过的实时系统从早期的裸机调度到后来的各种RTOS,再到嵌入式Linux,说实话,每个方案都有自己的一亩三分地,但又都差点意思。搞工业控制、智能电网或者航空航天相关的朋友应该深有体会&#xff1a…

作者头像 李华
网站建设 2026/10/24 10:06:54

ASP网页游戏源码解析:VBScript+Session实现回合制对战

简介:本资源是基于ASP技术开发的《新华山论剑》网页游戏完整源代码包,面向Web开发初学者、ASP编程学习者及传统Web游戏研究者,提供可运行、可调试的实战级教学案例。压缩包为ZIP格式,大小5.66MB,虽文件总数未提供&…

作者头像 李华