知识目录 / Agent 开发

高级特性:Plan 和 Sub-Agent 的妙用

学习如何使用 Plan 和 Sub-Agent 处理复杂任务,实现任务拆分和并行执行。

高级特性:Plan 和 Sub-Agent 的妙用

前言

在前面的文章中,我们学习了 Agent4J 的基础功能。现在让我们看看两个高级特性:PlanSub-Agent

这两个特性让 Agent 能处理更复杂的任务:

  • Plan:把复杂任务拆分成多个步骤,按顺序执行
  • Sub-Agent:生成子 Agent,并行处理独立的子任务

就像一个项目经理,既能制定计划,又能分配任务给团队成员。

Plan:任务计划

什么是 Plan?

当任务比较复杂时,Agent 会自动创建一个执行计划。计划包含多个步骤,每个步骤都是一个独立的 LLM 调用。

java
agent.createSession()
    .command("请帮我创建一个完整的电商系统,包括用户管理、商品管理、订单管理三个模块")
    .then(new AgentResultHandler() {
        public void onPlanCreated(Plan plan) {
            System.out.println("创建了计划,共 " + plan.getSteps().size() + " 步");
        }
        
        public void onPlanStepStart(Plan plan, int current, int total, String step) {
            System.out.println("开始执行第 " + current + " 步:" + step);
        }
        
        public void onPlanStepComplete(Plan plan, int current, int total, String step, String result) {
            System.out.println("完成第 " + current + " 步");
        }
    })
    .error(e -> e.printStackTrace());

Plan 的工作流程

  1. 分析任务:LLM 分析任务,决定是否需要创建计划
  2. 创建计划:如果需要,LLM 调用 create_plan 工具
  3. 执行步骤:框架按顺序执行每个步骤
  4. 反馈结果:每个步骤的结果会反馈给 LLM
  5. 调整计划:LLM 可能会根据结果调整后续步骤

什么时候会创建 Plan?

LLM 会根据任务的复杂度自动决定是否创建 Plan:

  • 简单任务:直接执行,不需要计划
  • 复杂任务:创建计划,分步骤执行
  • 非常复杂的任务:创建计划,每个步骤可能还会创建子计划

Plan 的回调

java
session.command(task).then(new AgentResultHandler() {
    
    // 计划创建时
    public void onPlanCreated(Plan plan) {
        System.out.println("计划创建,步骤数:" + plan.getSteps().size());
    }
    
    // 计划开始执行时
    public void onPlanExecuted(Plan plan) {
        System.out.println("开始执行计划");
    }
    
    // 每个步骤开始时
    public void onPlanStepStart(Plan plan, int current, int total, String step) {
        System.out.println("步骤 " + current + "/" + total + ":" + step);
    }
    
    // 每个步骤完成时
    public void onPlanStepComplete(Plan plan, int current, int total, String step, String result) {
        System.out.println("步骤 " + current + " 完成,结果:" + result);
    }
    
    // 步骤中调用工具时
    public void onPlanStepTool(Plan plan, ToolDescriptor tool, ToolStatus status) {
        System.out.println("调用工具:" + tool.getName());
    }
    
    // 步骤执行失败时
    public void onPlanStepError(Plan plan, int current, int total, String step, Exception error) {
        System.out.println("步骤 " + current + " 失败:" + error.getMessage());
    }
});

Plan 的实际例子

例子 1:创建项目结构

java
session.command("""
    请创建一个 Spring Boot 项目,要求:
    1. 创建 Maven 项目结构
    2. 创建 pom.xml,包含必要的依赖
    3. 创建主应用类
    4. 创建配置文件
    5. 创建示例 Controller
    """);

Agent 可能会创建这样的计划:

  1. 创建目录结构
  2. 生成 pom.xml
  3. 创建 Application.java
  4. 创建 application.properties
  5. 创建 HelloController.java

例子 2:代码重构

java
session.command("""
    请重构 UserService 类:
    1. 提取公共方法到 BaseService
    2. 使用策略模式重构状态处理
    3. 添加单元测试
    4. 更新文档
    """);

例子 3:数据分析

java
session.command("""
    请分析 sales.csv 文件:
    1. 读取文件,了解数据结构
    2. 清洗数据,处理缺失值
    3. 统计每月销售额
    4. 生成趋势图表
    5. 输出分析报告
    """);

Sub-Agent:子 Agent

什么是 Sub-Agent?

当任务中有多个独立的子任务时,Agent 可以生成子 Agent 来并行处理。

java
session.command("""
    请同时分析这三个文件:
    1. UserController.java
    2. OrderController.java
    3. ProductController.java
    
    告诉我每个 Controller 的功能和潜在问题。
    """);

Agent 可能会生成三个子 Agent,每个负责分析一个文件。

Sub-Agent 的工作流程

  1. 识别子任务:LLM 识别出可以并行处理的子任务
  2. 生成子 Agent:LLM 调用 create_sub_agent 工具
  3. 分配任务:每个子 Agent 负责一个子任务
  4. 并行执行:子 Agent 独立执行任务
  5. 汇总结果:父 Agent 汇总所有子 Agent 的结果

Sub-Agent 的回调

java
session.command(task).then(new AgentResultHandler() {
    
    // 子 Agent 创建时
    public void onSubAgent(AgentClient agent, String message) {
        System.out.println("生成子 Agent:" + agent.getName());
        System.out.println("任务描述:" + message);
    }
    
    // 子 Agent 开始执行时
    public void onSubAgentStart(AgentClient agent, String task) {
        System.out.println("子 Agent 开始执行:" + task);
    }
    
    // 子 Agent 返回结果时
    public void onSubAgentResult(AgentClient agent, String result) {
        System.out.println("子 Agent 完成,结果:" + result);
    }
});

