一个基于 Google ADK + Spring AI + LangChain4j 双引擎的 Java 多智能体脚手架,把 Agent 的定义、工具、技能、工作流全部 YAML 化,让「写 Agent」变成「配 Agent」。
如果你在 Java 生态里做过 AI Agent,大概率经历过如下流程:
java// Step 1: 定义 Agent A
LlmAgent researcherA = LlmAgent.builder()
.name("EVResearcher")
.model(new SpringAI(chatModel))
.instruction("调研电动车技术...")
.outputKey("ev_result")
.build();
// Step 2: 定义 Agent B
LlmAgent researcherB = LlmAgent.builder()
.name("EnergyResearcher")
.model(new SpringAI(chatModel))
.instruction("调研可再生能源...")
.outputKey("energy_result")
.build();
// Step 3: 定义 Agent C
LlmAgent researcherC = LlmAgent.builder()
.name("CarbonResearcher")
.model(new SpringAI(chatModel))
.instruction("调研碳捕获方法...")
.outputKey("carbon_result")
.build();
// Step 4: 并行执行
ParallelAgent parallel = ParallelAgent.builder()
.subAgents(researcherA, researcherB, researcherC)
.build();
// Step 5: 汇总 Agent
LlmAgent merge = LlmAgent.builder()
.name("Synthesis")
.instruction("汇总 {ev_result} {energy_result} {carbon_result}")
.build();
// Step 6: 串行编排
SequentialAgent pipeline = SequentialAgent.builder()
.subAgents(parallel, merge)
.build();
// Step 7: 创建 Runner + Session...
每次新增一个 Agent 就要改 Java 代码、重新编译、重新部署。团队协作时,代码冲突、版本管理、依赖注入都是噩梦。而且你会发现 —— 这些 Java 代码本质上是「配置」,而不是「逻辑」。
更致命的是:模型 API、MCP 工具连接、Skills 注入都被硬编码在 Java 类里。切换模型厂商?改代码。换个搜索工具?改代码。加一个 Agent 节点?还是得改代码。
ai-agent-scaffold-lite 的思路很直接 —— 把一切应该是「配置」的东西从 Java 代码里抽出来,放进 YAML:
yaml# 并行调研 → 汇总报告,三行 Java 代码都不用写
agent-workflows:
- type: parallel
name: ParallelResearch
sub-agents:
- EVResearcher # 预定义的子 Agent
- EnergyResearcher
- CarbonResearcher
- type: sequential
name: ResearchPipeline
sub-agents:
- ParallelResearch # 先并行
- SynthesisAgent # 再汇总
runner:
agent-name: ResearchPipeline # 👈 入口,就这么简单
这正是 "约定大于配置" 在 AI Agent 领域的实践:
| 传统写法 | 本项目 |
|---|---|
| 每个 Agent 写一个 Java 类 | 一个 YAML 节点 |
| 改模型需改代码 + 重新部署 | 改 YAML + 热加载 |
| MCP 工具硬编码 + 手动注册 | tool-mcp-list 声明式注册 |
| 工作流用建造者模式手写 | type: loop/parallel/sequential |
| Skills 需手动注入 | 指向文件夹自动扫描 |
整个项目的核心是 "责任链 + 树形装配" 模式。应用启动时,框架遍历 YAML 配置表,逐层装配:RootNode → AiApiNode → ChatModelNode → AgentNode → AgentWorkflowNode → RunnerNode,最终生成一个 Google ADK InMemoryRunner 实例注册到 Spring 容器。
flowchart TB
subgraph Config["📋 YAML 配置层"]
A["tables.myAgent"]
end
subgraph Armory["🏭 装配链 (Armory)"]
direction LR
RN["RootNode"] --> AN["AiApiNode\n→ 构建 OpenAI API 连接"]
AN --> CN["ChatModelNode\n→ 创建 ChatModel + MCP 工具"]
CN --> AGN["AgentNode\n→ 装配子 Agent (LlmAgent)"]
AGN --> AWN["AgentWorkflowNode\n→ 创建 Loop/Parallel/Sequential"]
AWN --> RUN["RunnerNode\n→ 创建 InMemoryRunner"]
end
subgraph Runtime["⚡ 运行时"]
RUN --> R["InMemoryRunner"]
R --> S["SessionService"]
end
subgraph Trigger["🌐 接入层"]
S --> API["REST API\n/chat /chat_stream"]
end
Config --> RN
DDD 六层分层:
graph LR
subgraph 接入层
T["trigger\nHTTP Controller"]
end
subgraph 应用层
APP["app\n启动 & 自动配置"]
end
subgraph 核心领域
D["domain\nAgent 装配 · 工作流 · MCP · Skills"]
end
subgraph 基础设施
I["infrastructure\nDAO / Redis / Gateway"]
end
subgraph 接口定义
A["api\nDTO / Service 契约"]
end
subgraph 通用类型
TP["types\n异常 / 枚举 / 响应码"]
end
T --> D
APP --> D
D --> A
D --> I
T --> TP
D --> TP
三种工作流原语涵盖了绝大多数 Agent 编排场景:
yamlagent-workflows:
# 🌀 循环:分析 → 执行 → 决策,重复至多 N 步
- type: loop
name: AnalyzeAndExecute
max-iterations: 5
sub-agents:
- Planner
- Executor
# ⚡ 并行:多 Agent 同时执行,结果互不干扰
- type: parallel
name: MultiDimensionResearch
sub-agents:
- TechResearcher
- MarketResearcher
- PolicyResearcher
# 🔗 串行:按序执行,后续 Agent 可用 {output_key} 获取前序结果
- type: sequential
name: CodePipeline
sub-agents:
- CodeWriterAgent
- CodeReviewerAgent
- CodeRefactorerAgent
其中 sequential 是胶水能力最强的原语 —— 它不仅可以串联单个 Agent,还能串联其他 workflow。你可以在一个 sequential 里放入 loop + parallel + 独立 Agent,自由组合。
Agent 之间通过 {output_key} 语法传递上下文,这是多 Agent 协作的关键:
yamlagents:
- name: CodeWriterAgent
instruction: |
你是代码生成器。基于用户需求,直接输出 Java 代码块。
output-key: generated_code # 👈 输出变量
- name: CodeReviewerAgent
instruction: |
你是代码评审专家。请审查以下代码:
```java
{generated_code} # 👈 引用上一 Agent 的输出
```
output-key: review_comments
- name: CodeRefactorerAgent
instruction: |
基于评审意见,重构以下代码:
代码:{generated_code}
意见:{review_comments}
实际效果:用户输入 "写一个线程安全的单例",三个 Agent 依次执行:生成 → 审查 → 重构,最终返回优化后的代码。全程在 YAML 中配置,不写一行 Java Agent 代码。
yamlchat-model:
tool-mcp-list:
# ① SSE 远程工具 —— 百度搜索、百度地图等
- sse:
name: baidu-search
base-uri: http://appbuilder.baidu.com/v2/ai_search/mcp/
sse-endpoint: sse?api_key=your_key
request-timeout: 500000
# ② Local 本地工具 —— 在 domain 模块实现
- local:
name: myToolCallbackProvider
# ③ Stdio 进程工具 —— Python、Node 等独立进程
- stdio:
name: python-tool
command: python
args: ["/path/to/mcp_server.py"]
工具会被自动注入到 ChatModel,Agent 在运行时通过 Google ADK 的 function calling 机制直接调用。
支持从 classpath 或文件系统自动扫描技能文件,Agent 启动时自动加载:
yamlchat-model:
tool-skills-list:
- type: resource # classpath 下
path: agent/skills
- type: directory # 文件系统绝对路径
path: /app/config/skills
目录结构示例:
agent/skills/ ├── code-review/SKILL.md # 代码审查规范 ├── math-reasoning/SKILL.md # 数学推理规则 └── sql-generator/SKILL.md # SQL 生成模板
每个 SKILL.md 会被作为系统 Prompt 注入到 Agent 的上下文中,实现领域知识的即插即用。
yamlrunner:
agent-name: demoAgent
plugin-name-list: # 拦截请求/响应
- myLogPlugin # 日志记录
- myTestPlugin # 内容过滤 / 审计
插件继承 Google ADK 的 BasePlugin,可在 Agent 执行链的各个环节插入自定义逻辑。
| 层面 | 选型 | 版本 |
|---|---|---|
| JDK | OpenJDK | 17 |
| 主框架 | Spring Boot | 3.4.3 |
| Agent 运行时 | Google ADK (Java) | 0.5.0 |
| AI 引擎 A | Spring AI | 1.1.0-M3 |
| AI 引擎 B | LangChain4j | 1.4.0 |
| DDD 框架 | xfg-wrench | 3.0.0 |
| ORM | MyBatis | 3.0.4 |
| 容器化 | Docker Compose | — |
双引擎设计的考量:Spring AI 和 LangChain4j 各有优劣。Spring AI 与 Spring 生态天然集成,配置简洁;LangChain4j 的工具链更成熟、社区更活跃。两者通过 Google ADK 的抽象层解耦,在 YAML 中可通过 chat-model 配置项自由切换。
用户提问:「调研最新的可再生能源、电动车、碳捕获技术进展」 ┌─────────────────────────────────────────────┐ │ ParallelResearch │ │ ┌───────────────┐ ┌───────────────┐ │ │ │ 可再生能源调研 │ │ 电动车调研 │ ... │ │ │ (百度搜索) │ │ (百度搜索) │ │ │ └───────┬───────┘ └───────┬───────┘ │ └──────────┼──────────────────┼───────────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────────┐ │ SynthesisAgent │ │ 汇总三份调研 → 结构化报告(分章节 + 结论) │ └─────────────────────────────────────────────┘
三个 Researcher Agent 通过百度搜索 MCP 并行获取信息,SynthesisAgent 汇总为章节化的技术综述报告。
flowchart LR
Input["用户需求"] --> A["CodeWriterAgent\n生成代码"]
A -->|"{generated_code}"| B["CodeReviewerAgent\n审查代码"]
B -->|"{review_comments}"| C["CodeRefactorerAgent\n重构代码"]
C --> Output["优化后的代码"]
style A fill:#e1f5fe
style B fill:#fff3e0
style C fill:#e8f5e9
代码生成、审查、重构三个环节串行执行,每一步的输出作为下一步的输入,形成完整的代码质量闭环。
bash# 1. 获取项目
git clone git@github.com:lechan775/ai-agent-scaffold-lite.git
cd ai-agent-scaffold-lite
# 2. 编译(跳过测试)
mvn clean install -DskipTests
# 3. 启动
cd ai-agent-scaffold-lite-app
mvn spring-boot:run
# 4. 验证
curl http://localhost:8080/api/v1/query_ai_agent_config_list
五分钟接入你自己的 Agent:
yaml# 在 application.yml 中添加:
ai:
agent:
config:
tables:
myFirstAgent:
app-name: myFirstAgent
agent:
agent-id: 10086
agent-name: "我的第一个助手"
agent-desc: "用 YAML 配置的智能体"
module:
ai-api:
base-url: https://your-api-endpoint
api-key: sk-your-key
completions-path: v1/chat/completions
chat-model:
model: gpt-4.1
agents:
- name: echoAgent
description: 回显测试
instruction: 原样重复用户说的话,并在末尾追加「—— 来自 YAML Agent」
runner:
agent-name: echoAgent
重启应用,Agent 即刻就绪。没写一行 Java,没有重新编译。
这个项目的核心理念很简单:写 Agent 应该像定义数据结构一样自然。你定义 Agent 的名字、指令、工具、工作流,剩下的事情交给框架。
YAML 不是银弹,但当你面对 10+ 个 Agent 的复杂编排时,纯代码写法会让你在 Builder 的海洋里窒息。此时,一个声明式的 YAML 配置体系就是最好的救生圈。
基于 小傅哥 xfg-frame-archetype v2.2 DDD 骨架重构
技术栈:Google ADK 0.5.0 + Spring Boot 3.4.3 + Spring AI 1.1.0-M3 + LangChain4j 1.4.0
如果你对这个项目有任何想法或改进建议,欢迎通过 GitHub Issues 讨论。


本文作者:williams
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!