跳至主要內容

AgentScope

mozzie大约 15 分钟AIAI

AgentScope 是阿里云公司开源的一款企业级开箱即用的智能体框架

什么是AgentScope

  • 简单: 使用内置的 ReAct 智能体、工具、技能、人机协作、记忆、计划、实时语音、评估和模型微调轻松构建智能体应用
  • 可扩展: 大量生态系统集成,包括工具、记忆和可观察性;内置 MCP 和 A2A 支持;消息中心(MsgHub)提供灵活的多智能体编排能力
  • 生产就绪: 在本地、云端 Serverless 或 K8s 集群上轻松部署智能体应用,并内置 OTel 可观察性支持

ReAct智能体

AgentScope 提供了开箱即用的 ReAct 智能体 ReActAgent 供开发者使用。

ReActAgent 是框架提供的主要实现,使用 ReAct 算法(推理 + 行动循环)

它同时支持以下功能:

  • 基础功能
    • 支持围绕 reasoningacting 的钩子函数(hooks)
    • 支持结构化输出
  • 实时介入(Realtime Steering)
    • 支持用户中断
    • 支持自定义中断处理
  • 工具
    • 支持同步/异步工具函数
    • 支持流式工具响应
    • 支持并行工具调用
    • 支持 MCP 服务器
  • 记忆
    • 支持智能体自主管理长期记忆
    • 支持"静态"的长期记忆管理

一个简单的demo:

public class HelloReActAgent {

    public static void main(String[] args) {
        // 准备工具
        Toolkit toolkit = new Toolkit();
        toolkit.registerTool(new SimpleTools());

        // 创建智能体
        ReActAgent jarvis = ReActAgent.builder()
                .name("Jarvis")
                .sysPrompt("你是一个名为 Jarvis 的助手")
                .model(DashScopeChatModel.builder()
                    .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                    .modelName("qwen3-max")
                    .build())
                .toolkit(toolkit)
                .build();

        // 发送消息
        Msg msg = Msg.builder()
                .textContent("你好!Jarvis,现在几点了?")
                .build();

        Msg response = jarvis.call(msg).block();
        System.out.println(response.getTextContent());
    }
}

// 工具类
class SimpleTools {
    @Tool(name = "get_time", description = "获取当前时间")
    public String getTime(
            @ToolParam(name = "zone", description = "时区,例如:北京") String zone) {
        return java.time.LocalDateTime.now()
                .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
}

支持的模型

提供商流式工具视觉推理
DashScopeDashScopeChatModel
OpenAIOpenAIChatModel
AnthropicAnthropicChatModel
GeminiGeminiChatModel
OllamaOllamaChatModel
  • OpenAIChatModel 兼容 OpenAI API 规范,可用于 vLLM、DeepSeek 等提供商
  • GeminiChatModel 同时支持 Gemini API 和 Vertex AI

通过 GenerateOptions 配置模型生成参数:

参数类型说明
temperatureDouble控制随机性,0.0-2.0
topPDouble核采样阈值,0.0-1.0
topKInteger限制候选 token 数量
maxTokensInteger最大生成 token 数
thinkingBudgetInteger思考 token 预算
seedLong随机种子
toolChoiceToolChoice工具选择策略

Hook

AgentScopeJava使用统一事件模型,所有Hook都需要实现onEvent(HookEvent)方法。Hook典型应用场景包括:监控、上下文压缩、日志、限流等。

  • 基于事件:所有智能体活动生成事件
  • 类型安全:对事件类型进行模式匹配
  • 优先级排序:钩子按优先级执行(值越小优先级越高)
  • 可修改:某些事件允许修改执行上下文

支持的事件

事件类型时机可修改描述
PreCallEvent智能体调用前智能体开始处理之前(仅通知)
PostCallEvent智能体调用后智能体完成响应之后(可修改最终消息)
PreReasoningEvent推理前LLM 推理之前(可修改输入消息)
PostReasoningEvent推理后LLM 推理完成之后(可修改推理结果)
ReasoningChunkEvent推理流式期间流式推理的每个块(仅通知)
PreActingEvent工具执行前工具执行之前(可修改工具参数)
PostActingEvent工具执行后工具执行之后(可修改工具结果)
ActingChunkEvent工具流式期间工具执行进度块(仅通知)
ErrorEvent发生错误时发生错误时(仅通知)

使用教程

