【Spring AI Graph:从0到Supervisor·预告】动手之前,先定好3个架构决策

起因

我的代码审查Agent跑了两个月,单链路一直没问题。直到需要加RAG查最佳实践------同一个入口要走不同检索路径,单链路搞不定,必须上Graph。

但Spring AI Graph的资料太少了,官方文档偏概念,社区文章偏Demo。我花了2周从零啃到能写出第一个子图,这里先说整体架构和技术亮点,周末发完整代码。

最终形态:三层拼装的Supervisor Graph

我要搭的不是"一个Graph",而是一个三层拼装系统

plaintext

yaml 复制代码
Layer 3: Supervisor Graph(底层StateGraph手写)
         意图识别 → 条件路由 → 子图分发
              ↓
Layer 2: SubGraph(高层API快搭 / 底层手写,按需选择)
         ├─ RAG问答子图:意图分类 → 条件路由 → keyword/hybrid双路 → rerank → 生成
         ├─ 代码审查子图:解析 → 并行扫描 → 风险评估 → HITL → 报告
         └─ 通用对话子图:简单链路
              ↓
Layer 1: Node(最小执行单元,实现NodeAction/EdgeAction接口)
         IntentAnalyzeNode / KeywordSearchNode / HybridSearchNode / ...

为什么要分三层?因为不同层的关注点不同

  • Layer 3 关心路由和编排,必须灵活,所以用底层StateGraph
  • Layer 2 关心业务流程,能用高层API就别手写
  • Layer 1 关心单一职责,每个Node只做一件事

这三层不是我自己发明的------LangGraph的图编排、Spring的DI分治、Erlang的Supervisor Tree,思想来源是这些。但用Spring AI Graph落地的时候,怎么拼、在哪层用什么API,没有现成答案。

3个架构亮点

亮点1:两层API混搭------不是全底层也不是全高层

Spring AI Alibaba提供两层API:

  • 高层:SequentialAgent / ParallelAgent / LlmRoutingAgent
  • 底层:StateGraph + Node + Edge

社区文章要么全用高层(搭个Demo没问题,复杂场景撑不住),要么全用底层(能干但开发慢)。

我的做法:Supervisor用底层手写,子图内部用高层快搭

为什么?因为Supervisor需要两样东西,高层API给不了:

  1. 条件路由:根据意图动态分发到不同子图,LlmRoutingAgent只能做一次路由,不支持多级条件判断
  2. HITL中断恢复:高风险代码暂停等人工确认,高层API没有"暂停→等人→继续"的机制

java

dart 复制代码
// Supervisor必须底层手写
StateGraph supervisor = new StateGraph(OverAllState.class)
    .addNode("intent", intentRouterNode)
    .addNode("code_review", codeReviewSubGraph)
    .addNode("rag_qa", ragQaSubGraph)
    .addNode("human_review", humanReviewNode)
    .addConditionalEdge("intent", this::routeByIntent,
        Map.of("code_review", "code_review", "rag_qa", "rag_qa"))
    .addConditionalEdge("code_review", this::needHumanReview,
        Map.of("yes", "human_review", "no", END));

但子图内部没必要全手写。代码审查的质量检查+安全扫描,ParallelAgent两行搞定。按需选择API层级,才是工程化的思路

亮点2:有状态编排------从"一次性调用"到"可恢复流程"

大多数Agent Demo是这样的:输入 → 模型 → 输出,无状态,跑完就完了。

但真实场景不是一次调用。代码审查需要:解析→并行扫描→风险评估→可能要等人确认→生成报告。中间任何一步都可能失败,需要从断点恢复而不是从头重跑。

StateGraph的OverAllState就是这个问题的解法------每个Node执行完,状态持久化到共享容器。下一个Node从容器读状态,不依赖上游传递。

java

ini 复制代码
// 每个子图注册自己需要的key,全部ReplaceStrategy
KeyStrategyFactory keyStrategyFactory = () -> {
    HashMap<String, KeyStrategy> strategies = new HashMap<>();
    strategies.put(DreamSaaSOverAllState.userInput, new ReplaceStrategy());
    strategies.put(DreamSaaSOverAllState.queryIntent, new ReplaceStrategy());
    strategies.put(DreamSaaSOverAllState.searchResult, new ReplaceStrategy());
    strategies.put(DreamSaaSOverAllState.finalAnswer, new ReplaceStrategy());
    return strategies;
};

Replace策略保证下游读到的始终是最新值。子图按需注册key,不跨层------RAG子图不需要riskLevel,代码审查子图不需要searchResult

这和Java里的Event Sourcing是同一个思路:状态是第一公民,流程是状态驱动的

亮点3:HITL不是confirm,是架构级的断点设计

"Human-in-the-Loop"很容易被理解成"弹个确认框"。但HITL在Graph架构里不是确认框,是架构级的断点

区别在哪?

  • 确认框:流程继续跑,弹个框让人点一下
  • 架构断点:流程暂停,状态持久化,等人回复后从断点恢复

这意味着:

  1. Agent不会在等人的时候占着资源
  2. 人工确认的结果会写回State,影响后续路由
  3. 断点可以跨Session------今天确认不了,明天接着来

代码审查场景:检测到SQL注入风险 → 暂停 → 等安全工程师确认 → 确认后才进报告生成。不是AI说了算,架构层面保证人可控

这个设计目前Spring AI Graph的Checkpoint机制还在完善中,我用的是手动实现的State快照方案,中篇会详细展开。

技术栈版本

spring-ai-bom 1.1.6 + spring-ai-alibaba 1.1.2.2。API还在迭代,跟着做的话版本对齐是前提。

连载计划

  • 上篇(本周末):【Spring AI Graph:从0到Supervisor·上】条件路由与RAG子图
  • 中篇(下周末):【Spring AI Graph:从0到Supervisor·中】HITL与并行执行
  • 下篇(6/6):【Spring AI Graph:从0到Supervisor·下】Supervisor三层拼装

每篇都放完整代码,不是snippet也不是伪代码。读者看完能直接写出同样的东西。

相关推荐
冬奇Lab11 小时前
Agent 系列(22):Context Engineering 深度——三种上下文管理策略的量化对比
人工智能·agent
葫芦和十三12 小时前
渐进发现|代码库不是文档库
langchain·agent·ai编程
米小虾13 小时前
告别单打独斗:2026年多Agent协作架构实战指南
人工智能·agent
用户35218024547515 小时前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程
东坡白菜18 小时前
破局全栈:一个前端开发的Java入门实战记录(1)
java·全栈
EternalRights18 小时前
skill 的终局是 agent 化:我给 SKILL.md 写了个编译器,6 个 Harness 把散文孵化成独立 Agent
agent
leeyi18 小时前
Document 组件:把文件喂给 AI 之前,必须先做这三步
aigc·agent·ai编程
唐青枫18 小时前
Java Tomcat 实战指南:从 Servlet 容器到 Spring Boot 部署
java
wsaaaqqq19 小时前
roudan:自由选择实体、灵活操作数据、快速写入数据库的 Java 框架
java
言川94519 小时前
【万字长文】手搓一个Agent教程
agent