阿里开源AgentScope多智能体框架解析系列(一)第1章:AgentScope-Java 概述与快速入门

总述

AgentScope-Java 是一个生产级的AI智能体编程框架 ,用Java构建LLM驱动的智能应用。它不仅提供了基础的Agent-模型-工具三角交互,更重要的是提供了企业级生产必需的运行时控制、内置工具、协议集成和可观测性

本章我们将从**What(是什么)、Why(为什么)、How(怎样用)**三个维度理解AgentScope-Java,并通过具体的生产场景示例展示框架如何解决真实问题。

主架构设计图

graph TB User[用户/应用] --> Agent[Agent接口层] Agent --> ReActAgent[ReActAgent
推理-行动循环] Agent --> UserAgent[UserAgent
用户交互] Agent --> OtherAgents[其他Agent实现] ReActAgent --> Model[Model层
LLM调用] ReActAgent --> Memory[Memory层
记忆管理] ReActAgent --> Toolkit[Toolkit层
工具管理] ReActAgent --> Hook[Hook系统
事件拦截] Model --> DashScope[DashScope] Model --> OpenAI[OpenAI] Model --> Anthropic[Anthropic] Model --> Gemini[Gemini] Model --> Formatter[Formatter
消息格式化] Memory --> InMemory[InMemoryMemory] Memory --> LongTerm[LongTermMemory] Memory --> Session[Session持久化] Toolkit --> ToolRegistry[ToolRegistry
工具注册表] Toolkit --> ToolExecutor[ToolExecutor
工具执行器] Toolkit --> MCP[MCP集成] Hook --> RAGHook[RAG Hook] Hook --> PlanHook[Plan Hook] Hook --> MemoryHook[Memory Hook] Hook --> CustomHook[自定义Hook] ReActAgent --> Pipeline[Pipeline
多智能体协作] ReActAgent --> Interruption[Interruption
中断机制] ReActAgent --> Tracing[Tracing
可观测性] style Agent fill:#e1f5ff style ReActAgent fill:#fff4e1 style Model fill:#e8f5e9 style Memory fill:#f3e5f5 style Toolkit fill:#fff9c4 style Hook fill:#ffe0b2

核心功能时序图

1. ReActAgent 执行流程

sequenceDiagram participant User as 用户 participant Agent as ReActAgent participant Hook as Hook系统 participant Model as LLM模型 participant Toolkit as 工具箱 participant Memory as 记忆系统 User->>Agent: call(msg) Agent->>Memory: 添加用户消息 loop 推理-行动循环 Agent->>Hook: PreReasoningEvent Hook-->>Agent: 处理钩子 Agent->>Memory: 获取历史消息 Memory-->>Agent: 返回消息列表 Agent->>Model: 请求推理 Model-->>Agent: 返回思考+工具调用 Agent->>Hook: PostReasoningEvent Hook-->>Agent: 处理钩子 alt 需要调用工具 Agent->>Hook: PreActingEvent Hook-->>Agent: 处理钩子 Agent->>Toolkit: 执行工具 Toolkit-->>Agent: 工具结果 Agent->>Hook: PostActingEvent Hook-->>Agent: 处理钩子 Agent->>Memory: 保存工具结果 else 无需工具调用 Agent->>Memory: 保存最终回答 Agent-->>User: 返回结果 end end

2. 工具调用流程

sequenceDiagram participant Agent as ReActAgent participant Toolkit as Toolkit participant Registry as ToolRegistry participant Executor as ToolExecutor participant Tool as 实际工具方法 participant Context as ExecutionContext Agent->>Toolkit: 调用工具 Toolkit->>Registry: 查找工具定义 Registry-->>Toolkit: 返回工具元数据 Toolkit->>Executor: 准备执行 Executor->>Context: 设置执行上下文 Executor->>Tool: 反射调用方法 Tool-->>Executor: 返回结果 Executor->>Context: 清理上下文 Executor-->>Toolkit: 返回执行结果 Toolkit-->>Agent: 返回格式化结果

3. Hook 系统执行流程

sequenceDiagram participant Agent as ReActAgent participant HookChain as Hook链 participant RAGHook as RAG Hook participant MemoryHook as Memory Hook participant PlanHook as Plan Hook participant Model as LLM模型 Agent->>HookChain: 触发PreReasoningEvent HookChain->>RAGHook: handle(event) RAGHook->>RAGHook: 检索相关知识 RAGHook->>HookChain: 添加知识到提示词 HookChain->>MemoryHook: handle(event) MemoryHook->>MemoryHook: 检索长期记忆 MemoryHook->>HookChain: 添加记忆到提示词 HookChain->>PlanHook: handle(event) PlanHook->>PlanHook: 获取当前计划 PlanHook->>HookChain: 添加计划提示 HookChain-->>Agent: 返回增强后的消息 Agent->>Model: 发送请求

4. 流式响应处理流程

sequenceDiagram participant User as 用户 participant Agent as ReActAgent participant Model as LLM模型 participant Accumulator as ContentAccumulator participant Stream as 事件流 User->>Agent: stream(msg, options) Agent->>Model: 请求流式响应 loop 流式接收 Model-->>Agent: ChatResponse chunk Agent->>Accumulator: 累积内容 alt 推理阶段 Accumulator->>Stream: ReasoningChunkEvent Stream-->>User: 实时推理内容 else 行动阶段 Accumulator->>Stream: ActingChunkEvent Stream-->>User: 实时执行内容 end end Model-->>Agent: 最终响应 Agent->>Stream: 完整事件(isLast=true) Stream-->>User: 最终结果

5. 中断与恢复流程

sequenceDiagram participant User as 用户 participant Agent as ReActAgent participant Context as InterruptContext participant Tool as 工具执行 participant Memory as 记忆系统 User->>Agent: call(msg) Agent->>Tool: 执行长时工具 User->>Agent: interrupt() Agent->>Context: 设置中断标志 Tool->>Context: 检查中断状态 Context-->>Tool: 已中断 Tool-->>Agent: 取消执行 Agent->>Memory: 保存中断状态 Agent-->>User: 返回中断信息 User->>Agent: call() 继续执行 Agent->>Memory: 恢复上下文 Agent->>Tool: 重新执行或跳过 Tool-->>Agent: 完成 Agent-->>User: 返回结果