  1. 自定义一个hook

    public class LoggingHook implements Hook {
    
        @Override
        public <T extends HookEvent> Mono<T> onEvent(T event) {
    
            if (event instanceof PreCallEvent) {
                System.out.println("智能体启动: " + event.getAgent().getName());
                return Mono.just(event);
            }
    
            if (event instanceof PostCallEvent) {
                System.out.println("智能体完成: " + event.getAgent().getName());
                return Mono.just(event);
            }
    
            return Mono.just(event);
        }
    }
    
  2. 使用

    public static void main(String[] args) {
        ReActAgent agent = ReActAgent.builder()
                .name("ai_assistant")
                .model(model)
                .hooks(List.of(new LoggingHook()))
                .build();
    
        Msg msg = Msg.builder()
                .textContent("2022年世界杯冠军")
                .build();
    
        Msg response = agent.call(msg).block();
        System.out.println(response.getTextContent());
    }
    
    智能体启动: ai_assistant
    智能体完成: ai_assistant
    2022年卡塔尔世界杯的冠军是**阿根廷队**。
    
    在决赛中,阿根廷队与法国队在常规时间和加时赛战成3-3平,最终通过点球大战以4-2击败对手,夺得冠军。这也是莱昂内尔·梅西(Lionel Messi)职业生涯中首次捧起大力神杯。
    

Tool

LLM本质上是基于历史数据的概率预测系统,只能依赖训练时学到的旧知识来生成回答,无法获取训练之后的数据,工具系统让智能体能够执行 API 调用、数据库查询、文件操作等外部操作。

使用 Toolkit 管理代理工具的注册、检索和执行

核心特性

  • 注解驱动:使用 @Tool@ToolParam 快速定义工具
  • 响应式编程:原生支持 Mono/Flux 异步执行
  • 自动 Schema:自动生成 JSON Schema 供 LLM 理解
  • 工具组管理:动态激活/停用工具集合
  • 预设参数:隐藏敏感参数(如 API Key)
  • 并行执行:支持多工具并行调用

Tool(工具):本质上是模型可以调用的外部接口,使得模型的能力得以延伸至其静态训练数据之外。

使用教程

  1. 定义工具
public static class WeatherService {
    @Tool(description = "获取指定城市的天气")
    public String getWeather(
            @ToolParam(name = "city", description = "城市名称") String city) {
        // 模拟获取天气数据
        return city + " 的天气:晴天,25°C";
    }
}

注意@ToolParamname 属性必须指定,因为 Java 默认不保留参数名。

  1. 注册和使用
Toolkit toolkit = new Toolkit();
toolkit.registerTool(new WeatherService());

ReActAgent agent = ReActAgent.builder()
    .name("助手")
    .model(model)
    .toolkit(toolkit)
    .build();

Msg msg = Msg.builder()
        .textContent("你好!北京的天气怎么样")
        .build();

Msg response = agent.call(msg).block();
System.out.println(response.getTextContent());
您好!根据最新的天气信息,北京今天的天气是晴天,气温为25°C。天气很不错,适合外出活动!

Tool Group

为什么需要工具组

企业级智能体通常会有多个智能体,会存在如下问题

  • 工具决策正确率降低,Agent没法正确完成任务
  • token耗费增多、响应延迟变大
  • 错误的工具调用存在安全隐患

工具分组机制

  1. 默认分组不激活

    • 所有工具按照类型分好组

    • 给出每组工具的基础信息

    • 默认情况下工具都不激活

  1. Mate Tool,enableMetaTool(boolean enableMetaTool) 发现未被激活的工具

    • 初始态下只注册一个元工具

    • LLM通过其来查询具体工具信息

    • 模型按需决定激活哪些分组信息

    • 激活工具后才会附带上工具信息

使用方式

按场景管理工具,支持动态激活/停用:

// 创建工具组
toolkit.createToolGroup("basic", "基础工具", true);   // 默认激活
toolkit.createToolGroup("admin", "管理工具", false);  // 默认停用

// 注册到工具组
toolkit.registration()
    .tool(new BasicTools())
    .group("basic")
    .apply();

// 动态切换
toolkit.updateToolGroups(List.of("admin"), true);   // 激活
toolkit.updateToolGroups(List.of("basic"), false);  // 停用

ReActAgent agent = ReActAgent.builder()
    .name("助手")
    .model(model)
    .toolkit(toolkit)
    .enableMetaTool(true) // 通过元工具发现未被激活的工具
    .build();

MCP

MCP(Model ContextProtocol,模型上下文协议),使用统一的客户端-服务器架构实现LLM和外部数据源及工具的调用

使用教程

  1. 创建一个MCP Client 注册到Toolkit

    Toolkit toolkit = new Toolkit();
    // 
    McpClientBuilder builder = McpClientBuilder.create("mcp").sseTransport("https://mcp.higress.ai/mcp-calendar-holiday-helper/xxxx/sse");
    McpClientWrapper client = builder.buildAsync().block();
    // 注册到Toolkit
    toolkit.registerMcpClient(client);
    
  2. 使用

    ReActAgent agent = ReActAgent.builder()
            .name("mcp_assistant")
            .model(model)
            .toolkit(toolkit)
            .build();
    
    Msg msg = Msg.builder()
            .textContent("查询一下2026年的春节是几号")
            .build();
    
    Msg response = agent.call(msg).block();
    System.out.println(response.getTextContent());
    
    2026年的春节是公历**2026年2月17日**(农历丙午年正月初一)
    

Memory

https://java.agentscope.io/zh/task/memory.html

记忆负责管理 AgentScope 中智能体的对话历史和上下文。AgentScope 提供两种类型的记忆:

  • 短期记忆 (Short-term Memory):存储当前会话的对话历史,需要结合 Session 进行持久化和恢复
  • 长期记忆 (Long-term Memory):存储跨会话的用户偏好和知识,依赖外部记忆组件(如 Mem0、ReMe)自动持久化

分工说明

  • 短期记忆:存储当前会话消息,提供给 LLM 作为上下文,支持推理循环
  • 长期记忆(独立组件):
    • 内部集成 LLM(记忆提取/总结)和向量数据库(存储/检索)
    • 召回:对话开始时,召回相关记忆注入短期记忆
    • 存储:回复用户后,异步存入长期记忆进行提取和持久化

RAG

AgentScope 中的 RAG 模块由两个核心组件组成:

  • Reader(读取器):负责读取和分块输入文档,将其转换为可处理的单元
  • Knowledge(知识库):负责存储文档、生成嵌入向量以及检索相关信息

支持范围

AgentScope 支持多种类型的知识库实现:

类型实现支持功能文档管理适用场景
本地知识库SimpleKnowledge完整的文档管理和检索通过代码管理(使用 Reader)开发、测试、完全控制数据
云托管知识库BailianKnowledge仅检索百炼控制台open in new window企业级、多轮对话、查询重写
Dify 知识库DifyKnowledge仅检索Dify 控制台多种检索模式、Reranking
RAGFlow 知识库RAGFlowKnowledge仅检索RAGFlow 控制台强大OCR、知识图谱、多数据集

集成模式

AgentScope提供了两种集成模式

模式描述优点缺点
Generic 模式在每个推理步骤之前自动检索和注入知识简单,适用于任何 LLM即使不需要也会检索
Agentic 模式Agent 使用工具决定何时检索灵活,只在需要时检索需要强大的推理能力

Generic 模式

通过Hook机制在推理前自动注入

工作原理

  1. 用户发送查询
  2. 知识库自动检索相关文档
  3. 检索到的文档被添加到用户消息之前
  4. Agent 处理增强后的消息并响应

.ragMode(RAGMode.GENERIC)

Agentic 模式

通过Tool 机制由 Agent主动调用

工作原理

  1. 用户发送查询
  2. Agent 推理并决定是否检索知识
  3. 如果需要,Agent 调用 retrieve_knowledge(query="...")
  4. 检索到的文档作为工具结果返回
  5. Agent 使用检索到的信息再次推理

.ragMode(RAGMode.AGENTIC

最佳实践

  1. 分块大小:根据模型的上下文窗口和使用场景选择分块大小。典型值:256-1024 个字符。
  2. 重叠:使用 10-20% 的重叠以保持块之间的上下文连续性。
  3. 分数阈值:从 0.3-0.5 开始,根据检索质量调整。
  4. Top-K:初始检索 3-5 个文档,根据上下文窗口限制调整。
  5. 模式选择
    • 使用 Generic 模式:简单问答、一致的检索模式、较弱的 LLM
    • 使用 Agentic 模式:复杂任务、选择性检索、强大的 LLM
  6. 向量存储选择
    • 使用 InMemoryStore:开发、测试、小型数据集(<10K 文档)
    • 使用 QdrantStore:生产环境、大型数据集、需要持久化
    • 使用 ElasticsearchStore: 生产环境、大型数据集、私有部署服务。

结构化输出

结构化输出让 Agent 生成符合预定义 Schema 的类型化数据,实现从自然语言到结构化数据的可靠转换。

使用方式

  1. 定义需要的schema

    public class ProductInfo {
        public String name;
        public Double price;
        public List<String> features;
    
        public ProductInfo() {}  // 必须有无参构造函数
    }
    
  2. 请求结构化输出

    // 发送查询,指定输出类型
    Msg response = agent.call(userMsg, ProductInfo.class).block();
    
    // 提取类型化数据
    ProductInfo data = response.getStructuredData(ProductInfo.class);
    
    System.out.println("产品: " + data.name);
    System.out.println("价格: $" + data.price);
    

两种模式

模式特点适用场景
TOOL_CHOICE(默认)强制调用工具,一次 API 调用支持 tool_choice 的模型(qwen3-max, gpt-4)
PROMPT提示词引导,可能多次调用兼容老模型
ReActAgent agent = ReActAgent.builder()
    .name("Agent")
    .model(model)
    .structuredOutputReminder(StructuredOutputReminder.TOOL_CHOICE)  // 或 PROMPT
    .build();

可观测能力

Agent Scope Studio:https://java.agentscope.io/zh/task/studio.html

三大基础能力:

  • 项目管理
  • 应用评测(企业版提供)
  • 链路追踪

一个内置智能体

  • Friday

启动项目

基于Node.Js

下载源码启动

git clone https://github.com/agentscope-ai/agentscope-studio
cd agentscope-studio
npm install
npm run dev  # 会自动启动client、server

前端UI:

界面访问地址:http://localhost:5173/

server端:

数据默认使用sqlite存储,启动server可以看到具体存储位置

目前提供了两种上报方式

Traces Endpoint:
HTTP:       http://localhost:3000/v1/traces
gRPC:       http://localhost:4317

Java 应用集成

依赖

<!-- Source: https://mvnrepository.com/artifact/io.agentscope/agentscope-extensions-studio -->
<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-extensions-studio</artifactId>
    <version>1.0.9</version>
    <scope>compile</scope>
</dependency>

初始化studio

// 初始化studio
StudioManager.init().studioUrl("http://localhost:3000")
        .project("AgentScope")
        .runName("Java - Demo")
        .initialize()
        .block();

基于hook的方式上报

ReActAgent agent = ReActAgent.builder()
                    .hook(new StudioMessageHook(StudioManager.getClient()))
                    .build();

Plan

PlanNotebook 为智能体提供计划管理能力,帮助智能体将复杂任务分解为结构化的子任务并逐步执行。

启用计划功能

  1. 使用默认配置
ReActAgent agent = ReActAgent.builder()
        .name("Assistant")
        .model(model)
        .toolkit(toolkit)
        .enablePlan()  // 启用计划功能
        .build();
  1. 自定义配置
PlanNotebook planNotebook = PlanNotebook.builder()
        .maxSubtasks(10)  // 限制子任务数量
        .build();

ReActAgent agent = ReActAgent.builder()
        .name("Assistant")
        .model(model)
        .toolkit(toolkit)
        .planNotebook(planNotebook)
        .build();

为什么要使用 PlanNotebook

  1. 对抗上下文噪声,锁定原始目标

    痛点:中间迷失(Lost in the Middle)

    解法:规划锚点

  1. 逻辑预演(Dry Run),避免高昂试错

    痛点:后期高耗损

    解法:提前校验

PlanNotebook实现原理

  • 模型通过工具操作PlanNotebook
  • 用户可以直接操作PlanNotebook
  • PlanNotebook 通过 hint message 提示模型

默认的提示实现:DefaultPlanToHint

A2A

https://java.agentscope.io/zh/task/a2a.html#a2aagent

A2A(Agent2Agent)简介

Nacos 3.1.0支持A2A注册中心

https://nacos.io/docs/latest/manual/user/ai/agent-registry

客户端

将远程 A2A 服务作为本地 Agent 使用。

import io.agentscope.core.a2a.agent.A2aAgent;
import io.agentscope.core.a2a.agent.card.WellKnownAgentCardResolver;

// 创建 A2A Agent
A2aAgent agent = A2aAgent.builder()
    .name("remote-agent")
    .agentCardResolver(new WellKnownAgentCardResolver(
        "http://127.0.0.1:8080",
        "/.well-known/agent-card.json",
        Map.of()))
    .build();

// 调用远程 Agent
Msg response = agent.call(userMsg).block();

配置选项

参数类型描述
agentCardAgentCard直接提供 AgentCard
agentCardResolverAgentCardResolver通过解析器获取 AgentCard
memoryMemory记忆组件
hook / hooksHook钩子函数

AgentCard 获取方式

// 方式 1:直接提供
A2aAgent.builder()
    .agentCard(agentCard)
    .build();

// 方式 2:从 well-known 路径获取
A2aAgent.builder()
    .agentCardResolver(new WellKnownAgentCardResolver(url, path, headers))
    .build();

// 方式 3:从 Nacos 中发现
A2aAgent.builder()
    .agentCardResolver(new NacosAgentCardResolver(nacosClient))
    .build();

// 方式 4:自定义解析器
A2aAgent.builder()
    .agentCardResolver(agentName -> customGetAgentCard(agentName))
    .build();
从 Nacos 中自动发现 A2A 服务

使用 Nacos 作为 A2A 注册中心,自动从 Nacos 中发现 A2A 服务进行调用。

import io.agentscope.core.a2a.agent.A2aAgent;
import io.agentscope.core.nacos.a2a.discovery.NacosAgentCardResolver;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.ai.AiFactory;
import com.alibaba.nacos.api.ai.AiService;

// 设置 Nacos 地址
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, "localhost:8848");
// 创建 Nacos Client
AiService aiService = AiFactory.createAiService(properties);
// 创建 Nacos 的 AgentCardResolver
NacosAgentCardResolver nacosAgentCardResolver = new NacosAgentCardResolver(aiService);
// 创建 A2A Agent
A2aAgent agent = A2aAgent.builder()
        .name("remote-agent")
        .agentCardResolver(nacosAgentCardResolver)
        .build();

服务端

将本地 Agent 暴露为 A2A 服务。

Spring Boot 方式(推荐)

<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-a2a-spring-boot-starter</artifactId>
    <version>${agentscope.version}</version>
</dependency>
# application.yml
agentscope:
  dashscope:
    api-key: your-api-key
  agent:
    name: my-assistant
  a2a:
    server:
      enabled: true
      card:
        name: My Assistant
        description: 基于 AgentScope 的智能助手
@SpringBootApplication
public class A2aServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(A2aServerApplication.class, args);
    }
}