Sub-Agent 的实际例子

例子 1:并行文件分析

java
session.command("""
    请分析以下三个日志文件,找出错误信息:
    1. /var/log/app1.log
    2. /var/log/app2.log
    3. /var/log/app3.log
    """);

例子 2:并行数据处理

java
session.command("""
    请处理以下三个 CSV 文件:
    1. users.csv - 提取用户信息
    2. orders.csv - 提取订单信息
    3. products.csv - 提取商品信息
    
    最后合并成一个完整的数据集。
    """);

例子 3:并行代码生成

java
session.command("""
    请同时生成以下三个模块的代码:
    1. 用户管理模块(entity、dao、service、controller)
    2. 订单管理模块(entity、dao、service、controller)
    3. 商品管理模块(entity、dao、service、controller)
    """);

Plan vs Sub-Agent

什么时候用 Plan,什么时候用 Sub-Agent?

用 Plan 的场景

  1. 任务有依赖关系:后续步骤依赖前面步骤的结果
  2. 需要严格控制顺序:比如先创建数据库,再创建表
  3. 需要人工干预:某些步骤需要人工确认
text
步骤 1 → 步骤 2 → 步骤 3 → 步骤 4
   ↓         ↓         ↓         ↓
 结果 1    结果 2    结果 3    结果 4

用 Sub-Agent 的场景

  1. 子任务相互独立:不依赖其他子任务的结果
  2. 可以并行处理:同时执行可以提高效率
  3. 任务性质相似:都是同类型的任务
text
        主任务
       /  |  \
      /   |   \
  子任务1 子任务2 子任务3
     ↓      ↓      ↓
   结果1  结果2  结果3
       \   |   /
        \  |  /
         汇总结果

组合使用

在实际应用中,Plan 和 Sub-Agent 可以组合使用:

java
session.command("""
    请帮我完成以下任务:
    
    第一阶段:数据准备
    1. 读取原始数据文件
    2. 清洗数据
    3. 生成三个子数据集
    
    第二阶段:并行分析(使用 Sub-Agent)
    4. 分析用户行为数据
    5. 分析销售趋势数据
    6. 分析库存变化数据
    
    第三阶段:报告生成
    7. 汇总分析结果
    8. 生成可视化图表
    9. 输出最终报告
    """);

在这个例子中:

  • 第一阶段和第三阶段用 Plan(有依赖关系)
  • 第二阶段用 Sub-Agent(可以并行)

实际案例:自动化部署

让我们看一个更复杂的例子:自动化部署。

java
session.command("""
    请帮我完成以下部署任务:
    
    1. 检查代码是否有未提交的更改
    2. 运行单元测试
    3. 构建项目(mvn clean package)
    4. 生成 Docker 镜像
    5. 并行部署到三个环境:
       - 开发环境(dev.example.com)
       - 测试环境(test.example.com)
       - 预发布环境(staging.example.com)
    6. 验证部署是否成功
    7. 发送部署通知邮件
    """);

Agent 的执行计划:

text
Plan:
├── Step 1: 检查代码状态
├── Step 2: 运行测试
├── Step 3: 构建项目
├── Step 4: 生成 Docker 镜像
├── Step 5: 并行部署(Sub-Agent)
│   ├── Sub-Agent 1: 部署到 dev
│   ├── Sub-Agent 2: 部署到 test
│   └── Sub-Agent 3: 部署到 staging
├── Step 6: 验证部署
└── Step 7: 发送通知

性能考虑

Plan 的性能

Plan 的每个步骤都是一个独立的 LLM 调用,所以:

  • 步骤越多,耗时越长
  • 每个步骤都会消耗 Token
  • 复杂的计划可能需要几分钟

Sub-Agent 的性能

Sub-Agent 可以并行执行,所以:

  • 可以显著提高效率
  • 但会增加并发请求
  • 需要考虑 API 限流

最佳实践

  1. 合理拆分任务:不要拆得太细,也不要太粗
  2. 识别并行机会:能并行的就并行
  3. 避免不必要的步骤:每个步骤都要有价值
  4. 监控执行过程:通过回调了解进度

错误处理

Plan 的错误处理

如果某个步骤失败,Agent 会:

  1. 记录错误信息
  2. 尝试修复问题
  3. 如果无法修复,可能会跳过该步骤
  4. 继续执行后续步骤
java
session.command(task).then(new AgentResultHandler() {
    public void onPlanStepError(Plan plan, int current, int total, String step, Exception error) {
        System.out.println("步骤 " + current + " 失败:" + error.getMessage());
        // Agent 会尝试自动修复
    }
});

Sub-Agent 的错误处理

如果某个子 Agent 失败,父 Agent 会:

  1. 记录错误信息
  2. 继续等待其他子 Agent 完成
  3. 汇总成功的结果
  4. 报告失败的子任务

总结

Plan 和 Sub-Agent 是 Agent4J 的两个强大特性:

  • Plan:把复杂任务拆分成步骤,按顺序执行
  • Sub-Agent:并行处理独立的子任务,提高效率

合理使用这两个特性,可以让 Agent 处理更复杂的任务,提高执行效率。

在下一篇文章中,我们将学习会话管理与持久化。


项目地址https://github.com/onlyGuo/agent4j

上一篇实战案例:用 Agent4J 构建全栈项目

下一篇会话管理与持久化:保存和恢复对话