1.1 项目背景与设计理念

1.1.1 为什么需要AgentScope-Java?

在使用LLM构建智能应用的过程中,开发者通常面临以下核心痛点

问题1:LLM的自主性与可控性矛盾

场景:你为一个电商平台构建了一个自主AI助手,它可以自主查询商品、推荐产品、处理订单。但当助手错误地向用户承诺了不合理的优惠或承诺了不能实现的服务时,你无法立即干预。

AgentScope解决方案

  • 安全中断:在任意时刻暂停Agent,完整保留上下文和工具状态,支持无损恢复
  • 优雅取消:终止长时间运行的工具调用,不破坏Agent状态
  • 人机协同:通过Hook系统在任何推理步骤注入修正、额外上下文或指导
graph LR A["自主决策循环"] -->|发现问题| B["暂停"] B -->|人工审核| C["修正/取消"] C -->|恢复上下文| D["继续执行"]

问题2:多步骤复杂任务的结构化管理

场景:用户请求Agent完成一个涉及10个步骤的复杂工作流(如数据分析 → 生成报告 → 发送邮件)。当中间某一步失败时,你很难追踪当前进度、修改计划或恢复执行。

AgentScope解决方案

  • PlanNotebook:结构化任务管理,自动跟踪多步骤工作流
  • 支持动态修改、暂停、恢复、并发执行多个计划
  • 与Agent推理集成,智能体可以主动创建和修改自己的计划
graph TB Plan["计划(Plan)"] Plan --> SubTask1["子任务1:准备数据"] Plan --> SubTask2["子任务2:生成图表"] Plan --> SubTask3["子任务3:撰写总结"] SubTask1 --> Status1["状态:待执行/进行中/完成/放弃"] SubTask2 --> Status2["状态:待执行/进行中/完成/放弃"] SubTask3 --> Status3["状态:待执行/进行中/完成/放弃"]

问题3:LLM输出的不可靠性

场景:你要求Agent调用一个API并返回JSON格式的数据,但LLM可能会:

  • 返回格式错误的JSON
  • 遗漏某些必需字段
  • 在字段中包含不符合类型的值

你需要一个自纠错的解决方案,而不是编写复杂的验证和重试逻辑。

AgentScope解决方案

  • 结构化输出:自动验证LLM输出,如果不符合预期格式,自动重试并指导LLM生成正确输出
  • 直接映射到Java POJO,实现类型安全
  • 减少人工解析和验证的代码量

问题4:知识库与LLM的集成

场景:你的AI助手需要基于企业内部的知识库(如FAQ、文档、培训资料)回答问题,但简单地将所有文档放入Prompt会导致Token溢出和回答不精准。

AgentScope解决方案

  • RAG(检索增强生成):智能检索相关文档,作为回答依据
  • 支持多知识库集成(自建、阿里云百炼、Dify等)
  • 通过Hook或Tool形式集成,透明地增强Agent能力

问题5:工具生态碎片化

场景:你的Agent需要集成多个外部服务(OpenAI API、企业内部服务、MCP生态的工具)。每次新增工具时,都需要重新编写集成代码。

AgentScope解决方案

  • MCP协议集成:连接到MCP生态的任何工具和服务
  • A2A协议:分布式多Agent协作,通过服务注册中心自动发现和调用
  • 统一的工具系统:无论是本地@Tool还是MCP工具,都通过统一接口调用

1.1.2 核心设计理念

理念1:响应式非阻塞架构

AgentScope-Java基于Project Reactor构建,所有操作都是非阻塞的:

复制代码
业务意义:
├─ 高吞吐量:一个线程可以处理数千个并发Agent
├─ 低延迟:充分利用CPU,避免线程阻塞浪费
├─ 良好扩展性:支持Serverless、容器编排等云原生部署
└─ 可观测性更好:异步操作更容易追踪和监控

代码体现:

java 复制代码
// 所有操作返回 Mono<T> 或 Flux<T>
Mono<Msg> response = agent.call(userMessage);
response.subscribe(msg -> System.out.println(msg.getTextContent()));

// 支持链式异步操作
agent.call(msg1)
    .flatMap(response -> agent.call(response))
    .subscribe();

理念2:消息驱动通信

Agent之间通过**不可变的Message对象(Msg)**通信,而不是直接调用:

复制代码
优势:
├─ 解耦:Agent不需要知道其他Agent的内部实现
├─ 可追踪:所有通信都记录为消息,便于调试和审计
├─ 支持存储:消息可以被持久化、重放、分析
└─ 支持扩展:消息可以包含多种内容类型(文本、图片、音频、工具调用等)

理念3:可组合与可扩展

  • Agent可组合:可以在Pipeline中组织多个Agent,实现复杂的协作模式
  • 工具可扩展:通过@Tool注解轻松添加新工具,或集成MCP/A2A工具
  • Hook可插拔:在Agent执行的任何阶段插入自定义逻辑,而不修改核心代码

1.2 核心特性介绍

1.2.1 ReAct 推理-行动循环

ReAct(Reasoning + Acting) 是AgentScope的核心,它让Agent能够自主规划和执行任务。

什么是ReAct?

ini 复制代码
第1轮:
用户: "帮我分析过去12个月的销售数据"
↓
[推理阶段] Agent思考: "我需要查询销售数据库,然后分析数据,最后生成报告"
↓
[行动阶段] Agent执行: 调用 query_sales_data 工具,获得数据
↓
[结果] 获得JSON格式的销售数据

第2轮:
[推理阶段] Agent思考: "现在我有数据了,我需要计算增长率、趋势等"
↓
[行动阶段] Agent执行: 调用 analyze_data 工具
↓
[结果] 获得分析结果

第3轮:
[推理阶段] Agent思考: "分析完成了,现在生成报告"
↓
[行动阶段] Agent执行: 调用 generate_report 工具
↓
[结果] 最终报告生成完成

为什么ReAct比Prompt Chaining更优?

