Eino学习笔记 —— Agentic 进阶 - MuxiaoWF跳到主要内容

Eino学习笔记 —— Agentic 进阶

Eino学习笔记 —— Agentic 高级功能

周一 7月 20 2026
1988 字 · 11 分钟

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

Eino Agentic 高级功能指南

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

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

📁 代码来源:

  • adk/agentic/research_assistant/ — AgenticModel + AgenticMessage 全功能研究助手
  • adk/agentic/retry_max_output_tokens/ — 输出截断自动重试

📖 前置知识:本指南假设你已经掌握 入门笔记 中一到五节的内容。


速览:ChatModel → AgenticModel 类型映射表(先看这里!)

在深入细节之前,先把核心映射记住——Agentic 就是所有类型名字加 Typed、所有 Message 换成 AgenticMessage:

普通版(Chat Completions)Agentic 版(Responses API)
openai.NewChatModel()agenticopenai.New() / agenticark.New()
schema.UserMessage("...")schema.UserAgenticMessage("...")
adk.NewChatModelAgent(...)adk.NewTypedChatModelAgent[*schema.AgenticMessage](...)
adk.NewRunner(...)adk.NewTypedRunner[*schema.AgenticMessage](...)
event.Output.MessageOutput.GetMessage()adk.TypedGetMessage(event)
adk.ChatModelAgentMiddlewareadk.TypedChatModelAgentMiddleware[*schema.AgenticMessage]
adk.ModelRetryConfigadk.TypedModelRetryConfig[*schema.AgenticMessage]
filesystem.New(...)filesystem.NewTyped[*schema.AgenticMessage](...)

🧠 一句话总结:Agentic 系列是 Eino 为 Responses API 设计的完整封装——用 AgenticModel 替代 ChatModel,用 AgenticMessage 替代 Message,其余概念(Agent / Runner / Middleware / Tool)的用法保持一致,但全部使用 Typed 泛型变体


背景:Chat Completions API → Responses API

入门笔记 中,所有代码都基于 Chat Completions APIChatModel + *schema.Message)。这是 OpenAI 2022 年推出的 API 形态。

但从 2025 年起,主流模型厂商开始推 Responses API,这是新一代 API 形态。两者的核心区别:

维度Chat Completions APIResponses API
消息类型*schema.Message(单一角色+内容)*schema.AgenticMessage(含 ContentBlocks)
模型接口einoModel.ChatModeleinoModel.AgenticModel
Agent 类型adk.NewChatModelAgentadk.NewTypedChatModelAgent[*schema.AgenticMessage]
Runner 类型adk.NewRunneradk.NewTypedRunner[*schema.AgenticMessage]
一次调用返回一条文本回复多个有序结构化事件(推理→工具调用→再推理→文本)
服务端工具❌ 全在客户端执行✅ 模型厂商侧直接执行(如 web_search)
输出截断检测无标准信号status=incomplete + reason=max_output_tokens

一、核心概念:AgenticMessage 与 ContentBlock

1.1 为什么需要 AgenticMessage?

在 Chat Completions API 中,一次模型调用只返回一条消息。Responses API 在一次调用中返回所有结构化的中间步骤。要承载这种”多事件”的返回,原来的 *schema.Message(只有一个 Role + Content 字符串)不够用了:

ChatModel 返回: ┌──────────────────────────┐
│ Role: Assistant │
│ Content: "答案是42" │
└──────────────────────────┘
只有一条扁平消息
AgenticModel ┌──────────────────────────────────────────────┐
返回: │ Role: Assistant │
│ ContentBlocks: [ │
│ [0] type: reasoning │
│ text: "我需要先搜索..." │
│ [1] type: server_tool_call │
│ name: web_search │
│ [2] type: reasoning │
│ text: "搜索结果显示..." │
│ [3] type: text │
│ text: "根据分析,答案是42" │
│ ] │
└──────────────────────────────────────────────┘
一条消息里装了多个有序的结构化 Block

1.2 ContentBlock 类型速查

每个 Block 有一个 Type 字段表示类别:

Block 类型含义谁产生出现在哪条消息里
reasoning模型的推理/思考过程模型Assistant 消息
text普通文本输出模型Assistant 消息
server_tool_call调用服务端工具(如 web_search)模型Assistant 消息
function_tool_call调用客户端本地工具模型Assistant 消息
function_tool_result本地工具执行结果框架User 消息(反馈给模型)
thinking深度思考内容模型Assistant 消息

