本文將會向您介紹如何利用 Eino ADK (Agent Development Kit) 構建一個強大的多智能體系統。
以 Excel Agent 這個實際業務場景為基礎,Excel Agent 是一個能夠“聽懂你的話、看懂你的表格、寫出並執行代碼”的智能助手。它把複雜的 Excel 處理工作拆解為清晰的步驟,通過自動規劃、工具調用與結果校驗,穩定完成各項Excel數據處理任務。
接下來我們將從 Excel Agent 的完整架構與功能出發,向您展示該 Agent 是如何通過 Eino ADK 逐步搭建的,進而深入淺出的理解 Eino ADK 的核心設計特點,助您快速上手 Eino ADK,向構建自定義智能體與 AI 應用系統更進一步。
本示例完整代碼位於 Github,您可以隨時瀏覽與下載。
Excel Agent 是什麼?
Excel Agent 是一個“看得懂 Excel 的智能助手”,它先把問題拆解成步驟,再一步步執行並校驗結果。它能理解用户問題與上傳的文件內容,提出可行的解決方案,並選擇合適的工具(系統命令、生成並運行 Python 代碼、網絡查詢等等)完成任務。
Excel Agent 整體是基於 Eino ADK 實現的 Multi-Agent 系統,完整架構如下圖所示:
Excel Agent 內部包含的幾個 Agent 功能分別為:
- Planner:分析用户輸入,拆解用户問題為可執行的計劃
- Executor:正確執行當前計劃中的首個步驟
- CodeAgent:接收來自 Executor 的指令,調用多種工具(例如讀寫文件,運行 python 代碼等)完成任務
- WebSearchAgent:接收來自 Executor 的指令,進行網絡搜索
- Replanner:根據 Executor 執行的結果和現有規劃,決定繼續執行、調整規劃或完成執行
- ReportAgent:根據運行過程與結果,生成總結性質的報告
Excel Agent 的典型使用場景
在真實業務裏,你可以把 Excel Agent 當成一位“Excel 專家 + 自動化工程師”。當你交付一個原始表格和目標描述,它會給出方案並完成執行:
- 數據清理與格式化:從一個包含大量數據的 Excel 文件中完成去重、空值處理、日期格式標準化操作。
- 數據分析與報告生成:從銷售數據中提取每月的銷售總額,聚合統計、透視,最終生成並導出圖表報告。
- 自動化預算計算:根據不同部門的預算申請,自動計算總預算並生成部門預算分配表。
- 數據匹配與合併:將多個不同來源的客户信息表進行匹配合並,生成完整的客户信息數據庫。
Excel Agent 的完整運行動線為:
核心收益:
- 更少的人工操作,把複雜繁瑣的 Excel 處理工作交給 Agent 自動完成。
- 更穩定的產出質量,通過“規劃—執行—反思”閉環減少漏項與錯誤。
- 更強的可擴展性,各 Agent 獨立構建,低耦合利於迭代更新。
Excel Agent 既可以單獨使用,也可以作為子 Agent,集成在一個複合的多專家系統中,由外部路由到此 Agent 上,解決 excel 領域相關的問題。
下面我們將逐步拆解 Excel Agent,深入瞭解 Eino ADK 的核心設計特點,以及如何利用這些特點構建高效、靈活的 AI 應用系統。
ChatModelAgent:與 LLM 交互的基石
ChatModelAgent是 Eino ADK 中的一個核心預構建的 Agent,內部使用了 ReAct 模式(一種讓模型‘思考-行動-觀察’的鏈式推理模式):
ChatModelAgent旨在讓 ChatModel 進行顯式的、一步一步的“思考”,結合思考過程驅動行動,觀測歷史思考過程與行動結果繼續進行下一步的思考與行動,最終解決複雜問題:
- 調用 ChatModel(Reason)
- LLM 返回工具調用請求(Action)
- ChatModelAgent 執行工具(Act)
- 將工具結果返回給 LLM(Observation),結合之前的上下文繼續生成,直到模型判斷不需要調用工具後結束
在 Excel Agent 中,每個 Agent 的核心都是這樣一個 ChatModelAgent,以 Executor 運行【讀取用户輸入表格的頭信息】這個步驟為例 ,我們可以通過觀察完整的運行過程來理解 ReAct 模式在 ChatModelAgent中的表現:
- Executor:經過判斷,將任務轉交給 CodeAgent 運行
- CodeAgent:接收到任務【讀取用户輸入表格的頭信息】
- Think-1:上下文未提供工作目錄下的所有文件,需要查看
- Act-1: 調用 Bash 工具,ls 查看工作目錄下的所有文件
- Think-2: 找到了用户輸入的文件,判斷需要編寫 Python 代碼讀取 xlsx 表格的首行
- Act-2: 調用 PythonRunner 工具,書寫代碼並運行,獲取運行結果
- Think-3: 獲取到了 xlsx 首行,判斷任務完成
- 運行完成,將表格頭信息返回給 Executor
Plan-Execute Agent:基於「規劃-執行-反思」的多智能體協作框架
Plan-Execute Agent 是 Eino ADK 中一種基於「規劃-執行-反思」範式的多智能體協作框架,旨在解決複雜任務的分步拆解、執行與動態調整問題。它通過 Planner(規劃器)、**Executor(執行器)**和 Replanner(重規劃器) 三個核心智能體的協同工作,實現任務的結構化規劃、工具調用執行、進度評估與動態 replanning,最終達成用户目標:
// 完整代碼: https://github.com/cloudwego/eino/blob/main/adk/prebuilt/planexecute/plan_execute.go
// NewPlanner creates a new planner agent based on the provided configuration.
func NewPlanner(_ context.Context, cfg *PlannerConfig) (adk.Agent, error)
// NewExecutor creates a new executor agent.
func NewExecutor(ctx context.Context, cfg *ExecutorConfig) (adk.Agent, error)
// NewReplanner creates a new replanner agent.
func NewReplanner(_ context.Context, cfg *ReplannerConfig) (adk.Agent, error)
// New creates a new plan-execute-replan agent with the given configuration.
func New(ctx context.Context, cfg *Config) (adk.Agent, error)
而 Excel Agent 的核心能力恰好為【解決用户在 excel 領域的問題】,與該智能體協作框架定位一致:
- 規劃者(Planner):明確目標,自動拆解可執行步驟
- 執行者(Executor):調用工具(Excel 讀取、系統命令、Python 代碼)完成規劃中的每一個詳細步驟
- 反思者(Replanner):根據執行進度決定繼續、調整規劃或結束
Planner 和 Replanner 會將用户模糊的指令拆解為清晰的、可執行的步驟清單,即包含多個步驟(Step)的計劃(Plan),Eino ADK 為此提供了靈活的 Plan 接口定義,支持用户自定義 Plan 結構與細節:
type Plan interface {
// FirstStep returns the first step to be executed in the plan.
FirstStep() string
// Marshaler serializes the Plan into JSON.
// The resulting JSON can be used in prompt templates.
json.Marshaler
// Unmarshaler deserializes JSON content into the Plan.
// This processes output from structured chat models or tool calls into the Plan structure.
json.Unmarshaler
}
默認情況下,框架會使用內置的 Plan 結構作為兜底配置,例如下面就是 Excel Agent 產生的一個完整運行計劃:
### 任務計劃
- [x] 1. Read the contents of '模擬出題.csv' from the working directory into a pandas DataFrame.
- [x] 2. Identify the question type (e.g., multiple-choice, short-answer) for each row in the DataFrame.
- [x] 3. For non-short-answer questions, restructure the data to place question, answer, explanation, and options in the same row.
- [x] 4. For short-answer questions, merge the answer content into the explanation column and ensure question and merged explanation are in the same row.
- [x] 5. Verify that all processed rows have question, answer (where applicable), explanation, and options (where applicable) in a single row with consistent formatting.
- [x] 6. Generate a cleaned report presenting the formatted questions with all relevant components (question, answer, explanation, options) in unified rows.
Workflow Agents:可控的多 Agent 運行流水線
Excel Agent 中,存在一些需要按照特定順序運行 agent 的情況:
- 順序運行:先運行 Planner,再運行 Executor 和 Replanner;Planner 只運行一次。
- 循環運行:Executor 和 Replanner 需要按需循環運行多次,每次循環運行都是先運行 Executor 後運行 Replanner
- 順序運行:Plan-Executor 整體運行完後,固定運行一次 ReportAgent 進行總結。
對於這些擁有固定執行流程的場景,Eino ADK 提供了三種流程編排方式,協助用户快速搭建可控的工作流:
- SequentialAgent:按照配置中提供的順序,依次執行一系列子 Agent。每個子 Agent 執行完成後,其輸出會通過 History 機制傳遞給下一個子 Agent,形成一個線性的執行鏈。
import github.com/cloudwego/eino/adk
// 依次執行 制定研究計劃 -> 搜索資料 -> 撰寫報告
sequential := adk.NewSequentialAgent(ctx, &adk.SequentialAgentConfig{
Name: "research_pipeline",
SubAgents: []adk.Agent{
planAgent, // 制定研究計劃
searchAgent, // 搜索資料
writeAgent, // 撰寫報告
},
})
- LoopAgent:重複執行配置的子 Agent 序列,直到達到最大迭代次數或某個子 Agent 產生 ExitAction,每次迭代的結果都會累積,後續迭代的輸入可以訪問所有歷史信息。LoopAgent 基於 SequentialAgent 實現。
import github.com/cloudwego/eino/adk
// 循環執行 5 次,每次順序為:分析當前狀態 -> 提出改進方案 -> 驗證改進效果
loop := adk.NewLoopAgent(ctx, &adk.LoopAgentConfig{
Name: "iterative_optimization",
SubAgents: []adk.Agent{
analyzeAgent, // 分析當前狀態
improveAgent, // 提出改進方案
validateAgent, // 驗證改進效果
},
MaxIterations: 5,
})
- ParallelAgent:允許多個子 Agent 基於相同的輸入上下文併發執行。所有子 Agent 接收相同的初始輸入,各自在獨立的 goroutine(Go 語言中一種輕量級的併發執行單元) 運行,最終收集所有子 Agent 的執行結果並按順序輸出到
AsyncIterator中。
import github.com/cloudwego/eino/adk
// 併發執行 情感分析 + 關鍵詞提取 + 內容摘要
parallel := adk.NewParallelAgent(ctx, &adk.ParallelAgentConfig{
Name: "multi_analysis",
SubAgents: []adk.Agent{
sentimentAgent, // 情感分析
keywordAgent, // 關鍵詞提取
summaryAgent, // 內容摘要
},
})
Agent 抽象:靈活定義 Agent 的基礎
Eino ADK 的核心是一個簡潔而強大的 Agent 接口,每個 Agent 都有明確的身份(Name)、清晰的職責(Description)和標準化的執行方式(Run),為 Agent 之間的發現與調用提供了基礎。無論是簡單的問答機器人,還是複雜的多步驟任務處理系統,都可以通過這個統一的接口加以實現。
- 統一的 Agent 抽象:ADK 提供的預構建 Agent(ChatModelAgent,Plan-Execute Agent,Workflow Agents)都遵循該接口定義。您也可以基於該接口,書寫自定義 Agent,完成定製化需求。
type Agent interface {
Name(ctx context.Context) string
Description(ctx context.Context) string
Run(ctx context.Context, input *AgentInput, options ...AgentRunOption) *AsyncIterator[*AgentEvent]
}
- 標準化輸入:Agent 通常以 LLM 為核心,因此 Eino ADK 定義的 Agent 的輸入與 LLM 接收的輸入一致:
type AgentInput struct {
Messages []Message
EnableStreaming bool
}
type Message = *schema.Message // *schema.Message 是模型輸入輸出的結構定義
- 異步事件驅動輸出:Agent 的輸出是一個 AgentEvent 的異步迭代器,其中的 AgentEvent 表示 Agent 在其運行過程中產生的核心事件數據。其中包含了 Agent 的元信息、輸出、行為和報錯信息:
type AgentEvent struct {
AgentName string // 產生 Event 的 Agent 名稱(框架自動填充)
RunPath []RunStep // 到達當前 Agent 的完整運行軌跡(框架自動填充)
Output *AgentOutput // Agent 輸出消息內容
Action *AgentAction // Agent 動作事件內容
Err error // Agent 報錯
}
type AgentOutput struct {
MessageOutput *MessageVariant // 模型消息輸出內容
CustomizedOutput any // 自定義輸出內容
}
type MessageVariant struct {
IsStreaming bool // 是否為流式輸出
Message Message // 非流式消息輸出
MessageStream MessageStream // 流式消息輸出
Role schema.RoleType // 消息角色
ToolName string // 工具名稱
}
type AgentAction struct {
Exit bool // Agent 退出
Interrupted *InterruptInfo // Agent 中斷
TransferToAgent *TransferToAgentAction // Agent 跳轉
CustomizedAction any // 自定義 Agent 動作
}
異步迭代器允許 Agent 在運行過程中的任意時刻向迭代器發送消息(Agent 調用模型結果、工具運行結果、中間狀態等等),同時調用方以一種有序、阻塞的方式消費這一系列事件:
iter := myAgent.Run(ctx, "hello") // get AsyncIterator
for {
event, ok := iter.Next()
if !ok {
break
}
// handle event
}
Agent 協作:隱藏在 Agent 後的數據傳遞
Excel Agent 架構圖中的節點代表每個具體的 Agent,邊代表了數據流通與任務轉移。在構建多 Agent 系統時,讓不同 Agent 之間高效、準確地共享信息至關重要。
這些信息不僅包含 Agent 的輸入輸出,還有全局的、部分可見的種種額外信息,例如:
- Executor 執行需要從 Planner / Replanner 拿到一個結構化的、可被拆分為詳細步驟(Step)的計劃(Plan),而非一段非結構化的 LLM 原始輸出消息。
- ReportAgent 需要拿到完整的運行計劃、運行過程與運行產物才能正確產生報告。
Eino ADK 包含兩種基礎的數據傳遞機制:
- History:每一個 Agent 產生的 AgentEvent 都會被保存到這個隱藏的 History 中,調用一個新 Agent 時 History 中的 AgentEvent 會被轉換並拼接到 AgentInput 中。默認情況下,其他 Agent 的 Assistant 或 Tool Message,被轉換為 User Message,這相當於在告訴當前的 LLM:“剛才, Agent\_A 調用了 some\_tool ,返回了 some_result 。現在,輪到你來決策了。”。 通過這種方式,其他 Agent 的行為被當作了提供給當前 Agent 的“外部信息”或“事實陳述”,而不是它自己的行為,從而避免了 LLM 的上下文混亂。
- 共享 Session:單次運行過程中持續存在的 KV 存儲,用於支持跨 Agent 的狀態管理和數據共享,一次運行中的任何 Agent 可以在任何時間讀寫 SessionValues。以 Plan-Execute Agent 模式為例,Planner 生成首個計劃並寫入 Session;Executor 從 Session 讀取計劃並執行;Replanner 從 Session 讀取當前計劃後,結合運行結果,將更新後的計劃寫回 Session 覆蓋當前的計劃。
// Agent 內獲取全部 SessionValues
func GetSessionValues(ctx context.Context) map[string]any
// Agent 內指定 key 獲取 SessionValues 中的值
func GetSessionValue(ctx context.Context, key string) (any, bool)
// Agent 內添加 SessionValues
func AddSessionValue(ctx context.Context, key string, value any)
// Agent 內批量添加 SessionValues
func AddSessionValues(ctx context.Context, kvs map[string]any)
// WithSessionValues 在 Agent 運行前由外部注入 SessionValues
func WithSessionValues(v map[string]any) AgentRunOption
除了完善的 Agent 間數據傳遞機制,Eino ADK 從實踐出發,提供了多種 Agent 協作模式:
- 預設 Agent 運行順序(Workflow):以代碼中預設好的流程運行, Agent 的執行順序是事先確定、可預測的。對應 Workflow Agents 章節提到的三種範式。
- 移交運行(Transfer):攜帶本 Agent 輸出結果上下文,將任務移交至子 Agent 繼續處理。適用於智能體功能可以清晰的劃分邊界與層級的場景,常結合 ChatModelAgent 使用,通過 LLM 的生成結果進行動態路由。結構上,以此方式進行協作的兩個 Agent 稱為父子 Agent:
// 設置父子 Agent 關係
func SetSubAgents(ctx context.Context, agent Agent, subAgents []Agent) (Agent, error)
// 指定目標 Agent 名稱,構造 Transfer Event
func NewTransferToAgentAction(destAgentName string) *AgentAction
- 顯式調用(ToolCall):將 Agent 視為工具進行調用,適用於 Agent 運行僅需要明確清晰的參數而非完整運行上下文的場景。常結合 ChatModelAgent,將 Agent 作為工具運行後將結果返回給 ChatModel 繼續處理。除此之外,ToolCall 同樣支持調用符合工具接口構造的、不含 Agent 的普通工具。
// 將 Agent 轉換為 Tool
func NewAgentTool(_ context.Context, agent Agent, options ...AgentToolOption) tool.BaseTool
Excel Agent 示例運行
配置環境與輸入輸出路徑
- 環境變量:Excel Agent 運行依賴的完整環境變量可參考項目 README。
-
運行輸入:包括一段用户需求描述和待處理的一系列文件,其中:
main.go中首行表示用户輸入的需求描述,可自行修改:
func main() {
// query := schema.UserMessage("統計附件文件中推薦的小説名稱及推薦次數,並將結果寫到文件中。凡是帶有《》內容都是小説名稱,形成表格,表頭為小説名稱和推薦次數,同名小説只列一行,推薦次數相加")
// query := schema.UserMessage("讀取模擬出題.csv 中的內容,規範格式將題目、答案、解析、選項放在同一行,簡答題只把答案寫入解析即可")
query := schema.UserMessage("請幫我將 question.csv 表格中的第一列提取到一個新的 csv 中")
}
adk/multiagent/integration-excel-agent/playground/input為默認的附件輸入路徑,附件輸入路徑支持配置,參考 README。adk/multiagent/integration-excel-agent/playground/test_data路徑下提供了幾個示例文件,您可以將文件複製到附件輸入路徑下來進行測試運行:
% tree adk/multiagent/integration-excel-agent/playground/test_data
adk/multiagent/integration-excel-agent/playground/test_data
├── questions.csv
├── 推薦小説.txt
└── 模擬出題.csv
1 directory, 3 files
- 運行輸出:Excel Agent 輸入的附件、運行的中間產物與最終結果都會放置在工作路徑下:
adk/multiagent/integration-excel-agent/playground/${uuid},輸出路徑支持配置,參考 README。
查看運行結果
Excel Agent 單次運行會在輸出路徑下創建一個新的工作目錄,並在該目錄下完成任務,運行時產生的中間產物與最終結果都會寫到該目錄下。
以請幫我將 question.csv 表格中的第一列提取到一個新的 csv 中這個任務為例,運行完成後在工作目錄下包含的內容有:
- 原始輸入:從輸入路徑獲取到的
question.csv - Planner / Replanner 給出的運行計劃:
plan.md
### 任務計劃
- [x] 1. {"desc":"Read the 'questions.csv' file into a pandas DataFrame."}
- [x] 2. Save the extracted first column to a new CSV file.
- Executor 中的 CodeAgent 書寫的代碼:
$uuid.py
import pandas as pd
df = pd.read_csv('questions.csv')
first_column = df.iloc[:, 0]
first_column.to_csv('extracted_first_column.csv', index=False)
- 運行中間產物:
extracted_first_column.csv和first_column.csv
type
multiple-choice
...
short-answer
- 最終報告:
final_report.json
{
"is_success": true,
"result": "Successfully extracted the first column from questions.csv and saved it to first_column.csv.",
"files": [
{
"path": "/User/user/go/src/github.com/cloudwego/eino-examples/adk/multiagent/integration-excel-agent/playground/00f118af-4bd8-42f7-8d11-71f2801218bd/first_column.csv",
"desc": "A CSV file containing only the first column data from the original questions.csv."
}
]
}
運行過程輸出
Excel Agent 會將每個步驟的運行結果輸出到日誌中。下面仍以請幫我將 question.csv 表格中的第一列提取到一個新的 csv 中這個任務為例,向您展示 Excel Agent 在運行過程中的幾個關鍵步驟及其輸出,並通過對步驟的解釋,直觀地呈現 Agent 的運行流程及其強大能力。:
- Planner 生成 JSON 格式的初始計劃
name: Planner
answer: {
"steps": [
{
"index": 1,
"desc": "Read the 'questions.csv' file into a pandas DataFrame."
},
{
"index": 2,
"desc": "Extract the first column from the DataFrame."
},
{
"index": 3,
"desc": "Save the extracted first column to a new CSV file."
}
]
}
- Executor 將 CodeAgent 作為工具進行調用,執行計劃中的首個步驟
name: Executor
tool name: CodeAgent
arguments: {"request":"Read the 'questions.csv' file into a pandas DataFrame using pandas. Use the pandas.read_csv function and store the result in a variable named df."}
- CodeAgent 使用 PythonRunner 工具運行代碼,並使用 ReAct 模式自動糾錯,修正代碼中的錯誤
# CodeAgent 使用 PythonRunner 工具運行代碼
name: Executor
tool name: PythonRunner
arguments: {"code":"```python\nfirst_column = df.iloc[:, 0]\n```"}
# PythonRunner 代碼運行報錯
name: Executor
tool response: Traceback (most recent call last):
File "/User/user/go/src/github.com/cloudwego/eino-examples/adk/multiagent/integration-excel-agent/playground/00f118af-4bd8-42f7-8d11-71f2801218bd/00f118af-4bd8-42f7-8d11-71f2801218bd.py", line 1, in <module>
first_column = df.iloc[:, 0]
^^
NameError: name 'df' is not defined
# ReAct 模式自動糾錯,修正無法運行的代碼
name: Executor
answer: The error occurs because the DataFrame `df` is not defined. We need to first load the data from the existing CSV file `questions.csv` into `df`. Here's the corrected code:
tool name: PythonRunner
arguments: {"code":"```python\nimport pandas as pd\ndf = pd.read_csv('questions.csv')\nfirst_column = df.iloc[:, 0]\nprint(first_column.head()) # Verify the result\n```"}
# 代碼運行成功,返回運行結果
name: Executor
path: [{SequentialAgent} {plan_execute_replan} {Planner} {execute_replan} {Executor}]
tool response:
0 multiple-choice
1 multiple-choice
2 multiple-choice
3 multiple-choice
4 multiple-choice
Name: type, dtype: object
- Replanner 判斷計劃完成,提交運行結果至 ReportAgent
name: Replanner
answer: {
"is_success": true,
"result": "已成功將'questions.csv'表格中的第一列提取到新的CSV文件'extracted_first_column.csv'中。",
"files": [
{
"desc": "包含原表格第一列數據的新CSV文件",
"path": "extracted_first_column.csv"
}
]
}
- ReportAgent 進行總結,結束執行
name: Report
tool name: SubmitResult
arguments: {
"is_success": true,
"result": "Successfully extracted the first column from questions.csv and saved it to first_column.csv.",
"files": [
{
"path": "/User/user/go/src/github.com/cloudwego/eino-examples/adk/multiagent/integration-excel-agent/playground/00f118af-4bd8-42f7-8d11-71f2801218bd/first_column.csv",
"desc": "A CSV file containing only the first column data from the original questions.csv."
}
]
}
總結
Excel Agent 所呈現的並非“單一智能體”的技巧,而是一套以 Eino ADK 為底座的 Multi-Agent 系統工程化方法論:
- 以 ChatModelAgent 的 ReAct 能力為基石,讓模型“可思考、會調用”。
- 以 WorkflowAgents 的編排能力,讓 Multi-Agent 系統中的每個 Agent 以用户預期的順序運行。
- 以 Planner–Executor–Replanner 的閉環,讓複雜任務“可拆解、能糾錯”。
- 以 History / Session 的數據傳遞機制,讓多 Agent “能協作、可回放”。
💡 立即開始你的智能體開發之旅
- ⌨️ 查看 Excel Agent 源碼:to do
- 📚 查看更多文檔:Eino ADK 文檔
- 🛠️ 瀏覽 ADK 源碼:Eino ADK 源碼
- 💡 探索 ADK 全部示例:Eino ADK Examples
- 🤝 加入開發者社區:與其他開發者交流經驗和最佳實踐
Eino ADK,讓智能體開發變得簡單而強大!
參考資料
[1] ReAct: _https://react-lm.github.io/_
[2] Eino 示例代碼: _https://github.com/cloudwego/eino-examples/tree/main/adk/multiagent/integration-excel-agent_
[3] Eino ADK 文檔: _https://www.cloudwego.io/zh/docs/eino/core\_modules/eino\_adk/_
[4] Eino ADK 源碼: _https://github.com/cloudwego/eino/tree/main/adk_
[5] Eino ADK Examples: _https://github.com/cloudwego/eino-examples/tree/main/adk_