方面 Prompt Chaining ReAct
灵活性 固定的步骤 动态决定下一步
适应性 无法处理出错情况 可以重试或改变策略
工具利用 预定义的工具序列 动态选择最合适的工具
可控性 很难干预 支持在任意步骤暂停和修正

生产场景示例:客服工单处理

bash 复制代码
用户问题: "我的订单 #12345 已经5天还没收到,我需要退款"
↓
Agent推理:
"我需要:
1. 查询订单状态(调用order_status工具)
2. 根据状态决定是否需要查询物流信息或直接处理退款
3. 生成解决方案"
↓
[工具调用] 查询订单 #12345
结果:订单状态为"已发货,预计3-5天送达",今天是第5天,已超期
↓
Agent推理:
"订单已超期,我需要:
1. 查询物流信息,确认是否丢失
2. 根据结果决定是补邮还是退款"
↓
[工具调用] 查询物流信息
结果:物流显示包裹在运输中,但延迟了
↓
Agent推理:
"物流延迟,我应该为客户自动赔偿100积分,并承诺加急配送。
如果客户坚持退款,触发人工审批"
↓
[工具调用] 给客户加100积分 + 加急配送处理
↓
返回给用户:自动方案 + 人工审批链接

1.2.2 工具调用系统

工具是Agent执行实际操作的手段。AgentScope提供了简洁而强大的工具系统。

快速定义工具

java 复制代码
// 第1步:创建一个类,添加@Tool注解的方法
public class WeatherTools {
    
    @Tool(name = "get_weather", 
          description = "Get current weather for a city")
    public String getWeather(
        @ToolParam(name = "city", description = "City name") String city,
        @ToolParam(name = "unit", description = "Temperature unit, celsius or fahrenheit") 
            String unit) {
        // 实际的获取天气的逻辑
        return String.format("Weather in %s: 25°%s, Sunny", city, unit);
    }
    
    @Tool(name = "get_forecast", 
          description = "Get 7-day forecast for a city")
    public String getForecast(
        @ToolParam(name = "city", description = "City name") String city) {
        return String.format("7-day forecast for %s: ...", city);
    }
}

// 第2步:注册到工具箱
Toolkit toolkit = new Toolkit();
toolkit.registerObject(new WeatherTools());

// 第3步:传给Agent,就可以自动使用
ReActAgent agent = ReActAgent.builder()
    .toolkit(toolkit)
    .build();

工具系统如何工作?

graph TB A["Agent"] B["推理:我需要查询天气"] C["Model返回:调用 get_weather 工具,参数:city=beijing, unit=celsius"] D["工具系统"] E["ToolRegistry:查找 get_weather 的定义"] F["ToolExecutor:反射调用 WeatherTools.getWeather方法"] G["WeatherTools.getWeather 执行"] H["返回结果给Agent"] A --> B B --> C C --> D D --> E E --> F F --> G G --> H

生产场景:销售订单系统

java 复制代码
public class OrderTools {
    
    @Tool(name = "create_order", description = "Create a new sales order")
    public String createOrder(
        @ToolParam(name = "customer_id") String customerId,
        @ToolParam(name = "items") String itemsJson,  // JSON格式: [{sku, qty, price}]
        @ToolParam(name = "discount_percent", description = "Discount 0-100") int discount) {
        
        // 生产环节:
        // 1. 验证输入
        if (discount < 0 || discount > 100) {
            throw new IllegalArgumentException("Discount must be 0-100");
        }
        
        // 2. 调用订单系统API
        OrderRequest req = new OrderRequest(customerId, itemsJson, discount);
        OrderResponse resp = orderService.createOrder(req);
        
        // 3. 返回结构化结果(方便Agent理解)
        return String.format("Order created: ID=%s, Total=%.2f, Status=%s",
            resp.getOrderId(), resp.getTotalPrice(), resp.getStatus());
    }
    
    @Tool(name = "query_order", description = "Query order status and details")
    public String queryOrder(
        @ToolParam(name = "order_id") String orderId) {
        OrderDetails details = orderService.getOrder(orderId);
        return ObjectMappers.toJson(details);
    }
    
    @Tool(name = "apply_promotion", description = "Apply a promotion code to an order")
    public String applyPromotion(
        @ToolParam(name = "order_id") String orderId,
        @ToolParam(name = "promo_code") String promoCode) {
        
        // 验证promo_code的有效性
        Promotion promo = promotionService.validatePromo(promoCode);
        if (promo == null) {
            return "Promotion code invalid or expired";
        }
        
        // 应用折扣
        ApplyResult result = orderService.applyPromotion(orderId, promo);
        return String.format("Promotion applied: new_total=%.2f, discount=%.2f",
            result.getNewTotal(), result.getDiscount());
    }
}

// 使用示例:
Toolkit toolkit = new Toolkit();
toolkit.registerObject(new OrderTools());

ReActAgent agent = ReActAgent.builder()
    .name("Sales Assistant")
    .sysPrompt("You are a helpful sales assistant. Help customers create orders and apply promotions. " +
               "Never apply discount > 20% unless customer has valid promotion code.")
    .model(model)
    .toolkit(toolkit)
    .build();

// Agent会自动调用这些工具
Msg response = agent.call(
    Msg.builder().textContent(
        "Customer: Zhang Wei wants to buy 2 units of SKU-001 at ¥100 each. " +
        "Create an order and apply promo code WELCOME10")
    .build()
).block();

1.2.3 记忆系统

Agent需要记住对话历史和关键信息,才能在多轮交互中保持上下文。

三层记忆架构

scss 复制代码
┌─────────────────────────────────────────┐
│  短期记忆 (Short-term Memory)            │
│  - 当前会话的所有消息                     │
│  - 最近N轮对话                           │
│  - 用途:即时上下文                       │
└─────────────────────────────────────────┘
               ↓ 当消息堆积时自动压缩
┌─────────────────────────────────────────┐
│  中期记忆 (Medium-term Memory)           │
│  - 重要对话的摘要                        │
│  - 关键决策和结果                        │
│  - 用途:跨越较长时间保留重要信息         │
└─────────────────────────────────────────┘
               ↓
