【铸灵】为什么 Java 开发者做 Agent,总要先写一堆胶水代码?我做了一个 YAML 驱动的 Spring AI 脚手架
【铸灵】为什么 Java 开发者做 Agent,总要先写一堆胶水代码?我做了一个 YAML 驱动的 Spring AI 脚手架
基于 Spring Boot 4.1 + Spring AI 2.0 + DDD 六边形架构,快速搭建可配置、可扩展、可观测的 Java Agent 应用。
如果你最近用 Spring AI 做过 Agent,应该很快会遇到一个问题:调用模型本身并不难,难的是把它真正做成一个可以长期维护的应用。
最开始,我们可能只需要几行代码:接入一个 OpenAI 兼容接口,发送一条消息,拿到模型回复。但需求很快会变成这样:
- 需要同时管理多个 Agent,而且彼此不能互相污染配置;
- 需要同步接口,也需要 SSE 流式输出;
- 需要保存会话和历史消息,让 Agent 具备多轮记忆;
- 需要让模型调用 Java 方法、远程 MCP Server 或脚本 Skill;
- 需要知道一次请求消耗了多少 Token、调用了哪些工具、花了多长时间;
- 需要在页面上看到完整的推理、工具调用和文本输出过程。
做到这里,项目就不再是一个简单的 Chat API 封装,而是一个完整的 Agent 应用基础设施。大量时间也会从“实现业务能力”,转移到“补齐各种胶水代码”。
所以我做了一个开源项目:【铸灵】 ZhuLing。
项目地址:https://github.com/vinist123/zhuling

图 1:【铸灵】登录页,首页直接呈现“铸造 AI 灵魂”的项目定位。
【铸灵】是什么?
为什么叫 【铸灵】?
这个名字不是随意起的。
“铸”代表把原本零散的模型调用、提示词、记忆、工具和运行状态,铸造成一套稳定、可复用、可扩展的 Agent 基础设施。它强调的是工程化:从一次性的 Demo,走向能够持续演进的应用。
“灵”代表 Agent 的灵魂。一个真正有用的 Agent,不只是返回一段文本,还应该有明确的角色设定、可持续的上下文、可调用的工具,以及能够被观察和调试的运行过程。
所以,【铸灵】的完整表达是“铸造 AI 灵魂”:把模型能力铸成可运行的 Agent,把业务知识和工具能力赋予它,再用工程化的方式让它稳定工作。
【铸灵】(ZhuLing)是一个面向 Java 开发者的 Agent 开发脚手架。它的核心思路很简单:
用 YAML 描述 Agent,用统一运行时加载 Agent,把会话、工具、流式事件和可观测性能力统一起来。
你不需要为每个 Agent 单独复制一套 Controller、Service 和模型配置。基础 Agent 可以直接通过 YAML 创建,业务工具和领域逻辑再按照项目边界扩展进去。
它不是只封装了一个 ChatClient,而是尝试把 Agent 应用中重复度最高、最容易失控的部分先整理出来:配置、运行时、会话、工具和观测。
它解决了哪些问题?
当前版本的核心能力包括:
| 能力 | 说明 |
|---|---|
| 多 Agent 运行时 | 多个 Agent 独立注册、加载和运行时隔离 |
| 统一对话目标 | 支持选择 Agent 或 Workflow 作为对话目标 |
| 对话接口 | 同步接口和 SSE 流式接口 |
| 会话记忆 | 会话、历史消息和 metadata 持久化 |
| MCP 工具 | 支持 Local、SSE、Stdio 三种接入模式 |
| Skills | 加载包含 SKILL.md 和脚本的 Skill 包 |
| 可观测性 | Token、Trace ID、上下文占用比和工具遥测 |
| SSE 事件信封 | 覆盖 turn、message、reasoning、tool 生命周期 |
| 对话工作台 | 内置纯静态 UI,查看对话和运行资源 |
这些能力组合在一起,解决的是 Agent 项目的“工程化”问题:你可以先用配置快速验证想法,再逐步增加领域服务、工具和业务流程,而不是一开始就搭一套分散的基础设施。

