惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
爱范儿
爱范儿
Recent Announcements
Recent Announcements
AI
AI
V
Visual Studio Blog
H
Heimdal Security Blog
L
LINUX DO - 最新话题
Attack and Defense Labs
Attack and Defense Labs
宝玉的分享
宝玉的分享
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
人人都是产品经理
人人都是产品经理
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
WordPress大学
WordPress大学
S
Secure Thoughts
S
Security Affairs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
N
News and Events Feed by Topic
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 聂微东
博客园 - Franky
阮一峰的网络日志
阮一峰的网络日志
Schneier on Security
Schneier on Security
Hugging Face - Blog
Hugging Face - Blog
Apple Machine Learning Research
Apple Machine Learning Research
Forbes - Security
Forbes - Security
The Cloudflare Blog
博客园 - 【当耐特】
酷 壳 – CoolShell
酷 壳 – CoolShell
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
月光博客
月光博客
有赞技术团队
有赞技术团队
博客园 - 司徒正美
博客园_首页
Recent Commits to openclaw:main
Recent Commits to openclaw:main
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
NISL@THU
NISL@THU
C
Cybersecurity and Infrastructure Security Agency CISA
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Proofpoint News Feed
罗磊的独立博客
V
Vulnerabilities – Threatpost
S
Securelist
N
News and Events Feed by Topic
Cloudbric
Cloudbric
P
Proofpoint News Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V2EX - 技术
V2EX - 技术
小众软件
小众软件

博客园 - Zhentiw

[GenAI] Migration Plan: Flat API → Layered Architecture [Skill] Frontend Design Skill Claude Code Hooks: Complete Guide [GenAI] Pre-retieval overview [GenAI] About Indexing [GenAI] Indexing overview [Vibe Coding] 降低大模型幻觉 - 重试机制 [Vibe coding] 降低大模型幻觉 - JSON 安全输出提示词 [Node.js] WebSocket基础知识 [LangGraph] 应用结构 [LangGrpah] Unit testing [LangGraph] Functional API [LangGraph] 中断注意事项 [LangGraph] 中断相关细节 [LangGrpah] 静态断点 [LangGrpah] 非阻塞式中断 [LangGraph] 阻塞式中断 [LangGraph] 语义搜索 [LangGraph] 长期记忆 [LangGraph] 管理短期记忆 [LangGraph] 自定义checkpointer [LangGraph] 短期记忆 [LangGraph] 时间旅行 [LangGraph] checkpoint常用API [LangGraph] 元数据标记 [LangGraph] 流 [Vitest] mockClear, mockReset, mockRestore
[LangGraph] 将子图添加为节点
Zhentiw · 2026-02-24 · via 博客园 - Zhentiw

核心概念

子图直接“嵌入”到父图内,成为父图的一部分,与父图共享 state 的 key。

示意图:

父图节点  ===>  { 子图内部的很多节点 } ===> 父图下一个节点

看起来像父图的一个 node,但内部却是一个完整的 graph。

也正因为如此:

  • 子图与父图使用同一个 state(共享部分或全部 key)

  • 子图内部的 node 可以读写父图 state

子图不再是一个“黑盒”,而是父图的一部分

适用场景:

  • 多团队协作,把一段流程拆成一个子图
  • 想复用一段常用流程(比如全局日志链路、消息管道)
  • 子图需要访问父图的多个 state 字段,不止输入/输出

快速上手

场景

客户注册需要执行复杂的 KYC(身份核验)流程:

子图负责:

  • OCR 身份证识别
  • 人脸对比
  • 风险评分
  • 写入结果到父图的 shared state

父图负责:

  • 收集用户信息
  • 调用 KYC 子图验证
  • 根据验证结果决定是否注册成功

示意图