┌─────────────────────────────────────────┐
│  长期记忆 (Long-term Memory)             │
│  - 跨会话的持久化存储                     │
│  - 支持语义搜索(向量化)                │
│  - 用途:学习过去的经验,做出更好的决策   │
└─────────────────────────────────────────┘

生产场景:客户关系管理

java 复制代码
// 场景:一个AI客服需要记住常见客户信息

ReActAgent agent = ReActAgent.builder()
    .name("Customer Service Agent")
    .model(model)
    .toolkit(toolkit)
    // 配置长期记忆:客户会自动记住重要信息
    .withLongTermMemory(
        longTermMemory,
        LongTermMemoryMode.HYBRID  // 自动+主动记录混合模式
    )
    .build();

// 第1次对话(User: Alice)
agent.call(
    Msg.builder().textContent(
        "Hello! I'm Alice from TechCorp. I've been a customer for 3 years. " +
        "We usually buy 100 units of Product X every month. " +
        "This month we need to increase to 200 units.")
    .build()
).block();
// Agent自动记住:Alice / TechCorp / 3年老客户 / 正常订购量100 / 本月200

// 一周后,Alice再次联系
agent.call(
    Msg.builder().textContent("Hi! It's Alice again. Can you remind me what we discussed last week?")
    .build()
).block();

// Agent的长期记忆让它能够:
// ✓ 立即认出Alice是老客户
// ✓ 回忆上周的增量订单需求
// ✓ 做出个性化的服务建议(如:由于你增量订购,这个月可以享受额外2%折扣)

1.2.4 多智能体协作

单个Agent的能力有限,AgentScope支持多个Agent在Pipeline中协作

Pipeline模式

yaml 复制代码
场景:内容创作工作流

用户输入: "写一篇关于AI技术趋势的文章"
       ↓
┌─────────────────────────────────┐
│ Agent 1: 研究员 Agent           │
│ 职责:搜索和整理相关资料          │
└──────────────┬──────────────────┘
               ↓
┌─────────────────────────────────┐
│ Agent 2: 写作 Agent             │
│ 职责:基于研究员的资料进行创作     │
└──────────────┬──────────────────┘
               ↓
┌─────────────────────────────────┐
│ Agent 3: 审核 Agent             │
│ 职责:检查文章的正确性和风格      │
└──────────────┬──────────────────┘
               ↓
           最终文章输出

并行工作流

yaml 复制代码
用户输入: "为我生成一份综合性的年度报告"
       ↓
       ├─→ Agent A: 财务分析      ─┐
       │                           │
       ├─→ Agent B: 市场分析      ─┤─→ 汇总 Agent → 最终报告
       │                           │
       └─→ Agent C: 竞争对手分析  ─┘

生产代码示例

java 复制代码
// 定义三个专业的Agent
ReActAgent researchAgent = ReActAgent.builder()
    .name("Research")
    .sysPrompt("You are a research expert. Search and gather relevant information.")
    .model(model)
    .toolkit(researchToolkit)
    .build();

ReActAgent writerAgent = ReActAgent.builder()
    .name("Writer")
    .sysPrompt("You are a professional writer. Write high-quality content.")
    .model(model)
    .toolkit(writerToolkit)
    .build();

ReActAgent reviewerAgent = ReActAgent.builder()
    .name("Reviewer")
    .sysPrompt("You are an editor. Review and improve content for clarity and style.")
    .model(model)
    .toolkit(reviewerToolkit)
    .build();

// 创建顺序Pipeline:研究 → 写作 → 审核
SequentialPipeline<Msg> pipeline = new SequentialPipeline<>(
    List.of(researchAgent, writerAgent, reviewerAgent),
    (response, nextAgent) -> {
        // 将前一个Agent的输出转为下一个Agent的输入
        return Msg.builder()
            .role(MsgRole.ASSISTANT)
            .content(TextBlock.builder()
                .text("Based on the previous work:\n" + response.getTextContent())
                .build())
            .build();
    }
);

// 执行
Msg result = pipeline.execute(
    Msg.builder().textContent("Write an article about AI trends")
    .build()
).block();

1.3 快速开始示例解析

1.3.1 最小化可工作示例

让我们从最简单的示例开始,一步步理解AgentScope的工作流:

java 复制代码
package com.example;

import io.agentscope.core.ReActAgent;
import io.agentscope.core.message.Msg;
import io.agentscope.core.model.DashScopeChatModel;

public class HelloAgentExample {
    
    public static void main(String[] args) {
        // 第1步:创建模型(连接到LLM)
        DashScopeChatModel model = DashScopeChatModel.builder()
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))  // 从环境变量读取API Key
            .modelName("qwen-plus")  // 使用通义千问Plus模型
            .build();
        
        // 第2步:创建Agent
        ReActAgent agent = ReActAgent.builder()
            .name("Assistant")
            .sysPrompt("You are a helpful AI assistant.")  // 系统提示词
            .model(model)
            .build();
        
        // 第3步:调用Agent
        Msg userMessage = Msg.builder()
            .textContent("你好!请告诉我2024年有哪些重要的科技事件")
            .build();
        
        Msg response = agent.call(userMessage).block();  // .block() 等待响应
        
        // 第4步:获取结果
        System.out.println("Agent: " + response.getTextContent());
    }
}

执行流程详解

scss 复制代码
第1步:创建模型(DashScopeChatModel)
  ├─ 初始化HTTP客户端
  ├─ 配置API Key和模型名称
  └─ 准备与DashScope API通信

第2步:创建Agent(ReActAgent)
  ├─ 初始化系统提示词
  ├─ 设置内存为默认的InMemoryMemory
  ├─ 注册模型和默认工具箱
  └─ 准备好处理用户输入

第3步:创建用户消息(Msg)
  ├─ 设置消息内容为纯文本
  ├─ 默认角色为USER
  └─ 自动生成唯一ID和时间戳

第4步:调用Agent
  agent.call(userMessage) 返回 Mono<Msg>
  .block() 阻塞等待响应(生产环境应使用异步处理)
  └─ 返回Agent的完整响应

第5步:提取并显示结果
  response.getTextContent() 获取文本内容
  └─ 输出:Agent生成的回答

1.3.2 使用工具的示例