手动创建方式

import io.agentscope.core.a2a.server.AgentScopeA2aServer;
import io.agentscope.core.a2a.server.transport.DeploymentProperties;

// 创建 A2A Server
AgentScopeA2aServer server = AgentScopeA2aServer.builder(
        ReActAgent.builder()
            .name("my-assistant")
            .sysPrompt("你是一个有用的助手"))
    .deploymentProperties(DeploymentProperties.builder()
        .host("localhost")
        .port(8080)
        .build())
    .build();

// 获取传输处理器用于 Web 框架
JsonRpcTransportWrapper transport =
    server.getTransportWrapper("JSON-RPC", JsonRpcTransportWrapper.class);

// Web 服务就绪后调用
server.postEndpointReady();

配置 AgentCard

import io.agentscope.core.a2a.server.card.ConfigurableAgentCard;

ConfigurableAgentCard agentCard = new ConfigurableAgentCard.Builder()
    .name("My Assistant")
    .description("智能助手")
    .version("1.0.0")
    .skills(List.of(
        new AgentSkill("text-generation", "文本生成"),
        new AgentSkill("question-answering", "问答")))
    .build();

AgentScopeA2aServer.builder(agentBuilder)
    .agentCard(agentCard)
    .build();

自动注册 A2A 服务到 Nacos 注册中心

