Dayward AI
Week 3 · D15About 6 hours

A Tour of Multi-Agent Patterns (Router/Supervisor, Planner-Executor, Critic, Swarm, Blackboard) and When Not to Use Them; Getting Started With LangGraph

Get acquainted with the common patterns for multi-agent systems, get clear on when a single agent is enough and when you actually need multiple agents, and build your first three-node graph with LangGraph.

Today's goals 0/3

Sign in to tick these off and save your progress.

今日目标

  1. 能说出 Router/Supervisor、Planner-Executor、Critic、Swarm、Blackboard 分别是什么样的协作结构
  2. 能判断一个业务场景该用单 Agent 还是多 Agent,并说明理由
  3. 能用 LangGraph.js 搭一个三节点的图并跑通一次执行

昨天收尾时留了一句:一个 Agent 的生产形态已经完整了,但客服要先分诊、要查库存、要拟退款方案、方案还得有人复核——一个 Agent 干不完。今天进入第三周,先认全这些分工的形状,再学会拒绝其中大部分。读完回到页面顶部把三条目标勾掉。

小白版讲解

一个人的作坊,和一张组织架构图

公司刚起步时只有一个人:谈客户、写方案、做交付、开发票,全是他。这种状态效率极高,因为没有任何沟通成本——所有信息都在同一个脑子里。等业务复杂到一个人转不过来,才开始招人,于是有了岗位、有了流程、有了一张组织架构图。

但你一定见过另一种公司:明明三个人能干完的活,硬是设了八个岗位,每件事都要过三道会签,最后没人对结果负责。招人有时候是在解决问题,有时候只是把一个人的困惑,变成了三个人的沟通成本。 这句话是今天全部内容的底色,也是本章的立论。

先看那个「一个人转不过来」的现场长什么样。到 W2 为止,我们的电商客服 Agent 是这样的:一段系统提示词里既要求它「对退款请求严格核对规则、不要轻易承诺」,又要求它「语气热情、多挽留」;工具挂了十二个,其中 query_orderquery_refund 光看名字就容易混;用户问一句「我这单能退吗」,模型要同时完成识别意图、选对工具、遵守退款规则、还要说得像个人。

结果是可预期的:提示词越写越长,每加一条规则就压掉另一条的权重;工具选错的比例随工具数上升;最要命的是你无法定位问题——回答不对,你不知道是意图判错了、工具选错了、还是规则被那句「多挽留」盖过去了。整段提示词是一个黑箱,只能整体重写、整体重测。

多 Agent 的本质,就是把这个黑箱切成几块,让每一块有自己的职责、自己的提示词、自己的失败方式。切法有五种经典形状:

  • Router / Supervisor(路由 / 监督者):一个节点先判断「这一单该谁接」,然后交给对应的子 Agent,一次只交给一个。适合一次只需要一个专家、难点在于判断该找谁的任务。这是最常用的一种,明天(D16)整天都在讲它。
  • Planner-Executor(规划 - 执行):一个节点把大任务拆成几个互不依赖的小任务,几个执行者并行做完,最后有人把结果合成一份交付。适合一件事必须拆成几件、几件之间没有先后的任务。
  • Critic(评审):执行者产出之后交给评审者,不合格打回重做,合格才放行。适合产出的对错有明确判据,且错了重做比错了发出去便宜的任务。Planner-Executor 与 Critic 通常一起用,D17 会把它们拼成一条完整链路。
  • Swarm(群集):没有中心节点,下一棒交给谁由当前这位自己决定。适合全局顺序事先说不清的探索型任务。代价是你事先不知道它会走多少步,成本和延迟都难封顶。
  • Blackboard(黑板):参与者互相不知道对方存在,只认一块公共状态:谁看到黑板上出现了自己能处理的东西,就接着往下写。适合参与方经常增减、不想每加一个就改一次编排逻辑的场景。

背这五个名字没有意义。真正能迁移的是:模式的差别不在名字,在图(graph)的形状。 只要盯住四件事,五种模式就自动分开了——有没有分叉(运行时三选一)、有没有扇出(同时交给多个人)、有没有汇合(多份产出合到一起)、有没有回边(可以打回重做)。

patterns.js
// 边分两种:always 是无条件边(都走),choice 是条件边(运行时只走一条)。
// 把这两种边分开数,才能看出「同时交给三个人」和「三选一交给一个人」的根本差别。
const critic = {
  name: 'Critic',
  edges: [
    { from: 'START', to: 'executor', kind: 'always' },
    { from: 'executor', to: 'critic', kind: 'always' },
    { from: 'critic', to: 'executor', kind: 'choice' }, // 回边:打回重做
    { from: 'critic', to: 'END', kind: 'choice' },
  ],
}
 
function analyzeShape(pattern) {
  // START 天然只有一条出边、END 天然收很多入边,不排除掉五种模式会长得一模一样
  const tally = (pick, kind, skip) => {
    const acc = new Map()
    for (const e of pattern.edges) {
      if (e.kind !== kind || pick(e) === skip) continue
      acc.set(pick(e), (acc.get(pick(e)) ?? 0) + 1)
    }
    return [...acc.values()].some((n) => n > 1)
  }
  return {
    branch: tally((e) => e.from, 'choice', 'START'),
    fanOut: tally((e) => e.from, 'always', 'START'),
    join: tally((e) => e.to, 'always', 'END'),
  }
}

跑一遍会看到:Router 只有分叉,Planner-Executor 是扇出加汇合,Critic 是分叉加回边。有意思的是 Critic 和 Swarm 的四个布尔值完全一样——这不是判据失效,而是它俩的差别落在回边由谁决定上:Critic 是一个固定的评审节点在决定要不要打回,Swarm 是当前这位自己决定把棒子交给谁。形状分不开的地方,判据要用人话补上。

到这里你已经能把任何一篇多 Agent 论文里的架构图翻译成这四个布尔值了。但真正难的问题还没回答:这五种形状听起来都挺美,你手上这个需求,到底该不该拆?

先泼一盆冷水:三条判据,一条都不命中就别拆

先把代价摆出来,因为大多数人在决定拆之前从来没算过这笔账。

延迟乘上倍数。 单 Agent 一次回答是一到两次模型调用;上了 Supervisor 就多一次路由调用;再上 Critic 的评审回路,一次不合格就再来两次。原来两秒的回答变成六秒,而用户对客服机器人的耐心大约就是三秒。

成本按调用次数线性涨。 沿用本课的价目表(openai/gpt-4o-mini,输入每百万 token 零点一五美元、输出每百万 token 零点六美元),一次对话原来一千 token 进一千 token 出,约合零点零零零七五美元。拆成「路由 + 执行 + 评审」三步之后,每一步都要把当前状态重新塞进上下文,token 用量大约是原来的三倍,成本也是三倍。十万日活、人均十轮,一天从七百五十美元涨到两千两百五十美元。这是拆之前必须先在心里过一遍的数字。

调试难度按状态维度涨。 单 Agent 出错,你看一条对话记录;多 Agent 出错,你要回答「路由判对了吗、每个子 Agent 拿到的状态对吗、合并的时候有没有互相覆盖」。这就是为什么 D21 整天在讲可观测——没有链路追踪(tracing)的多 Agent 系统,出了问题基本靠猜。

所以判据要严。我给三条,命中任意一条才拆,一条都不命中就别拆

  1. 单个 Agent 的系统提示词里出现了互斥的行为要求。 比如既要「严格核对退款规则」又要「热情挽留」。这两条不是难写,是不可能同时最优——你调高一边必然压低另一边。这时候拆成两个 Agent,本质上是把一个无解的加权问题,变成两个各自有解的问题。
  2. 工具数量超过模型能稳定选对的规模。 本课取八个作为告警线:不是模型的硬上限,是选错率开始明显上升的经验线。注意超线之后的第一反应应该是合并工具、收敛描述query_orderquery_refund 合成一个带类型参数的工具),拆 Agent 是第二反应。
  3. 某一步需要独立的失败与重试语义。 比如「生成一封对外邮件」失败了应该只重试这一步,而不是把整轮对话从头再来。有独立的失败语义,就该有独立的执行单元——这一条和 W2 讲的「一条消息一个 run」是同一个道理。
decide.js
const TOOL_LIMIT = 8 // 不是模型硬上限,是选错率开始明显上升的经验线
 
function shouldSplit(s) {
  const reasons = []
  if (s.conflictingRules) reasons.push('提示词里有互斥的行为要求,一个人格没法同时满足')
  if (s.toolCount > TOOL_LIMIT) reasons.push(`工具 ${s.toolCount} 个,超过告警线,选错率会明显上升`)
  if (s.needsOwnRetry) reasons.push('某一步需要独立的失败与重试语义,不该整轮重来')
  if (reasons.length > 0) return { split: true, reasons }
  // 默认答案是「不拆」,不是「视情况而定」——这才是一条可执行的判据
  return { split: false, reasons: ['三条判据一条都没命中:拆了只会更慢、更贵、更难查'] }
}

节点、边、状态:不用框架你会写成什么样

假设判据命中了,你决定拆。不用任何框架,你会怎么写?大概率是这样:一个 while 循环,里面一串 if 判断现在该走哪一步,中间用一个大对象在各步之间传数据。

写到第三个分支你就会撞上三件事。第一,状态怎么合并。 两步都往结果里写东西,是覆盖还是追加?你会在每个分支里手写合并逻辑,写五遍就错一遍。第二,怎么知道走到哪了。 中间过程全在局部变量里,出错只能靠打印。第三,怎么从中间恢复。 进程一挂就得从头重来,模型调用的钱白花。

LangGraph 就是把这三件事收敛成三个概念:

  • 节点(node):一个普通函数。读全量状态,返回一个只包含「这一步改了什么」的增量对象。不要在节点里原地修改状态——那样合并规则就被绕过去了。
  • 边(edge):节点之间的连接。无条件边写死顺序,条件边在运行时决定下一步去哪(明天的 Supervisor 就是靠它)。
  • 状态(state):一张字段表,每个字段是一条独立通道,通道自带一条合并规则(reducer)。累加型字段用拼接,覆盖型字段用后写为准。

第三条是最容易被略过、也最值钱的一条:合并规则是声明在字段上的,不是写在节点里的。 这意味着新增一个节点时你不需要考虑「我该怎么和别人的写入合并」,字段自己知道。D17 让多个执行者并行写同一个字段时,靠的就是这个。

graph.js
import { Annotation, StateGraph, START, END } from '@langchain/langgraph'
 
// 状态:每个字段一条通道,通道自带合并规则。这一份 D16 到 D18 直接照抄
const AgentAnnotation = Annotation.Root({
  messages: Annotation({ reducer: (a, b) => a.concat(b), default: () => [] }),
  workspace: Annotation({ reducer: (a, b) => a.concat(b), default: () => [] }),
  degraded: Annotation({ reducer: (_old, next) => next, default: () => false }),
})
 
// 节点:读全量状态,返回只含改动字段的增量
const intake = (state) => ({ workspace: [{ id: 't-1', goal: lastText(state), status: 'pending' }] })
const handle = async (state) => {
  const task = state.workspace.at(-1)
  const reply = await callModel(task.goal)
  return { workspace: [{ ...task, result: reply, status: 'done' }] }
}
const respond = (state) => {
  const done = state.workspace.filter((t) => t.status === 'done')
  return { messages: [{ role: 'assistant', content: done.map((t) => t.result).join('\n') }] }
}
 
// 边:今天这三条是写死的直线,运行时不会变。让边由模型决定,是明天的正题
export const graph = new StateGraph(AgentAnnotation)
  .addNode('intake', intake)
  .addNode('handle', handle)
  .addNode('respond', respond)
  .addEdge(START, 'intake')
  .addEdge('intake', 'handle')
  .addEdge('handle', 'respond')
  .addEdge('respond', END)
  .compile()

图执行:状态是怎么在节点之间流动的

把上面那张图跑一遍,LangGraph 内部发生的事只有三步,循环执行:挑出这一轮该跑的节点 → 把当前状态整份交给它 → 拿它返回的增量,按每个字段的合并规则并回状态。 就这么简单。所有复杂度都藏在「该跑哪个节点」和「怎么合并」这两个问题里,而这两个问题被分别交给了边和通道。

关键是你要看得见这个过程。invoke 只给你最终状态,中间全丢了;调试图必须用 stream 并把流式模式设成 updates,它会在每个节点结束时吐出一个「节点名到这一步增量」的对象——那份增量正好就是「这个节点写了什么」。今天实验里跑出来长这样:

TextText
intake   写入 [workspace] t-1:pending
handle   写入 [workspace] t-1:done
respond  写入 [messages, degraded] assistant: 订单 SO20260901 已发出…|degraded=false

三行胜过一堆断点。多 Agent 的绝大多数 bug 都是「某个字段在某一步被谁写坏了」,而这三行直接告诉你是谁。 顺便注意 route 字段全程没出现——它是明天 Supervisor 的地盘,今天这条直线上没有人需要判断该谁接。

这里有个坑值得单独拎出来:节点里千万不要原地改状态。state.workspace.push(task) 看起来能用,实际是绕过了通道的合并规则——单线程时你察觉不到,等 D17 有多个执行者并行写同一个字段,两边各自 push 的结果会互相覆盖,而且是那种「跑十次错一次」的偶发问题。正确写法永远是返回一个新的增量对象。

从单 Agent 升级到多 Agent,通常是被什么逼的

最后回到组织架构的类比。公司从一个人变成一个团队,从来不是因为老板读了一本管理学的书,而是因为撞上了具体的墙。多 Agent 也一样,真实的触发点就那么几个,你会依次撞上:

第一个信号是提示词开始互相打架。 你加一条「退款要严格」,客服满意度掉了;改回去,退款损失涨了。这是判据一,也是最干净的一个拆点——按互斥的行为要求切,切完每个 Agent 的提示词都会短一半。

第二个信号是工具列表长到你自己都要查文档。 这时先合并、再拆分,顺序不能反(判据二)。

第三个信号是有一步的失败需要单独处理。 生成对外文案、调用有副作用的写操作、需要人工复核的动作——这些天然应该是独立的执行单元(判据三)。

第四个信号是你想给某一步单独换模型。 分诊这种短判断用便宜的小模型,拟退款方案用大模型。单 Agent 做不到按步换模型,多 Agent 天然可以——这也是多 Agent 唯一一个能省钱的场景,值得记住,面试里是个亮点。

第五个信号是评估颗粒度不够。 单 Agent 只能整体打分:好或不好。拆开之后你能分别评估「分诊准不准」「方案合不合规」,才知道该改哪一块。D21 会把这件事做成标准样本集(golden set)加链路追踪。