上一个示例中,Agent只能通过对话回答。现在让我们添加工具能力,让Agent能够执行实际操作:

java 复制代码
package com.example;

import io.agentscope.core.ReActAgent;
import io.agentscope.core.message.Msg;
import io.agentscope.core.model.DashScopeChatModel;
import io.agentscope.core.tool.Tool;
import io.agentscope.core.tool.ToolParam;
import io.agentscope.core.tool.Toolkit;

public class AgentWithToolsExample {
    
    // 第1步:定义工具类
    public static class CalculatorTools {
        
        @Tool(name = "add", description = "Add two numbers")
        public String add(
            @ToolParam(name = "a", description = "First number") double a,
            @ToolParam(name = "b", description = "Second number") double b) {
            return String.valueOf(a + b);
        }
        
        @Tool(name = "multiply", description = "Multiply two numbers")
        public String multiply(
            @ToolParam(name = "a", description = "First number") double a,
            @ToolParam(name = "b", description = "Second number") double b) {
            return String.valueOf(a * b);
        }
    }
    
    public static void main(String[] args) {
        // 第2步:创建模型
        DashScopeChatModel model = DashScopeChatModel.builder()
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .modelName("qwen-plus")
            .build();
        
        // 第3步:创建工具箱并注册工具
        Toolkit toolkit = new Toolkit();
        toolkit.registerObject(new CalculatorTools());
        
        // 第4步:创建Agent并配置工具箱
        ReActAgent agent = ReActAgent.builder()
            .name("MathAssistant")
            .sysPrompt("You are a helpful math assistant. " +
                      "Use the calculator tools to solve math problems.")
            .model(model)
            .toolkit(toolkit)  // 传入工具箱
            .build();
        
        // 第5步:调用Agent
        Msg response = agent.call(
            Msg.builder().textContent("25乘以48等于多少?")
            .build()
        ).block();
        
        System.out.println("Result: " + response.getTextContent());
    }
}

带工具调用的执行流程

css 复制代码
用户: "25乘以48等于多少?"
  ↓
[推理阶段]
Agent收到问题,思考:需要调用 multiply(25, 48)
Model返回:{"tool_call": "multiply", "args": {"a": 25, "b": 48}}
  ↓
[行动阶段]
ToolExecutor找到 CalculatorTools.multiply 方法
反射调用:multiply(25.0, 48.0)
得到结果:1200.0
  ↓
[反馈到内存]
Agent记住:multiply(25, 48) = 1200
  ↓
[推理阶段]
Agent继续思考:我已经得到结果了,可以回答用户
Model返回:最终答案的文本
  ↓
[完成]
返回给用户:25乘以48等于1200

1.3.3 包含记忆的对话示例

让我们创建一个能够记住对话历史的Agent:

java 复制代码
package com.example;

import io.agentscope.core.ReActAgent;
import io.agentscope.core.memory.InMemoryMemory;
import io.agentscope.core.message.Msg;
import io.agentscope.core.model.DashScopeChatModel;

public class ConversationWithMemoryExample {
    
    public static void main(String[] args) throws InterruptedException {
        DashScopeChatModel model = DashScopeChatModel.builder()
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .modelName("qwen-plus")
            .build();
        
        // 创建Agent并配置记忆
        ReActAgent agent = ReActAgent.builder()
            .name("Conversational AI")
            .sysPrompt("You are a friendly assistant. Remember the context of conversations.")
            .model(model)
            .memory(new InMemoryMemory())  // 明确创建记忆对象
            .build();
        
        // 第1轮对话
        System.out.println("=== 第1轮对话 ===");
        Msg msg1 = agent.call(
            Msg.builder().textContent("我叫张三,我是一个工程师")
            .build()
        ).block();
        System.out.println("User: 我叫张三,我是一个工程师");
        System.out.println("Agent: " + msg1.getTextContent());
        
        Thread.sleep(1000);  // 等待1秒
        
        // 第2轮对话:Agent应该记得张三的身份
        System.out.println("\n=== 第2轮对话 ===");
        Msg msg2 = agent.call(
            Msg.builder().textContent("我的工作是什么?")
            .build()
        ).block();
        System.out.println("User: 我的工作是什么?");
        System.out.println("Agent: " + msg2.getTextContent());
        // Agent会回答:你是一个工程师,之前告诉我的
        
        // 第3轮对话
        System.out.println("\n=== 第3轮对话 ===");
        Msg msg3 = agent.call(
            Msg.builder().textContent("我最擅长的编程语言是Java。这个信息对我的工作有什么影响?")
            .build()
        ).block();
        System.out.println("User: 我最擅长的编程语言是Java。这个信息对我的工作有什么影响?");
        System.out.println("Agent: " + msg3.getTextContent());
        // Agent能综合前面的信息做出回答
    }
}

记忆如何工作?

scss 复制代码
第1轮对话:
Agent.call(msg) → memory.addMessage(userMsg) + memory.addMessage(agentResponse)
记忆状态:
  [UserMessage: "我叫张三,我是一个工程师"]
  [AssistantMessage: "Nice to meet you, 张三! 很高兴认识你..."]

第2轮对话:
Agent.call(msg) → 
  1. memory.addMessage(userMsg)
  2. memory.getMessages() 返回所有历史消息(包括第1轮)
  3. 将完整的历史消息发送给Model
  4. Model生成响应,记住了张三的身份
  5. memory.addMessage(agentResponse)

记忆状态:
  [UserMessage: "我叫张三,我是一个工程师"]
  [AssistantMessage: "..."]
  [UserMessage: "我的工作是什么?"]
  [AssistantMessage: "根据你之前告诉我..."]

1.4 项目结构与模块划分

1.4.1 整体模块组织

