96SEO 2026-08-10 05:41 35
使用者痛点:手动搭建 compose 图需要写大量样板代码。调试时还要在节点与边之间来回切换,导致开发效率低下。

Eino 底层使用 compose 包搭图——你手动加节点、连边、配分支、编译、运行。强大,但代码量不小,话说回来,
ADK 是建在 compose 之上的高层封装目标是:只需配置就能建 Agent。不用关心图的结构,包方法是 github.com/cloudwego/eino/adk。其实,
ADK 和 compose 的关系。类似 Web 框架和 HTTP 库的关系:底层是同一套机制,上层帮你省掉重复的“建图 → 编译 → 运行”三步。
ChatModelAgent 是 ADK 里使用最频繁的类型。说到主要原因,配置一个模型,可选配工具,剩下的 ADK 自动处理.
// eino-examples/adk/helloworld/helloworld.go
agent,err := adk.NewChatModelAgent(ctx,&adk.ChatModelAgentConfig{
至于Name,"hello_agent",Description: "A friendly greeting assistant",Instruction: "You are a friendly assistant. Please respond in a warm tone."。Model: model,})
内部结构:
使用者输入 → → ChatModel → 输出
# 只调用一次模型,不循环
User Pain Point:自己实现 ReAct 循环需要处理工具调用返回值、上下文维护还有最大迭代次数等细节,容易出错且代码冗长。
给 ToolsConfig 传工具,ChatModelAgent 自动升级为 ReAct Agent:
// eino-examples/adk/intro/chatmodel/subagents/agent.go
_,err := adk.NewChatModelAgent(ctx,&adk.ChatModelAgentConfig{
再看Name,"BookRecommender",Description: "An agent that can recommend books"。Instruction: `You are an expert book recommender. Use "search_book" to find books.`,Model: model.NewChatModel,ToolsConfig: adk.ToolsConfig{
ToolsNodeConfig: compose.ToolsNodeConfig{
从Tools来看,tool.BaseTool{NewBookRecommender,NewAskForClarificationTool},},},})
↓ ChatModel
使用者输入 → 是否需要工具?├─ 是 → ToolsNode → 回到 ChatModel
└─ 否 → 输出结果
循环最多 MaxIterations 次
*两种模式切换全自动*:
User Pain Point: 在实际项目中,需要统一管理流式输出、断点持久化还有恢复逻辑;如果自行实现,这些细节往往散落在业务代码里难以维护。
Agent 本身只负责执行逻辑。Runner 是执行入口,它负责生命周期管理:启动、流式输出、断点持久化与恢复。
// eino-examples/adk/intro/chatmodel/chatmodel.go
runner := adk.NewRunner(ctx。adk.RunnerConfig{
EnableStreaming: true,Agent: a,CheckPointStore: store.NewInMemoryStore,})
iter := runner.Query)
for {
event,ok := iter.Next
if!ok { break }
if event.Err!= nil { log.Fatal }
prints.Event
}
`iter.Next` 每次返回一个 AgentEvent{}
alert.Output.MessageOutput: 模型输出或工具结果 alert.Action: 特殊动作 alert.Err: 错误 `runner.Query` 接收字符串,会自动包装成 `UserMessage`;`runner.Run` 接收 `Message`,适合多轮对话场景。
User Pain Point: 业务交互中经常出现“使用者信息不足,需要等待使用者补充”的场景。如果没有统一的中断与恢复机制。 就只能把状态序列化写到业务层,导致代码耦合度升高。
ADK 的中断机制允许一个工具"在执行中途暂停整个 Agent,等待使用者输入后继续".
The tool `ask_for_clarification` demonstrates this:
func NewAskForClarificationTool tool.InvokableTool {
t,_ := utils.InferOptionableTool(
"ask_for_clarification","Call this when user's request is ambiguous.",func {
o := tool.GetImplSpecificOptions
if o.NewInput == nil {
// 没有使用者回复 → 触发中断,把问题文本作为 payload
return "",compose.NewInterruptAndRerunErr
}
// 有使用者回复 → 继续执行。返回使用者答案
return *o.NewInput,nil
})
return t
}
① Agent 调用工具
② 工具返回 compose.NewInterruptAndRerunErr
③ Runner 检测到中断 → 状态存入 CheckPointStore → 事件流结束
④ 使用者看到问题并输入答案
⑤ 调用 runner.Resume,注入使用者答案,从断点继续
The resume call:
// eino‑examples/adk/intro/chatmodel/chatmodel.go iter,err := runner.Resume(ctx,"",adk.WithToolOptions})) *关键点*的观点是,
- `CheckPointID` 把一次对话绑定为唯一标识;`Query` 时创建,`Resume` 时读取。
- `CheckPointStore` 在两次调用之间持久化状态——示例里使用内存 Map,生产环境可换成 Redis / MySQL 等持久化方案。
五、Custom Agent:从头实现 Agent 接口
If built‑in `ChatModelAgent` cannot satisfy your needs—比如需要混合多个模型、自定义流控或注入外部状态——直接实现 `Agent` 接口即可。
go // adk/interface.go type Agent interface { Name string Description string Run(ctx context.Context,input *AgentInput,options ...AgentRunOption) *AsyncIterator } **最小实现示例**(源码 `adk/intro/custom/myagent.go`): go type MyAgent struct {} func Name string { return "MyAgent" } func Description string { return "My custom agent" } func Run( ctx context.Context。input *adk.AgentInput,opts ...adk.AgentRunOption,) *adk.AsyncIterator { iter,gen := adk.NewAsyncIteratorPair go func { defer func { if e := recover;e,= nil { gen.Send}) } gen.Close // 必须 Close,否则 iter.Next 永远阻塞 } // 这里可以放任意业务逻辑——调模型、查 DB、调 API…,gen.Send(&adk.AgentEvent{ 说到Output,&adk.AgentOutput{ MessageOutput: &adk.MessageVariant{ Message: &schema.Message{Role: schema.Assistant,Content: "hello world"},Role: schema.Assistant。},},}) } return iter } 使用方式和 `ChatModelAgent` 完全相同: go runner := adk.NewRunner **关键点**:ADK 不关心内部实现,只要遵守接口并通过 `AsyncIterator` 异步推送 `AgentEvent` 并最终调用 `gen.Close` 即可。六、三种类型怎么选
ChatModelAgent ChatModelAgent Custom Agent 内部结构 单条 chain 自动 ReAct 循环 完全自定义代码 实现成本 极低,仅配置模型 略增,只需添加 ToolsConfig 最高。需要自行实现接口并处理所有细节 是否支持 中断 / 恢复 内置支持 内置支持 自行集成 CheckPointStore 与 Interrupt 逻辑 还有一种 ` 适用场景 问答 / 摘要 / 翻译 等单轮任务 需要调用外部工具或搜索 / 数据库查询等多轮任务 混合多模型、自定义流控、多源数据聚合等高级需求 TypedChatModelAgent`,专为原生支持工具调用的模型设计——模型内部自行完成工具调用,Eino 只做一次请求,不跑外部 ReAct 循环。一般场景直接使用默认 `ChatModelAgent` 即可。话说回来,七、完整代码:从零到可运行
"github.com/cloudwego/eino/adk" "github.com/cloudwego/eino-ext/components/model/openai")
func main { ctx := context.Background
// ★ 初始化模型 ★ m。_ := openai.NewChatModel(ctx,&其实,openai.ChatModelConfig{ APIKey : os.Getenv,Model : os.Getenv。BaseURL : os.Getenv,}) // ★ 创建 Agent ★ agent,_ := adk.NewChatModelAgent(ctx,&adk.ChatModelAgentConfig{ Name : "demo_agent",Description : "A demo agent",Instruction : "You are a helpful assistant.",Model : m。}) // ★ 创建 Runner ★ runner := adk.NewRunner(ctx,adk.RunnerConfig{ Agent : agent,EnableStreaming : true,// 若需持久化,可替换为 RedisStore / MySQLStore…CheckPointStore : store.NewInMemoryStore。}) // ★ 执行查询并消费事件流 ★ iter := runner.Query for { ev,ok := iter.Next if!ok { break } if ev.Err!怎么说呢,= nil { log.Fatal } if msg。err := ev.Output.MessageOutput.GetMessage;err == nil { fmt.Println } }}
五步走 1️⃣ 初始化模型 2️⃣ 创建 Agent 3️⃣ 创建 Runner 4️⃣ 调用 Query 5️⃣ 消费事件流。整个过程无需手工绘制图谱。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback