本文基于 Spring AI 2.0.0 与 spring-ai-agent-utils 0.10.0(截至 2026-08-19)编写。该领域迭代极快,请以官方文档为准。
当 Claude Code 被"移植"到了 Java
摘要: 本文带你拆解
spring-ai-agent-utils——一个由 Spring AI Community 出品、把 Claude Code 核心能力用 Spring AI Tool 抽象重新实现的 Java Agent 工具库。文章从项目定位与五分钟上手讲起,梳理其与 Claude Code 一一对应的工具体系,手把手组装 CLI 编码 Agent,并深入架构分层、子 Agent 委派、Markdown 即 Agent、A2A 跨进程协作等核心设计;最后以逆向工程视角解读系统提示词这一"资产",客观总结 0.x 版本的局限,指出它作为 Spring AI 2.0 时代 Agent 工程化教科书的价值。
先看一句官方定位,来自 Spring AI Community 的项目 README:
“reimplements core Claude Code capabilities as Spring AI tools”
(将 Claude Code 的核心能力重新实现为 Spring AI 工具)
Claude Code 是 Anthropic 推出的终端 AI 编码助手,也是目前 Agentic Coding 的标杆产品。但它是一个黑盒产品——你只能用,不能拆。而 spring-ai-agent-utils 做了一件有意思的事:把 Claude Code 的工具体系逐个逆向、拆解,再用 Spring AI 的 Tool 抽象重新实现了一遍。
连细节都在复刻:系统提示词模板命名为 MAIN_AGENT_SYSTEM_PROMPT_V2.md,默认子 Agent 叫 general-purpose 和 Explore,技能目录约定为 .claude/skills/——用过 Claude Code 的人会心一笑。
对 Java 开发者而言,这个项目的意义不只是"玩具":它是一个生产级自主 Agent 的参考实现,展示了 2026 年 Java 生态构建 Agentic 应用的完整技术栈。
它到底是什么
先交代背景:
- 出品方:Spring AI Community(spring-ai-community 组织),是 Spring AI 2.0 GA 发布公告中官方点名的社区扩展项目(另一个是事件溯源记忆库 spring-ai-session);
- 版本:0.10.0,Apache 2.0 协议(版本还在 0.x,API 可能变动);
- 基线要求:Java 17+,Spring Boot 3.x / 4.x,Spring AI 2.0.0+,Maven 3.6+;
- 定位:Spring AI 提供通用 LLM 能力(ChatClient、Advisor、工具调用),agent-utils 在其上补齐"软件工程 Agent"所需的全部工具件。
一个容易混淆的概念先澄清:这里的 “agent” 与 JVM 的 java.lang.instrument Agent、AOP 的 agentmain 毫无关系,指的是 LLM 驱动的自主智能体(AI Agent)。
五分钟上手
引入依赖
推荐用 BOM 统一管理版本:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springaicommunity</groupId>
<artifactId>spring-ai-agent-utils-bom</artifactId>
<version>0.10.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springaicommunity</groupId>
<artifactId>spring-ai-agent-utils</artifactId>
</dependency>
<!-- 任选一个 LLM 提供商 starter,比如 Anthropic / OpenAI / Google GenAI -->
</dependencies>
核心库对 Spring AI 的依赖声明为 provided 作用域,不会和你的项目版本打架。
最小配置
# LLM 提供商(以 Anthropic 为例)
spring.ai.anthropic.api-key=${ANTHROPIC_API_KEY}
# 可选:Brave 搜索
BRAVE_API_KEY=${BRAVE_API_KEY}
# 可选:注入到系统提示词的模型元信息
agent.model=claude-sonnet-4-5
agent.model.knowledge.cutoff=2025-09
就这么点东西,下面进入正题。
工具体系:与 Claude Code 一一对应
agent-utils 的工具清单,几乎就是 Claude Code 的能力地图:
| agent-utils 工具 | 对应 Claude Code 能力 | 说明 |
|---|---|---|
FileSystemTools | Read / Write / Edit | 分页读文件(带行号)、写文件、精确字符串替换(带唯一性校验) |
ShellTools | Bash | Shell 命令执行 |
GrepTool | Grep | 内容正则搜索 |
GlobTool | Glob | 文件模式匹配查找 |
SmartWebFetchTool | WebFetch | 智能网页抓取,内部用一个独立 ChatClient 做 AI 摘要,HTML 转 Markdown |
BraveWebSearchTool | WebSearch | Brave API 网络搜索 |
TaskTool | Task | 子 Agent 任务委派 |
TaskOutputTool | — | 取回后台异步任务的执行结果 |
TodoWriteTool | TodoWrite | 结构化任务清单与进度跟踪 |
AskUserQuestionTool | AskUserQuestion | 向用户提出澄清式问题 |
SkillsTool | Skills | 加载 Markdown 编写的技能模块 |
AutoMemoryTools | Memory | 沙箱化的长期记忆读写 |
所有工具都通过 XxxTool.builder()...build() 流式构建,标准 Spring AI Tool 抽象,可以直接注册给任何 ChatClient。
核心实战:组装你的 CLI 编码 Agent
官方仓库 examples/code-agent-demo 是最完整的参考实现——全部核心逻辑集中在一个 156 行的 Application.java 里。下面是整理简化后的骨架(基于官方示例改写):
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder,
@Value("classpath:/prompt/MAIN_AGENT_SYSTEM_PROMPT_V2.md") Resource systemPrompt,
@Value("${agent.skills.paths}") List<Resource> skillPaths,
ToolCallbackProvider mcpTools, // 外部 MCP 工具,按需注入
@Value("${BRAVE_API_KEY:}") String braveApiKey) {
return args -> {
ChatClient chatClient = chatClientBuilder
// 1. 系统提示词:注入运行时环境上下文
.defaultSystem(sb -> sb.text(systemPrompt)
.param("model", "claude-sonnet-4-5")
.param("knowledgeCutoff", "2025-09"))
// 2. MCP 外部工具
.defaultToolCallbacks(mcpTools)
// 3. 技能系统:从 Markdown 加载
.defaultToolCallbacks(SkillsTool.builder()
.addSkillsResources(skillPaths).build())
// 4. 任务清单与用户交互
.defaultTools(TodoWriteTool.builder().build())
.defaultTools(AskUserQuestionTool.builder()
.questionHandler(new CommandLineQuestionHandler())
.answersValidation(false) // 允许自由文本回答
.build())
// 5. 核心工具:文件、Shell、搜索
.defaultTools(FileSystemTools.builder().build())
.defaultTools(ShellTools.builder().build())
.defaultTools(GrepTool.builder().build())
.defaultTools(GlobTool.builder().build())
// SmartWebFetchTool 需要一个独立的 ChatClient 做摘要
.defaultTools(SmartWebFetchTool.builder()
.chatClient(chatClientBuilder.clone().build())
.build())
.defaultTools(BraveWebSearchTool.builder()
.apiKey(braveApiKey).build())
// 6. Advisor:会话记忆(500 条消息窗口)
.defaultAdvisors(MessageChatMemoryAdvisor.builder()
.maxMessages(500).build())
.build();
// 交互主循环
System.out.println("I am your assistant.");
var scanner = new Scanner(System.in);
while (true) {
System.out.print("> USER: ");
String input = scanner.nextLine();
String answer = chatClient.prompt()
.user(input)
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, "main"))
.call()
.content();
System.out.println(answer);
}
};
}
}
几个值得注意的细节:
- 装配顺序有讲究:系统提示词(确立身份)→ 动态工具回调(MCP、Skills)→ 静态工具实例 → Advisor(包裹调用逻辑、管理记忆)。这是官方示例刻意示范的分层。
SmartWebFetchTool用chatClientBuilder.clone():它内部需要另一个 LLM 实例把网页内容摘要成 Markdown,克隆 Builder 保证了隔离,不影响主 Agent 配置。answersValidation(false):让AskUserQuestionTool接受预置选项之外的自由文本,CLI 交互更自然。
跑起来之后,你可以让它"帮我看下这个项目的 README 然后总结架构"——它会自己组合 GlobTool 找文件、FileSystemTools 读取、必要时用 TodoWriteTool 拆任务,全程无需你写任何编排代码。编排逻辑完全由 LLM 的工具调用循环驱动,这正是 Agentic 应用的核心特征。
架构拆解
整体架构一张图:

从上往下四层:
- 输入层:CLI 交互主循环(也可以换成任何入口);
- Agent 核心:
ChatClient+ Spring AI 2.0 的 Advisor 链,工具循环由ToolCallingAdvisor承载(这是 Spring AI 2.0 最大的架构变化,详见官方发布公告);左侧系统提示词经AgentEnvironment注入模型名、Git 状态、知识截止日期等运行时元信息;右侧是分层记忆; - 工具层:五大类工具组;
- 子 Agent 层:
TaskTool委派出的隔离执行环境。
四个贯穿全局的架构模式值得单独说:
1. 组合优于继承。高层工具(SkillsTool、TaskTool)全部通过组合基础工具实现,没有继承层级——这让每个工具都可以独立替换。
2. 动态工具生成。SkillsTool 和 TaskTool 不是静态工具,而是 ToolCallbackProvider 实现:运行时扫描目录里的 Markdown 文件,动态产出工具定义。技能即文件、Agent 即文件,这和 Claude Code 的扩展哲学一脉相承。
3. 隔离上下文窗口。每个子 Agent 拥有独立的 ChatClient 实例,从空历史开始,只把最终结果交还主 Agent——保护主对话不被大量中间过程污染。
4. 回调式集成。AskUserQuestionTool 通过 handler 函数把"提问逻辑"与"UI 实现"解耦:CLI 场景传 CommandLineQuestionHandler,换成 Web 前端只需实现自己的 handler。
子 Agent 委派:最值得学的设计
多 Agent 编排是 2026 年 Agent 框架的竞争焦点,agent-utils 用一套非常轻的机制实现了它。
三个核心组件
| 组件 | 职责 |
|---|---|
TaskToolCallbackProvider | 工厂,同时产出 TaskTool 和 TaskOutputTool |
TaskTool | 启动子 Agent,按配置过滤其可用工具 |
TaskOutputTool | 检索后台异步任务的结果 |
用法
// 子 Agent 从主 Builder 克隆,天然隔离
var taskTools = TaskToolCallbackProvider.builder()
.chatClientBuilder(chatClientBuilder.clone())
// 自定义子 Agent 定义目录(Markdown 文件)
.agentDirectories(".claude/agents")
// 子 Agent 也可以加载技能
.skillsDirectories(".claude/skills")
.build()
.getToolCallbacks(); // TaskTool + TaskOutputTool
ChatClient agent = chatClientBuilder
.defaultToolCallbacks(taskTools)
.build();
子 Agent 也是 Markdown
自定义子 Agent 放在 .claude/agents/ 目录,一个 .md 文件就是一个 Agent——YAML front-matter 定义元信息,正文就是它的系统提示词:
---
name: code-reviewer
description: 专注代码审查,输出结构化审查报告
tools: [Read, Grep, Glob] # 最小权限:只给读和搜索
---
你是一名资深 Java 代码审查员。收到代码后按以下维度输出:
1. 正确性风险 2. 并发问题 3. 性能隐患 4. 风格建议
框架启动时会递归扫描目录、解析 front-matter、注册为可委派的 Agent 类型。工具过滤有两条关键规则:tools() 为空表示全部工具可用;指定了列表则精确匹配、只给子集——这就是按 Agent 粒度的最小权限控制。TaskType 中还有 permissionMode、skills() 字段,目前标注"尚未实现",属于预留设计。
隔离到什么程度
| 维度 | 主 Agent | 子 Agent |
|---|---|---|
| 上下文窗口 | 会话内共享 | 每任务专用,从空历史开始 |
| 工具访问 | 全部注册工具 | 按 tools() 过滤 |
| 系统提示词 | MAIN_AGENT_SYSTEM_PROMPT_V2 | TaskType 正文 |
| 会话记忆 | MessageChatMemoryAdvisor | 无(除非显式添加) |
| Advisors | 完整链 | 最小化集合 |
还支持异步模式:LLM 调 TaskTool 时传 run_in_background=true,立即拿到任务 ID 继续干别的,之后用 TaskOutputTool 轮询取结果——后台任务存在 TaskRepository(默认内存实现,可替换)。
A2A:委派可以跨进程
多模块结构里有个 spring-ai-agent-utils-a2a 模块,实现了 A2A 协议(Agent2Agent)远程子 Agent——Task 委派的目标不一定是本地进程,可以是另一台机器上用完全不同框架写的 Agent。“Agent 的微服务化”,这就是雏形。A2A 协议本身值得单独写一篇,这里先埋个坑。
逆向工程视角:提示词也是资产
这个项目最有学习价值的部分,其实是 MAIN_AGENT_SYSTEM_PROMPT_V2.md 这个系统提示词模板——它完整展示了 Claude Code 这类产品如何用提示词工程定义 Agent 行为:
- 环境感知:通过
AgentEnvironment把模型名、知识截止日期、Git 状态注入提示词,让模型"知道自己是谁、在哪、能用什么"; - 工具使用指引:明确告诉 LLM 什么时候该用
TaskTool委派、什么时候直接用Read/Grep,降低误判; - 行为约束:任务规划、进度同步、提问澄清的时机全写进了提示词。
一个顶级 Agent 产品的核心竞争力,一半在模型,一半在提示词。能读到一份工业级的提示词模板并观察它如何与工具体系咬合,是比任何教程都珍贵的学习材料。
局限与展望
客观说几个不足:
- 版本 0.x:API 不稳定,
permissionMode、子 Agent 级skills()等字段尚未实现,生产使用需谨慎锁定版本; - 安全边界依赖自觉:
ShellTools、FileSystemTools执行的都是高危操作,沙箱隔离要自己做(对比之下,Spring AI Alibaba 的 Sandbox 组件做了专门设计); - 与 Claude Code 的差距:复刻的是工具体系和提示词设计,Claude Code 的模型侧优化(工具选择的微调、上下文管理策略)依然是不公开的。
但作为 Spring AI 2.0 时代 Agent 工程化的教科书,它的价值已经足够:Builder 模式的工具 API、Markdown 即 Agent 的扩展机制、隔离上下文的多 Agent 委派、A2A 远程协作——这四件事对应着 2026 年 Java Agent 开发的四个核心命题,每个都值得展开写。
小结
spring-ai-agent-utils 证明了"用 Java 造 Claude Code"不是噱头:Spring AI 2.0 把工具循环做进 Advisor 链之后,Agent 的骨架已经就位,剩下的就是工具件与工程化——而这份答卷来自官方社区,可信度拉满。

307

被折叠的 条评论
为什么被折叠?