🧠 关键理解server_tool_call 在模型厂商的服务器上执行(你的代码看不到执行过程),function_tool_call 返回给你的 Agent 本地执行。


二、AgenticModel:连接 Responses API

2.1 两种厂商接入

import (
einoModel "github.com/cloudwego/eino/components/model"
"github.com/cloudwego/eino-ext/components/model/agenticark" // 火山方舟 ARK
"github.com/cloudwego/eino-ext/components/model/agenticopenai" // OpenAI
)
// ARK
model, err := agenticark.New(ctx, &agenticark.Config{
APIKey: os.Getenv("ARK_API_KEY"),
Model: os.Getenv("ARK_MODEL_ID"),
BaseURL: os.Getenv("ARK_BASE_URL"),
})
// OpenAI
model, err := agenticopenai.New(ctx, &agenticopenai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
Model: os.Getenv("OPENAI_MODEL_ID"),
BaseURL: os.Getenv("OPENAI_BASE_URL"),
})

不需要自己写搜索 Tool——直接声明即可,搜索在模型厂商侧完成:

// ARK 服务端 web_search
agenticark.WithServerTools([]*agenticark.ServerToolConfig{
{WebSearch: &arkResponses.ToolWebSearch{
Type: arkResponses.ToolType_web_search,
Limit: ptrOf[int64](6),
}},
})
// OpenAI 服务端 web_search
agenticopenai.WithServerTools([]*agenticopenai.ServerToolConfig{
{WebSearch: &openaiResponses.WebSearchToolParam{
Type: openaiResponses.WebSearchToolTypeWebSearch,
}},
})

💡 服务端 vs 本地工具:服务端工具的调用和执行都在模型厂商侧,你的代码只会在 content_blocks 中看到一个 server_tool_call block,不会有对应的 function_tool_result——结果被模型直接在内部消费了。


三、Typed 泛型体系

3.1 完整组装示例(与 入门笔记 §3 对照)

入门笔记 第三节的 Agent 组装步骤一模一样,只是类型都换成了 Typed + AgenticMessage:

func newResearchAssistant(ctx context.Context) (adk.TypedAgent[*schema.AgenticMessage], error) {
// ─── 第1步:创建 AgenticModel ───
agenticModel, _ := newAgenticModel(ctx)
// ─── 第2步:创建本地工具(和之前一模一样,InferTool)───
tools, _ := buildTools()
// ─── 第3步:创建 TypedChatModelAgent ───
agent, err := adk.NewTypedChatModelAgent[*schema.AgenticMessage](ctx,
&adk.TypedChatModelAgentConfig[*schema.AgenticMessage]{
Name: "AgenticResearchAssistant",
Instruction: "...",
Model: agenticModel, // ← AgenticModel
ToolsConfig: adk.ToolsConfig{ // ← 和 ChatModel 版本一样!
ToolsNodeConfig: compose.ToolsNodeConfig{
Tools: tools,
},
},
MaxIterations: 8,
})
return agent, err
}

其余逻辑(Middleware 等)和 ChatModel 版本完全一样,只需加 Typed 前缀

3.2 TypedRunner 的使用方式

// 创建(和之前一样的模式)
runner := adk.NewTypedRunner[*schema.AgenticMessage](adk.TypedRunnerConfig[*schema.AgenticMessage]{
Agent: agent,
EnableStreaming: true,
})
// 构造输入(用 UserAgenticMessage 替代 UserMessage)
input := schema.UserAgenticMessage("请写一份研究报告...")
// 运行
iter := runner.Run(ctx, []*schema.AgenticMessage{input})
// 消费事件 —— ⚠️ 关键变化:用 TypedGetMessage
for {
event, ok := iter.Next()
if !ok { break }
msg, _, err := adk.TypedGetMessage(event) // ← 不是 GetMessage()
if msg != nil {
fmt.Print(msg.String())
}
}

🧠 入门笔记 的对比

// 旧:ChatModel 路径
msg, err := event.Output.MessageOutput.GetMessage()
// 新:AgenticModel 路径
msg, typedagentevent, err := adk.TypedGetMessage(event)

四、ModelRetryConfig:输出截断自动重试

4.1 问题场景

Responses API 中对每次调用有 max_output_tokens 限制。设置太小时输出被截断:

