总述
AgentScope-Java 是一个生产级的AI智能体编程框架 ,用Java构建LLM驱动的智能应用。它不仅提供了基础的Agent-模型-工具三角交互,更重要的是提供了企业级生产必需的运行时控制、内置工具、协议集成和可观测性。
本章我们将从**What(是什么)、Why(为什么)、How(怎样用)**三个维度理解AgentScope-Java,并通过具体的生产场景示例展示框架如何解决真实问题。
主架构设计图
推理-行动循环] 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 执行流程
2. 工具调用流程
3. Hook 系统执行流程
4. 流式响应处理流程
5. 中断与恢复流程
1.1 项目背景与设计理念
1.1.1 为什么需要AgentScope-Java?
在使用LLM构建智能应用的过程中,开发者通常面临以下核心痛点:
问题1:LLM的自主性与可控性矛盾
场景:你为一个电商平台构建了一个自主AI助手,它可以自主查询商品、推荐产品、处理订单。但当助手错误地向用户承诺了不合理的优惠或承诺了不能实现的服务时,你无法立即干预。
AgentScope解决方案:
- 安全中断:在任意时刻暂停Agent,完整保留上下文和工具状态,支持无损恢复
- 优雅取消:终止长时间运行的工具调用,不破坏Agent状态
- 人机协同:通过Hook系统在任何推理步骤注入修正、额外上下文或指导
问题2:多步骤复杂任务的结构化管理
场景:用户请求Agent完成一个涉及10个步骤的复杂工作流(如数据分析 → 生成报告 → 发送邮件)。当中间某一步失败时,你很难追踪当前进度、修改计划或恢复执行。
AgentScope解决方案:
- PlanNotebook:结构化任务管理,自动跟踪多步骤工作流
- 支持动态修改、暂停、恢复、并发执行多个计划
- 与Agent推理集成,智能体可以主动创建和修改自己的计划
问题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();
工具系统如何工作?
生产场景:销售订单系统
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%可用性
架构设计
完整代码实现
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之间进行高效、安全的通信。