核心摘要
ADK(Agent Development Kit)是 Eino 框架的最顶层抽象,提供开箱即用的 AI 智能体构建模式。本文从最简单的 ChatModelAgent 出发,逐步深入 Tool Use 循环、DeepAgent 深度推理、中断/恢复机制和状态管理,并通过一个完整的数据分析 Agent 实战案例,帮助你掌握用 Go 构建生产级智能体的核心技能。
目录
- 核心要点
- 什么是 ADK
- ChatModelAgent 详解
- Tool Use 完整流程
- DeepAgent 深度推理
- 人机协作:中断与恢复
- Agent 状态管理
- 预置 Agent 模式对比
- 实战:构建数据分析 Agent
- 最佳实践
- 常见问题
- 总结与相关资源
核心要点
- ADK 定位:Eino 组件和编排能力之上的高层 Agent 抽象,封装了 Tool Use 循环、对话管理和状态持久化
- ChatModelAgent:最简单的 Agent 模式——一个 ChatModel + 一组 Tools,自动处理多轮工具调用
- DeepAgent:支持计划、反思和子任务分解的深度推理 Agent,适合复杂多步任务
- 中断/恢复:原生支持人机协作(Human-in-the-Loop),Agent 可在任意步骤暂停等待人工审核
- 状态管理:内置对话历史维护和 Checkpoint 机制,支持跨会话持久化
什么是 ADK
ADK(Agent Development Kit)是 Eino 框架的第三层能力,位于 Components(组件层)和 Composition(编排层)之上:
ADK 解决的核心问题是:将 LLM 能力从「一次性问答」提升为「持续推理与行动」。它封装了以下关键能力:
- Tool Use 循环:自动执行 LLM ↔ Tool 的多轮交互,直到任务完成
- 对话记忆:自动维护多轮对话的上下文历史
- 状态管理:支持 Checkpoint 序列化,实现中断后恢复
- 预置模式:提供 ChatModelAgent、DeepAgent 等开箱即用的 Agent 模式
ChatModelAgent 详解
ChatModelAgent 是 ADK 中最简单也最常用的 Agent 模式,其核心组成为一个 ChatModel 加一组 Tools:
package main
import (
"context"
"fmt"
"github.com/cloudwego/eino/adk"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/schema"
)
func main() {
ctx := context.Background()
// 初始化 ChatModel(以 OpenAI 为例)
chatModel := initOpenAIChatModel()
// 定义工具
searchTool := createSearchTool()
calculatorTool := createCalculatorTool()
// 创建 ChatModelAgent
agent, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Model: chatModel,
Tools: []tool.BaseTool{searchTool, calculatorTool},
SystemPrompt: "你是一个有帮助的助手,可以搜索信息和进行计算。",
MaxSteps: 10,
})
if err != nil {
panic(err)
}
// 运行 Agent
result, err := agent.Run(ctx, "北京今天的气温是多少?换算成华氏度。")
if err != nil {
panic(err)
}
fmt.Println(result.Content)
}
配置参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
Model |
ChatModel |
底层大模型实例 |
Tools |
[]tool.BaseTool |
可用工具列表 |
SystemPrompt |
string |
系统提示词,定义 Agent 行为 |
MaxSteps |
int |
最大推理步数,防止无限循环 |
Tool Use 完整流程
Tool Use 是 Agent 的核心执行机制。以下是完整的交互流程:
执行步骤详解:
- 用户输入:用户发送消息到 Agent
- LLM 决策:Agent 内部的 LLM 根据系统提示和对话历史决定下一步动作
- 工具调用:若 LLM 返回
tool_call,框架自动解析并执行对应工具 - 结果反馈:工具执行结果以
tool_result消息形式反馈给 LLM - 循环判断:LLM 可能继续调用工具或生成最终回复
- 终止条件:达到 MaxSteps 或 LLM 返回不含 tool_call 的消息时循环结束
// 自定义工具的实现示例
func createSearchTool() tool.BaseTool {
return tool.NewSimpleTool(
"web_search",
"搜索互联网上的实时信息",
func(ctx context.Context, params map[string]interface{}) (string, error) {
query := params["query"].(string)
// 调用搜索 API
results, err := searchAPI.Search(ctx, query)
if err != nil {
return "", err
}
return formatResults(results), nil
},
tool.WithStringParam("query", "搜索关键词", true),
)
}
DeepAgent 深度推理
DeepAgent 相比 ChatModelAgent 增加了计划、反思和子任务分解能力,适合处理复杂多步任务:
deepAgent, err := adk.NewDeepAgent(ctx, &adk.DeepAgentConfig{
Model: chatModel,
Tools: tools,
SystemPrompt: "你是一个数据分析专家,擅长分解复杂问题并逐步解决。",
MaxSteps: 25,
Planning: true, // 启用任务规划
Reflection: true, // 启用执行反思
})
DeepAgent 的推理流程:
- 任务理解:分析用户请求,识别目标和约束
- 计划制定:将复杂任务拆解为有序的子任务列表
- 逐步执行:按计划依次执行子任务,每步可调用工具
- 中间反思:检查中间结果是否符合预期,必要时调整计划
- 结果整合:汇总所有子任务结果,生成最终回复
人机协作:中断与恢复
ADK 原生支持 Human-in-the-Loop(人机协作)模式,允许 Agent 在关键步骤暂停执行,等待人工审核后恢复:
// 注册工具调用拦截器
agent.OnToolCall(func(ctx context.Context, call *schema.ToolCall) (*schema.ToolResult, error) {
// 对敏感操作(如发送邮件)进行拦截
if call.Name == "send_email" {
recipient := call.Args["to"].(string)
subject := call.Args["subject"].(string)
// 返回 Interrupt 暂停 Agent 执行
return nil, adk.Interrupt(fmt.Sprintf(
"请确认发送邮件:\n收件人: %s\n主题: %s",
recipient, subject,
))
}
return nil, nil // 其他工具正常执行
})
// 执行 Agent(可能在某步中断)
result, err := agent.Run(ctx, "给张三发一封会议通知邮件")
if errors.Is(err, adk.ErrInterrupted) {
// Agent 已中断,获取 Checkpoint
checkpoint := agent.GetCheckpoint()
// 持久化 checkpoint(如存入 Redis)
saveCheckpoint(checkpoint)
// 展示中断信息给用户
fmt.Println("等待审核:", checkpoint.InterruptMessage)
}
// --- 人工审核后 ---
// 读取 checkpoint
checkpoint := loadCheckpoint()
// 构造人工审批结果
approvedResult := &schema.ToolResult{
Name: "send_email",
Content: "邮件已确认发送",
}
// 恢复 Agent 执行
result, err := agent.Resume(ctx, checkpoint, approvedResult)
fmt.Println(result.Content) // "邮件已成功发送给张三"
中断/恢复的典型场景:
- 敏感操作确认(发送邮件、转账、删除数据)
- 中间结果审核(报告生成、数据修改)
- 分阶段长任务(需人工补充信息后继续)
Agent 状态管理
Agent 在执行过程中维护以下状态信息:
// Checkpoint 结构示意
type AgentCheckpoint struct {
ConversationHistory []schema.Message // 完整对话历史
CurrentStep int // 当前执行步骤
PendingToolCalls []schema.ToolCall // 待执行的工具调用
InterruptMessage string // 中断原因
Metadata map[string]any // 自定义元数据
}
// 状态持久化示例
func saveCheckpoint(cp *adk.AgentCheckpoint) error {
data, err := json.Marshal(cp)
if err != nil {
return err
}
return redis.Set(ctx, "agent:checkpoint:"+sessionID, data, 24*time.Hour).Err()
}
// 状态恢复
func loadCheckpoint(sessionID string) (*adk.AgentCheckpoint, error) {
data, err := redis.Get(ctx, "agent:checkpoint:"+sessionID).Bytes()
if err != nil {
return nil, err
}
var cp adk.AgentCheckpoint
return &cp, json.Unmarshal(data, &cp)
}
状态管理最佳实践:
- 对话历史自动维护,无需手动追加消息
- Checkpoint 支持 JSON 序列化,可存储于任意持久化层
- 建议为 Checkpoint 设置 TTL,避免长期累积
- 通过 Metadata 注入业务上下文(如用户 ID、会话 ID)
预置 Agent 模式对比
| 模式 | 适用场景 | 推理能力 | 复杂度 | Tool Use |
|---|---|---|---|---|
| ChatModelAgent | 简单工具调用、问答增强 | 单步推理 | 低 | 支持 |
| DeepAgent | 复杂分析、研究调研 | 多步推理+反思 | 中 | 支持 |
| Multi-Agent | 多角色协作、任务分工 | 协调推理 | 高 | 支持 |
选择建议:
- 80% 的场景使用 ChatModelAgent 即可满足
- 需要任务分解和反思时升级为 DeepAgent
- 需要多个专业角色协作时使用 Multi-Agent(详见下一篇文章)
实战:构建数据分析 Agent
以下是一个完整的数据分析 Agent 示例,集成了数据查询、JSON 处理和报告生成能力:
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"github.com/cloudwego/eino/adk"
"github.com/cloudwego/eino/components/model/openai"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/schema"
)
// 数据查询工具
func createQueryTool() tool.BaseTool {
return tool.NewSimpleTool(
"query_database",
"执行 SQL 查询获取数据",
func(ctx context.Context, params map[string]interface{}) (string, error) {
sql := params["sql"].(string)
rows, err := db.QueryContext(ctx, sql)
if err != nil {
return "", fmt.Errorf("查询失败: %w", err)
}
defer rows.Close()
results := scanRows(rows)
data, _ := json.Marshal(results)
return string(data), nil
},
tool.WithStringParam("sql", "SQL 查询语句", true),
)
}
// 数据分析工具
func createAnalysisTool() tool.BaseTool {
return tool.NewSimpleTool(
"analyze_data",
"对数据进行统计分析(均值、中位数、趋势等)",
func(ctx context.Context, params map[string]interface{}) (string, error) {
data := params["data"].(string)
method := params["method"].(string)
result := performAnalysis(data, method)
return result, nil
},
tool.WithStringParam("data", "JSON 格式的数据", true),
tool.WithStringParam("method", "分析方法: mean/median/trend/distribution", true),
)
}
// 报告生成工具
func createReportTool() tool.BaseTool {
return tool.NewSimpleTool(
"generate_report",
"根据分析结果生成 Markdown 格式报告",
func(ctx context.Context, params map[string]interface{}) (string, error) {
findings := params["findings"].(string)
title := params["title"].(string)
report := fmt.Sprintf("# %s\n\n%s\n", title, findings)
return report, nil
},
tool.WithStringParam("title", "报告标题", true),
tool.WithStringParam("findings", "分析发现的内容", true),
)
}
func main() {
ctx := context.Background()
// 初始化模型
chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
Model: "gpt-4o",
APIKey: os.Getenv("OPENAI_API_KEY"),
})
if err != nil {
log.Fatal(err)
}
// 创建数据分析 Agent
agent, err := adk.NewDeepAgent(ctx, &adk.DeepAgentConfig{
Model: chatModel,
Tools: []tool.BaseTool{
createQueryTool(),
createAnalysisTool(),
createReportTool(),
},
SystemPrompt: `你是一个专业的数据分析师。你的工作流程是:
1. 理解用户的分析需求
2. 编写 SQL 查询获取数据
3. 对数据进行统计分析
4. 生成结构化分析报告
注意:SQL 查询必须包含 LIMIT 子句防止数据量过大。`,
MaxSteps: 20,
Planning: true,
Reflection: true,
})
if err != nil {
log.Fatal(err)
}
// 添加敏感操作拦截
agent.OnToolCall(func(ctx context.Context, call *schema.ToolCall) (*schema.ToolResult, error) {
if call.Name == "query_database" {
sql := call.Args["sql"].(string)
if containsDangerousSQL(sql) {
return nil, adk.Interrupt("检测到危险 SQL 操作,请人工审核: " + sql)
}
}
return nil, nil
})
// 执行分析任务
result, err := agent.Run(ctx, "分析过去 30 天的用户注册趋势,按日统计并识别异常波动")
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Content)
}
func containsDangerousSQL(sql string) bool {
// 检测 DROP、DELETE、UPDATE 等危险操作
dangerousKeywords := []string{"DROP", "DELETE", "UPDATE", "TRUNCATE", "ALTER"}
upperSQL := strings.ToUpper(sql)
for _, keyword := range dangerousKeywords {
if strings.Contains(upperSQL, keyword) {
return true
}
}
return false
}
该示例展示了如何将 JSON 数据结构与 Agent 工具链结合,构建端到端的数据分析流水线。
最佳实践
工具设计原则:
- 每个工具职责单一,描述清晰准确(LLM 依赖描述决定何时调用)
- 工具返回值使用结构化格式(JSON),便于 LLM 解析
- 对耗时工具添加 Context 超时控制
Agent 配置建议:
- SystemPrompt 明确指定 Agent 角色、能力边界和工作流程
- MaxSteps 根据任务复杂度合理设置(简单 5-10,复杂 15-25)
- 生产环境必须配置 Callback 监控每步执行耗时和 Token 消耗
错误处理:
- 工具执行失败时返回有意义的错误信息(LLM 可据此调整策略)
- 为 Agent 添加全局超时,防止异常情况下无限执行
- 使用 Eino 的回调系统记录执行链路
常见问题
Q: ADK 和直接使用 Eino 组件有什么区别?
ADK 是 Eino 组件和编排能力之上的高层抽象。直接使用组件需要你手动处理 Tool Use 循环、对话历史管理和错误重试;ADK 将这些封装为开箱即用的 Agent 模式,让你专注于业务逻辑而非基础设施。
Q: ChatModelAgent 和 DeepAgent 应该选哪个?
ChatModelAgent 适合简单的工具调用场景(如搜索、计算、API 查询);DeepAgent 适合需要多步推理、任务分解和反思的复杂任务(如数据分析、报告生成、研究调研)。选择依据是任务的推理深度。
Q: 中断/恢复机制在生产环境中如何持久化?
Checkpoint 数据可以序列化为 JSON 并存储在 Redis、数据库或文件系统中。恢复时读取 checkpoint 反序列化后传入 agent.Resume() 即可。建议给 checkpoint 设置 TTL 避免无限累积。
Q: MaxSteps 设置为多少合适?
简单工具调用场景建议 5-10 步;复杂多工具协作场景建议 15-25 步。设置过小会导致 Agent 无法完成任务,设置过大可能导致无限循环消耗 Token。建议配合 Callback 监控实际步数分布后调优。
Q: Eino ADK 支持流式输出吗?
支持。ChatModelAgent 和 DeepAgent 均可通过 StreamRun 方法启用流式输出,配合 Eino 的 Callback 系统可以实时追踪每一步推理过程。详见本系列第四篇关于流式与回调的文章。
总结与相关资源
ADK 是 Eino 框架中将 LLM 能力转化为实际行动力的关键层。通过 ChatModelAgent 快速构建工具增强型 Agent,通过 DeepAgent 处理复杂推理任务,再配合中断/恢复机制实现安全的人机协作——这套组合拳覆盖了绝大多数生产级 Agent 场景。
下一步学习:Eino 多 Agent 协调模式将深入探讨如何让多个 Agent 协作完成更复杂的任务。
相关资源:
- Eino GitHub 仓库
- Eino 流式与回调系统(系列上一篇)
- AI Agent 术语解释
- Agent Memory 概念详解
- JSON 格式化工具 — 调试 Agent 工具返回值
- JSON 转 Go 结构体 — 快速生成工具参数类型定义