Java 调用 AgentScope 示例

概述

AgentScope Java SDK 是 AgentScope 多智能体框架的 Java 版本,当前版本为 2.0,支持在 Java 项目中直接构建和运行 AI Agent,无需调用外部 Python 服务。

官方文档:https://java.agentscope.io/v2/zh/docs/index.html

本文通过 4 个渐进式 Demo 演示核心用法:

Demo 功能
Demo01 基础对话(非流式)
Demo02 流式输出(逐 token)
Demo03 多轮对话 + 会话持久化 + 用户隔离
Demo04 Skill 调用 + Think 过程打印

环境要求

  • JDK 17+
  • Maven 3.9+

Maven 依赖

<properties>
    <agentscope.version>2.0.2</agentscope.version>
</properties>

<dependencies>
    <!-- AgentScope Harness:HarnessAgent + 工作区 + 记忆管理 + 子 Agent -->
    <dependency>
        <groupId>io.agentscope</groupId>
        <artifactId>agentscope-harness</artifactId>
        <version>${agentscope.version}</version>
    </dependency>

    <!-- OpenAI 兼容模型扩展(支持 DeepSeek、本地代理等) -->
    <dependency>
        <groupId>io.agentscope</groupId>
        <artifactId>agentscope-extensions-model-openai</artifactId>
        <version>${agentscope.version}</version>
    </dependency>
</dependencies>

agentscope-harness 会自动引入 agentscope-core。其他模型提供商(DashScope、Anthropic、Gemini 等)有独立的 agentscope-extensions-model-* 扩展包。


模型配置

Demo 中统一使用 OpenAI 兼容接口,配置示例(使用环境变量管理敏感信息):

// 从环境变量读取,避免硬编码
static final String API_KEY  = System.getenv("OPENAI_API_KEY");
static final String BASE_URL = System.getenv("OPENAI_BASE_URL"); // 兼容接口时设置
static final String MODEL    = "deepseek-v4-flash";              // 替换为实际模型名

若使用 DashScope(通义千问),可改用 agentscope-extensions-model-dashscope 并设置 DASHSCOPE_API_KEY

import io.agentscope.extensions.model.dashscope.DashScopeChatModel;

DashScopeChatModel model = DashScopeChatModel.builder()
        .apiKey(System.getenv("DASHSCOPE_API_KEY"))
        .modelName("qwen-max")
        .stream(false)
        .build();

Demo01:基础对话

最简单的用法:构建 HarnessAgent → 发送消息 → 获取回复。

import io.agentscope.core.agent.RuntimeContext;
import io.agentscope.core.message.UserMessage;
import io.agentscope.extensions.model.openai.OpenAIChatModel;
import io.agentscope.harness.agent.HarnessAgent;
import java.nio.file.Paths;

public class Demo01BasicChat {

    public static void main(String[] args) {
        // 1. 构建模型(OpenAI 兼容)
        OpenAIChatModel model = OpenAIChatModel.builder()
                .apiKey(System.getenv("OPENAI_API_KEY"))
                .baseUrl(System.getenv("OPENAI_BASE_URL"))   // 兼容接口时设置
                .modelName("deepseek-v4-flash")
                .stream(false)
                .build();

        // 2. 构建 HarnessAgent
        HarnessAgent agent = HarnessAgent.builder()
                .name("assistant")
                .sysPrompt("你是一个乐于助人的 AI 助手,请用中文回答用户问题。")
                .model(model)
                .workspace(Paths.get("/tmp/agentscope-demo/workspace"))
                .disableCompaction()       // demo 中关闭上下文压缩
                .disableFilesystemTools()  // demo 中关闭文件系统工具
                .disableShellTool()        // demo 中关闭 shell 工具
                .build();

        // 3. 构建运行上下文(sessionId 标识会话,userId 标识用户)
        RuntimeContext ctx = RuntimeContext.builder()
                .sessionId("demo01-session")
                .userId("demo-user")
                .build();

        // 4. 发送消息,call() 返回 Mono<Msg>,.block() 阻塞等待回复
        var reply1 = agent.call(
                new UserMessage("你好!请用一句话介绍 AgentScope Java SDK。"), ctx
        ).block();
        System.out.println("助手:" + (reply1 != null ? reply1.getTextContent() : ""));

        var reply2 = agent.call(
                new UserMessage("Java 和 Python 哪个更适合做后端开发?"), ctx
        ).block();
        System.out.println("助手:" + (reply2 != null ? reply2.getTextContent() : ""));

        agent.close();
    }
}

