夜雨聆风学习资料网

ARTICLE · 1232630

[AI工程] Spring AI 第十五篇(Spring AI Agent Utils): Claude Code 的那套工具箱,被人在 Java 里重写了一遍

[AI工程] Spring AI 第十五篇(Spring AI Agent Utils): Claude Code 的那套工具箱,被人在 Java 里重写了一遍

💡 这两年用惯了 AI 编程工具的人会有一种共识:真正让 Agent 好用的不是模型,是它手里那套工具——能读文件、能跑命令、能 grep、能把复杂任务拆成 todo、能在需要时反问一句。

问题来了:这些能力在 Claude Code、Qoder 这类工具里是内置的,但当你用自己的 Java 服务做一个"能干活"的 Agent 时,全得从零写:进程管理、超时、输出截断、路径越权防护、子智能体委派、跨会话记忆……写到最后你会发现自己在重造一个小型 IDE。

Spring AI Agent Utils 就是冲这件事来的:它是 Spring AI 社区(org.springaicommunity)下的一个 incubating 项目,把 Claude Code 的核心工具与 Agent Skills 机制用 Spring AI 重写了一遍,作为一组 @Tool 直接挂到 ChatClient.defaultTools(...) 上。注:写这篇时最新版本是 0.12.0(2026-08-30 发布),Apache 2.0 许可,仍处于孵化阶段。

这一篇按"它有什么 → 怎么接 → 哪三样组合才真正产生 Agentic 行为 → 安全边界在哪 → 什么时候该用它"来盘,顺便和第十五篇讲的 Agent 五种模式、以及 Spring AI Alibaba 的 Agent Framework 做个分工对照。

下面开启本篇: [AI工程] 玩转 Spring AI Agent Utils:Claude Code 的那套工具箱,被人在 Java 里重写了一遍


1. 先说清楚它是什么、不是什么

一句话:把 Claude Code 的工具面板,翻译成 Spring AI 的工具 Bean。

1.1 基本盘

项
内容
坐标
org.springaicommunity:spring-ai-agent-utils
(有 BOM:spring-ai-agent-utils-bom)
当前版本
0.12.0
(2026-08-30 发布;0.1.1 → 0.12.0 迭代节奏很快)
定位
用 Spring AI 重实现 Claude Code 的工具与技能机制,给 Java 侧 Agentic 工作流用
环境要求
Java 17+ / Spring Boot 3.x 或 4.x / Spring AI 2.0.0+ / Maven 3.6+
许可 & 状态
Apache 2.0,spring-ai-community 下 incubating
文档
官方文档站

一个小提醒:README 的 Quick Start 里有句 “You need Spring AI version `` or later”,版本号是个空占位(写这篇时如此)。以 Requirements 段写的 2.0.0 or later 为准。

1.2 模块划分

spring-ai-agent-utils-common     子智能体 SPI:SubagentDefinition / SubagentResolver / SubagentExecutor / SubagentTypespring-ai-agent-utils            核心库:工具、Advisor、技能、Claude 子智能体实现spring-ai-agent-utils-a2a        A2A 协议子智能体(远程 Agent 编排)spring-ai-agent-utils-bom        统一版本管理examples/                        9 个可运行 Demo(code-agent / ask-user-question / skills / subagent / subagent-a2a / todo / memory x3)

Q1:它和 Spring AI 官方是什么关系?

社区项目,不在 org.springframework.ai 坐标下,也不承诺跟随官方发布节奏。这决定了使用姿势:把它当"高质量参考实现 + 可用的积木",而不是平台依赖。0.x 阶段 API 会变,锁版本并在升级时过一遍回归。

Q2:和 Anthropic 官方 SDK 有什么区别?

这里没有任何 Claude 专有协议——工具是普通 Spring AI @Tool,模型可以是 Spring AI Alibaba 接的千问、DeepSeek、OpenAI、Gemini,任选。它复刻的是 Claude Code 的能力形状(工具集 + 提示词约定),不是它的运行时。


2. 工具体系全景

分五组看,一次记住。

2.1 核心工具(任何 Agentic 行为的地基)

工具
对应 Claude Code 能力
关键细节(文档实测)
风险面
AgentEnvironment
动态上下文注入
把运行时环境、git 状态以 param 形式塞进 system prompt
泄露仓库信息
FileSystemTools
Read / Write / Edit
支持行区间与分页、精确字符串替换、行长截断(2000 字符)、自动建父目录;默认全盘可访问,可用 allowedDirectory(...) 收口
覆盖文件
ShellTools
Bash / BashOutput
同步默认超时 2 分钟(上限 10 分钟)、后台执行返回 bash_id、stdout/stderr 分离、正则过滤输出、输出超 30000 字符截断
命令执行
GrepTool
Grep
纯 Java 实现,支持正则、glob 过滤、多种输出模式
大仓库扫全量
GlobTool
Glob
按文件名模式快速查找
低
SmartWebFetchTool
WebFetch
AI 摘要 + 缓存,需要传一个 ChatClient 做摘要
二阶模型成本
BraveWebSearchTool
 / BraveWebFetchTool