顺带提一句,第一周用的 Pi SDK 和这一周的 LangGraph 不是替代关系,定位不同——完整的选型判据放在 D21 收口,今天不展开。

源码导读

动手实验

🧪 D15 实验:三节点 LangGraph

Code location: labs/agent-30days/day-15-langgraph-intro

验收标准:

  1. MOCK=1 SELFTEST=1 pnpm start 四项自检全部 ✅、退出码 0(starter/ 原样跑四项全 ❌,每项点名对应哪个练习)。
  2. 第 1 项:五种模式的形状依次判成分叉、扇出加汇合、分叉加回边、分叉加回边、扇出加汇合加回边,终端上能看到五张 ASCII 结构图,条件边画成虚线。
  3. 第 2 项:四个场景判对四个——只读的查订单助手判不拆,另外三个各命中一条判据判,并打印命中的是哪一条。
  4. 第 3 项:三节点图跑通,工作区里恰好一件活是 done,末条消息是 assistant 且带着订单号;物流问句和退款问句的回复内容不同。
  5. 第 4 项:能打印出 intakehandlerespond 三步、每步写了哪几个字段,且 route 字段全程没被写入。

今天没有基础设施依赖,所以本实验没有 docker-compose.yml:图的执行、状态合并、逐节点追踪全在进程内。唯一的网络出口是模型调用,MOCK=1 下返回随输入变化的离线回复——问物流、问退款、问发票会得到三种不同答案,所以离线也能看出状态真的被算过,而不是打印了一段固定文案。src/shared/state.ts 是本周的地基,D16 到 D18 会原样复制它,今天把字段占好就行。卡住了先看 README 的「常见坑」。

  1. 先原样跑一次 MOCK=1 SELFTEST=1 pnpm start,那四条 ❌ 的文案就是你的待办清单。
  2. 练习 1,模式结构图:把分叉、扇出、汇合三个布尔值算出来(回边已经写好),第 1 项从五个「直线」变成五种不同的形状。
  3. 练习 2,该不该拆:按三条判据实现 shouldSplit,把默认那句「先拆了再说」换掉,第 2 项从判对三个变成判对四个。
  4. 练习 3,把 handle 挂进图里并接好边,第 3 项的工作区从零件做完变成一件做完,回复里出现订单号。
  5. 练习 4,把 invoke 换成 streamupdates 模式并记录每步增量,第 4 项能打印出完整的三步路径。

面试题

今天 4 道题在下方题库区,侧重模式对比与「单 Agent 还是多 Agent」的取舍,最后一道专门考「什么时候不该拆」——这是本周最容易答成布道文的题。展开后先看「分析过程」再看要点,照着推导练,比背要点管用。标注「国内高频 / 海外高频」方便按目标市场取舍。

检查清单与明日预告

  • 能说出 Router/Supervisor、Planner-Executor、Critic、Swarm、Blackboard 分别是什么样的协作结构
  • 能判断一个业务场景该用单 Agent 还是多 Agent,并说明理由
  • 能用 LangGraph.js 搭一个三节点的图并跑通一次执行
  • 能用分叉、扇出、汇合、回边四个特征把五种模式区分开,并说清哪两种分不开、为什么
  • 能背出拆分的三条判据,并算得出拆完之后延迟与成本大概涨多少
  • 实验的 5 条验收标准全部通过(四项自检全 ✅)
  • 4 道面试题不看要点也能答出至少 3 道

明天(D16)讲监督者(Supervisor)的动态路由。为什么是它排第一?因为今天这张图有个明显的假:三条边全是写死的,intake 之后永远是同一个 handle。真实的客服请求进来,第一件事是判断「这一单该谁接」——查订单、拟退款、还是纯闲聊,而这条边只能由模型在运行时决定。明天会把这个判断做成一次结构化输出(structured output),顺便回答一个更要紧的问题:为什么不能让模型输出一句自然语言再用正则去解析。