使用 Nacos 作为 A2A 注册中心,将 AgentScope 所提供的 A2A 服务自动注册到 Nacos 中

  • Spring Boot 方式添加(推荐)
<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-a2a-spring-boot-starter</artifactId>
    <version>${agentscope.version}</version>
</dependency>

<!-- 额外添加 Nacos Spring Boot starter 的依赖 -->
<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-nacos-spring-boot-starter</artifactId>
    <version>${agentscope.version}</version>
</dependency>
# application.yml
agentscope:
  dashscope:
    api-key: your-api-key
  agent:
    name: my-assistant
  a2a:
    server:
      enabled: true
      card:
        name: My Assistant
        description: An intelligent assistant based on AgentScope
    # 在 `agentscope.a2a` 下添加Nacos相关配置
    nacos:
      server-addr: ${NACOS_SERVER_ADDRESS:127.0.0.1:8848}
      username: ${NACOS_USERNAME:nacos}
      password: ${NACOS_PASSWORD:nacos}
@SpringBootApplication
public class A2aServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(A2aServerApplication.class, args);
    }
}
  • 手动创建方式添加
<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-extensions-nacos-a2a</artifactId>
    <version>${agentscope.version}</version>
</dependency>
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.ai.AiFactory;
import com.alibaba.nacos.api.ai.AiService;
import io.agentscope.core.a2a.server.AgentScopeA2aServer;
import io.agentscope.core.a2a.server.transport.DeploymentProperties;
import io.agentscope.core.nacos.a2a.registry.NacosAgentRegistry;

// 设置 Nacos 地址
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, "localhost:8848");
// 创建 Nacos Client
AiService aiService = AiFactory.createAiService(properties);
// 添加 Nacos 的 AgentRegistry
AgentScopeA2aServer server = AgentScopeA2aServer.builder(
        ReActAgent.builder()
            .name("my-assistant")
            .sysPrompt("你是一个有用的助手"))
    .deploymentProperties(DeploymentProperties.builder()
        .host("localhost")
        .port(8080)
        .build())
    .withAgentRegistry(NacosAgentRegistry.builder(aiService).build())
    .build();
配置选项
NacosA2aRegistryProperties registryProperties = NacosA2aRegistryProperties.builder()
        .setAsLatest(true)
        .enabledRegisterEndpoint(true)
        .overwritePreferredTransport("http")
        .build();

NacosAgentRegistry agentRegistry = NacosAgentRegistry
        .builder(aiService)
        .nacosA2aProperties(registryProperties)
        .build();
参数类型描述
setAsLatestboolean注册的 A2A 服务始终为最新版本,默认为false
enabledRegisterEndpointboolean自动注册所有Transport作为此 A2A 服务的 Endpoint,默认为true,当设置为false时,仅会发布Agent Card。
overwritePreferredTransportString注册 A2A 服务时,使用此Transport覆盖 Agent Card 中的preferredTransporurl,默认为null

中断任务

// 客户端中断
agent.interrupt();

// 带消息的中断
agent.interrupt(Msg.builder()
    .textContent("用户取消了操作")
    .build());
贡献者: mozzie