status=incomplete
incomplete_details.reason=max_output_tokens

4.2 解决方案

Eino ADK 提供 TypedModelRetryConfig,自动丢弃不完整输出、调大 budget、重新调用:

var retryMaxTokens = []int{4096, 8192, 16384}
ModelRetryConfig: &adk.TypedModelRetryConfig[*schema.AgenticMessage]{
MaxRetries: len(retryMaxTokens),
ShouldRetry: func(ctx context.Context, retryCtx *adk.TypedRetryContext[*schema.AgenticMessage]) *adk.TypedRetryDecision[*schema.AgenticMessage] {
if !isMaxOutputTokensIncomplete(retryCtx.OutputMessage) {
return nil // 不需要重试
}
nextMaxTokens := retryMaxTokens[retryCtx.RetryAttempt-1]
return &adk.TypedRetryDecision[*schema.AgenticMessage]{
Retry: true,
AdditionalOptions: []einoModel.Option{einoModel.WithMaxTokens(nextMaxTokens)},
Backoff: 100 * time.Millisecond,
}
},
},

4.3 与 入门笔记 §4.4 节 ModelRetryConfig 的对比

维度ChatModel 版Agentic 版
类型adk.ModelRetryConfigadk.TypedModelRetryConfig[*schema.AgenticMessage]
检测依据err(HTTP 错误)OutputMessage.ResponseMeta(响应状态)
重试方式原样重试调大 max_output_tokens 后重试
适用场景限流、网络错误输出截断

五、Agentic 全景速查

5.1 新增能力

能力ChatModel 有吗AgenticModel 如何实现
推理过程可见reasoning ContentBlock
服务端工具server_tool_call + WithServerTools
输出截断检测间接(finish_reason)直接:status=incomplete
一次调用多事件❌ 需多次往返✅ 单次调用返回多个 ContentBlock
深度思考thinking ContentBlock + WithReasoning

5.2 常用 import 路径

// AgenticModel 实现
"github.com/cloudwego/eino-ext/components/model/agenticopenai" // OpenAI Responses API
"github.com/cloudwego/eino-ext/components/model/agenticark" // 火山方舟 ARK
// 核心接口
"github.com/cloudwego/eino/components/model" // AgenticModel 接口
"github.com/cloudwego/eino/schema" // AgenticMessage, ContentBlock
"github.com/cloudwego/eino/adk" // TypedChatModelAgent, TypedRunner, TypedModelRetryConfig
// 中间件(Typed 版)
"github.com/cloudwego/eino/adk/middlewares/filesystem" // filesystem.NewTyped
// 后端
"github.com/cloudwego/eino-ext/adk/backend/local" // localbackend.NewBackend

5.3 总结:什么时候该用 Agentic?

你的场景 → 用什么
─────────────────────────────────────────────────────────
简单问答、一次性调用 → ChatModel([入门笔记](./note) §2)
多轮对话 + 本地工具 + 中断恢复 → ChatModelAgent([入门笔记](./note) §3)
需要服务端搜索(web_search) → AgenticModel ✅
需要看到模型的推理过程 → AgenticModel ✅
需要处理输出截断自动重试 → AgenticModel ✅
需要一次调用中混合推理+工具+文本 → AgenticModel ✅
现有 ChatModelAgent 代码跑得好好的 → 不用迁移,除非需要上述特性

🧠 渐进式采用:Agentic 并不是要替代 ChatModel——它们是两套并行的体系。当需要高级特性时,迁移路径也很清晰:把类型从 ChatModel/Message 换成 AgenticModel/AgenticMessage,其余逻辑基本不变

📇 本篇速记卡片

见到 Typed 就用 AgenticMessage:
NewChatModelAgent → NewTypedChatModelAgent[*AgenticMessage]
NewRunner → NewTypedRunner[*AgenticMessage]
GetMessage() → TypedGetMessage()
ModelRetryConfig → TypedModelRetryConfig
filesystem.New → filesystem.NewTyped[*AgenticMessage]
ContentBlock 六种类型:reasoning / text / server_tool_call
function_tool_call / function_tool_result / thinking
新增能力:
reasoning Block(推理可见)、server_tool_call(服务端工具)
web_search(不用自己写搜索Tool)、输出截断检测+重试

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

📖 继续阅读


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

Eino学习笔记 —— Agentic 进阶

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