bash 复制代码
agentscope-java/
├── agentscope-core/                          # 核心模块(必需)
│   ├── src/main/java/io/agentscope/core/
│   │   ├── agent/                            # Agent接口和实现
│   │   ├── message/                          # 消息系统(Msg、ContentBlock等)
│   │   ├── model/                            # 模型接口和实现
│   │   ├── tool/                             # 工具系统(@Tool、Toolkit)
│   │   ├── memory/                           # 记忆系统
│   │   ├── hook/                             # Hook系统(事件拦截)
│   │   ├── plan/                             # PlanNotebook任务管理
│   │   ├── rag/                              # RAG检索增强生成
│   │   ├── pipeline/                         # 多Agent协作管道
│   │   ├── session/                          # 会话管理(持久化)
│   │   ├── skill/                            # 技能系统
│   │   ├── interruption/                     # 中断和取消机制
│   │   ├── tracing/                          # 可观测性追踪
│   │   └── ReActAgent.java                   # 核心实现
│   └── pom.xml
│
├── agentscope-extensions/                    # 扩展模块(可选)
│   ├── agentscope-extensions-scheduler/      # 定时调度
│   ├── agentscope-extensions-rag-*/          # 各种RAG集成
│   ├── agentscope-extensions-a2a/            # A2A多Agent协议
│   ├── agentscope-extensions-studio/         # Studio集成
│   ├── agentscope-spring-boot-starters/      # Spring Boot集成
│   └── ...
│
├── agentscope-examples/                      # 示例代码
│   ├── quickstart/                           # 快速开始
│   ├── boba-tea-shop/                        # 完整应用示例
│   ├── werewolf/                             # 游戏示例
│   └── ...
│
└── docs/                                     # 文档
    ├── zh/                                   # 中文文档
    ├── en/                                   # 英文文档
    └── llm/                                  # LLM相关文档

1.4.2 核心模块详解