flowchart TD %% ---------- 父图 ---------- subgraph ParentGraph[父图:用户注册流程] P_START([START]) P1[父节点:kycFlow<br/>(子图作为复合节点)] P2[父节点:finish<br/>根据 kycPassed 生成注册结果] P_END([END]) P_START --> P1 --> P2 --> P_END end %% ---------- 子图 ---------- subgraph Subgraph[子图:KYC 验证流程(共享父图 State)] S_START([START]) S1[子节点:OCR 校验<br/>ocrPassed] S2[子节点:人脸比对<br/>faceMatch] S3[子节点:KYC 汇总<br/>kycPassed] S_END([END]) S_START --> S1 --> S2 --> S3 --> S_END end %% ---------- 连接关系 ---------- %% 说明:父图的 kycFlow 节点 == 整个子图执行 P1 -. 调用并共享 state .-> S_START S_END -. 返回更新后的 state .-> P2

index.ts

import { mainGraph } from "./mainGraph.ts";

async function main() {
  // 模拟数据
  const input = {
    userName: "张三",
    idCardImage: "path/idcard.jpg",
    selfImage: "path/selfie.jpg",
  };

  const result = await mainGraph.invoke(input);

  console.log("\n=== 最终结果 ===");
  console.log(result);
}
main();

mainGraph.ts

// 父图
import { StateGraph, START, END } from "@langchain/langgraph";
import { z } from "zod/v4";
import { kycSubgraph } from "./kycSubgraph.ts";

// 父图的状态
const MainState = z.object({
  // 用户注册的基本信息
  userName: z.string().describe("用户名"),
  idCardImage: z.string().describe("用户身份证图片"),
  selfImage: z.string().describe("用户相关的图片"),

  // 各种验证
  ocrPassed: z.boolean().optional().describe("ocr验证是否通过"),
  faceMatch: z.boolean().optional().describe("人脸匹配是否通过"),
  kycPassed: z.boolean().optional().describe("kyc验证是否通过"),

  // 最终注册的结果
  registerResult: z.string().optional().describe("最终注册的结果"),
});

type TMainState = z.infer<typeof MainState>;

function finish(state: TMainState) {
  if (state.kycPassed) {
    return {
      registerResult: "注册成功",
    };
  }
  return {
    registerResult: "注册失败,KYC验证没有通过",
  };
}

export const mainGraph = new StateGraph(MainState)
  .addNode("kycFlow", kycSubgraph)
  .addNode("finish", finish)
  // 边
  .addEdge(START, "kycFlow")
  .addEdge("kycFlow", "finish")
  .addEdge("finish", END)
  .compile();

kycSubgraph.ts

// 做身份验证的子图
import { StateGraph, START, END } from "@langchain/langgraph";
import { z } from "zod/v4";

const KycState = z.object({
  // 用户注册的基本信息
  userName: z.string().describe("用户名"),
  idCardImage: z.string().describe("用户身份证图片"),
  selfImage: z.string().describe("用户相关的图片"),

  // 各种验证
  ocrPassed: z.boolean().optional().describe("ocr验证是否通过"),
  faceMatch: z.boolean().optional().describe("人脸匹配是否通过"),
  kycPassed: z.boolean().optional().describe("kyc验证是否通过"),
});

type TKycState = z.infer<typeof KycState>;

// 检查的节点:1. OCR验证   2. 人脸比对
async function ocrCheck() {
  const randomPass = Math.random() > 0.5; // 90% 通过

  console.log("🔍 [子图] OCR 检查:", randomPass);

  return { ocrPassed: randomPass };
}

async function faceMatchCheck() {
  const randomPass = Math.random() > 0.5; // 80% 通过

  console.log("🔍 [子图] 人脸比对:", randomPass);

  return { faceMatch: randomPass };
}

// 汇总节点
async function summary(state: TKycState) {
  // 这两项验证都通过了,那就是通过了
  const passed = state.ocrPassed && state.faceMatch;

  return {
    kycPassed: passed,
  };
}

export const kycSubgraph = new StateGraph(KycState)
  .addNode("ocrCheck", ocrCheck)
  .addNode("faceMatchCheck", faceMatchCheck)
  .addNode("summary", summary)
  // 边
  .addEdge(START, "ocrCheck")
  .addEdge("ocrCheck", "faceMatchCheck")
  .addEdge("faceMatchCheck", "summary")
  .addEdge("summary", END)
  .compile();