1. 什么是ADK

ADK 是 Eino 框架中 adk 包提供的高层 Agent 开发工具包,全称 Agent Development Kit。它的定位很明确:让你用最少的代码构建多 Agent 协作系统。
在 ADK 出现之前,如果你想让多个 Agent 协作,得自己用 Graph 编排——定义节点、连边、写条件路由、处理数据传递。这种方式很灵活,但写起来啰嗦,而且多 Agent 协作有很多通用的模式(顺序执行、并行执行、循环迭代),每次都从头画 Graph 显然是重复劳动。

2. agent 调用示例

package main

import (
	"context"
	"fmt"
	"io"

	"github.com/cloudwego/eino-ext/components/model/openai"
	"github.com/cloudwego/eino/adk"
	"log"
)

func main() {
	ctx := context.Background()

	// 创建大模型实例
	model, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
		BaseURL: "https://api-inference.modelscope.cn/v1/",
		APIKey:  "xxx", // api_key 
		Model:   "Qwen/Qwen3.5-35B-A3B",
	})
	if err != nil {
		log.Fatalf("创建 ChatModel 失败: %v", err)
	}

	// 创建chatModelAgent
	agent, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "translator",
		Description: "一个专业的中英互译助手",
		Instruction: "你是一个专业的{role}助手。用户发送{lang1}时翻译成{lang2},发送{lang2}时翻译成{lang1}。翻译要准确、自然、符合目标语言的表达习惯。",
		Model:       model,
	})
	if err != nil {
		log.Fatalf("创建 ChatModelAgent 失败: %v", err)
	}

	// runner 运行
	runner := adk.NewRunner(ctx, adk.RunnerConfig{
		Agent: agent,
		// 开启流式模式	EnableStreaming: true,
	})

	// 使用 Query 快捷方法发送问题
	iter := runner.Query(ctx, "Go语言是世界上最好的编程语言。", adk.WithSessionValues(map[string]any{
		"role":  "翻译",
		"lang1": "中文",
		"lang2": "英语",
	}))

	for {
		event, ok := iter.Next()
		if !ok {
			break
		}
		if event.Err != nil {
			log.Fatalf("执行出错: %v", event.Err)
		}
		if event.Output != nil && event.Output.MessageOutput != nil {
			mv := event.Output.MessageOutput
			if mv.IsStreaming && mv.MessageStream != nil {
				// 流式模式:从 MessageStream 逐块读取
				for {
					msg, err := mv.MessageStream.Recv()
					if err == io.EOF {
						break
					}
					if err != nil {
						log.Fatalf("读取流失败: %v", err)
					}
					fmt.Print(msg.Content)
				}
			} else if mv.Message != nil {
				// 非流式模式:直接取完整消息
				fmt.Print(mv.Message.Content)
			}
		}
	}

	fmt.Println()
}

3. 多智能体编排示例 (串式调用)

package main

import (
	"context"
	"fmt"
	"github.com/cloudwego/eino-ext/components/model/openai"
	"github.com/cloudwego/eino/adk"
	"log"
)

// 多agent 应用示例
func main() {
	ctx := context.Background()

	// 创建大模型实例
	model, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
		BaseURL: "https://api-inference.modelscope.cn/v1/",
		APIKey:  "xxx",  // api_key
		Model:   "Qwen/Qwen3.5-35B-A3B",
	})
	if err != nil {
		log.Fatalf("创建 ChatModel 失败: %v", err)
	}

	// 创建agent
	analyst, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "analyst",
		Description: "分析文章质量问题的专家",
		Instruction: `你是一个文章质量分析师。请仔细阅读用户提供的文章,从以下维度分析问题:
1. 逻辑结构是否清晰
2. 用词是否准确
3. 是否有语病或歧义
4. 表达是否简洁有力

请列出具体的问题清单,每个问题说明位置和改进建议。`,
		Model: model,
	})

	if err != nil {
		log.Fatal(err)
	}

	editor, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "editor",
		Description: "文章编辑专家",
		Instruction: `你是一个专业的文章编辑。你会收到一篇原文以及质量分析师的改进建议。
请根据这些建议对原文进行润色修改,输出修改后的完整文章。
修改时保持原文的核心意思不变,重点优化表达质量。`,
		Model: model,
	})

	if err != nil {
		log.Fatal(err)
	}

	// 用 SequentialAgent 把两个 Agent 串起来
	agent, err := adk.NewSequentialAgent(ctx, &adk.SequentialAgentConfig{
		Name:        "article_polisher",
		Description: "文章润色流水线",
		SubAgents:   []adk.Agent{analyst, editor},
	})
	if err != nil {
		return
	}
	// 创建 Runner 运行整个流水线
	runner := adk.NewRunner(ctx, adk.RunnerConfig{Agent: agent})

	article := `Go语言是很好的语言。它的并发性能很强大。
goroutine让并发编程变得简单了很多。
而且Go的编译速度也很快,部署也方便,只需要一个二进制文件就行了。
总之Go是一门值得学习的语言。`

	iter := runner.Query(ctx, "请帮我润色以下文章:\n\n"+article)

	for {
		event, ok := iter.Next()
		if !ok {
			break
		}
		if event.Err != nil {
			log.Fatalf("执行出错: %v", event.Err)
		}
		if event.Output != nil && event.Output.MessageOutput != nil {
			fmt.Printf("\n===== [%s] 输出 =====\n%s\n",
				event.AgentName,
				event.Output.MessageOutput.Message.Content)
		}
	}
}

4. 带工具的ChatModelAgent

package main

import (
    "context"
    "fmt"
    "log"
    "math"
    "os"

    "github.com/cloudwego/eino-ext/components/model/openai"
    "github.com/cloudwego/eino/adk"
    "github.com/cloudwego/eino/components/tool"
    "github.com/cloudwego/eino/components/tool/utils"
    "github.com/cloudwego/eino/compose"
)

// 计算器工具的参数
type CalcParams struct {
    Operation string  `json:"operation" jsonschema:"description=运算类型,必须是以下之一: add(加法) sub(减法) mul(乘法) div(除法) sqrt(开方) pow(幂运算),required"`
    A         float64 `json:"a" jsonschema:"description=第一个操作数,required"`
    B         float64 `json:"b" jsonschema:"description=第二个操作数(sqrt时可省略)"`
}

// 计算器工具函数
func calculate(ctx context.Context, params *CalcParams) (string, error) {
    var result float64
    switch params.Operation {
    case "add":
       result = params.A + params.B
    case "sub":
       result = params.A - params.B
    case "mul":
       result = params.A * params.B
    case "div":
       if params.B == 0 {
          return "错误:除数不能为零", nil
       }
       result = params.A / params.B
    case "sqrt":
       result = math.Sqrt(params.A)
    case "pow":
       result = math.Pow(params.A, params.B)
    default:
       return fmt.Sprintf("不支持的运算类型: %s", params.Operation), nil
    }
    return fmt.Sprintf("计算结果: %.4f", result), nil
}

func main() {
    ctx := context.Background()

    chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
			BaseURL: "https://api-inference.modelscope.cn/v1/",
			APIKey:  "xxx",  // api_key
			Model:   "Qwen/Qwen3.5-35B-A3B",
    })
    if err != nil {
       log.Fatal(err)
    }

    // 创建工具
    calcTool, err := utils.InferTool(
       "calculator",
       "数学计算器,支持加减乘除、开方、幂运算。必须指定 operation 和操作数",
       calculate,
    )
    if err != nil {
       log.Fatal(err)
    }

    // 创建带工具的 ChatModelAgent
    agent, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
       Name:        "math_assistant",
       Description: "一个数学计算助手,能够进行各种数学运算",
       Instruction: "你是一个数学助手。当用户提出数学计算问题时,使用 calculator 工具进行精确计算,不要自己心算。",
       Model:       chatModel,
       ToolsConfig: adk.ToolsConfig{
          ToolsNodeConfig: compose.ToolsNodeConfig{
             Tools: []tool.BaseTool{calcTool},
          },
       },
    })
    if err != nil {
       log.Fatal(err)
    }

    runner := adk.NewRunner(ctx, adk.RunnerConfig{Agent: agent})
    iter := runner.Query(ctx, "请帮我计算:(15.7 + 3.3) 的平方根,然后再乘以 2.5")

    for {
       event, ok := iter.Next()
       if !ok {
          break
       }
       if event.Err != nil {
          log.Fatal(event.Err)
       }
       // 打印 Agent 名称和输出
       if event.Output != nil && event.Output.MessageOutput != nil {
          fmt.Printf("[%s] %s\n", event.AgentName, event.Output.MessageOutput.Message.Content)
       }
    }
}

5. 并行执行多个agent

package main

import (
	"context"
	"fmt"
	"github.com/cloudwego/eino-ext/components/model/openai"
	"github.com/cloudwego/eino/adk"
	"io"
	"log"
)

func main() {
	ctx := context.Background()

	// 创建大模型基础
	model, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
		BaseURL: "https://api-inference.modelscope.cn/v1/",
		APIKey:  "xxxx",  // api_key
		Model:   "Qwen/Qwen3.5-35B-A3B",
	})
	if err != nil {
		log.Fatalf("创建 ChatModel 失败: %v", err)
	}

	// Agent 1:性能分析师
	performanceAnalyst, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "performance_analyst",
		Description: "性能分析师",
		Instruction: "你是一个专业的性能分析师。请根据用户提供的性能测试报告,分析性能瓶颈,并给出改进建议。",
		Model:       model,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Agent 2: 安全分析师
	securityAnalyst, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "security_analyst",
		Description: "安全分析师",
		Instruction: "你是一个专业的安全分析师。请根据用户提供的安全测试报告,分析安全风险,并给出改进建议。",
		Model:       model,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Agent 3: 可维护性分析师
	maintainabilityAnalyst, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "maintainability_analyst",
		Description: "可维护性分析师",
		Instruction: "你是一个专业的可维护性分析师。请根据用户提供的代码,分析代码可维护性,并给出改进建议。",
		Model:       model,
	})
	if err != nil {
		log.Fatal(err)
	}
	// 用 ParallelAgent 让三个分析师同时工作
	multiAnalyzer, err := adk.NewParallelAgent(ctx, &adk.ParallelAgentConfig{
		Name:        "multi_analyzer",
		Description: "多视角技术方案分析器",
		SubAgents:   []adk.Agent{performanceAnalyst, securityAnalyst, maintainabilityAnalyst},
	})
	if err != nil {
		return
	}

	runner := adk.NewRunner(ctx, adk.RunnerConfig{
		Agent:           multiAnalyzer,
		EnableStreaming: true, // 开启流模式
	})
	iter := runner.Query(ctx, "我计划用 Redis 作为用户Session的存储方案,替代当前的基于Cookie的方案。请分析这个方案。")

	for {
		event, ok := iter.Next()
		if !ok {
			break
		}
		if event.Err != nil {
			log.Fatalf("执行出错: %v", event.Err)
		}
		if event.Output != nil && event.Output.MessageOutput != nil {
			/*fmt.Printf("\n===== [%s] 分析 =====\n%s\n",
			event.AgentName,
			event.Output.MessageOutput.Message.Content)*/

			// 使用流式输出
			mv := event.Output.MessageOutput
			if mv.IsStreaming && mv.MessageStream != nil {
				for {
					msg, err := mv.MessageStream.Recv()
					if err == io.EOF {
						break
					}
					if err != nil {
						log.Fatalf("读取流失败: %v", err)
					}
					fmt.Print(msg.Content)
				}
			}
		}
	}
	fmt.Println("执行完成")
}

6. LoopAgeng 循环编排

LoopAgent 即循环编排,让子 Agent 反复执行,直到某个退出条件被满足或者达到最大迭代次数。这在需要"迭代优化"的场景下非常有用——比如让 Agent 反复审核和修改内容,直到质量达标。

package main

import (
	"context"
	"fmt"
	"github.com/cloudwego/eino-ext/components/model/openai"
	"github.com/cloudwego/eino/adk"
	"log"
)

// 循环调用

func main() {
	ctx := context.Background()

	// 模型
	model, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
		BaseURL: "https://api-inference.modelscope.cn/v1/",
		APIKey:  "xxx", // api_key
		Model:   "Qwen/Qwen3.5-35B-A3B",
	})
	if err != nil {
		log.Fatalf("创建 ChatModel 失败: %v", err)
	}

	// Agent 1:代码生成/修改者
	codeGenerator, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "generator",
		Description: "根据需求编写或修改Go代码",
		Instruction: `你是一个Go开发者。
- 如果是第一次收到需求,请编写完整的Go代码实现
- 如果收到了代码审核意见,请根据意见修改代码并输出修改后的完整代码
- 只输出代码和简要说明,不要输出无关内容`,
		Model: model,
	})

	if err != nil {
		log.Fatal(err)
	}

	// Agent 2:代码审核者
	codeReviewer, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "reviewer",
		Description: "审核Go代码质量",
		Instruction: `你是一个严格的Go代码审核专家。请审核代码的以下方面:
1. 错误处理是否完善
2. 是否有潜在的并发安全问题
3. 命名是否规范
4. 代码是否简洁高效

如果代码质量合格,请回复"APPROVED: "加上审核通过的理由。
如果不合格,请列出具体问题和修改建议。`,
		Model: model,
	})
	if err != nil {
		log.Fatal(err)
	}

	oneRound, err := adk.NewSequentialAgent(ctx, &adk.SequentialAgentConfig{
		Name:        "code_generator_reviewer",
		Description: "代码生成/修改/审核流水线",
		SubAgents:   []adk.Agent{codeGenerator, codeReviewer},
	})
	if err != nil {
		log.Fatal(err)
	}
	// 用 LoopAgent 循环执行,最多迭代 3 次
	loopAgent, err := adk.NewLoopAgent(ctx, &adk.LoopAgentConfig{
		Name:          "code_generator_reviewer_loop",
		Description:   "代码生成/修改/审核流水线循环执行",
		SubAgents:     []adk.Agent{oneRound},
		MaxIterations: 3,
	})
	if err != nil {
		log.Fatal(err)
	}
	runner := adk.NewRunner(ctx, adk.RunnerConfig{Agent: loopAgent})
	iter := runner.Query(ctx, "请用Go写一个线程安全的LRU Cache,支持Get和Put操作,容量为构造参数")

	round := 0
	for {
		event, ok := iter.Next()
		if !ok {
			break
		}
		if event.Err != nil {
			log.Fatalf("执行出错: %v", event.Err)
		}
		if event.Output != nil && event.Output.MessageOutput != nil {
			if event.AgentName == "reviewer" {
				round++
				fmt.Printf("\n===== 第 %d 轮审核 [%s] =====\n", round, event.AgentName)
			} else {
				fmt.Printf("\n===== [%s] =====\n", event.AgentName)
			}
			fmt.Println(event.Output.MessageOutput.Message.Content)
		}
	}
}