图 2:【铸灵】工作台的对话目标和会话入口。
最核心的体验:配置即 Agent
创建一个 Agent,不需要先写一堆 Java 配置类。你可以在 zhuling-app/src/main/resources/agent-config/agents/ 下创建 YAML 文件:
id: my-agent
app-name: zhuling-app
agent:
agent-id: my-agent
agent-name: 我的助手
agent-desc: |
你是一个专业、友好的 AI 助手。
module:
ai-api:
base-url: https://your-api-provider.com/v1
api-key: sk-your-api-key
chat-model:
model: gpt-4o
context:
max-messages: 20
max-characters: 12000
context-window-tokens: 128000
这里的 agent-desc 不只是展示用的描述,它同时可以作为 Agent 的系统提示词。模型地址采用 OpenAI 兼容格式,因此可以接入 OpenAI、通义千问、智谱、Moonshot 以及各种兼容网关。
如果要开启观测和工具能力,还可以继续补充:
module:
observability:
react-enabled: true
reasoning-content-enabled: true
tool-call-enabled: true
mcp:
enabled: true
mode: local
servers:
- type: local
name: my-local-tools
tools:
- name: myCustomToolService
enabled: true
配置校验也在启动阶段完成。Agent ID、模型地址、API Key、模型名称和 Skill 路径等关键配置缺失时,应用会直接提示问题;外部 MCP 连接失败时,则只会影响对应 Agent,不会拖垮其他 Agent。
最短路径启动一个 Agent 应用
环境要求
- JDK 21+
- Maven 3.8+
- MySQL 8.0+ 或 PostgreSQL 15+
克隆项目
git clone https://github.com/vinist123/zhuling.git
cd zhuling
初始化数据库
项目使用会话表和消息表保存多轮对话。创建数据库后,执行仓库 README 中的建表 SQL,核心表包括:
agent_session:保存目标 Agent、用户、标题、状态和消息数量;agent_message:保存角色、消息内容和可观测 metadata。
修改数据源
编辑 zhuling-app/src/main/resources/application-dev.yml:
spring:
datasource:
username: root
password: your_password
url: jdbc:mysql://localhost:3306/agent_scaffold?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
配置模型和 Agent
在 agent-config/agents/ 下增加一个 YAML 文件,填入你的模型服务地址、API Key 和模型名。
编译启动
mvn clean package -DskipTests
cd zhuling-app
java -jar target/zhuling-app-1.0-SNAPSHOT.jar
启动后,可以直接打开项目内的 ui/index.html 查看工作台,也可以通过 API 调用 Agent。
对话接口:同步和流式都支持
创建会话:
curl -X POST http://localhost:8091/api/v1/session/create \
-H "Content-Type: application/json" \
-d '{
"targetId": "default-agent",
"targetType": "AGENT",
"userId": "user-001",
"title": "测试会话"
}'
同步聊天:
curl -X POST http://localhost:8091/api/v1/chat/sync \
-H "Content-Type: application/json" \
-d '{
"sessionId": "上一步返回的sessionId",
"message": "你好"
}'
流式聊天:
curl -N -X POST http://localhost:8091/api/v1/chat/stream \
-H "Content-Type: application/json" \
-d '{
"sessionId": "上一步返回的sessionId",
"message": "你好"
}'
SSE 流不是简单地吐出一串文本。【铸灵】对事件做了版本化封装,一轮对话可以看到:
turn.started
message.delta
reasoning.delta
tool.started
tool.completed
turn.completed
当请求失败时,会收到 turn.failed,并携带错误信息。这样,前端不仅能显示最终答案,也能知道这一轮对话什么时候开始、调用过什么工具、什么时候结束,以及本轮的 metadata。
Tool如何交给 LLM 调用?
业务系统通常不会只满足于聊天,还希望 Agent 能查询订单、读取库存、调用内部服务。【铸灵】支持通过 Spring AI 的 @Tool 注解开发本地 工具。
第一步,在领域模块中编写工具类:
@Slf4j
@Service
public class MyCustomToolService {
@Tool(description = "查询用户订单信息,传入用户ID,返回订单列表")
public OrderResult queryOrder(OrderRequest request) {
log.info("查询订单: userId={}", request.getUserId());
return new OrderResult();
}
}
第二步,把它注册为 ToolCallbackProvider:
@Bean("myCustomToolService")
public ToolCallbackProvider myCustomTools(MyCustomToolService toolService) {
return MethodToolCallbackProvider.builder()
.toolObjects(toolService)
.build();
}
第三步,在 Agent YAML 中引用 Bean 名称:
module:
mcp:
enabled: true
servers:
- type: local
name: my-custom-tools
tools:
- name: myCustomToolService
enabled: true
完整链路是:
@Tool 方法
→ Spring @Service Bean
→ ToolCallbackProvider
→ LocalMcpToolCallbackBuilder
→ AgentRuntime
→ LLM 调用
除了 Local 模式,项目还支持通过 SSE 或 Stdio 接入外部 MCP Server。对于已有工具服务的团队,这意味着不必把所有能力重写到当前应用里。
Skills:把脚本能力封装成可加载模块
有些能力用 Python 或命令行脚本实现更方便,例如 PDF 处理、数据查询或文件转换。【铸灵】的 Skill 是一个包含 SKILL.md 和可执行脚本的目录:
agent-config/skills/my-skill/
├── SKILL.md
├── scripts/
│ └── main.py
└── data/
└── catalog.json
SKILL.md 负责描述这个能力什么时候使用、调用哪个脚本、参数如何传递。Agent 通过统一的 Skill 执行入口使用脚本结果,不需要把每一个脚本都改写成 Java Bean。
这让 Agent 的扩展方式更灵活:核心业务逻辑可以留在 Java 领域层,适合快速试验或数据处理的能力则可以通过 Skill 包加载。
为什么强调可观测性?
Agent 出问题时,单看最终文本往往不够。
用户可能只看到“回答失败”,但开发者真正想知道的是:
- 使用了哪个 Agent 和模型?
- 本轮请求的 Trace ID 是什么?
- 模型消耗了多少输入和输出 Token?
- 上下文窗口用了多少?
- LLM 是否调用了工具?工具耗时和结果是什么?
- 是模型请求失败,还是外部 MCP Server 失败?