关键 API:

API 说明
HarnessAgent.builder() 构建 Agent,包含工作区、记忆、会话持久化等工程能力
RuntimeContext 每次调用的上下文,携带 sessionIduserId
agent.call(msg, ctx) 发送消息,返回 Mono<Msg>(响应式)
reply.getTextContent() 从回复中提取纯文本内容

Demo02:流式输出

使用 streamEvents() 订阅事件流,实时打印每个 token。

import io.agentscope.core.event.AgentEventType;
import io.agentscope.core.event.TextBlockDeltaEvent;
import io.agentscope.core.event.ToolCallStartEvent;

// 开启流式模式
OpenAIChatModel model = OpenAIChatModel.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .baseUrl(System.getenv("OPENAI_BASE_URL"))
        .modelName("deepseek-v4-flash")
        .stream(true)   // 关键:开启流式
        .build();

HarnessAgent agent = HarnessAgent.builder()
        .name("stream-assistant")
        .sysPrompt("你是一个乐于助人的 AI 助手,请用中文回答用户问题。")
        .model(model)
        .workspace(Paths.get("/tmp/agentscope-demo/workspace"))
        .disableCompaction()
        .disableFilesystemTools()
        .disableShellTool()
        .build();

RuntimeContext ctx = RuntimeContext.builder()
        .sessionId("demo02-session")
        .userId("demo-user")
        .build();

// streamEvents 返回 Flux<AgentEvent>,逐事件处理
agent.streamEvents(new UserMessage("请列出 Java 的 5 个核心特性,每条一行。"), ctx)
        .doOnNext(event -> {
            AgentEventType type = event.getType();

            if (type == AgentEventType.TEXT_BLOCK_DELTA) {
                // 文本增量:实时打印 token
                System.out.print(((TextBlockDeltaEvent) event).getDelta());
                System.out.flush();

            } else if (type == AgentEventType.TOOL_CALL_START) {
                // 工具调用开始
                System.out.println("\n[工具调用] "
                        + ((ToolCallStartEvent) event).getToolCallName());

            } else if (type == AgentEventType.AGENT_END) {
                System.out.println("\n[回复完成]");
            }
        })
        .blockLast();  // 阻塞直到流结束

常用 AgentEventType:

事件类型 说明
TEXT_BLOCK_START / TEXT_BLOCK_DELTA / TEXT_BLOCK_END 文本块开始/增量/结束
THINKING_BLOCK_START / THINKING_BLOCK_DELTA / THINKING_BLOCK_END 模型思考过程(Think)
TOOL_CALL_START / TOOL_CALL_END 工具调用开始 / 结束
TOOL_RESULT_START / TOOL_RESULT_END 工具结果开始 / 结束
MODEL_CALL_START / MODEL_CALL_END 模型调用开始 / 结束
AGENT_START / AGENT_END / AGENT_RESULT Agent 级别事件

Demo03:多轮对话与会话持久化

HarnessAgent 通过 sessionId 自动管理上下文,不同 userId 的会话完全隔离。

import io.agentscope.harness.agent.memory.compaction.CompactionConfig;

// 开启压缩:超过 30 条消息时触发,保留最近 10 条
HarnessAgent agent = HarnessAgent.builder()
        .name("chat-assistant")
        .sysPrompt("你是一个乐于助人的 AI 助手,请用中文回答用户问题,回答简洁。")
        .model(model)
        .workspace(Paths.get("/tmp/agentscope-demo/workspace"))
        .compaction(CompactionConfig.builder()
                .triggerMessages(30)
                .keepMessages(10)
                .build())
        .disableFilesystemTools()
        .disableShellTool()
        .build();

// ── 场景 1:Alice 的多轮对话(同一 session,Agent 记住上下文)──────
RuntimeContext aliceCtx = RuntimeContext.builder()
        .sessionId("alice-session-01")
        .userId("alice")
        .build();

agent.call(new UserMessage("我叫 Alice,今天想学习 AgentScope。"), aliceCtx).block();
agent.call(new UserMessage("AgentScope 支持哪些模型?"), aliceCtx).block();