7. TooAgent 工具委派

ADK 提供了一个非常强大的能力:通过 adk.NewAgentTool 把一个 Agent 包装成 Tool,然后绑定到另一个 Agent 上。这意味着上层 Agent 可以像调用普通工具一样"委派"任务给下层 Agent——上层 Agent 决定什么时候需要委派、委派什么任务,下层 Agent 负责具体执行。

package main

import (
	"context"
	"fmt"
	"github.com/cloudwego/eino-ext/components/model/openai"
	"github.com/cloudwego/eino/adk"
	"github.com/cloudwego/eino/components/tool"
	"github.com/cloudwego/eino/compose"
	"io"
	"log"
)

func main() {
	ctx := context.Background()

	// 创建大模型基础
	model, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
		BaseURL: "https://api-inference.modelscope.cn/v1/",
		APIKey:  "xxx", // api_key
		Model:   "Qwen/Qwen3.5-35B-A3B",
	})
	if err != nil {
		log.Fatalf("创建 ChatModel 失败: %v", err)
	}

	// 创建子agent 1: 翻译专家
	trnslator, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "translator",
		Description: "将文本翻译成指定语言。输入格式:目标语言|待翻译文本",
		Instruction: "你是一个翻译专家。用户会发送'目标语言|文本'格式的内容,请将文本翻译成指定语言。只输出翻译结果,不要输出其他内容。",
		Model:       model,
	})
	if err != nil {
		return
	}

	// 创建子agent2: 文案写手
	copywriter, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "copywriter",
		Description: "根据主题和风格要求撰写营销文案",
		Instruction: "你是一个创意文案写手。根据用户给出的主题和风格要求,撰写简短有力的营销文案。",
		Model:       model,
	})
	if err != nil {
		return
	}

	// 把子 Agent 包装成 Tool
	translatorTool := adk.NewAgentTool(ctx, trnslator)
	copywriterTool := adk.NewAgentTool(ctx, copywriter)

	// 主 Agent:项目经理,根据需求委派任务给不同的子 Agent
	manager, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "manager",
		Description: "任务调度经理",
		Instruction: `你是一个项目经理。用户会提出各种内容创作需求。
你手下有两个专家:
- translator:翻译专家,负责翻译任务
- copywriter:文案写手,负责撰写营销文案

请根据用户需求判断应该委派给哪个专家,并将任务分发出去。
如果需求涉及多个专家,请分别调用。`,
		Model: model,
		ToolsConfig: adk.ToolsConfig{
			ToolsNodeConfig: compose.ToolsNodeConfig{
				Tools: []tool.BaseTool{translatorTool, copywriterTool},
			},
		},
	})

	if err != nil {
		log.Fatalf("创建 Agent 失败: %v", err)
	}

	runner := adk.NewRunner(ctx, adk.RunnerConfig{
		Agent:           manager,
		EnableStreaming: true,
	})

	results := runner.Query(ctx, "请帮我写一段关于'Go语言云原生开发'的营销文案,然后把它翻译成英文")

	for {
		event, ok := results.Next()
		if !ok {
			break
		}
		if event.Err != nil {
			log.Fatalf("执行出错: %v", event.Err)
		}
		/*if event.Output != nil && event.Output.MessageOutput != nil {
			fmt.Printf("[%s] %s\n\n", event.AgentName, event.Output.MessageOutput.Message.Content)
		}*/
		mv := event.Output.MessageOutput
		if mv.IsStreaming && mv.MessageStream != nil {
			for {
				rec, err := mv.MessageStream.Recv()
				if err == io.EOF {
					break
				}

				if err != nil {
					log.Fatalf("读取流失败: %v", err)
				}
				fmt.Print(rec.Content)
			}
		}
	}

	fmt.Println("执行完成")
}