1. Agent接口层(agent/

bash 复制代码
核心类:
├── Agent                    # 所有Agent的接口
├── AgentBase                # Agent的基础实现
├── ReActAgent               # ReAct推理-行动循环实现
├── UserAgent                # 用户交互Agent
└── StructuredOutputHandler  # 结构化输出处理

职责 :定义Agent的行为和生命周期 关键方法call()observe()interrupt()stream()

2. 消息系统(message/

bash 复制代码
核心类:
├── Msg                      # 消息对象(不可变)
├── MsgRole                  # 消息角色枚举
│   ├── USER                 # 用户消息
│   ├── ASSISTANT            # Agent回复
│   ├── SYSTEM               # 系统消息
│   └── TOOL                 # 工具执行结果
└── ContentBlock及其实现
    ├── TextBlock            # 文本内容
    ├── ImageBlock           # 图像内容
    ├── AudioBlock           # 音频内容
    ├── VideoBlock           # 视频内容
    ├── ToolUseBlock         # 工具调用
    └── ToolResultBlock      # 工具结果

设计特点

  • 不可变设计(Immutable),线程安全
  • 支持多种内容类型(多模态)
  • 元数据支持,用于结构化数据

3. 模型层(model/

bash 复制代码
核心接口/类:
├── Model                    # 模型接口
│   └── stream()  # 流式调用LLM
├── Model实现
│   ├── DashScopeChatModel   # 阿里云通义千问
│   ├── OpenAiChatModel      # OpenAI GPT
│   ├── GeminiChatModel      # Google Gemini
│   └── AnthropicChatModel   # Anthropic Claude
├── GenerateOptions          # 生成参数(temperature、max_tokens等)
├── ChatResponse             # 模型响应
└── Formatter                # 消息格式化器

职责:屏蔽不同LLM的差异,提供统一接口

4. 工具系统(tool/

less 复制代码
核心类:
├── @Tool                    # 工具注解
├── @ToolParam              # 工具参数注解
├── Toolkit                 # 工具箱(管理多个工具)
├── AgentTool               # 工具接口
├── ToolSchema              # 工具定义(发送给LLM的描述)
├── ToolExecutor            # 工具执行器
├── ToolRegistry            # 工具注册表
└── mcp/
    └── McpTool             # MCP协议工具适配

工作流

css 复制代码
@Tool注解 → ToolRegistry(发现) → ToolSchema(生成定义) 
  → Model(选择工具)→ ToolExecutor(执行)→ 结果返回

5. 记忆系统(memory/

bash 复制代码
核心类:
├── Memory                  # 记忆接口
├── InMemoryMemory          # 内存实现
├── LongTermMemory          # 长期记忆(跨会话)
├── LongTermMemoryTools     # LTM相关工具
├── LongTermMemoryMode      # LTM工作模式
└── StaticLongTermMemoryHook# LTM Hook集成

特点

  • 短期记忆:当前对话历史
  • 长期记忆:跨会话持久化存储,支持语义搜索

6. Hook系统(hook/

bash 复制代码
核心类:
├── Hook                    # Hook接口
├── HookEvent               # Hook事件基类
│   ├── PreReasoningEvent   # 推理前
│   ├── ReasoningChunkEvent # 推理流式
│   ├── PostReasoningEvent  # 推理后
│   ├── PreActingEvent      # 行动前
│   ├── ActingChunkEvent    # 行动流式
│   └── PostActingEvent     # 行动后
└── HookChain               # Hook链(责任链模式)

用途:在Agent执行的各个阶段插入自定义逻辑

7. 任务管理(plan/

bash 复制代码
核心类:
├── PlanNotebook            # 计划管理工具
├── Plan                    # 计划模型
├── SubTask                 # 子任务模型
├── PlanState               # 计划状态
└── PlanStorage             # 计划存储抽象
    ├── InMemoryPlanStorage # 内存存储
    └── JsonPlanStorage     # JSON文件存储

8. RAG系统(rag/

bash 复制代码
核心类:
├── Knowledge               # 知识库接口
├── Document                # 文档模型
├── RetrieveConfig          # 检索配置
├── KnowledgeRetrievalTools # RAG工具
└── GenericRAGHook          # RAG Hook集成

9. Pipeline(pipeline/

r 复制代码
核心类:
├── Pipeline<T>             # Pipeline接口
├── SequentialPipeline      # 顺序执行
├── FanoutPipeline          # 并行执行
└── MsgHub                  # 消息中心(多Agent通信)

10. Session(session/

bash 复制代码
核心类:
├── Session                 # Session接口
├── InMemorySession         # 内存Session
├── JsonSession             # JSON文件Session
├── MysqlSession            # MySQL Session
└── RedisSession            # Redis Session

1.5 生产场景详解

1.5.1 场景:智能客服系统

需求

yaml 复制代码
需求:为电商平台构建一个智能客服系统
├─ 功能1:自动回答常见问题(FAQ)
├─ 功能2:处理订单相关查询
├─ 功能3:处理投诉和退货
├─ 功能4:支持知识库检索(RAG)
├─ 功能5:关键问题升级到人工
└─ 约束:每小时处理 1000+ 消息,99.9%可用性

架构设计

graph TB User["用户消息"] User --> Agent["智能客服 Agent"] Agent --> Tools["工具箱"] Tools --> FAQ["FAQ工具"] Tools --> Order["订单查询工具"] Tools --> Return["退货处理工具"] Tools --> Escalate["人工升级工具"] Agent --> Memory["记忆系统"] Memory --> ShortMem["短期:当前对话"] Memory --> LongMem["长期:客户历史"] Agent --> RAG["RAG系统"] RAG --> KB["知识库检索"] Agent --> Monitor["监控和指标"] Output["最终回复"] Agent --> Output

完整代码实现

java 复制代码
package com.example.ecommerce;

import io.agentscope.core.ReActAgent;
import io.agentscope.core.memory.InMemoryMemory;
import io.agentscope.core.memory.LongTermMemory;
import io.agentscope.core.memory.LongTermMemoryMode;
import io.agentscope.core.message.Msg;
import io.agentscope.core.model.DashScopeChatModel;
import io.agentscope.core.rag.Knowledge;
import io.agentscope.core.rag.RAGMode;
import io.agentscope.core.tool.Tool;
import io.agentscope.core.tool.ToolParam;
import io.agentscope.core.tool.Toolkit;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SmartCustomerServiceExample {
    
    // 第1步:定义工具类
    public static class CustomerServiceTools {
        
        private Map<String, String> faqDatabase = new ConcurrentHashMap<>();
        private Map<String, Order> orderDatabase = new ConcurrentHashMap<>();
        
        public CustomerServiceTools() {
            // 初始化FAQ数据库
            faqDatabase.put("shipping", "标准快递3-5天送达,加急1-2天。支持到付和预付。");
            faqDatabase.put("return", "收货后30天内无损产品可无条件退货。已使用产品需扣除使用费。");
            faqDatabase.put("warranty", "所有产品享受1年保修,覆盖生产缺陷但不包括人为损坏。");
        }
        
        @Tool(name = "search_faq", 
              description = "Search FAQ database for common questions")
        public String searchFAQ(
            @ToolParam(name = "question", description = "Customer question or keyword") 
                String question) {
            
            // 简单的关键词匹配(生产环境应使用向量搜索)
            for (Map.Entry<String, String> entry : faqDatabase.entrySet()) {
                if (question.toLowerCase().contains(entry.getKey())) {
                    return String.format("FAQ: %s → %s", entry.getKey(), entry.getValue());
                }
            }
            return "No matching FAQ found for: " + question;
        }
        
        @Tool(name = "query_order", 
              description = "Query order status and details")
        public String queryOrder(
            @ToolParam(name = "order_id", description = "Order ID to query") 
                String orderId) {
            
            Order order = orderDatabase.get(orderId);
            if (order == null) {
                return String.format("Order not found: %s", orderId);
            }
            
            return String.format(
                "Order %s: Status=%s, Total=¥%.2f, Items=%d, " +
                "Created=%s, EstimatedDelivery=%s",
                orderId, order.status, order.total, order.itemCount,
                order.createdTime, order.estimatedDelivery);
        }
        
        @Tool(name = "process_return_request", 
              description = "Initiate a return or refund process")
        public String processReturnRequest(
            @ToolParam(name = "order_id", description = "Order to return") 
                String orderId,
            @ToolParam(name = "reason", description = "Reason for return") 
                String reason,
            @ToolParam(name = "damage_percent", 
                       description = "Damage percentage 0-100, 0=unused, 100=unusable") 
                int damagePercent) {
            
            if (damagePercent < 0 || damagePercent > 100) {
                return "Invalid damage_percent. Must be 0-100.";
            }
            
            Order order = orderDatabase.get(orderId);
            if (order == null) {
                return String.format("Order not found: %s", orderId);
            }
            
            // 计算退款金额
            double refundRate = 1.0 - (damagePercent / 100.0);
            double refundAmount = order.total * refundRate;
            
            // 更新订单状态
            order.status = "RETURN_PROCESSING";
            
            return String.format(
                "Return request created: Order=%s, Reason=%s, " +
                "RefundAmount=¥%.2f, RefundRate=%.0f%%, " +
                "Status=RETURN_PROCESSING. Refund will be processed within 3-5 days.",
                orderId, reason, refundAmount, refundRate * 100);
        }
        
        @Tool(name = "escalate_to_human", 
              description = "Escalate issue to human agent")
        public String escalateToHuman(
            @ToolParam(name = "reason", description = "Reason for escalation") 
                String reason,
            @ToolParam(name = "priority", description = "Priority: normal, high, urgent") 
                String priority) {
            
            if (!priority.matches("(?i)normal|high|urgent")) {
                return "Invalid priority. Must be: normal, high, or urgent.";
            }
            
            // 生产环境:创建升级工单,分配给人工客服
            return String.format(
                "Escalated to human agent. Reason: %s, Priority: %s. " +
                "Ticket ID: TICKET_%d. " +
                "Average wait time: 5 minutes.",
                reason, priority, System.currentTimeMillis() % 100000);
        }
    }
    
    // 第2步:订单模型
    public static class Order {
        String status;
        double total;
        int itemCount;
        String createdTime;
        String estimatedDelivery;
        
        public Order(String status, double total, int itemCount, 
                     String createdTime, String estimatedDelivery) {
            this.status = status;
            this.total = total;
            this.itemCount = itemCount;
            this.createdTime = createdTime;
            this.estimatedDelivery = estimatedDelivery;
        }
    }
    
    // 第3步:初始化系统
    public static void main(String[] args) {
        System.out.println("=== 智能客服系统启动 ===\n");
        
        // 创建模型
        DashScopeChatModel model = DashScopeChatModel.builder()
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .modelName("qwen-plus")
            .requestTimeout(java.time.Duration.ofSeconds(30))
            .build();
        
        // 创建工具箱
        Toolkit toolkit = new Toolkit();
        CustomerServiceTools tools = new CustomerServiceTools();
        
        // 添加初始测试订单数据
        tools.orderDatabase.put("ORD-20240101-001",
            new Order("DELIVERED", 499.99, 2, "2024-01-01 10:00:00", "2024-01-05"));
        tools.orderDatabase.put("ORD-20240110-002",
            new Order("PROCESSING", 1299.99, 1, "2024-01-10 14:30:00", "2024-01-12"));
        
        toolkit.registerObject(tools);
        
        // 创建Agent(配置长期记忆用于学习客户信息)
        ReActAgent agent = ReActAgent.builder()
            .name("CustomerServiceBot")
            .sysPrompt(
                "You are a professional e-commerce customer service agent. Your responsibilities:\n" +
                "1. Answer FAQs about shipping, returns, warranty, etc.\n" +
                "2. Query order status and provide details\n" +
                "3. Handle return/refund requests fairly and efficiently\n" +
                "4. Escalate complex issues to human agents when necessary\n" +
                "5. Always be polite, professional, and solution-focused\n" +
                "6. When you don't have enough info, ask clarifying questions\n" +
                "\n" +
                "Decision rules:\n" +
                "- For simple FAQ questions: answer from FAQ knowledge\n" +
                "- For order-related: first check order status\n" +
                "- For returns: process if within policy (30 days, condition matters)\n" +
                "- For disputes: escalate if customer is unhappy or value > ¥5000"
            )
            .model(model)
            .toolkit(toolkit)
            .maxIters(5)  // 限制推理循环次数,避免无限循环
            .memory(new InMemoryMemory())
            .build();
        
        // 第4步:模拟客户对话
        simulateConversations(agent);
    }
    
    private static void simulateConversations(ReActAgent agent) {
        // 场景1:简单FAQ查询
        System.out.println("=== 场景1:FAQ查询 ===");
        simulateConversation(agent, 
            "请问你们的标准快递需要多长时间?");
        
        System.out.println("\n=== 场景2:订单状态查询 ===");
        simulateConversation(agent, 
            "我想查询订单 ORD-20240101-001 的状态");
        
        System.out.println("\n=== 场景3:处理退货请求 ===");
        simulateConversation(agent,
            "订单 ORD-20240110-002 的产品有问题,我想退货。" +
            "产品完全没有使用过,我需要全额退款。");
    }
    
    private static void simulateConversation(ReActAgent agent, String userInput) {
        System.out.println("Customer: " + userInput);
        System.out.println("---");
        
        try {
            Msg response = agent.call(
                Msg.builder().textContent(userInput).build()
            ).block();
            
            System.out.println("Agent: " + response.getTextContent());
            
            // 显示Token使用情况
            if (response.getChatUsage() != null) {
                System.out.printf("\n[Token Usage] Input: %d, Output: %d, Total: %d\n",
                    response.getChatUsage().getInputTokens(),
                    response.getChatUsage().getOutputTokens(),
                    response.getChatUsage().getTotalTokens());
            }
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
    }
}

关键设计点

markdown 复制代码
1. 工具系统设计:
   ✓ 每个工具职责单一
   ✓ 工具参数有清晰的描述
   ✓ 返回结果结构化,便于Agent理解
   ✓ 错误处理明确(返回错误信息而不是抛异常)

2. Agent配置:
   ✓ 系统提示词清晰定义Agent的角色和决策规则
   ✓ maxIters=5 防止无限循环
   ✓ 使用InMemoryMemory保持会话上下文

3. 生产考虑:
   ✓ 工具执行超时控制(RequestTimeout)
   ✓ Token使用监控(getChatUsage)
   ✓ 错误输入验证(如damagePercent的范围检查)
   ✓ 可扩展的工具架构(易于添加新工具)

数据量和性能调优

参数 建议值 说明
maxIters 5-10 推理循环次数,过多会导致成本增加
model temperature 0.3-0.5 降低温度提高确定性和一致性
max_tokens 1000-2000 限制单次回复长度
内存消息数 100-500 超过此数量自动清理或压缩
并发Agent数 100-1000 根据服务器资源调整

总结

核心要点回顾

方面 要点
What AgentScope-Java是生产级的AI智能体框架,核心是ReAct推理-行动循环
Why 解决LLM应用的可控性、多步骤管理、输出可靠性、知识库集成、工具生态等问题
How 通过Agent、工具、记忆、Hook、Pipeline等模块化组件,灵活组合构建智能应用
何时用 需要构建自主、可控、生产级的AI应用时
何时不用 简单的一次性提示工程,或者只需要基础的LLM调用

在下一章中,我们将深入探讨**消息系统(Message)**的设计,了解如何在Agent之间进行高效、安全的通信。

相关推荐
语落心生2 小时前
阿里开源AgentScope多智能体框架解析系列(四)第4章:Agent 接口与 AgentBase 基类
agent
潘锦3 小时前
AI Agent 核心管理逻辑:工具的管理和调度
agent
Jay Kay5 小时前
Agent沙箱执行服务
agent·沙箱服务
小马过河R5 小时前
ReAct和Function Calling之间的纠葛与恩恩怨怨
人工智能·语言模型·agent·智能体
大模型真好玩7 小时前
LangGraph智能体开发设计模式(二)——协调器-工作者模式、评估器-优化器模式
人工智能·langchain·agent
沛沛老爹8 小时前
Web开发者实战AI Agent:基于Dify实现OpenAI Deep Research智能体
前端·人工智能·gpt·agent·rag·web转型
沛沛老爹8 小时前
Web开发者实战AI Agent:基于Dify的多模态文生图与文生视频智能体项目
前端·人工智能·llm·agent·rag·web转型
EdisonZhou21 小时前
MAF快速入门(9)多路分支路由工作流
llm·aigc·agent·.net core
sandwu1 天前
AI自动化测试(一)
人工智能·agent·playwright·ai自动化测试·midscene