Interview questions

  • What are the common multi-agent collaboration patterns, and what shape of task suits each?常见的多 Agent 协作模式有哪些?分别适合什么形状的任务?
    Common in ChinaCommon overseasBasic#multi-agent#orchestration#architecture

    How to reason about it · think before answering

    1. This looks like a giveaway but it separates people who memorised names from people who have split a system. Listing five names is a bare pass; the interviewer wants the axis you use to tell them apart, because an axis means you can classify an architecture you have never seen.
    2. Offer a reusable axis: the difference is not the name, it is the shape of the graph. Four questions suffice — is there a branch (pick one at runtime), a fan-out (hand it to several at once), a join (merge several outputs), a back edge (send it back for rework).
    3. Then place each one: Router/Supervisor is branch only, one specialist per turn, the hard part is deciding who; Planner-Executor is fan-out plus join, for work that splits into independent pieces; Critic is branch plus back edge, for output with a clear pass/fail test where redoing is cheaper than shipping; Swarm is also branch plus back edge, but the next hop is chosen by whoever holds the baton; Blackboard is fan-out plus join plus back edge, participants unaware of each other, reacting only to shared state.
    4. Point out yourself that Critic and Swarm score identically on all four, and that the real difference is who decides the back edge — a fixed reviewer node versus the current agent. Volunteering where your own criterion breaks down scores better than reciting one more pattern name, because it proves you have used the axis rather than invented it on the spot.
    5. Attach a cost to each: Router adds one routing call of latency; Planner-Executor's parallelism creates write conflicts so fields need merge rules; Critic loops need a hard retry cap or nothing ever ships; Swarm has no upfront bound on steps so cost and latency are hard to cap; Blackboard has the hardest termination condition and tends to either stall or re-trigger.
    6. Expect: which do you use most in production? Say Router/Supervisor, because its failure mode is the easiest to read — check the recorded routing reason — and because it is the one pattern that can save money, by routing simple intents to a cheaper model.

    分析过程 · 先想清楚再作答

    1. 这题看似送分,其实在筛「背过名词」和「拆过系统」。只报五个名字最多拿及格分,面试官真正想听的是你用什么维度把它们区分开——有维度说明你能给没见过的架构归类,没维度说明你只是读过一篇综述。
    2. 给一个可复用的维度:模式的差别不在名字,在图的形状。盯四件事就够——有没有分叉(运行时三选一)、有没有扇出(同时交给多个人)、有没有汇合(多份产出合到一起)、有没有回边(可以打回重做)。
    3. 然后逐个落位:Router/Supervisor 只有分叉,一次只找一个专家,难点在判断该找谁;Planner-Executor 是扇出加汇合,适合一件事拆成几件、几件之间没有先后;Critic 是分叉加回边,适合对错有明确判据、且重做比发出去便宜的产出;Swarm 也是分叉加回边,但下一棒交给谁由当前这位自己决定;Blackboard 是扇出加汇合加回边,参与者互相不知道对方存在,只认公共状态。
    4. 主动指出 Critic 和 Swarm 的四个特征一模一样,区别落在「回边由谁决定」——Critic 是固定的评审节点在判,Swarm 是当前这位自己判。**主动承认自己的判据在哪里失效,比多背一个模式名更能加分**,因为它证明你真的用过这套维度而不是刚编出来。
    5. 每种模式还要配一句代价,这是区分度所在:Router 多一次路由调用的延迟;Planner-Executor 的并行会带来状态写冲突,字段必须配合并规则;Critic 的回路必须有次数上限,否则永远出不了稿;Swarm 事先不知道会走多少步,成本和延迟都难封顶;Blackboard 的终止条件最难写,容易谁都不接活或者反复触发。
    6. 可以预期的追问:生产上你最常用哪个?答 Router/Supervisor,理由是它的失败模式最好理解——路由判错了看一眼路由理由就知道,而且它是唯一一个能顺便省钱的模式,简单意图可以路由到便宜的小模型。

    Key points

    • Give the axis before the names: branch, fan-out, join and back edge separate all five patterns
    • Router/Supervisor is branch only — one specialist per turn, the hard part is choosing who
    • Planner-Executor is fan-out plus join — split into independent subtasks, then merge into one deliverable
    • Critic is branch plus back edge — for output with a clear pass/fail test, and it needs a hard retry cap
    • Swarm scores the same as Critic; the difference is who decides the back edge. Blackboard decouples via shared state and has the hardest termination condition
    • Pair each with a cost: extra call latency, parallel write conflicts, infinite review loops, unbounded step count, fuzzy termination

    答题要点

    • 先给维度再给名字:分叉、扇出、汇合、回边四个特征就能把五种模式分开
    • Router/Supervisor 只有分叉,一次只找一个专家,难点是判断该找谁
    • Planner-Executor 是扇出加汇合,适合拆成几件互不依赖的小任务再合成一份交付
    • Critic 是分叉加回边,适合对错有明确判据、重做比发出去便宜的产出,必须配打回次数上限
    • Swarm 与 Critic 的四个特征相同,区别在回边由谁决定;Blackboard 靠公共状态解耦,终止条件最难写
    • 每种模式配一句代价:多一次调用的延迟、并行的写冲突、回路的死循环、步数不封顶、终止条件难定
  • In LangGraph, what roles do nodes, edges and state play? If you had no framework, how would you implement it yourself?LangGraph 里节点、边、状态分别扮演什么角色?如果不用框架,你自己会怎么实现?
    Common in ChinaCommon overseasIntermediate#langgraph#orchestration#state-management

    How to reason about it · think before answering

    1. The hinge is the second half. Defining the three concepts only proves you read the docs; explaining what hurts without a framework proves you know what it buys you. The general move for this family of questions is: describe your hand-rolled version first, then name what the framework collapsed.
    2. Hand-rolled version: a loop, a chain of conditionals picking the next step, and one big object carrying data between steps. By the third branch you hit three walls — when two steps write the same field, is it overwrite or append, and you hand-write that merge in every branch; intermediate state lives in local variables so debugging means print statements; a crash restarts from zero and the model calls you already paid for are wasted.
    3. Then map them: a node is an ordinary function that reads the whole state and returns a delta containing only what it changed; edges connect nodes, unconditional ones fix the order and conditional ones decide at runtime; state is a table of fields where each field is its own channel carrying a merge rule.
    4. Dwell on the third, which is the most skipped and most valuable point: the merge rule is declared on the field, not written inside the node. Adding a node therefore requires no thought about how to combine with other writers, and parallel writes to one field behave deterministically instead of depending on who returns first.
    5. Add two concrete traps to show you have actually run this: mutating state in place inside a node bypasses the merge rule — invisible single-threaded, an intermittent overwrite once things run in parallel; and adding a node without wiring an edge raises no error at all, it simply never executes, which only per-node tracing reveals.
    6. Expect: so why not just write it yourself? Because the three primitives are genuinely light — a few dozen lines. What the framework actually sells is checkpointing and recovery, parallel execution, and per-step observability, all of which cost far more to build than the primitives. Mention too that there is no official LangGraph for Java or Swift, so in those languages you do hand-roll exactly these three.

    分析过程 · 先想清楚再作答

    1. 题眼在后半句。只答三个概念的定义,面试官会认为你读过文档;能说出「不用框架会难受在哪」,才证明你知道框架替你解决了什么。这类题的通用解法是:先讲自己手写的版本,再讲框架把哪几处收敛了。
    2. 先给手写版:一个循环,里面一串条件判断决定下一步走哪,中间用一个大对象在各步之间传数据。写到第三个分支就会撞上三件事——两步都往同一个字段写,是覆盖还是追加,你要在每个分支里手写一遍合并逻辑;中间过程全在局部变量里,出错只能靠打印;进程一挂就从头重来,已经花掉的模型调用钱白付。
    3. 然后一一对上:节点是一个普通函数,读全量状态、返回只含改动字段的增量;边是节点之间的连接,无条件边写死顺序,条件边在运行时决定去哪;状态是一张字段表,每个字段是一条独立通道,通道上挂着合并规则。
    4. 重点讲第三条,因为它是最容易被略过、也最值钱的一条:**合并规则是声明在字段上的,不是写在节点里的**。这意味着新增节点时不需要考虑「我该怎么和别人的写入合并」,字段自己知道;也意味着并行写同一个字段时行为是确定的,而不是取决于谁先返回。
    5. 配两个具体的坑,证明你真跑过:一是在节点里原地修改状态(比如直接往数组里 push)会绕过合并规则,单线程时察觉不到,并行时变成偶发覆盖;二是加了节点没连边不会报错,表现只是那个节点永远不执行,只能靠逐节点追踪发现。
    6. 可以预期的追问:那你为什么不直接自己写?答:三要素本身很轻,核心逻辑几十行就能手写出来——框架真正值钱的是检查点与恢复、并行执行、以及每一步的可观测,这三样自己写的成本远高于三要素本身。顺带说明 Java 和 Swift 没有官方 LangGraph,真要在这两门语言里做,就是把这三要素手写一遍。

    Key points

    • A node is a plain function: read the full state, return a delta of changed fields only, never mutate in place
    • Edges set execution order: unconditional edges are fixed, conditional edges decide the next hop at runtime — that is what a supervisor uses
    • State is a table of fields, each field a channel carrying a merge rule declared on the field rather than inside nodes
    • Without a framework you hit three walls: hand-written merges in every branch, no visibility into intermediate steps, and full restart after a crash
    • Two real traps: in-place mutation bypasses the merge rule and causes intermittent overwrites under parallelism; an unwired node raises no error, it just never runs
    • What the framework really sells is checkpoint recovery, parallel execution and per-step observability — not the three primitives themselves

    答题要点

    • 节点是普通函数:读全量状态,返回只含改动字段的增量,不在节点里原地改状态
    • 边决定执行顺序:无条件边写死,条件边在运行时决定下一步去哪(Supervisor 就靠它)
    • 状态是一张字段表,每个字段一条通道,通道上挂合并规则——规则声明在字段上而不是写在节点里
    • 不用框架会撞三堵墙:合并逻辑在每个分支手写一遍、中间过程只能靠打印、进程挂了从头重来
    • 两个真实的坑:原地改状态绕过合并规则(并行时偶发覆盖)、加了节点没连边不报错只是永不执行
    • 框架真正值钱的不是这三要素,而是检查点恢复、并行执行和逐步可观测
  • What signals typically trigger the move from a single agent to a multi-agent system, and what does the upgrade cost you?从单 Agent 升级到多 Agent,通常是被什么信号触发的?升级之后系统会多付出什么?
    Common in ChinaCommon overseasIntermediate#multi-agent#cost#architecture

    How to reason about it · think before answering

    1. This question tests whether business pain forced the split or a blog post did. Answering the business got complex is a non-answer; the interviewer wants observable signals — what symptom made you act.
    2. Give five, in the order they usually appear: prompts start fighting each other (add one rule, another metric drops); the tool list grows until you need the docs yourself; one step's failure needs isolated handling instead of redoing the whole turn; you want a different model for one specific step; and evaluation granularity is too coarse to say more than good or bad.
    3. Expand on the fourth, the counter-intuitive one: multi-agent is usually more expensive, but per-step model selection is the one case where it saves money — a short triage decision on a cheap small model, a drafting step on a larger one. A single agent cannot swap models per step. This lands well in interviews.
    4. Then volunteer the costs, or the answer reads as evangelism: latency multiplies by step count (two seconds becomes six, while user patience is about three); cost grows linearly with calls because every step re-sends the current state as context, typically three times; and debugging cost grows with state dimensions, since a failure now requires checking routing, each sub-agent's input state, and whether merges overwrote each other.
    5. Add the reverse check to show you are not splitting reflexively: too many tools should first prompt consolidation and tighter descriptions, with splitting as the second response; poor quality should first prompt tuning the single-agent version to its best, which then becomes the baseline the multi-agent version is measured against.
    6. Expect: how do you prove the split helped? Keep the single-agent version as a baseline and A/B both against the same golden set, comparing accuracy alongside per-conversation cost and latency. People who cannot name a baseline usually cannot explain why they split either.

    分析过程 · 先想清楚再作答

    1. 这题考的是「你是被业务逼着拆的,还是照着博客拆的」。答「业务变复杂了」等于没答,面试官要的是**可观测的信号**:什么现象出现时你才动手。
    2. 给五个按出现顺序排的信号:一是提示词开始互相打架(加一条规则,另一个指标就掉);二是工具列表长到自己都要查文档;三是某一步的失败需要单独处理,不该整轮重来;四是想给某一步单独换模型;五是评估颗粒度不够,只能整体打分好或不好。
    3. 第四个信号要展开讲,它是唯一一个反常识的:多 Agent 通常更贵,但按步换模型是它唯一能省钱的场景——分诊这种短判断走便宜的小模型,拟方案走大模型。单 Agent 做不到按步换模型。这一条在面试里是明显的亮点。
    4. 然后主动给代价,不给代价的回答会被当成布道:延迟按步数乘倍数(原来两秒变六秒,而用户耐心大约三秒);成本按调用次数线性涨,因为每一步都要把当前状态重新塞进上下文,典型是三倍;调试难度按状态维度涨,出错要同时回答路由对不对、每个子 Agent 拿到的状态对不对、合并有没有互相覆盖。
    5. 再补一句反向判断,证明你不是无脑拆:工具太多的第一反应应该是合并工具、收敛描述,拆 Agent 是第二反应;质量差的第一反应应该是把单 Agent 版本调到最好,那个版本还会成为多 Agent 的对照基线。
    6. 可以预期的追问:拆完怎么证明比原来好?答:留住单 Agent 版本当基线,用同一批标准样本集跑 A/B,比准确率也比每次对话的成本与延迟。说不出对照基线的人,通常也说不清自己为什么拆。

    Key points

    • Five observable signals: prompts fighting each other, a tool list you must look up, one step needing isolated retries, wanting a different model per step, and evaluation too coarse to act on
    • Per-step model selection is the only case where multi-agent saves money: small model for triage, larger model for drafting — impossible in a single agent
    • Cost one: latency multiplies with step count, two seconds becomes six, while patience for a support bot is about three
    • Cost two: spend grows linearly with calls since every step re-sends state as context, typically three times the original
    • Cost three: debugging cost grows with state dimensions, so multi-agent and tracing have to ship together
    • Reverse check: consolidate tools before splitting, and tune the single agent to its best first — that version becomes your baseline

    答题要点

    • 五个可观测信号:提示词互相打架、工具多到要查文档、某一步需要独立重试、想按步换模型、评估颗粒度不够
    • 按步换模型是多 Agent 唯一能省钱的场景:短判断走小模型、拟方案走大模型,单 Agent 做不到
    • 代价一:延迟按步数乘倍数,两秒变六秒,而用户对客服机器人的耐心大约三秒
    • 代价二:成本线性涨,每一步都要把状态重新塞进上下文,典型是原来的三倍
    • 代价三:调试难度按状态维度涨,所以多 Agent 和链路追踪必须一起上
    • 反向判断:工具多先合并再拆分,质量差先把单 Agent 调到最好——那个版本还是多 Agent 的对照基线
  • When should you not introduce a multi-agent system? Give operational criteria, not it depends.什么情况下不应该引入多 Agent 系统?请给出可操作的判据,而不是「视情况而定」。
    Common in ChinaCommon overseasDeep dive#multi-agent#architecture#trade-offs

    How to reason about it · think before answering

    1. This is the highest-signal question in the set because it is asked in reverse. Most candidates keep selling how powerful multi-agent is, while the interviewer is looking for someone who will say no — on a real team, blocking one unnecessary architecture upgrade is worth more than implementing three patterns.
    2. Lead with the default: do not split. Then give three criteria, any one of which justifies splitting — the system prompt contains mutually exclusive behavioural requirements (strictly enforce refund rules while also warmly retaining the customer; these are not hard to write, they are impossible to optimise together); the tool count exceeds what the model picks reliably (roughly eight as a rule of thumb, and the first response to crossing it is consolidating tools, not splitting agents); or one step needs its own failure and retry semantics. None of the three, and a single agent with a few tools is enough.
    3. Then name the most common bad split: treating a prompt problem as an architecture problem. Quality is poor, so we split into three agents — but nine times out of ten poor quality comes from vague prompts, tool descriptions that interfere with each other, or irrelevant history in the context. All three survive the split and are now harder to find. Splitting fixes conflicting responsibilities, not weak capability.
    4. Add two scenarios that clearly should not split: latency-sensitive interactions, where each extra hop is another model round trip and voice or realtime completion becomes unusable; and read-only lookup flows, where a support assistant with three or four tools gains no accuracy from splitting and simply triples the bill.
    5. Then offer an executable verification path, which earns points: keep the single-agent version as a baseline for any split and A/B both against the same golden set, comparing accuracy, per-conversation cost and latency together. An architecture upgrade with no baseline is a refactor with no evidence.
    6. Expect: what if your manager insists on multi-agent? Frame it as a reversible experiment — make the one cut you are most confident in (usually the conflicting-rules criterion), keep the baseline, and bring data in two weeks. That answer shows technical judgement and a way to disagree without stonewalling.

    分析过程 · 先想清楚再作答

    1. 这是本组最有区分度的题,因为它反着问。绝大多数候选人会顺着「多 Agent 很强大」讲下去,而面试官问这题正是想找那个会说不的人——**在真实团队里,拦住一次不必要的架构升级,价值高于实现三个模式**。
    2. 先给结论式的默认值:默认答案是不拆。然后给三条判据,命中任意一条才拆——一是单个 Agent 的系统提示词里出现了互斥的行为要求(既要严格核对退款规则又要热情挽留,这两条不是难写,是不可能同时最优);二是工具数量超过模型能稳定选对的规模(经验线大约八个,超线的第一反应是合并工具而不是拆 Agent);三是某一步需要独立的失败与重试语义。三条都不命中,单 Agent 加几个工具就够。
    3. 接着点名最常见的错拆:把提示词问题当成架构问题。「回答质量不好,所以拆成三个 Agent」——质量差有九成来自提示词含糊、工具描述互相干扰、上下文塞了无关历史,这三样拆完一样存在,只是分散到三个地方更难查。**拆 Agent 解决的是职责冲突,不是能力不足。**
    4. 再补两类明确不该拆的场景:一是低延迟要求的场景,多一跳就多一次模型往返,对语音或实时补全这类交互直接不可用;二是只读的简单查询链路,三五个工具的客服助手拆了只是把一次调用变成三次,准确率不会涨、账单会涨。
    5. 然后给一条可执行的验证路径,这是加分项:任何拆分都先留住单 Agent 版本当对照基线,用同一批标准样本集跑 A/B,同时比准确率、每次对话成本和延迟。**拿不出对照基线的架构升级,等于没有证据的重构。**
    6. 可以预期的追问:那如果老板就是要求上多 Agent 呢?答:那就把它当成一个可回退的实验来做——先按判据拆最有把握的那一刀(通常是互斥规则那一条),保留基线,两周后拿数据说话。这个回答同时展示了技术判断和沟通方式,比硬顶或硬上都好。

    Key points

    • Default to not splitting; split only if one of three criteria holds: mutually exclusive prompt requirements, tool count past the roughly-eight warning line, or a step needing its own failure and retry semantics
    • Too many tools should first trigger tool consolidation and tighter descriptions; splitting agents is the second response
    • The most common bad split is treating a prompt problem as an architecture problem — vague prompts, interfering tool descriptions and irrelevant history all survive the split
    • Clear do-not-split cases: latency-sensitive interactions where every hop adds a model round trip, and read-only lookup flows where accuracy does not move but the bill does
    • Always keep the single-agent version as a baseline and compare accuracy, cost and latency on the same golden set
    • Say the costs out loud: latency multiplies with steps, spend roughly triples, and debugging now spans routing plus state merging

    答题要点

    • 默认答案是不拆;三条判据命中任意一条才拆:提示词有互斥要求、工具超过约八个的告警线、某一步需要独立的失败与重试语义
    • 工具太多的第一反应是合并工具与收敛描述,拆 Agent 是第二反应
    • 最常见的错拆是把提示词问题当架构问题——质量差多半来自提示词含糊、工具描述干扰、上下文塞了无关历史,拆完这三样照旧存在
    • 明确不该拆:低延迟交互(每多一跳就多一次模型往返)、只读的简单查询链路(准确率不涨、账单涨)
    • 任何拆分都要留单 Agent 版本当对照基线,用同一批标准样本集比准确率、成本和延迟
    • 代价要说出口:延迟按步数乘倍数、成本约三倍、调试要同时排查路由与状态合并

Comments

Sign in to join the discussion

No comments yet — be the first.