图 3:【铸灵】可观测对话工作台,同时展示推理、工具调用、Token、Trace ID 和上下文资源。
【铸灵】把这些信息纳入对话生命周期,并在工作台中展示。内置的纯静态 UI 不需要单独部署,可以直接打开 ui/index.html,完成目标 Agent 选择、会话切换、流式对话、历史回放和资源检查。
这对调试尤其重要:你可以把一次对话当作一个完整的运行单元,而不是只保存最后返回的字符串。
DDD 六边形架构,给后续扩展留空间
项目的模块依赖方向是:
Trigger → API → Case → Domain ← Infrastructure
各层职责相对清晰:
zhuling-trigger:HTTP Controller 和外部请求入口;zhuling-api:DTO、VO 和接口定义;zhuling-case:聊天流程和用例编排;zhuling-domain:核心业务、Port 和 Repository 接口;zhuling-infrastructure:数据库、Gateway、Redis、MCP 和可观测性实现;zhuling-app:应用启动、配置文件、Agent YAML 和 Skills;zhuling-types:公共枚举、异常和通用类型。
这种分层的价值不在于“目录看起来更复杂”,而在于后续替换模型供应商、持久化方案或工具实现时,业务用例不必跟着一起重写。
适合哪些场景?
【铸灵】更适合以下几类项目:
- 想用 Java/Spring Boot 快速验证 Agent 产品原型;
- 需要接入多个 OpenAI 兼容模型服务的内部助手;
- 需要保存会话、历史消息和调用 metadata 的企业应用;
- 需要把 Java 服务、MCP Server 或脚本能力交给 LLM 调用的业务系统;
- 想系统学习 Spring AI、MCP、Agent 运行时和可观测性实现的开发者。
如果你的需求只是调用一次模型并返回文本,那么直接使用 Spring AI 可能已经足够;当项目开始出现多 Agent、工具调用、会话管理和运行追踪时,脚手架的价值会更明显。
当前进度和后续计划
README 中已经标记完成的阶段包括基础框架、LLM 集成、会话管理、工具调用、可观测性、MCP、多 Agent 运行时基础和可观测性增强。
后续路线图还包括:
- Phase 7:ReAct 模式;
- Phase 8:多 Agent 协同;
- Phase 9:多模态支持;
- Phase 10:测试与文档完善。
这些是项目继续演进的方向,不代表当前版本已经完整交付。开源项目最需要的,往往不是一句“已经完美”,而是持续的反馈、真实的使用场景和愿意一起完善代码的人。
写在最后:欢迎试用,也欢迎点一个 Star
如果你正在用 Java 做 Agent,或者正在学习 Spring AI,希望 【铸灵】能帮你少写一些重复的基础代码。
欢迎访问项目:
GitHub: https://github.com/vinist123/zhuling
Gitee: https://gitee.com/vinsit/zhuling
你可以先从 README 的快速开始跑起来,再根据自己的业务增加 Agent、工具和 Skill。如果遇到问题,欢迎提交 Issue;如果你有更好的实现,也欢迎提交 Pull Request。
如果这个项目对你有帮助,欢迎顺手点一个 Star。
你的 Star 不只是一个数字,它会帮助这个项目获得更多关注,也会成为我继续完善工具生态、可观测性和 Agent 协同能力的动力。
感谢每一位试用、反馈、提 Issue 和贡献代码的朋友。
相关标签
Java Spring Boot Spring AI AI Agent MCP DDD 六边形架构 SSE 开源项目
更多推荐
所有评论(0)