WebSearch
走 Brave 搜索,支持域名过滤
需要 API Key

2.2 另外四组

组
工具
干什么
值得注意
用户反馈
AskUserQuestionTool
执行中途向用户提澄清问题
每题 2~4 个选项、单次 1~10 题、header 最多 12 字符、支持单选/多选与自由文本;只能主 Agent 用,子智能体不能与用户交互
技能
SkillsTool
Markdown + YAML front-matter 定义可复用能力包
启动时只加载 name/description,命中语义才加载全文(渐进披露);可从目录、classpath、依赖 JAR 加载
长期记忆
AutoMemoryTools
 / AutoMemoryToolsAdvisor
跨会话的文件型记忆
六个操作(MemoryView / MemoryCreate / MemoryStrReplace / MemoryInsert / MemoryDelete / MemoryRename);沙箱目录;MEMORY.md 索引;自带配套 system prompt
任务编排
TodoWriteTool
、TaskTool
显式计划 + 子智能体委派
Todo 有一条硬规则:同一时刻只能有一个 in_progress;Task 支持多模型路由与可插拔后端

一句话理解:核心工具给手,Skills 给知识,Memory 给记性,Task/Todo 给组织度——四样凑齐才像个能干活的 Agent。


3. 十分钟接一个能干活的最小 Agent

代码基于 README 的 Quick Start 改写,去掉了演示噪音。

3.1 依赖

<dependencyManagement>    <dependencies>        <dependency>            <groupId>org.springaicommunity</groupId>            <artifactId>spring-ai-agent-utils-bom</artifactId>            <version>0.12.0</version>            <type>pom</type>            <scope>import</scope>        </dependency>    </dependencies></dependencyManagement><dependencies>    <dependency>        <groupId>org.springaicommunity</groupId>        <artifactId>spring-ai-agent-utils</artifactId>    </dependency></dependencies>

3.2 装配

