同一个 Agent,用 Spring AI 2.0 和 AgentScope Java 各实现一遍:差的不止代码量

本文基于 Spring AI 2.0.1 (截至 2026-08-28 核实的当前稳定版)与 AgentScope Java 2.0.1 (截至本文写作的最新版)编写,两家的 API 均迭代极快,代码细节请以Spring AI 官方文档AgentScope Java 官方文档为准。

开篇:写完两遍,结论有点反直觉

上一篇拆完 AgentScope Java 2.0 的架构,后台被问得最多的一句话是:"和 Spring AI 二选一,到底选哪个?"

为了回答这个问题,我把同一个 Agent 用两个框架各写了一遍。写完的结论有点反直觉:

代码量的差距其实不大------差的是你操心的事。Spring AI 2.0 卖你零件,AgentScope 卖你整车;真正的选型问题不是"哪个框架好",而是"你的团队缺的是零件,还是整车"。

下面是全过程。先交代实验设计,再看两份代码,最后给选型判断。

实验设计:控制变量

同一个需求------订单查询助手,一个最典型不过的业务 Agent:

  • 一个工具:查询订单状态(读操作,带 @Tool 注解)
  • 多轮会话记忆:用户能接着上一句问"那它什么时候发货"
  • 流式输出:前端要打字机效果

控制变量:

变量 取值
模型 同一个 DeepSeek(OpenAI 兼容端点,deepseek-chat
工具逻辑 同一个 OrderTools 类,同样的查询逻辑
版本 Spring AI 2.0.1 / AgentScope Java 2.0.1
JDK 17+

模型、工具、JVM 全部拉平,剩下纯看框架本身给了你什么、要你管什么。

第一遍:Spring AI 2.0------自己装配的零件车

第一步,引入 starter,配模型。 Spring AI 的模型接入走 OpenAI 兼容端点,改三个配置项(注意 2.0 的配置键没有 .options 段,1.x 写法已废弃------这个坑升级实战里详细拆过):

yaml 复制代码
spring:
  ai:
    openai:
      base-url: https://api.deepseek.com
      api-key: ${DEEPSEEK_API_KEY}
      chat:
        model: deepseek-chat

第二步,写工具。 一个普通的 Spring Bean,方法上加 @Tool

java 复制代码
@Component
public class OrderTools {

    @Tool(description = "查询订单状态,入参为订单号")
    public String getOrderStatus(String orderId) {
        return orderService.query(orderId).toJson();
    }
}

第三步,装配 ChatClient。 这是 Spring AI 侧的核心动作------你要自己把"Agent"装配出来:

java 复制代码
@Service
public class OrderAssistant {

    private final ChatClient chatClient;

    public OrderAssistant(ChatClient.Builder builder, OrderTools tools) {
        this.chatClient = builder
                .defaultSystem("你是订单客服助手,查订单状态用工具")
                .build();
    }

    public Flux<String> chat(String message, OrderTools tools) {
        return chatClient.prompt()
                .user(message)
                .tools(tools)          // @Tool 方法自动生成 schema 交给模型
                .stream()
                .content();            // Flux<String>:token 级内容流
    }
}

一句话结论:Spring AI 2.0 里,Agent 不是框架给你的类,是你用 ChatClient + advisor 链装配出来的结果 ------2.0 把工具调用循环收进了 ToolCallingAdvisor,且它由 DefaultChatClient 自动注册,所以工具循环开箱即用,你不需要手写 while 循环(工具也可以在 builder 上全局注册,API 名以官方文档为准)。

会话记忆呢?1.x 时代挂一个 MessageChatMemoryAdvisor 就有;2.0 的官方方向是 spring-ai-session(事件溯源式对话记忆)。这个维度的分野比代码大,放到对比表里说。

第二遍:AgentScope Java------整车直接开

第一步,引入依赖。 两个包:harness 主包 + 模型扩展包:

xml 复制代码
<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-harness</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-extensions-model-openai</artifactId>
    <version>2.0.1</version>
</dependency>

第二步,同一个工具类。 @Tool 注解原样复用,一行没改。

第三步,构建 Agent。 注意这里没有"装配"动作------ReAct 循环、工具调度、记忆、权限,框架已经在 Builder 里给了:

java 复制代码
OpenAIChatModel model = OpenAIChatModel.builder()
        .apiKey(System.getenv("DEEPSEEK_API_KEY"))
        .baseUrl("https://api.deepseek.com")
        .modelName("deepseek-chat")
        .stream(true)
        .build();

HarnessAgent agent = HarnessAgent.builder()
        .name("OrderAssistant")
        .sysPrompt("你是订单客服助手,查订单状态用工具")
        .model(model)
        .workspace(Path.of("./workspace"))  // 记忆/技能/状态都落在这里
        .build();
// OrderTools 注册进 Toolkit(装配 API 以官方文档为准)

String reply = agent.call(
        new UserMessage("帮我查一下订单 SO-1024"),
        RuntimeContext.builder()
                .userId("user-42")
                .sessionId("session-1024")
                .build()
).block().getTextContent();

一句话结论:AgentScope 侧的"Agent"是框架给你的现成类 ------你填参数,不搭骨架。RuntimeContext 不是可选参数,它是强制入口:传了 userId/sessionId,工作区、记忆、状态就自动按身份隔离。

流式呢?agent.streamEvents() 返回的不是 token 流,而是 28 种类型化事件(TextBlockDelta 文本增量、ToolCallStart 工具调用、RequireUserConfirmEvent 审批请求......),前端、可观测、审批流消费的是同一套事件。

五个维度看差距

把两份代码并排放,差距浮出水面:

维度 Spring AI 2.0 AgentScope Java 2.0
Agent 是什么 你装配的结果(ChatClient + advisor 链) 框架给你的类(HarnessAgent)
装配心智 自己组合零件,每个 advisor 都可替换 填 Builder 参数,复杂度集中在 build 阶段
会话记忆 advisor / session 插件,方向是 spring-ai-session 事件溯源 RuntimeContext 强制入口 + AgentStateStore 状态外置,按 (userId, sessionId) 分桶
流式语义 Flux<String> 内容流------打字机 Flux<AgentEvent> 事件流------执行生命周期直播
工具放行 advisor 链可以拦,但"允不允许"的逻辑自己写 PermissionEngine 三态(ALLOW / ASK / DENY),ASK 是一等公民,审批事件直接进事件流

第四、五行是两框架真正的分水岭:

  • 内容流 vs 事件流 :Spring AI 的流给你打字机,AgentScope 的流给你全程直播------工具调用开始/结束、模型调用耗时、人工确认请求,全在一个 Flux 里。做对话 UI 两者都够,做 Agent 运营平台(看每个会话正在干什么、卡在哪)后者是碾压级便利。
  • 权限有没有引擎:Spring AI 的哲学是"给你拦的点"(advisor),AgentScope 的哲学是"替你想好放行规则"(三态权限 + 子 Agent 强制继承父级 DENY 规则)。单体应用无所谓,多租户 SaaS 场景这是安全底线。

判断:什么团队选什么

写了两遍之后,我的选型建议非常明确:

选 Spring AI 2.0,如果 Agent 是你现有系统的一个功能。 已有 Spring Boot 服务、Agent 是众多模块之一、对话场景为主------零件装进你现有的车,不用为"Agent"这个功能引入一套新运行时概念。你的团队对每个零件都有完全控制权,坏哪儿修哪儿。

选 AgentScope Java,如果 Agent 是产品主体。 多用户多会话、需要权限审批和审计、计划水平扩展多副本------整车直接开走。状态外置换来的"任意副本接续工作"、权限引擎、沙箱,这些自己用 advisor 拼一遍,工作量不是"多写几个类",是"重新发明一遍框架"。

还有一个隐藏选项:组合。 官方已明确同属阿里系的 Spring AI Alibaba 后续版本会把内核升级为 AgentScope------你的 Spring 服务里嵌 AgentScope 并不冲突。上一篇说过,它甚至不要求你换掉 Spring AI。

一句话收尾:模型月抛时代,框架选型别问"哪个更强",问"我的 Agent 要活成什么形态"------功能选零件,产品选整车。

参考资料

相关推荐
桃西西呀22 分钟前
AI 为什么一本正经地胡说八道?3 个底层原因 + 2 个防坑法
人工智能·llm·ai编程
天空11022 分钟前
Claude Code 怎么换用 Claude Fable 5.1:配置步骤、端点验证方法,以及缓存降价 75% 到底省了多少(2026 年 9 月)
人工智能·ai编程
宋哥转AI29 分钟前
深入理解 AI Agent:从黑盒到全链路——生产级 Agent 的可观测性体系怎么建
人工智能·agent·ai编程
打呵欠的猫30 分钟前
前端接口超时从 15s 改到动态值后,用户投诉降了 60%——AI 帮我分析出的方案
前端·ai编程
guanguan0_01 小时前
用 AI 做技术方案评审:输入 3 个方案,输出对比矩阵 + 推荐理由
javascript·人工智能·矩阵·ai编程
杨杨杨大侠1 小时前
现在的大模型怎么分类:别把 MoE、推理模型和多模态混在一起
aigc·openai·ai编程
一用书生1 小时前
我给 ChatGPT、DeepSeek、Kimi 都加了一个「保存为笔记」按钮
前端·ai编程·vibecoding
AI编程实验室1 小时前
Agent Handoff 自动跟踪 Skill:安装、事件映射与证据分级
前端·ai编程
小海豚儿1 小时前
从一句话,到一套系统
ai编程