24 · Graph Engineering 图工程
用 Codex、crewAI 源码和 Anthropic 多智能体系统的生产数据讲透图工程:Agent、代码、工具、人四类节点之间怎么组织工作。
本章任务
要回答的问题
任务装不进一个 Loop 时,怎样在 Agent、代码、工具和人之间拆节点与交接?
读完你能
- 在 Agent、代码、工具和人四类节点中选择执行者
- 为每条边定义载荷、状态所有者、预算和失败语义
- 估算委派成本并设置人工门禁
- 适合现在读
- 正在判断是否需要 Workflow、多 Agent、人工门禁或异步编排的工程师
- 先修知识
- 理解单 Agent Loop;理解状态所有权
- 实践产物
- 一份真实任务的节点、边、状态与验收规范
- 证据边界
- 案例和生产数据依赖任务与组织上下文,不能外推成多 Agent 的通用收益
先用一个真实任务判断要不要拆图
Section titled “先用一个真实任务判断要不要拆图”任务:读取 8 家 Agent 平台的官方文档,抽取版本与能力,形成带引用的对比报告,最后把推荐结果发布到团队知识库。
先把所有工作塞进一个 Agent Loop,常见结果是:检索内容挤掉写作上下文、版本抽取反复做、引用遗漏在最后才发现、发布动作与研究动作共享同一权限。此时不要直接说“上多 Agent”,先逐项判断执行者:
| 子任务 | 首选节点 | 原因 |
|---|---|---|
| 抓取页面、解析版本字段 | 代码或工具节点 | 路径确定、可测试,不值得持续花模型 Token |
| 识别不同平台术语的等价关系 | Agent 节点 | 需要语义判断,规则难预写完整 |
| 检查引用是否覆盖结论 | 代码检查加 Reviewer 节点 | 先做确定性覆盖检查,再处理语义质量 |
| 发布到团队知识库 | 人工门禁后的工具节点 | 不可逆外发,执行前需要明确批准 |
只有满足至少一个条件才值得拆:独立子任务能并行;上下文彼此污染;权限必须分层;或人需要成为正式门禁。否则保留一个 Loop,少一次交接就少一次信息损失。
图工程处理两件事:节点选谁执行,边规定怎样交接。节点只有四类:会即兴但昂贵的 Agent、确定且可测试的代码、面向模型的工具、负责审批和判断的人。每条边至少写清目标、上下文、权限、预算和输出格式。
你的实践产物不是一张漂亮流程图,而是一份可以验收的图规范:每个节点的输入输出、状态所有者、失败去向、预算与人工门禁都能被测试。
边上带什么:三个独立来源给出同一个答案
Section titled “边上带什么:三个独立来源给出同一个答案”图里最容易被轻视的是边。节点拆得再漂亮,交接时上下文断了、权限漏了、预算没限,图照样崩。有意思的是,三个互相独立的系统对”一条边该带什么”给出了几乎相同的答案。
Hermes 的 delegate_task:
delegate_task(goal, context, toolset, max_iterations)# 目标 上下文 权限白名单 预算crewAI(commit f15844b)的委派工具,tools/agent_tools/delegate_work_tool.py:
class DelegateWorkToolSchema(BaseModel): task: str = Field(..., description="The task to delegate") context: str = Field(..., description="The context for the task") coworker: str = Field(..., description="The role/name of the coworker")Anthropic 研究系统的调度 prompt 要求每个子任务描述必须包含:objective(目标)、output format(输出格式)、tool guidance(工具指引)、task boundaries(任务边界)。他们还留下了反面教材:早期允许调度者下达”research the semiconductor shortage”这种一句话任务,结果一个子 agent 去查 2021 年汽车芯片危机,另外两个重复调查 2025 年供应链——边上信息不足,工人就会重复劳动或者跑偏。
三家合起来,一条边的完整定义是五要素:目标、上下文、权限、预算、输出格式。缺哪样,哪样就在运行时爆。
返程 payload 同样有实现可抄。smolagents(agents.py:868,commit e3a5b89)的 managed agent 被调用时,返回的不是裸结论:结论套进固定的 report 模板,可选再附一段 <summary_of_work> 工作摘要(截断后的关键步骤)。父节点拿到的是”结论加依据”,可以判断质量,而不是只能盲信。
边上不带什么:权限只收窄,不放宽
Section titled “边上不带什么:权限只收窄,不放宽”这条纪律在 Codex 源码里是白纸黑字。codex-rs/core/codex_delegate.rs(commit fa1d4c4)spawn 子 agent 时:
inherited_exec_policy: Some(Arc::clone(&parent_session.services.exec_policy)), // L130inherited_multi_agent_version: Some(MultiAgentVersion::Disabled), // L143第一行:子代理强制继承父的执行策略,没有”开个子代理绕过权限”的后门。第二行更狠:子代理的多 agent 能力直接置为 Disabled——子代理天生不能再派子代理,递归禁令不靠 prompt 恳求,靠构造函数参数。
Hermes 的对应做法是从子节点工具集里硬删 5 个工具:再派活、反问用户、写长期记忆、跨通道发消息、执行代码。两家共识一句话:边是权限收窄的地方,不是放宽的地方。
五种拓扑,与两个真实实现
Section titled “五种拓扑,与两个真实实现”组织方式收敛到五种形状。前四种在 crewAI 和 Anthropic 系统里都有可以直接读的实现。
流水线加闸门。 固定顺序的步骤串行,步间放确定性检查。crewAI 的 Process.sequential 就是它:任务列表按序执行,前一个任务的产出作为后一个的上下文。适用前提是步骤能预先写死。
分诊路由。 入口用便宜节点分类,再送对应专门节点。每条路的 prompt 和工具做窄做专;路由不准比不分诊更糟。
并行扇出。 独立子任务同时跑:切分(各管一块再拼)或投票(同题多跑比对)。Anthropic 的数据:调度者并行 spawn 3-5 个子 agent、每个子 agent 并行调 3 个以上工具,复杂查询的耗时降了 90%。代价是聚合逻辑——结果冲突谁裁决,要提前定。
调度者加工人。 子任务没法预先列出时,一个 agent 节点当调度者,运行时决定拆几个活、派给谁。crewAI 的 Process.hierarchical 是这个拓扑的显式实现,而且框架用校验器强制了它的前提——crew.py 的 check_manager_llm:不给 manager_llm 或 manager_agent 直接报错。调度者不是可选装饰,是这个拓扑的定义。
调度还有个预算刻度问题:多大的活配多少工人?Anthropic 把刻度直接写进 prompt:简单事实查询 1 个 agent、3-10 次工具调用;直接对比 2-4 个子 agent、每个 10-15 次调用;复杂研究 10 个以上子 agent 分工明确。这条刻度值得抄——他们加它是因为早期系统会为一个简单问题 spawn 50 个子 agent。
评审回路。 一个节点干活,另一个挑毛病,循环到通过。图里合法的环,但必须带出口:轮次上限加”意见不再变化就停”。
真实系统是组合拓扑。Anthropic 研究系统完整走一遍是:调度者-工人(并行检索)→ 结果汇总 → 流水线尾巴上接一个确定性的 CitationAgent 专门补引用。三种形状拼成一张图。
状态归谁:黑板还是信件
Section titled “状态归谁:黑板还是信件”多节点干活,马上遇到状态问题:中间结果放哪、谁能改。
两种基本方案。共享黑板:所有节点读写同一份状态。协作方便,但写权限必须管——Hermes 禁止子节点写长期记忆:子节点的结论没经验证,直接写进父的记忆等于污染水源。消息传递:只通过边上的 payload 交换信息,状态私有。隔离好,代价是每条边都要认真设计。
实践是混合。Anthropic 有个细节值得注意:调度者在 spawn 工人之前先把研究计划写进 Memory——因为上下文超 20 万 token 会被截断,计划必须存在循环外部才能活过截断。这就是黑板的正确用法:放计划这类”必须活得比上下文长”的东西。任务清单(todo list)同理,本站第 21 章拆了四种实现。
原则层面是 12-Factor 的 Factor 5:执行状态和业务状态尽量统一。图跑到哪一步和业务数据什么状态分两处存,迟早对不上账。事件日志是同时承载两者的好载体——每个 agent 节点的日志拼起来就是整张图的执行历史(见 Loop Engineering 部件 4)。
人是节点,不是意外
Section titled “人是节点,不是意外”多数系统把人的介入做成特例:弹窗、卡死等输入。图工程把人当正规节点:有触发条件、输入输出、超时行为。
手段是 12-Factor 的 Factor 7:模型通过工具调用联系人。request_approval(action, reason)、ask_human(question) 是普通工具,模型自己决定何时调。人工介入由此进了事件日志,可回放可统计。
三个设计要点。路由:审批送谁面前?Codex 的答案是一律回父 session,子代理永不弹 UI——用户面对三个弹窗分不清哪个是哪个。超时:人不在怎么办?降级方案(保守默认、挂起任务)预先定义,别让整张图挂在一个人的下班时间上。粒度:按不可逆程度分级——读操作放行,可逆写事后汇报,不可逆操作(外发、删数据、花钱)事前审批。
冻结:图的演化方向
Section titled “冻结:图的演化方向”静态图(代码定边)和动态图(模型选边)是同一张图的不同区域,边界随时间移动。健康方向是从动态往静态冻。
判断标准一个问题:这段路径最近 100 次执行走的是不是同一条路?是,就把它从 agent 节点改写成代码节点——不花 token、不抽风、可写单测。Anthropic 的 CitationAgent 是现成例子:补引用这件事路径固定,就从主循环里拆出来变成流水线上一个专职节点。12-Factor 作者的观察同向:生产里最好的”AI 产品”大多是确定性代码,LLM 步骤只出现在真正需要即兴的那几个点。
反方向也成立:写死的流程异常分支多到 if-else 写不完,说明它需要即兴,让给 agent 节点。图工程是持续再平衡。
动态图里模型能自己开节点,防护栏必须写进代码,不是写进 prompt。
- 深度上限。 Hermes 硬编码 MAX_DEPTH=2;Codex 直接给子代理
MultiAgentVersion::Disabled(上文源码),深度上限做成了类型系统层面的 1。 - 递归禁令。 派活工具不下发给子节点。防子派孙、孙派曾孙的指数爆炸——Anthropic 那个”50 个子 agent”事故就是没有数量闸门的下场。
- 并发上限加心跳。 活跃节点数封顶;长任务节点定期心跳(Hermes 每 30 秒),外层才分得清”还在干”和”已经死了”。
- 预算随边下发。 每条边带 max_iterations,父预算是所有子预算的硬上界。
自己动手:什么时候需要图
Section titled “自己动手:什么时候需要图”诚实的答案:多数时候不需要。每条边都是一次上下文复述,每次复述都丢信息;多 agent 的 token 消耗是成倍的(这正是它有效的原因,也是它昂贵的原因)。Anthropic 明确说他们的架构只对”广度优先、多方向并行”的查询占优。
三个信号出现再拆:
- 上下文互相污染。 一个窗口里两摊事互相挤占(边查资料边写代码),拆成两个节点各管一摊。
- 权限需要分层。 一部分工作放开跑、另一部分必须收紧,边天生是权限边界。
- 有人要进来。 有审批点就建模成人工节点,比循环里挂弹窗干净。
拆的顺序:先写清每条边的五要素(目标、上下文、权限、预算、输出格式),再定状态归属(计划上黑板、细节走消息),最后装防护栏(深度、并发、递归禁令)。节点内部最不用操心——每个 agent 节点就是一个标准循环,Loop Engineering 的部件原样适用。
为了图而图。 一个循环能干的活拆成七个节点,得到的是七次交接损耗。节点数是成本,不是成熟度。
一句话委派。 “research the semiconductor shortage”式的模糊任务让 Anthropic 的工人们重复劳动、互相踩线。边的五要素一个都不能省,输出格式尤其容易忘。
边上只传结论不传依据。 学 smolagents:report 模板加可选的工作摘要。父节点要能判断子结论的质量。
防护栏写进 prompt。 “请不要递归调用自己”是请求,MultiAgentVersion::Disabled 是构造函数参数。模型会在长上下文里忘掉请求,绕不过硬编码。
人工节点没有超时。 审批发出去,人在度假,图挂一周。每个人工节点都要超时和降级路径。
所有节点用同一个模型。 Anthropic 的配方就是异构的:Opus 当调度者,Sonnet 当工人。节点拆开的直接红利是按节点选型号。
本章带走什么与下一步实验
Section titled “本章带走什么与下一步实验”先保留一个 Loop,直到出现并行价值、上下文污染、权限分层或人工门禁。拆分后,每条边都必须携带目标、上下文、权限、预算和输出格式;节点数、Agent 数和图的复杂度都不是成熟度指标。
下一步实验就用开篇的 8 平台调研任务:先跑单 Loop 基线,再只拆出一个确定性版本抽取节点和一个引用 Reviewer。比较总 Token、墙钟时间、重复检索数、缺失引用数与人工修正时间。只有至少一个质量或时间指标改善,并且新增成本可解释,才继续拆更多节点。
附录:需要复盘时再打开
Section titled “附录:需要复盘时再打开”六个检查问题与三道练习
Q1 · 基础:图工程和 LangGraph 这类图框架是什么关系?一句话说清图工程在管什么。
图框架是实现手段,图工程是设计决策——用不用框架都绕不开。图工程管两件事:节点怎么分(哪段活给模型、哪段给确定性代码、哪段给人)和边怎么连(交接时带什么、结果怎么回来、失败归谁)。
四类节点是完备的选项集:Agent 节点(贵、慢、会即兴,用在路径没法预写的地方)、代码节点(便宜、可测试,用在路径已知的地方)、工具节点(面向模型的代码接口)、人工节点(审批和拿主意)。任何”多智能体架构”拆到底都是这四类的组合。
源码:本章研究底稿里 crewAI 和 Codex 的对应实现。 追问:「那 LangGraph 的 StateGraph 对应图工程的哪部分?」它替你实现了边的执行机制(消息传递、checkpoint),但节点怎么分、边上带什么,仍然是你的设计决策——框架不替你回答。
Q2 · 边设计:一条委派边应该带哪五要素?漏掉任何一个会出什么事故?
目标、上下文、权限、预算、输出格式。三个独立来源收敛到同一答案:Hermes 的 delegate_task(goal, context, toolset, max_iterations)、crewAI 的 DelegateWorkTool(task, context, coworker)、Anthropic 调度 prompt 的四要素(objective / output format / tool guidance / task boundaries)。
事故对号入座:缺目标会跑偏;缺上下文会瞎猜;缺权限会越权;缺预算会跑飞;缺输出格式会重复劳动——Anthropic 有真实案例:一句话委派”research the semiconductor shortage”,一个工人跑去查 2021 年芯片危机,另两个重复调查 2025 年供应链。
返程也是边的一部分:结论必须带依据。smolagents 的 managed agent 把答案套进 report 模板再附工作摘要,父节点才有能力判断子结论的质量。
源码:research/crewAI/.../delegate_work_tool.py(f15844b);smolagents agents.py:868。
追问:「五要素里最常被漏的是哪个?」输出格式。目标和上下文人人会写,格式不约定,父节点就要写解析代码兜各种自由发挥。
Q3 · 权限:为什么说”边是权限收窄的地方,不是放宽的地方”?给出一个代码层面的证据。
因为子节点的行为父节点无法逐步监督,任何放宽都等于开了无人看守的口子。经典事故:子代理拿到父没有的工具(提权)、子代理再派子代理(递归爆炸)、子代理写父的长期记忆(未验证的结论污染水源)。
代码证据在开源 Codex 的 codex_delegate.rs(commit fa1d4c4):L130 inherited_exec_policy 强制子代理继承父的执行策略——没有绕过通道;L143 inherited_multi_agent_version: Some(MultiAgentVersion::Disabled)——子代理在构造时就被禁用再派活能力,递归禁令是构造函数参数,不是 prompt 恳求。
Hermes 的等价做法:从子节点工具集硬删 5 个工具(再派活、反问用户、写记忆、跨通道发消息、执行代码)。
源码:research/codex/codex-rs/core/src/codex_delegate.rs L130/L143。
追问:「为什么防护栏不能写在 prompt 里?」模型会在长上下文里忘掉请求,但绕不过硬编码常量。“请不要递归”是请求,Disabled 是法律。
Q4 · 成本判断:Anthropic 的数据说多 agent 比单 agent 好 90.2%,为什么你仍然应该默认不拆?
看归因:那 90.2% 的提升里,token 用量一项解释了 80% 的性能方差。多 agent 有效的主因是多个独立上下文窗口让系统在一个任务上花更多 token——本质是用钱换性能,不是架构魔法。
所以判断标准是经济的:任务价值配得上成倍的 token 账单吗?子任务真的能并行吗?Anthropic 自己划的适用边界是”广度优先、多方向并行”的查询;线性任务拆成图只会增加交接损耗(每条边都是一次上下文复述,每次复述都丢信息)。
正确的触发信号有三个:上下文互相污染、权限需要分层、有人要进来审批。没有这三个信号,一个循环加好工具就是最优解。
源码:Anthropic multi-agent research system 报告的 BrowseComp 归因分析。 追问:「调度者的预算刻度怎么定?」抄 Anthropic 写进 prompt 的刻度:简单事实 1 agent 3-10 次调用;对比类 2-4 工人各 10-15 次;复杂研究 10+ 工人明确分工。他们加这条是因为早期系统给简单问题 spawn 了 50 个子 agent。
Q5 · 演化:什么叫”从动态往静态冻结”?给出可操作的判断标准和一个真实例子。
动态区域(模型选边)和静态区域(代码定边)共存于一张图,边界随时间移动。健康方向是把跑稳的动态路径改写成确定性代码:不花 token、不抽风、可写单测。
可操作的判断标准一句话:这段路径最近 100 次执行走的是不是同一条路?是,就冻结成代码节点。
真实例子:Anthropic 研究系统的 CitationAgent。补引用这件事路径固定(拿结论和文档、定位出处、插标注),于是从主循环里拆出来,变成流水线尾部的专职节点。反方向同样成立:写死的流程异常分支多到 if-else 写不完,说明它需要即兴,让给 agent 节点。
源码:Anthropic 报告的架构图(LeadResearcher → Subagents → CitationAgent)。 追问:「冻结会不会把 agent 的灵活性冻没了?」冻的是已经不需要灵活性的路径。图工程是持续再平衡——每个季度看一次哪些动态路径已经走成了直线。
Q6 · 开放题:设计一个”自动处理用户退款申请”的系统,画出你的节点和边。哪里用 agent,哪里用代码,哪里用人?
一个参考答案(不唯一,考察的是分工理由):
入口分诊用代码节点(或小模型):按金额和订单状态分流——规则清楚,不需要即兴。小额且符合政策的走代码节点直接退:路径 100% 固定,用 agent 是浪费。争议单走agent 节点:读聊天记录、查物流、判断责任——路径没法预写。超过阈值的金额进人工节点审批:不可逆动作(打钱)事前审批,走工具调用 request_approval(order, reason),超时 24h 自动挂起转人工队列。
边的设计:agent 节点拿到的 toolset 只有查询类工具,不给打款工具(权限收窄);预算 15 步;输出格式固定为「结论 + 三条依据 + 建议动作」。打款永远由代码节点执行,agent 只产出建议。
这个设计里 agent 只出现在一个节点——这是对的。图工程的成熟度看的是每类节点用得是否恰当,不是 agent 数量。
源码:拓扑对照 crewAI Process 两种模式;审批路由对照 Codex 回父 session 的设计。
追问:「如果争议单 agent 的结论质量不稳定怎么办?」加评审回路:第二个便宜模型按 checklist 审一遍,通过才放行,轮次上限 2。这比换更贵的主模型便宜。
- 读源码:打开
research/crewAI/lib/crewai/src/crewai/crew.py,找到check_manager_llm校验器,回答:为什么 hierarchical 模式强制要求 manager,而 sequential 不需要? - 改设计:把本章退款系统(Q6 答案)里的人工节点加上完整定义:触发条件、输入输出、超时时长、降级路径。写成一个工具的 JSON schema。
- 审计题:找一个你用过的多 agent 框架(或你自己写的委派逻辑),对照五要素检查它的委派边:缺哪个?防护栏是在 prompt 里还是在代码里?
本章结论基于以下一手材料(代码库已 clone 到本仓库 research/ 目录,行号以对应 commit 为准):
| 来源 | 版本 | 读了什么 |
|---|---|---|
| openai/codex | fa1d4c4 | codex-rs/core/src/codex_delegate.rs(权限继承 L130、递归禁令 L143)、protocol/src/protocol.rs SubAgentSource(L2822) |
| crewAIInc/crewAI | f15844b | process.py(sequential/hierarchical)、crew.py check_manager_llm、tools/agent_tools/delegate_work_tool.py |
| huggingface/smolagents | e3a5b89 | agents.py managed agents 的 __call__(task 模板、report 模板、summary_of_work) |
| How we built our multi-agent research system | Anthropic | 90.2% 提升、token 解释 80% 方差、委派四要素、预算刻度、50-subagent 事故、CitationAgent |
| Building Effective Agents | Anthropic | workflow/agent 区分、五种模式原始出处 |
| 12-Factor Agents | HumanLayer | Factor 5 / 7 / 10 |
四个 harness 的 subagent 机制横向对照(含 OpenClaw 的 push 事件、Hermes 的 5 工具硬禁源码),见本站第 10 章和第 12 章——那里是逐行对照的实现细节,本章是方法。
每个节点内部怎么跑得稳,回到 Loop Engineering。