---
Description: ""
date: "2025-12-02"
lastmod: ""
tags: []
title: 用 Eino ADK 构建你的第一个 AI 智能体：从 Excel Agent 实战开始
weight: 7
---

## 从 Excel Agent 详解 Eino ADK

本文将会向您介绍如何利用 **Eino ADK** (**Agent Development Kit**) 构建一个强大的多智能体系统，往期 Eino ADK 介绍链接：[Eino ADK：一文搞定 AI Agent 核心设计模式，从 0 到 1 搭建智能体系统](https://mp.weixin.qq.com/s/ffGjlDEzEzroo8w6knlLqw)

示例以 Excel Agent 这个实际业务场景为基础，Excel Agent 是一个能够“听懂你的话、看懂你的表格、写出并执行代码”的智能助手。它把复杂的 Excel 处理工作拆解为清晰的步骤，通过自动规划、工具调用与结果校验，稳定完成各项 Excel 数据处理任务。

接下来我们将从 Excel Agent 的完整架构与功能出发，向您展示该 Agent 是如何通过 Eino ADK 逐步搭建的，进而深入浅出的理解 Eino ADK 的核心设计特点，助您快速上手 Eino ADK，向构建自定义智能体与 AI 应用系统更进一步。

本示例完整代码位于 [Github](https://github.com/cloudwego/eino-examples/tree/main/adk/multiagent/integration-excel-agent)，您可以随时浏览与下载。

### Excel Agent 是什么？

Excel Agent 是一个“看得懂 Excel 的智能助手”，它先把问题拆解成步骤，再一步步执行并校验结果。它能理解用户问题与上传的文件内容，提出可行的解决方案，并选择合适的工具（系统命令、生成并运行 Python 代码、网络查询等等）完成任务。

Excel Agent 整体是基于 Eino ADK 实现的 Multi-Agent 系统，完整架构如下图所示：

<a href="/img/eino/eino_adk_excel_agent_architecture.png" target="_blank"><img src="/img/eino/eino_adk_excel_agent_architecture.png" width="100%" /></a>

Excel Agent 内部包含的几个 Agent 功能分别为：

- **Planner**：分析用户输入，拆解用户问题为可执行的计划
- **Executor**：正确执行当前计划中的首个步骤
- **CodeAgent**：接收来自 Executor 的指令，调用多种工具（例如读写文件，运行 python 代码等）完成任务
- **WebSearchAgent**：接收来自 Executor 的指令，进行网络搜索
- **Replanner**：根据 Executor 执行的结果和现有规划，决定继续执行、调整规划或完成执行
- **ReportAgent**：根据运行过程与结果，生成总结性质的报告

### Excel Agent 的典型使用场景

在真实业务里，你可以把 Excel Agent 当成一位“Excel 专家 + 自动化工程师”。当你交付一个原始表格和目标描述，它会给出方案并完成执行：

- **数据清理与格式化**：从一个包含大量数据的 Excel 文件中完成去重、空值处理、日期格式标准化操作。
- **数据分析与报告生成**：从销售数据中提取每月的销售总额，聚合统计、透视，最终生成并导出图表报告。
- **自动化预算计算**：根据不同部门的预算申请，自动计算总预算并生成部门预算分配表。
- **数据匹配与合并**：将多个不同来源的客户信息表进行匹配合并，生成完整的客户信息数据库。

Excel Agent 的完整运行动线为：

<a href="/img/eino/eino_adk_excel_agent_complete.png" target="_blank"><img src="/img/eino/eino_adk_excel_agent_complete.png" width="100%" /></a>

> 💡
> **核心收益**：
>
> - **更少的人工操作**，把复杂繁琐的 Excel 处理工作交给 Agent 自动完成。
> - **更稳定的产出质量**，通过“规划—执行—反思”闭环减少漏项与错误。
> - **更强的可扩展性**，各 Agent 独立构建，低耦合利于迭代更新。

Excel Agent 既可以单独使用，也可以作为子 Agent，集成在一个复合的多专家系统中，由外部路由到此 Agent 上，解决 excel 领域相关的问题。

下面我们将逐步拆解 Excel Agent，深入了解 Eino ADK 的核心设计特点，以及如何利用这些特点构建高效、灵活的 AI 应用系统。

### ChatModelAgent：与 LLM 交互的基石

`ChatModelAgent` 是 Eino ADK 中的一个核心预构建的 Agent，内部使用了 [ReAct](https://react-lm.github.io/) 模式（一种让模型‘思考-行动-观察’的链式推理模式）：

<a href="/img/eino/eino_adk_react_pattern.png" target="_blank"><img src="/img/eino/eino_adk_react_pattern.png" width="100%" /></a>

`ChatModelAgent` 旨在让 ChatModel 进行显式的、一步一步的“思考”，结合思考过程驱动行动，观测历史思考过程与行动结果继续进行下一步的思考与行动，最终解决复杂问题：

- 调用 ChatModel（Reason）
- LLM 返回工具调用请求（Action）
- ChatModelAgent 执行工具（Act）
- 将工具结果返回给 LLM（Observation），结合之前的上下文继续生成，直到模型判断不需要调用工具后结束

<a href="/img/eino/eino_adk_excel_chat_model_agent_view.png" target="_blank"><img src="/img/eino/eino_adk_excel_chat_model_agent_view.png" width="100%" /></a>

在 Excel Agent 中，每个 Agent 的核心都是这样一个 `ChatModelAgent`，以 Executor 运行【读取用户输入表格的头信息】这个步骤为例 ，我们可以通过观察完整的运行过程来理解 ReAct 模式在 `ChatModelAgent` 中的表现：

1. Executor：经过判断，将任务转交给 CodeAgent 运行
2. CodeAgent：接收到任务【读取用户输入表格的头信息】
   1. **Think-1**：上下文未提供工作目录下的所有文件，需要查看
   2. **Act-1**: 调用 Bash 工具，ls 查看工作目录下的所有文件
   3. **Think-2**: 找到了用户输入的文件，判断需要编写 Python 代码读取 xlsx 表格的首行
   4. **Act-2**: 调用 PythonRunner 工具，书写代码并运行，获取运行结果
   5. **Think-3**: 获取到了 xlsx 首行，判断任务完成
3. 运行完成，将表格头信息返回给 Executor

### Plan-Execute Agent：基于「规划-执行-反思」的多智能体协作框架

Plan-Execute Agent 是 Eino ADK 中一种基于「规划-执行-反思」范式的多智能体协作框架，旨在解决复杂任务的分步拆解、执行与动态调整问题。它通过 **Planner（规划器）**、**Executor（执行器）**和 **Replanner（重规划器）** 三个核心智能体的协同工作，实现任务的结构化规划、工具调用执行、进度评估与动态 replanning，最终达成用户目标：

```go
// 完整代码: 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)
```

<a href="/img/eino/eino_adk_why_excel_plan_executor.png" target="_blank"><img src="/img/eino/eino_adk_why_excel_plan_executor.png" width="100%" /></a>

而 Excel Agent 的核心能力恰好为【解决用户在 excel 领域的问题】，与该智能体协作框架定位一致：

- **规划者**（**Planner**）：明确目标，自动拆解可执行步骤
- **执行者（Executor）**：调用工具（Excel 读取、系统命令、Python 代码）完成规划中的每一个详细步骤
- **反思者（Replanner）**：根据执行进度决定继续、调整规划或结束

Planner 和 Replanner 会将用户模糊的指令拆解为清晰的、可执行的步骤清单，即包含多个步骤（Step）的计划（Plan），Eino ADK 为此提供了灵活的 Plan 接口定义，支持用户自定义 Plan 结构与细节：

```go
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 产生的一个完整运行计划：

```sql
### 任务计划
- [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 的情况：

1. **顺序运行**：先运行 Planner，再运行 Executor 和 Replanner；Planner 只运行一次。
2. **循环运行**：Executor 和 Replanner 需要按需循环运行多次，每次循环运行都是先运行 Executor 后运行 Replanner
3. **顺序运行**：Plan-Executor 整体运行完后，固定运行一次 ReportAgent 进行总结。

对于这些拥有固定执行流程的场景，Eino ADK 提供了三种流程编排方式，协助用户快速搭建可控的工作流：

- **SequentialAgent**：按照配置中提供的顺序，依次执行一系列子 Agent。每个子 Agent 执行完成后，其输出会通过 History 机制传递给下一个子 Agent，形成一个线性的执行链。

  ```go
  import github.com/cloudwego/eino/adk

  // 依次执行 制定研究计划 -> 搜索资料 -> 撰写报告
  sequential := adk.NewSequentialAgent(ctx, &adk.SequentialAgentConfig{
      Name: "research_pipeline",
      SubAgents: []adk.Agent{
          planAgent,    // 制定研究计划
          searchAgent,  // 搜索资料
          writeAgent,   // 撰写报告
      },
  })
  ```

<a href="/img/eino/eino_adk_excel_agent_sequential.png" target="_blank"><img src="/img/eino/eino_adk_excel_agent_sequential.png" width="100%" /></a>

- **LoopAgent**：重复执行配置的子 Agent 序列，直到达到最大迭代次数或某个子 Agent 产生 ExitAction，每次迭代的结果都会累积，后续迭代的输入可以访问所有历史信息。LoopAgent 基于 SequentialAgent 实现。

  ```go
  import github.com/cloudwego/eino/adk

  // 循环执行 5 次，每次顺序为：分析当前状态 -> 提出改进方案 -> 验证改进效果
  loop := adk.NewLoopAgent(ctx, &adk.LoopAgentConfig{
      Name: "iterative_optimization",
      SubAgents: []adk.Agent{
          analyzeAgent,  // 分析当前状态
          improveAgent,  // 提出改进方案
          validateAgent, // 验证改进效果
      },
      MaxIterations: 5,
  })
  ```

<a href="/img/eino/eino_adk_loop_agent_max_iterations_example.png" target="_blank"><img src="/img/eino/eino_adk_loop_agent_max_iterations_example.png" width="100%" /></a>

- **ParallelAgent**：允许多个子 Agent 基于相同的输入上下文并发执行。所有子 Agent 接收相同的初始输入，各自在独立的 goroutine（Go 语言中一种轻量级的并发执行单元） 运行，最终收集所有子 Agent 的执行结果并按顺序输出到 `AsyncIterator` 中。

  ```go
  import github.com/cloudwego/eino/adk

  // 并发执行 情感分析 + 关键词提取 + 内容摘要
  parallel := adk.NewParallelAgent(ctx, &adk.ParallelAgentConfig{
      Name: "multi_analysis",
      SubAgents: []adk.Agent{
          sentimentAgent,  // 情感分析
          keywordAgent,    // 关键词提取
          summaryAgent,    // 内容摘要
      },
  })
  ```

<a href="/img/eino/eino_adk_yet_another_parallel.png" target="_blank"><img src="/img/eino/eino_adk_yet_another_parallel.png" width="100%" /></a>

### Agent 抽象：灵活定义 Agent 的基础

Eino ADK 的核心是一个简洁而强大的 Agent 接口，每个 Agent 都有明确的身份（Name）、清晰的职责（Description）和标准化的执行方式（Run），为 Agent 之间的发现与调用提供了基础。无论是简单的问答机器人，还是复杂的多步骤任务处理系统，都可以通过这个统一的接口加以实现。

- **统一的 Agent 抽象**：ADK 提供的预构建 Agent（ChatModelAgent，Plan-Execute Agent，Workflow Agents）都遵循该接口定义。您也可以基于该接口，书写自定义 Agent，完成定制化需求。

  ```go
  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 接收的输入一致：

  ```go
  type AgentInput struct {
      Messages        []Message
      EnableStreaming bool
  }

  type Message = *schema.Message // *schema.Message 是模型输入输出的结构定义
  ```
- **异步事件驱动输出**：Agent 的输出是一个 AgentEvent 的异步迭代器，其中的 AgentEvent 表示 Agent 在其运行过程中产生的核心事件数据。其中包含了 Agent 的元信息、输出、行为和报错信息：

  ```go
  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 调用模型结果、工具运行结果、中间状态等等），同时调用方以一种有序、阻塞的方式消费这一系列事件：

```go
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 的上下文混乱。

<a href="/img/eino/eino_adk_history.png" target="_blank"><img src="/img/eino/eino_adk_history.png" width="100%" /></a>

- **共享 Session**：单次运行过程中持续存在的 KV 存储，用于支持跨 Agent 的状态管理和数据共享，一次运行中的任何 Agent 可以在任何时间读写 SessionValues。以 Plan-Execute Agent 模式为例，Planner 生成首个计划并写入 Session；Executor 从 Session 读取计划并执行；Replanner 从 Session 读取当前计划后，结合运行结果，将更新后的计划写回 Session 覆盖当前的计划。

  ```go
  // 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
  ```

<a href="/img/eino/eino_adk_plan_execute_replan_session.png" target="_blank"><img src="/img/eino/eino_adk_plan_execute_replan_session.png" width="100%" /></a>

除了完善的 Agent 间数据传递机制，Eino ADK 从实践出发，提供了多种 Agent 协作模式：

- **预设 Agent 运行顺序（Workflow）**：以代码中预设好的流程运行， Agent 的执行顺序是事先确定、可预测的。对应 Workflow Agents 章节提到的三种范式。
- **移交运行（Transfer）**：携带本 Agent 输出结果上下文，将任务移交至子 Agent 继续处理。适用于智能体功能可以清晰的划分边界与层级的场景，常结合 ChatModelAgent 使用，通过 LLM 的生成结果进行动态路由。结构上，以此方式进行协作的两个 Agent 称为父子 Agent：

<a href="/img/eino/eino_adk_excel_transfer.png" target="_blank"><img src="/img/eino/eino_adk_excel_transfer.png" width="100%" /></a>

```go
// 设置父子 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 的普通工具。

<a href="/img/eino/eino_adk_agent_as_tool_case.png" target="_blank"><img src="/img/eino/eino_adk_agent_as_tool_case.png" width="100%" /></a>

```go
// 将 Agent 转换为 Tool
func NewAgentTool(_ context.Context, agent Agent, options ...AgentToolOption) tool.BaseTool
```

## Excel Agent 示例运行

### 配置环境与输入输出路径

- 环境变量：Excel Agent 运行依赖的完整环境变量可参考项目 README。
- 运行输入：包括一段用户需求描述和待处理的一系列文件，其中：

  - `main.go` 中首行表示用户输入的需求描述，可自行修改：

    ```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` 路径下提供了几个示例文件，您可以将文件复制到附件输入路径下来进行测试运行：

    ```go
    % 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 中` 这个任务为例，运行完成后在工作目录下的文件包含：

<a href="/img/eino/eino_adk_excel_directory.png" target="_blank"><img src="/img/eino/eino_adk_excel_directory.png" width="100%" /></a>

1. 原始输入：从输入路径获取到的 `question.csv`
2. Planner / Replanner 给出的运行计划：`plan.md`

   ```go
   ### 任务计划
   - [x] 1. {"desc":"Read the 'questions.csv' file into a pandas DataFrame."}
   - [x] 2. Save the extracted first column to a new CSV file.
   ```
3. Executor 中的 CodeAgent 书写的代码：`$uuid.py`

   ```go
   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_)
   ```
4. 运行中间产物：`extracted_first_column.csv` 和 `first_column.csv`

   ```go
   type
   multiple-choice
   ...
   short-answer
   ```
5. 最终报告：`final_report.json`

   ```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 格式的初始计划

  ```yaml
  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 作为工具进行调用，执行计划中的首个步骤

  ```yaml
  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 模式自动纠错，修正代码中的错误

  ```yaml
  # 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

  ```yaml
  name: Replanner
  answer: {
      **"is_success"**: **true**,
      **"result"**: **"已成功将'questions.csv'表格中的第一列提取到新的CSV文件'extracted_first_column.csv'中。"**,
      **"files"**: [
          {
              **"desc"**: **"包含原表格第一列数据的新CSV文件"**,
              **"path"**: **"extracted_first_column.csv"**
          }
      ]
  }
  ```
- ReportAgent 进行总结，结束执行

  ```yaml
  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 源码：[Github Excel Agent 源码](https://github.com/cloudwego/eino-examples/tree/main/adk/multiagent/integration-excel-agent)
> - 📚 查看更多文档：[Eino ADK 文档](https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/)
> - 🛠️ 浏览 ADK 源码：[Eino ADK 源码](https://github.com/cloudwego/eino/tree/main/adk)
> - 💡 探索 ADK 全部示例：[Eino ADK Examples](https://github.com/cloudwego/eino-examples/tree/main/adk)
> - 🤝 加入开发者社区：与其他开发者交流经验和最佳实践
>
> Eino ADK，让智能体开发变得简单而强大！

<a href="/img/eino/eino_adk_excel_agent_user_group.png" target="_blank"><img src="/img/eino/eino_adk_excel_agent_user_group.png" width="100%" /></a>