8. 结合之前的示例,进行汇总

通过三个专家评审Agent并行执行,得到不同的评审结果,然后进行汇总,最终得到一份完整的评审报告。

package main

import (
	"context"
	"fmt"
	"github.com/cloudwego/eino-ext/components/model/openai"
	"github.com/cloudwego/eino/adk"
	"log"
)

func main() {
	ctx := context.Background()

	chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
		BaseURL: "https://api-inference.modelscope.cn/v1/",
		APIKey:  "xxxx", //api_key
		Model:   "Qwen/Qwen3.5-35B-A3B",
	})
	if err != nil {
		log.Fatal(err)
	}

	// ===== 第一阶段:三个并行分析师 =====

	perfAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "perf_reviewer",
		Description: "性能评审专家",
		Instruction: `你是性能评审专家。请从性能维度评审用户提出的技术方案,输出格式:
【性能评分】1-10分
【核心发现】列出2-3个关键点
【改进建议】如有性能风险,给出具体建议`,
		Model: chatModel,
	})

	secAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "sec_reviewer",
		Description: "安全评审专家",
		Instruction: `你是安全评审专家。请从安全维度评审用户提出的技术方案,输出格式:
【安全评分】1-10分
【核心发现】列出2-3个关键点
【改进建议】如有安全风险,给出具体建议`,
		Model: chatModel,
	})

	costAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "cost_reviewer",
		Description: "成本评审专家",
		Instruction: `你是成本评审专家。请从成本维度评审用户提出的技术方案,输出格式:
【成本评分】1-10分
【核心发现】列出2-3个关键点
【改进建议】如有成本优化空间,给出具体建议`,
		Model: chatModel,
	})

	// 并行执行三个评审
	parallelReview, _ := adk.NewParallelAgent(ctx, &adk.ParallelAgentConfig{
		Name:        "parallel_review",
		Description: "并行技术评审",
		SubAgents:   []adk.Agent{perfAgent, secAgent, costAgent},
	})

	// ===== 第二阶段:综合汇总 =====

	summarizer, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
		Name:        "summarizer",
		Description: "评审报告汇总专家",
		Instruction: `你是技术评审委员会主席。你会收到三位专家(性能、安全、成本)的独立评审意见。
请综合所有评审意见,生成一份结构化的最终评审报告,格式如下:

# 技术方案评审报告

## 综合评分
(三个维度的加权平均,权重:性能40%、安全35%、成本25%)

## 各维度概要
(简要汇总每个维度的核心发现)

## 关键风险
(列出最需要关注的风险项)

## 最终结论
(通过/有条件通过/不通过,并说明理由)

## 行动项
(按优先级列出需要落实的改进项)`,
		Model: chatModel,
	})

	// ===== 组装完整流水线 =====

	fullPipeline, _ := adk.NewSequentialAgent(ctx, &adk.SequentialAgentConfig{
		Name:        "tech_review_system",
		Description: "完整技术方案评审系统",
		SubAgents:   []adk.Agent{parallelReview, summarizer},
	})

	// ===== 运行 =====

	runner := adk.NewRunner(ctx, adk.RunnerConfig{Agent: fullPipeline})

	proposal := `技术方案:将公司核心交易系统从单体架构迁移到微服务架构

关键设计决策:
1. 使用 Kubernetes 作为容器编排平台
2. 服务间通信采用 gRPC + Protobuf
3. 数据库从单一 MySQL 拆分为每个服务独立的数据库(Database per Service)
4. 引入 Apache Kafka 作为异步消息队列
5. 使用 Istio 服务网格处理流量治理
6. API Gateway 使用 Kong

预计影响范围:核心交易链路、用户中心、库存管理、支付系统`

	iter := runner.Query(ctx, "请评审以下技术方案:\n\n"+proposal)

	for {
		event, ok := iter.Next()
		if !ok {
			break
		}
		if event.Err != nil {
			log.Fatal(event.Err)
		}
		if event.Output != nil && event.Output.MessageOutput != nil {
			fmt.Printf("\n========== [%s] ==========\n%s\n",
				event.AgentName,
				event.Output.MessageOutput.Message.Content)
		}
	}
}

来源于: 秀才的进阶之路

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