多步 AI Agent 为什么执行起来像在排队?Claude 动态工作流中的图 vs 链 多步 AI Agent 为什么执行起来像在排队Claude 动态工作流中的图 vs 链你正在用 Claude 构建一个复杂的多文件代码审查系统提示里写着“先读取所有路由文件总结差异然后检查缺失的权限控制然后生成最终报告”。执行时Agent 却像单线程队列一样一步步等前一步的总结还没产出后面的安全检查就空转上下文窗口越来越满早期发现的细节开始被遗忘某个子步骤抛错整个流程就直接中断。这不是个例而是大多数人构建多步 Agent 的默认模式——一条直线。我起初也以为只要把任务拆得更细、步骤写得更清晰Agent 就能可靠地处理复杂工作。后来真正理解 Claude Code 动态工作流的底层机制后才发现问题的核心从来不是步骤数量而是执行拓扑的形状。一条“然后”链和一个真正的图差的不是一点点速度而是整个系统的并行能力、容错能力和可验证性。节点与边的真正定义工作单元与数据流动的承诺一个节点就是一个有界的工作单元明确输入、明确输出、单一职责。它可以是一个子 Agent也可以是纯代码处理。边则更严格——它只在数据真正从上游流向下游时才存在。“总结文件差异然后查询天气”里“然后”并不是边。因为天气查询并不消费差异总结的输出。这两个节点其实是独立的只是被人为按顺序串起来了。真正的边必须回答一个问题下游节点是否需要上游的输出结果如果不需要这条等待就是纯浪费。类比一下这就像工厂里的装配线。你以为“先组装引擎然后安装车轮”必须顺序执行但如果引擎组装和车轮安装互不依赖它们本可以同时开工。只有当车轮需要用到引擎的安装孔位数据时才真正建立一条边。把“顺序”误认为“依赖”就是线性 Agent 最大的隐形税。你的线性脚本其实是退化的图当你写下“做 A然后 B然后 C然后 D”时你已经在画图了——只不过画了一条没有分支、没有冗余的单链。每个节点只有一条入边和一条出边。这样的链能跑通但跑得慢且脆弱C 卡住D 就永远等不到A 的工作成果被困在上游无法被其他并行路径复用。把链重绘成图的第一步就是对每一条“然后”箭头问同一个问题它是否真的在传递数据把那些不传递数据的箭头剪掉链就会自然展开成更宽的结构——几个独立节点可以同时运行最后只在真正需要汇总的节点处汇聚。给每个节点一个清晰的契约无法被独立推理的节点就无法被安全地并行化。解决办法是给节点立一个契约输入是什么形状、输出是什么形状、只做一件事。在 Claude 动态工作流里这个契约通过 JSON Schema 强制执行。当你用带 schema 的agent()调用时Claude 生成的子 Agent 必须返回结构化数据验证失败会自动重试而不是把一堆自由文本扔给你让你手动解析。这和“把输出扔给人类再读”完全是两回事。前者是可被图连接的节点后者只是一个黑盒。边是数据契约而非执行顺序把边命名为它实际传递的数据形状而不是“第 3 步之后”两件事会立刻变简单你能一眼看出这条边是否真实存在以及你可以在不破坏下游的前提下随时替换上游或下游的节点实现。更重要的是大量原本需要 Agent 思考的工作其实只是边上的数据处理——去重、过滤、扁平化。这些操作用纯 JavaScript 完成零 token 消耗。这也是图思维带来的安静红利很多人烧掉的模型 token其实本该由编排代码免费承担。扇出并行parallel是真正能回本的动作当你有 N 个独立来源需要检查、N 个文件需要审查、N 条路由需要审计时不要把它们串成链。直接让 Claude 用parallel()把它们扇出同时运行。这个 barrier 会等待所有并行任务完成后再返回结果同时单个任务失败只会返回 null不会拖垮整个批次。之后只要.filter(Boolean)即可。并发上限受限于你的核心数多余任务会排队但整体吞吐量远超线性等待。关键在于并行执行的上下文是分散在各个子 Agent 里的主会话的上下文永远不会同时塞进九个来源。这让 Claude 能轻松协调几十甚至上百个子 Agent而不会因为上下文爆炸而失忆。只有真正需要全局视角时才用扇入屏障扇出之后必须有扇入但屏障barrier是有成本的。只有当后续阶段确实需要看到所有上游结果的完整集合时才应该用它——比如跨来源去重、按影响排序、或根据整体情况提前退出。如果中间只是简单扁平化一个列表那就直接用代码在边上处理不要强行加一个 barrier。写出parallel → transform → parallel的模式时要问自己这个 transform 是否真的有跨项目的依赖如果没有就该改成 pipeline让快任务早点完成而不是让所有任务都等最慢的那个。钻石拓扑分发 → 并行工作 → 合并把扇出和扇入组合起来就得到了几乎所有严肃 Agent 图的核心骨架——钻石。一个节点负责拆分任务Split多个节点并行执行具体工作Work一个节点负责合并与合成Merge。市场扫描、依赖审计、代码审查、研究报告……几乎所有需要广度 深度的工作都能套用这个骨架。规范形式可以记住为扇出收集广度 → 纯代码 Reduce 压缩 → 最终 Agent Synthesize 写答案。一旦你看到钻石形状就不会再问“怎么让 Agent 多做几步”而是问“在哪里拆分在哪里合并”——这才是真正能 scale 的问题。建议的逻辑架构图用 Mermaid 表示钻石拓扑Split: 任务拆分Parallel: 工作节点1Parallel: 工作节点2Parallel: 工作节点3Reduce: 代码去重/过滤Synthesize: 最终合成与判断运行时路由让图具备条件分支不是所有图都是静态的。有时下游走哪条路取决于上游节点发现了什么。路由节点读取结果后决定分支票据分类后走不同处理路径diff 规模小就快速审查大就启动完整审计。这个决策可以用子 Agent 做判断但路由本身是 Claude 写的 JavaScript 代码——确定性执行不会因为“Claude 今天心情好”就突然跳过审计。边缘上的验证器用怀疑杀死不可靠发现图结构真正的杠杆不是“更多 Agent”而是你在结构里能包裹的置信度机制。验证器节点坐在边上只做一件事试图杀死上游的发现。如果它活下来了就放行杀不死就不往下传。常见模式包括对抗性验证为每个发现 spawning 多个独立怀疑者多数通过才保留视角多样验证不同验证者分别从正确性、安全性、可复现性等角度攻击评委面板多角度生成再用并行评委打分合成最佳结果。这正是让真实团队把 Bun runtime 成功移植时内置对抗性代码审查的原因。隔离节点让单点失败无法毒害全局链式结构里一个节点死掉后续全军覆没。图结构则要求失败被严格隔离在自己的节点内。parallel()里抛错的 thunk 已经默认解析为 null扇入阶段要设计成能容忍缺失输入当节点需要并行写文件时使用独立 git worktree 做沙箱隔离避免碰撞。收敛循环直到干涸才停止有些任务的规模事先未知未知数量的 bug 扫描、持续发现新来源。这需要受控的循环边。危险在于不收敛的循环会无限消耗预算。收敛模式是loop-until-dry连续 K 轮没有新发现就停止。关键细节是去重对象必须是“所有已见过的发现”而不是仅“已确认的结果”。否则被拒绝的发现会反复出现循环永远干涸不了。跨节点分层模型把贵模型用在真正需要判断的地方图结构让模型分层变得显而易见重复性、边界清晰的节点字段提取、票据分类可以用廉价模型需要综合判断的节点最终合成、裁决发现才用顶级模型。在动态工作流里单个agent()调用可以指定模型Claude 会把该节点路由到对应层级而不会让整个大规模运行都按会话默认的高价模型计费。拓扑本身就是成本与延迟的杠杆parallel()的 barrier 会让所有后续阶段等待最慢节点pipeline()则让每个项目独立流经所有阶段快项目早完成。默认用 pipeline。只有当阶段真的需要看到完整上游集合时跨集合去重、基于整体的提前退出才用 barrier。“代码更干净”不是理由barrier 带来的真实等待时间才是。让 Claude 自己绘制图动态工作流最高阶的做法是不再手动画图。对于无法提前规划的任务直接描述目标让 Claude 自己写编排脚本——它会分解任务、选择扇出、生成协调子 Agent 的舰队并合成结果。三种进入方式提示里说“workflow”直接运行已保存的 workflow如/deep-research就是现成的 scope → 并行搜索 → 获取 → 对抗验证 → 合成或开启 ultracode让 Claude 为每个实质性任务自动规划 workflow。好的 workflow 可以保存到.claude/workflows/版本控制按名称重新运行。可立即落地的 6 个图结构场景跨所有路由的安全扫描每个路由文件一个子 Agent并行 hunting 缺失权限验证器再确认所有发现。带引用的研究报告使用内置/deep-research图并行多角度搜索、去重、对抗验证后再合成。模块逐文件移植并行翻译 测试门禁 失败循环反馈。Diff 的对抗性审查根据 diff 大小路由到快速审查或完整并行审计 评委面板。定时生态系统扫描保存一次 workflow永久重跑并行检查多源、按影响排序、生成摘要。未知规模的发现任务并行 finder 全量去重 验证 loop-until-dry直到连续两轮无新发现。真正决定上限的从来不是 Agent 的“聪明程度”而是它站立的形状一个提示是一句话一个循环是一个周期而编排脚本才是 Agent 真正站立的地板。线性链只是大家最先抓到的形状因为它和我们打字的习惯一致。一旦你能看到节点和边就不再追问“怎么让 Agent 多做几步”而是开始问“哪里可以扇出哪里需要验证哪里该用廉价模型”——这些问题才能真正让 Agent 跑出舰队而不是永远卡在单线程队列里。下一次你设计多步 Agent 时先停下来画一张节点与边的草图问问自己这些“然后”里有多少其实没有数据流动把它们剪掉之后结构会变成什么样子我是紫微AI在做一个「人格操作系统ZPF」。后面会持续分享AI Agent和系统实验。感兴趣可以关注我们下期见。