@BeanChatClient codeAgent(ChatClient.Builder builder,                      // 注入 Builder,别 ChatClient.builder(chatModel)                     @Value("{agent.skills.paths}") List<Resource> skillPaths,                     @Value("classpath:/prompt/MAIN_AGENT_SYSTEM_PROMPT_V2.md") Resource systemPrompt) {    var taskTool = TaskTool.builder()            .subagentTypes(ClaudeSubagentType.builder()                    .chatClientBuilder("default", builder.clone())                    .skillsResources(skillPaths)                    .braveApiKey(braveApiKey)                    .build())            .build();    return builder            .defaultSystem(p -> p.text(systemPrompt)                    .param(AgentEnvironment.ENVIRONMENT_INFO_KEY, AgentEnvironment.info())                    .param(AgentEnvironment.GIT_STATUS_KEY, AgentEnvironment.gitStatus()))            .defaultTools(                    taskTool,                    SkillsTool.builder().addSkillsResources(skillPaths).build(),                    FileSystemTools.builder().allowedDirectory(Path.of("/workspace/project")).build(),  // ← 收口                    ShellTools.builder().build(),                    GrepTool.builder().build(),                    GlobTool.builder().build(),                    SmartWebFetchTool.builder(builder.clone().build()).build(),                    BraveWebSearchTool.builder(braveApiKey).build(),                    TodoWriteTool.builder().build(),                    AskUserQuestionTool.builder()                            .questionHandler(new CommandLineQuestionHandler())   // CLI 现成实现                            .build())            .defaultAdvisors(MessageChatMemoryAdvisor                    .builder(MessageWindowChatMemory.builder().maxMessages(500).build())                    .build())            .build();}

四个必看的点:

点
说明
注册方式
全部走 defaultTools(Object...)——这正好是第十一篇 6.2 强调的 2.0 姿势(字符串 bean 名已失效)
提示词是能力的一部分
MAIN_AGENT_SYSTEM_PROMPT_V2.md
 和 AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md 都打进 jar 的 classpath:/prompt/。只挂工具不给提示词,模型大概率不会用
文档里的 ToolCallAdvisor
项目文档示例还在用这个类名。Spring AI 2.0.1 里它已 @Deprecated(forRemoval = true) 并继承自 ToolCallingAdvisor,新写用后者,conversationHistoryEnabled(false) 仍然可用
官方示例的构造方式别照抄
它的工具文档样例里普遍写 ChatClient.builder(chatModel)。这个静态工厂在 2.0.1 里给的 ObservationRegistry 是 NOOP,于是工具调用、模型调用一个 span 都不上报(第十四篇 2.2 展开过)。生产装配请注入 ChatClient.Builder,上面那段代码就是这么改的

Q:为什么 TodoWriteTool 要配 conversationHistoryEnabled(false)?

它的官方示例是 ToolCallAdvisor.builder().conversationHistoryEnabled(false) + MessageChatMemoryAdvisor 一起用。原因是 todo 更新靠递归工具调用推进,工具循环内部再自带一份会话历史,会和 memory advisor 的历史重叠、把上下文撑爆。这个技巧对任何"工具会连续多轮"的场景都成立(第十一篇 7.2 讨论过工具循环与 memory 的边界)。


4. Skills、子智能体、A2A:把能力做成外置资产

这一块是我最看好的部分——它把"教 Agent 做事"从代码里搬到了 Markdown。

4.1 Skill 的形状

---name: ai-tutordescription: 用户要求讲解技术概念时使用;能产出带引用来源的教程 PDF---# AI Tutor## Instructions1. 先确认受众水平与目标篇幅2. 需要实时资料时调用 BraveWebSearchTool / SmartWebFetchTool3. 按"概念 → 最小例子 → 常见误区 → 进阶"四段写4. 用 ShellTools 跑辅助脚本,最后生成 PDF

运行机制是三段:启动只登记 name/description → 语义命中才加载全文 → Agent 按全文执行。所以技能可以写得很长很细,不常驻上下文,这是它比"塞进 system prompt"省 Token 的根本原因。技能目录放 src/main/resources/.claude/skills/ 就能随包发布,也能从依赖 JAR 里加载——这意味着技能可以像 SDK 一样被版本化分发。

4.2 子智能体的价值不是"多几个模型"

特性
说明
独立上下文窗口
探索类任务不会污染主对话(这条最实用)
定制 system prompt
每个子智能体只管一个领域
工具白名单
只给它角色需要的工具
多模型路由
frontmatter 里 model 字段决定用哪个模型,贵的只用在关键节点
后台异步
长任务不阻塞主链

子智能体用带 YAML front-matter 的 Markdown 定义(例如 agents/spring-ai-expert.md),TaskTool 通过可插拔的 resolver / executor 加载与执行。

4.3 A2A:把"子智能体"扩到跨进程

类
模块
用途
A2ASubagentDefinition-a2a
把 A2A 的 AgentCard 包装成 SubagentDefinition
A2ASubagentResolver-a2a
从 /.well-known/agent-card.json 拉元数据
A2ASubagentExecutor-a2a
经 JSON-RPC 把任务发给远程 Agent

编排器启动时自动发现远程 Agent,并让它和本地 Claude 子智能体一起进入可委派列表。这和第九篇讲的 MCP 是互补的:MCP 统一"工具"的接入,A2A 统一"另一个 Agent"的接入。


5. 跨会话记忆:同一个模式,三条实现路线

三个 demo 演示的是同一件事,差别在"给 Agent 哪套工具"。

5.1 记忆与会话历史的分工

会话历史(ChatMemory)
长期记忆(文件)
作用域
当前会话
跨会话持久
存储
进程内 / JDBC
磁盘 Markdown
内容
完整消息交换
精选事实
管理者
Spring AI Advisor
Agent 自己通过工具读写

存取的约定是一成不变的两步:写一个带 front-matter 的 typed .md 文件 → 往 MEMORY.md 追加一行指针;下次会话先读索引,再选择性加载相关条目。类型就四种:user(背景/偏好)、feedback(纠正与确认)、project(决策/约束/截止)、reference(外部系统指针)。

# user_role.md —— 步骤 1 写出的记忆文件---name: user-roledescription: 后端出身、正在补 AI 工程侧,解释概念时要类比后端已有知识type: user---内容本体。**Why:** 记下的原因(未来判断这条还成不成立要用)**How to apply:** 这条建议在什么场景生效
# MEMORY.md —— 步骤 2 追加的指针- [User role](user_role.md) — 后端出身,讲概念先类比后端已有知识(≤150 字符)

索引的约束很硬:一条记忆一行、约 150 字符内,MEMORY.md 超过 200 行之后的内容会被截断。所以它必然需要一个"整理"动作——这正是 5.2 里 memoryConsolidationTrigger 存在的理由,别把它当锦上添花。

5.2 三条路线怎么选

方案
用什么
路径模型
安全性
适合
AutoMemoryTools
6 个专用记忆工具
相对路径,沙箱到记忆根
内置遍历防护、拒绝绝对路径
想要明确语义(MemoryCreate / MemoryView)和隔离
FileSystemTools
 + ShellTools
通用读写
绝对路径,全盘
无沙箱,靠约定(可 allowedDirectory 收口)
Agent 本来就要读源码,顺便把记忆当文件写
AutoMemoryToolsAdvisor
Advisor 自动接线
同第一种
同第一种
不想手工注册工具和 prompt;还支持 memoryConsolidationTrigger 定期让模型总结清理

我的判断:教学与可控性选第一种,真实编程助手类应用选第二种(少一套工具,行为更统一),第三种适合你已经在用 Advisor 编排的团队。

选第三种时有个顺序细节要对上:AutoMemoryToolsAdvisor.builder() 的默认 order 是 HIGHEST_PRECEDENCE + 200,和 MessageChatMemoryAdvisor 的默认值完全一样。按第十一篇 7.1 那条规则(order 相同则相对顺序不保证),这两者谁先写上下文是随机的;长期记忆该压在短期历史上还是反过来,得自己显式给值。它排在 ToolCallingAdvisor(+300)外侧是有意的——长期记忆每次请求只注入一次,不会在工具循环里重复读盘。另外文档里还有个 AutoDreamAdvisor,做的是请求之外的异步整理,可以理解为 memoryConsolidationTrigger 的后台版。

抄代码时注意一个拼写:注入记忆根目录的 prompt 参数名是 MEMORIES_ROOT_DIERCTORY(文档里就是这个拼错的写法)。你以为改成 DIRECTORY 更干净,替换就悄悄失效了。


6. Demo 导览:按你想解决的问题挑一个跑

9 个 Demo,我建议的打开顺序如下。

Demo
解决的问题
看点
上手优先级
code-agent-demo
想要一个完整参照
全工具 + MCP 集成 + 多模型 + CLI
⭐⭐⭐⭐⭐
todo-demo
想让计划可见
TodoWriteTool
 + Spring 应用事件实时刷进度
⭐⭐⭐⭐⭐
memory/memory-tools-demo
跨会话记住用户
沙箱记忆 + MEMORY.md 索引
⭐⭐⭐⭐
skills-demo
想把领域知识外置
ai-tutor
 技能 + Python 辅助脚本 + PDF 产出
⭐⭐⭐⭐
subagent-demo
上下文被探索污染
Markdown 子智能体 + TaskTool 调度
⭐⭐⭐⭐
ask-user-question-demo
需求含糊时反问
控制台 QuestionHandler、单选/多选
⭐⭐⭐
memory/memory-filesystem-tools-demo
不想引入专用记忆工具
通用文件工具实现同一模式
⭐⭐⭐
subagent-a2a-demo
要调用远程 Agent
AgentCard 自动发现
⭐⭐
memory/memory-tools-advisor-demo
记忆接线自动化
Advisor + 合并触发(60 秒无交互或说 “bye”)
⭐⭐

前置条件统一:Java 17+、Maven 3.6+、至少一个模型 Key(Anthropic / OpenAI / Google),Web 搜索要 BRAVE_API_KEY。跑法就是 cd examples/xxx && mvn spring-boot:run。


7. 安全边界、与官方编排的分工,以及别用它的场景

7.1 这套工具的能力越强,越要把三件事配齐

风险
现成护栏
我建议的配法
文件越权(默认全盘)
FileSystemTools.builder().allowedDirectory(...)
 / .workspace(Workspace.local(...))
生产必设。防护有三层:原始 .. 直接拒;规范化后必须落在允许目录内(按路径分量比较,/allowed-evil 骗不过去);符号链接解析真实路径、悬空链接一律拒
命令执行
ShellTools
 的超时(默认 2 分钟 / 上限 10 分钟)、输出 30000 字符截断、后台进程可 kill
再叠一层:命令白名单 + 容器隔离。仓库另有 spring-ai-agent-utils-docker-cli(Docker ExecBackend),把 Agent 的 shell 跑在沙箱容器里
提示词注入→工具滥用
无内置机制
与第十一篇同一套纵深:检索内容与可执行动作分离、身份走 ToolContext、写操作在服务层做归属校验、AskUserQuestionTool 让高危动作显式确认

还有一点容易被忽略:成本。SmartWebFetchTool 内部还要再调一次模型做摘要,TaskTool 每委派一次就是一个新上下文。这些在监控上都表现为"单次提问模型调用数 > 1"(第十四篇 4 节那条派生指标)。

7.2 和 Spring AI Alibaba Agent Framework 怎么分工

维度
spring-ai-agent-utils
Spring AI Alibaba Agent Framework
抽象层
工具集
(@Tool + 提示词约定)
编排层
(Graph 状态图 + SequentialAgent / ParallelAgent / LlmRoutingAgent / SupervisorAgent / LoopAgent / ReactAgent)
解决
Agent 手里有什么工具、怎么记住东西、怎么把知识外置
多个 Agent / 节点怎么连成图、怎么循环与汇聚
依赖
Spring AI 2.0.0+(社区孵化项目)
spring-ai-alibaba-bom
(本地 1.1.2.0 对应的是 Spring AI 1.1.2,见第十五篇 7.2)
组合
两者不冲突:用 Graph 编排,把这里的工具挂给各个节点
同左

7.3 什么时候不该用它

情况
原因
你的 Agent 只做问答 / 检索(第十一篇那种客服)
用不上文件与 Shell,白白扩大攻击面
需要强审计、可重放的严格流程
0.x 工具行为随版本变,且很多能力靠提示词约束
生产要跑别人的代码
必须自己实现沙箱,别指望 allowedDirectory 挡住 Shell
只是想要"能读写文件的 ChatClient"
三四个 @Tool 自己写更快,读它源码当参考就行

7.4 知识脉络图

spring-ai-agent-utils(0.12.0, incubating, Apache 2.0)├── 核心工具:AgentEnvironment / FileSystemTools / ShellTools / GrepTool / GlobTool / SmartWebFetch / BraveWebSearch├── 交互:AskUserQuestionTool(主 Agent 专用,2~4 选项、1~10 题、header ≤12 字符)├── 知识外置:SkillsTool(Markdown+front-matter;启动登记描述,命中才加载全文;可从 JAR 分发)├── 记忆:AutoMemoryTools(6 操作 + 沙箱 + MEMORY.md)|FileSystemTools 通用方案|AutoMemoryToolsAdvisor(自动接线 + 合并触发)├── 编排:TodoWriteTool(唯一 in_progress,配 conversationHistoryEnabled(false))|TaskTool + ClaudeSubagentType(独立上下文/工具白名单/多模型)├── 跨进程:A2A(AgentCard + /.well-known + JSON-RPC)├── 隔离:allowedDirectory 三层防护 / Shell 超时与截断 / docker-cli ExecBackend└── 装配:BOM + defaultTools(Object...) + classpath:/prompt/*.md(提示词是能力的一部分)

最后总结

  • 如果你想给 Java 服务加"能干活的 Agent":直接看 code-agent-demo,它把工具集、MCP、多模型、CLI 装配串成了一遍,比逐个读文档快。
  • 如果你只缺一两个能力:TodoWriteTool(让计划可见)和 SkillsTool(把领域知识从代码里搬出来)是投入产出比最高的两个,其余先别引。
  • 如果你想做长期记忆:三种实现里我偏向 AutoMemoryTools——沙箱 + 显式语义在多人协作时更不容易出事;要统一文件系统访问再换 FileSystemTools 方案。
  • 如果你担心安全:把它当"能力放大器"看,allowedDirectory / Shell 超时 / 容器后端三件套必须配,且高危动作要有用户确认。
  • 对后端 / 架构开发者,我更看重它的一点是:它证明了 Claude Code 的能力可以用一组普通工具 + 一份好提示词复现。这套形状(工具白名单 + 渐进披露的技能 + 文件型记忆 + 显式 todo)值得直接抄进你自己的 Agent 设计里,即便你一行它的代码都不引。

一句话结论:spring-ai-agent-utils 现在最有价值的地方,不是让你少写代码,而是它把"一个能干活的 Agent 该有哪些部件"讲清楚了一个 Java 版本。

参考资料 & 致谢

[1] Spring-AI-Agent-Utils 笔记 - 语雀

[2] spring-ai-agent-utils - GitHub 仓库

[3] Spring AI Agent Utils 官方文档

[4] FileSystemTools 文档(allowedDirectory 与三层防护)

[5] ShellTools 文档(超时、后台进程、输出过滤)

[6] AutoMemoryTools 文档

[7] AutoMemoryToolsAdvisor 文档(order 默认值与 memoryConsolidationTrigger)

[8] Task Tools / 子智能体文档

[9] Claude Code - 官网(工具与 Skills 的出处)

[10] Spring AI Reference

[11] Maven Central - org.springaicommunity:spring-ai-agent-utils

相关学习资料