// Agent 记住了用户名字
var r3 = agent.call(new UserMessage("你还记得我叫什么名字吗?"), aliceCtx).block();
System.out.println(r3.getTextContent()); // → "你叫 Alice"

// ── 场景 2:Bob 的独立会话(不同 userId,完全隔离)──────────────────
RuntimeContext bobCtx = RuntimeContext.builder()
        .sessionId("bob-session-01")
        .userId("bob")
        .build();

// Bob 不知道 Alice 的存在
var r4 = agent.call(new UserMessage("你知道 Alice 是谁吗?"), bobCtx).block();
System.out.println(r4.getTextContent()); // → "我不知道 Alice"

// ── 场景 3:Alice 恢复会话(相同 sessionId,跨进程持久化)────────────
// 进程重启后,相同 sessionId 依然能恢复上下文
var r5 = agent.call(new UserMessage("我之前跟你说我在学什么?"), aliceCtx).block();
System.out.println(r5.getTextContent()); // → "你说你在学 AgentScope"

会话状态存储:

默认使用 JsonFileAgentStateStore,状态保存到 ~/.agentscope/state/<agentId>/<userId>/<sessionId>/agent_state.json。生产环境可替换为 Redis 或 MySQL:

// Redis 状态存储(需引入 agentscope-extensions-redis)
HarnessAgent agent = HarnessAgent.builder()
        // ...
        .stateStore(new RedisAgentStateStore(redisClient))
        .build();

Demo04:Skill 调用

Skill 是基于 Markdown 的指令包,无需写新工具代码即可扩展 Agent 能力。Agent 通过内置工具 load_skill_through_path 读取 SKILL.md 指令,再用已有工具按指令执行。

Skill 目录结构

src/main/resources/skills/
├── code-reviewer/
│   ├── SKILL.md                   # 必需:frontmatter 元数据 + 指令
│   └── references/
│       └── java-style-guide.md    # 可选:参考资料,Agent 按需读取
└── data-analyzer/
    └── SKILL.md

SKILL.md 格式

---
name: code-reviewer
description: 当用户需要代码评审、代码质量分析、风格检查或最佳实践建议时使用。
---

# Code Reviewer Skill

你是一位专业的代码评审专家。当用户提交代码片段进行评审时,请按以下步骤执行:

## 评审维度
1. **代码质量**:检查代码逻辑是否正确、是否有潜在 bug
2. **安全性**:是否存在安全漏洞(如 SQL 注入、空指针等)
...

参考规范请见 `references/java-style-guide.md`

注意description 决定 Agent 是否使用这个 Skill,要写得具体("当用户需要… 时使用"),而不是泛泛的功能描述。

加载并使用 Skill

import io.agentscope.core.skill.repository.ClasspathSkillRepository;

// 1. 从 classpath 加载(对应 src/main/resources/skills/)
ClasspathSkillRepository skillRepo = new ClasspathSkillRepository("skills");

// 查看已加载的 skill
skillRepo.getAllSkillNames().forEach(name -> System.out.println("  - " + name));
// 输出:
//   - code-reviewer
//   - data-analyzer

// 2. 构建带 skill 的 Agent(注意:不要 disableFilesystemTools/disableShellTool)
HarnessAgent agent = HarnessAgent.builder()
        .name("skill-agent")
        .sysPrompt("你是一个专业的技术助手,擅长代码评审和数据分析。\n"
                 + "当用户提出相关需求时,请主动使用合适的 skill 来完成任务。\n"
                 + "请用中文回复。")
        .model(model)
        .workspace(Paths.get("/tmp/agentscope-demo/skill-workspace"))
        .skillRepository(skillRepo)   // 注册 skill 仓库
        .disableCompaction()
        .build();

// 3. 每次使用唯一 sessionId,确保每次全新推理(避免 session 缓存影响 think 输出)
RuntimeContext ctx = RuntimeContext.builder()
        .sessionId("code-review-" + System.currentTimeMillis())
        .userId("demo-user")
        .build();

// 4. 直接提问,Agent 会自动判断并加载对应 skill
String question = "请帮我评审以下代码:\n```java\nString sql = \"SELECT * FROM users WHERE id=\" + userId;\n```";
streamAndPrint(agent, question, ctx);

打印 Think 过程

支持思考型模型时,THINKING_BLOCK_* 事件携带模型的推理过程,可用于调试 Agent 决策逻辑:

import io.agentscope.core.event.ThinkingBlockDeltaEvent;

private static void streamAndPrint(HarnessAgent agent, String message, RuntimeContext ctx) {
    agent.streamEvents(new UserMessage(message), ctx)
            .doOnNext(event -> {
                AgentEventType type = event.getType();

                // ── 思考过程(Think)──────────────────────────────────────────
                if (type == AgentEventType.THINKING_BLOCK_START) {
                    System.out.println("\n┌─ 💭 Think ─────────────────────────────");

                } else if (type == AgentEventType.THINKING_BLOCK_DELTA) {
                    System.out.print(((ThinkingBlockDeltaEvent) event).getDelta());
                    System.out.flush();

                } else if (type == AgentEventType.THINKING_BLOCK_END) {
                    System.out.println("\n└────────────────────────────────────────\n");

                // ── 正式回复文本 ──────────────────────────────────────────────
                } else if (type == AgentEventType.TEXT_BLOCK_DELTA) {
                    System.out.print(((TextBlockDeltaEvent) event).getDelta());
                    System.out.flush();

                // ── 工具调用(含 Skill 加载)─────────────────────────────────
                } else if (type == AgentEventType.TOOL_CALL_START) {
                    String toolName = ((ToolCallStartEvent) event).getToolCallName();
                    if (toolName.contains("load_skill")) {
                        System.out.println("\n\n[>> 正在加载 Skill: " + toolName + " <<]");
                    } else {
                        System.out.println("\n[工具调用] " + toolName);
                    }

                // ── 回复结束 ──────────────────────────────────────────────────
                } else if (type == AgentEventType.AGENT_END) {
                    System.out.println();
                }
            })
            .blockLast();
}

运行输出示例:

=== 已加载 Skills ===
  - code-reviewer
  - data-analyzer

┌─ 💭 Think ─────────────────────────────
用户要求评审一段 SQL 拼接代码。这是 SQL 注入漏洞的典型写法。
有 code-reviewer 技能可用,我应该先加载它来提供专业评审。
└────────────────────────────────────────

[>> 正在加载 Skill: load_skill_through_path <<]

## 代码评审报告

### 总体评价
**1 / 5** — 存在严重 SQL 注入漏洞,不可上生产...

Think 不显示的原因:若 sessionId 复用,Agent 直接返回缓存的历史回复,不会重新推理,自然没有 think 事件。每次调用使用 System.currentTimeMillis() 生成唯一 sessionId 即可解决。


其他 Skill 仓库类型

ClasspathSkillRepository 外,还支持多种来源:

// 文件系统(本地目录)
new FileSystemSkillRepository(Paths.get("/path/to/skills"))

// Git 仓库(需引入 agentscope-extensions-skill-git-repository)
new GitSkillRepository("https://github.com/your-org/team-skills.git")

// 多仓库叠加(后注册的优先级更高,同名 skill 后者覆盖前者)
HarnessAgent.builder()
    .skillRepository(communitySkills)   // 低优先级
    .skillRepository(teamSkills)        // 高优先级
    .build();

项目结构

agentscope-java-demo/
├── pom.xml
└── src/main/
    ├── java/com/example/demo/
    │   ├── Demo01BasicChat.java      # 基础对话
    │   ├── Demo02StreamOutput.java   # 流式输出
    │   ├── Demo03MultiTurnChat.java  # 多轮对话 + 会话持久化
    │   └── Demo04SkillDemo.java      # Skill 调用 + Think 打印
    └── resources/skills/
        ├── code-reviewer/
        │   ├── SKILL.md
        │   └── references/java-style-guide.md
        └── data-analyzer/
            └── SKILL.md

编译运行:

mvn package -q -DskipTests

java -cp target/agentscope-java-demo-1.0-SNAPSHOT.jar com.example.demo.Demo01BasicChat
java -cp target/agentscope-java-demo-1.0-SNAPSHOT.jar com.example.demo.Demo02StreamOutput
java -cp target/agentscope-java-demo-1.0-SNAPSHOT.jar com.example.demo.Demo03MultiTurnChat
java -cp target/agentscope-java-demo-1.0-SNAPSHOT.jar com.example.demo.Demo04SkillDemo

参考资料

  • AgentScope Java SDK GitHub
  • AgentScope Java 官方文档 v2
  • 快速开始
  • Tool 与 Skill 文档
  • Harness Skill 文档