面试官问:“Planner 已经把任务拆成步骤了,为什么还要做计划校验?”
一个很危险的回答是:“因为大模型偶尔会幻觉,所以再让模型检查一遍。”
问题不只在于模型可能写错,而在于“计划”连接了自然语言目标和真实工具。一份看起来顺畅的计划,可能引用不存在的工具、漏掉必要前置步骤、使用无来源参数、超过预算,甚至包含当前用户无权执行的动作。它如果直接进入 Executor,模型的一次语言错误就会变成系统行为。
因此,LLM Planner 输出的是候选计划,不是执行授权。工程系统要把候选计划变成可检查对象,逐层验证,再一次释放一个可以安全执行的节点。
先给出 30 秒回答
Planner 输出的计划可能漏步、依赖冲突、引用不存在的工具、缺少参数来源或包含越权动作,所以不能直接交给执行器。我会先约束它输出结构化计划,再依次检查字段完整性、依赖图、工具与参数、权限、预算和完成条件。执行中如果新的 Observation 让某个前提失效,就冻结已验证结果,只重规划受影响节点;用户目标改变、关键状态不可信或工具能力整体变化时,才全量重建。每份计划、状态和重规划原因都带版本进入 Trace,写操作另外记录幂等键与副作用状态,避免计划变化后重复执行。
这段回答把四个层次说清了:计划是数据、校验分层、重规划有范围、执行有历史。
为什么“步骤写得合理”还不够
人阅读计划时容易被语言流畅度影响。模型写出“先收集资料,再做比较,最后生成报告”,逻辑似乎没有问题,但执行器仍然不知道:收集哪些资料、使用哪个工具、输入从哪里来、怎样判断收集完成、资料缺失时怎么办。
可执行计划必须回答机器问题,而不是只回答人类的阅读问题。
计划可能引用不存在的能力
模型根据训练知识写出一个工具名,并不代表当前系统真的注册了它。即使名字存在,版本和参数也可能不同。工具注册表才是能力事实来源。
计划可能漏掉必要步骤
教学场景中,模型计划直接“读取记录并发送结果”,但业务要求先做身份和数据权限检查。漏掉的不是优化步骤,而是不能绕过的边界。
计划中的参数可能没有来源
模型写出日期、对象 ID 或过滤条件,却无法指出来自用户输入、当前状态还是工具结果。参数看起来合法,也可能是猜出来的。
计划依赖可能无法执行
步骤 B 依赖步骤 A 的输出,步骤 A 又要求先获得 B 的结论;或者两个节点都等待对方完成。自然语言列表不容易发现这种环,依赖图可以检查。
完成条件可能只是主观描述
“分析充分”“结果合理”“资料完整”无法由系统直接验证。需要改成可观察条件,例如必需字段已获得、指定测试通过、每条结论有来源或缺失项已明确标记。
计划先要成为一个有契约的数据对象
具体字段可以按项目调整,但一份教学计划至少应包含:
- 全局目标和边界;
- 子任务 ID;
- 子任务目标;
- 前置依赖;
- 候选工具或动作类型;
- 参数以及参数来源;
- 成功条件;
- 可预期失败;
- 风险等级与是否需要确认;
- 预算或截止条件。
下面是为说明结构而写的教学示例,不代表现有项目代码:
{
"plan_id": "teaching-plan",
"goal": "比较资料 A 与资料 B 的适用条件",
"steps": [
{
"id": "extract_a",
"depends_on": [],
"tool": "read_document",
"args_from": ["user.document_a"],
"success": "返回条件列表及原文位置",
"risk": "read_only"
},
{
"id": "compare",
"depends_on": ["extract_a", "extract_b"],
"tool": "compare_evidence",
"success": "输出相同项、差异项与缺失项",
"risk": "read_only"
}
]
}
结构化并不自动保证计划正确,但它让错误可以被定位。字段缺失是结构错误;工具不存在是能力错误;用户无权访问是权限错误;资料变更导致前提失效是运行时错误。不同错误走不同处理路径。

计划越接近真实执行,越不能只靠自然语言“看起来合理”。
计划校验应该分成哪几层
第一层:Schema 与字段完整性
检查输出是否能解析,必填字段是否存在,类型和枚举是否正确,子任务 ID 是否唯一。结构错误不必调用工具,更不应进入权限系统。
Schema 校验适合确定性代码。模型可以根据错误摘要修复一次,但如果反复生成相同错误,应停止或切换到受控模板,不能无限修复。
第二层:依赖和图结构
检查前置节点是否存在、是否有非法环、是否出现永远不可达节点、多个节点是否争用同一不可并发资源。计划如果允许并行,还要明确汇合条件。
这层也主要由代码完成。图算法能判断结构是否合法,模型没有必要用自然语言猜。
第三层:工具与参数
工具名必须来自当前用户可见的注册表;参数类型、范围和枚举符合工具 Schema;参数来源必须存在。一个日期字段通过类型校验,但若来源只是模型自行补全,仍不能执行。
工具版本也要进入计划。工具升级后字段变化,旧计划不能默认兼容。
第四层:业务完整性
固定规则要求的节点是否都在,例如身份、权限、审批、结果验证。这类规则不应仅依赖 Planner 自觉生成,应由模板或 Policy 检查器强制验证。
第五层:权限与副作用
用户能否访问数据,Agent 是否有权调用工具,动作是只读还是写入,是否需要人工确认,全部由后端判断。模型写在计划里的 risk=read_only 只是请求声明,系统要按真实工具元数据重新计算。
第六层:预算与可完成性
估计节点数量、串并行关系、必需工具和剩余预算。如果计划明显超出任务允许的总耗时或工具次数,应要求缩减、拆分或转异步,而不是执行到一半才发现无法完成。
预算估计只能作为控制依据,不应被包装成精确成本预测。实际值仍从执行日志获得。
第七层:完成条件
每个节点必须能通过工具结果、测试、规则或人工确认判断是否完成。“模型觉得够了”可以触发检查,但不是最终证据。
哪些校验交给代码,哪些可以交给模型
可以确定判断的项目优先交给代码:字段类型、枚举、唯一性、依赖环、工具存在、参数边界、用户权限、预算硬限制和必须节点。
需要理解语义的项目可以使用模型辅助,例如子任务是否偏离用户目标、两个步骤是否语义重复、完成条件是否覆盖用户要求。但模型判断应输出理由和引用的计划字段,并接受规则或人工抽检。
不要让同一个 Planner 在没有新证据的情况下回答“我生成的计划是否正确”。这容易产生自我确认。可以使用独立规则、不同提示的 Critic、工具模拟、测试或人工审核,但仍要承认它们各自的边界。

校验错误必须保留原始类别,统一让 Planner 重写会让根因消失。
执行时为什么一次只释放一个或一组安全节点
通过校验的整份计划也可能在运行中失效。外部数据会变化,工具会失败,用户会补充约束。一次性把整份计划转换成不可中断脚本,会让后续步骤继续基于旧前提执行。
更稳妥的方式是保存计划和任务状态,只释放当前前置依赖已经满足的节点。工具完成后,验证结果并更新状态,再决定后继节点是否仍然有效。
允许并行时,也要确认并行节点没有共享写冲突,结果汇合有确定规则。并行不是 Planner 写了“同时执行”就能安全发生。
什么情况下只做局部重规划
局部重规划的前提是:用户目标没变;已完成节点的结果仍然可验证;失效范围可以从依赖关系确定。
例如教学资料比较中,资料 B 的读取工具临时不可用,但资料 A 的解析结果仍然有效。系统可以冻结 A,只替换读取 B 的方案以及依赖 B 的比较节点,不必重新读取 A。
局部重规划通常经历:标记失败节点;找到所有依赖它的未完成节点;暂时失效这些节点;保留不受影响的完成证据;在剩余预算和工具范围内生成替代子图;重新校验后接回计划。
这里不能简单按节点编号删除。一个失败结果可能已被后续节点使用,必须依据真实依赖传播失效范围。
什么情况下必须全量重建
用户改变目标,原计划的整体方向已不成立;关键输入被证明错误,已完成结果无法信任;工具能力或权限发生大范围变化;计划 Schema 版本变化,旧节点无法安全解释。这些情况下继续局部修补会保留错误根基。
全量重建也不等于丢掉全部历史。原始输入、用户确认、工具证据和失败记录仍应保留,只是不能把它们继续标记为当前计划的有效完成节点。

重规划范围由目标与状态可信度决定,不由模型一句“重新规划”决定。
计划变化后,怎样避免重复副作用
这是动态重规划最危险的一环。
假设旧计划已执行“发送通知”,但在写回完成状态前进程中断。恢复后 Planner 看不到成功记录,又生成一次相同动作。没有幂等或外部状态核验,就会重复发送。
写操作至少需要:稳定的业务幂等键;请求与外部结果记录;副作用状态;恢复前查询真实业务结果;无法确认时转人工。计划节点 ID 可以帮助追踪,但不要把随机生成的节点 ID 直接当作业务幂等键,因为重规划后 ID 可能变化。
计划版本和状态版本也要分开。计划描述“准备做什么”,状态描述“实际上发生了什么”。修改计划不能覆盖已经发生的事实。
计划、状态和事件日志要分成三类数据
如果把三者都塞进一个 JSON,每次模型重写计划都可能覆盖已完成事实,恢复时也无法判断某个字段是模型建议还是工具确认。
计划保存目标、节点、依赖和候选动作;当前状态保存哪些节点待执行、运行中、完成、失败或等待确认;事件日志追加记录每次计划生成、校验、工具请求、结果、审批和状态迁移。事件日志不应被模型修改,它是回放与审计依据。
例如 Planner 把节点名称从“读取资料”改为“提取元数据”,计划变化不代表旧工具调用从未发生。状态仍要引用已经完成的事件和证据,再判断新节点能否复用它。
状态迁移要使用比较条件
并发执行或进程恢复时,两个执行器可能同时读取旧状态并写回。仅靠最后写入覆盖,容易丢失已完成结果或重复释放后继节点。
可以为状态保存版本号,更新时要求“当前版本仍等于我读取的版本”。若不一致,重新读取最新状态并判断本次结果是否仍然有效。具体数据库实现可不同,但核心是不能把并发一致性交给模型。
计划节点需要稳定的业务身份
重规划后节点 ID 可能变化。若系统仅按模型生成的字符串判断是否执行过,就无法识别“发送同一通知”实际上是同一业务动作。
只读动作可以按工具、规范化参数和输入版本做去重;写操作应使用由业务语义生成的幂等键,例如任务、对象和动作类型的组合。幂等键设计必须基于真实业务,不能简单复制教学格式。
结果复用要验证来源与有效期
局部重规划希望复用旧结果,但旧结果不一定仍然有效。系统要检查它来自哪个工具版本、查询参数、数据时间和权限上下文。用户权限变化后,即使文本内容没有变,旧结果也可能不能继续使用。
因此“冻结已验证结果”不是无条件缓存。每个结果要带来源、状态版本和必要的有效期,重规划时由规则判断复用、刷新或作废。
并行节点和汇合节点怎么校验
计划允许并行时,需要明确节点之间没有数据依赖和写冲突。两个只读查询通常可以并行;两个同时修改同一对象的动作则要串行或使用业务并发控制。
汇合节点要写清等待策略:必须全部成功、至少一个成功,还是达到某个证据集合。若一路失败,其他成功结果是否可形成部分答案,也要进入完成条件。
Planner 只写“并行处理”远远不够。校验器要检查共享资源、汇合条件、失败传播和取消策略,Executor 才能安全调度。
计划差异也应该进入评审
同一个任务在更换模型、Prompt 或工具描述后,可能生成结构不同但都能通过 Schema 的计划。发布前应比较新旧计划:必要节点是否丢失;新增工具是否扩大权限;串行是否变成并行;完成条件是否变松;调用范围是否无故扩大。
差异评审不要求计划文字完全一致。重点是行为边界有没有变化。若只是节点名称和解释改写,可以通过;若审批节点消失或写操作提前,则必须拒绝并查清来源。
对于无法自动判断的语义差异,可以抽样人工审查,并把结论沉淀为新的规则或回归样本。这样计划质量会随着真实坏例积累,而不是只靠不断加长 Prompt。
常见失败模式与诊断
失败一:自动修复掩盖原始错误
解析器发现工具名不存在,直接换成名字相似的工具继续执行。最终即使成功,也无法知道模型原本为何选错,更可能调用语义不同的能力。
正确做法是保留原始计划、校验错误和修复版本。确定性的小格式错误可规范化,涉及语义的替换必须重新确认。
失败二:每次 Observation 都整份重规划
这会让计划抖动,已完成步骤不断改名,难以追踪,也增加模型调用。只有前提或目标变化时才重规划;正常成功结果只更新状态并释放后继节点。
失败三:完成条件由 Planner 自己解释
Planner 生成“拿到足够信息”,执行后又说“信息已经足够”。没有独立证据,计划形成自我闭环。
完成条件应尽量绑定工具字段、测试、规则或人工确认。
失败四:状态与计划混在一个长 Prompt
每次修改都让模型重写整段文本,无法知道哪些是已发生事实、哪些是待执行建议。应分离 immutable Trace、当前状态和候选计划。
失败五:全量重建后重复写操作
没有副作用记录、幂等键和外部核验,新的计划把旧动作当作未完成。此问题不能靠 Prompt 提醒解决。
怎样验证计划校验和重规划
准备四类计划样本
第一类结构错误:缺字段、重复 ID、类型错误。第二类依赖错误:前置缺失、非法环、不可达节点。第三类业务错误:漏权限、超预算、越权工具。第四类运行时变化:工具失败、结果冲突、用户修改目标。
对每层定义可观察结果
结构错误应在执行前拒绝;依赖错误不能释放节点;越权动作不能通过换工具绕过;局部变化应只失效受影响子图;目标变化应生成新计划版本;已完成副作用不能重复。
比较逐题明细而不是单一总分
记录每个样本在哪一层被发现、错误是否解释清楚、是否错误放行、重规划范围是否正确、是否重复执行。一个“计划通过率”无法区分严格校验和漏检。
回放版本变化
更换模型、Prompt、工具 Schema 或规则后,用相同状态重放。对比生成计划、校验错误、节点释放和最终状态。必须保存版本,否则无法解释差异来源。
面试官会怎样连续追问
追问一:计划至少有哪些字段
目标、子任务 ID、依赖、候选工具、参数及来源、完成条件、失败条件、风险和预算。字段名可变,但必须能校验与回放。
追问二:为什么不再让模型检查一遍
模型可辅助语义检查,但字段、依赖、工具、权限和预算都有确定事实,应由代码验证。同一个模型自评不能成为唯一安全门。
追问三:什么时候局部重规划
目标不变、已有结果可信、失效范围可以沿依赖图定位时。只替换失败节点和受影响下游。
追问四:什么时候全量重建
用户目标改变、关键输入不可信、整体权限或工具能力变化、旧计划版本无法安全解释时。
追问五:重规划如何避免重复执行
计划和执行状态分离;写操作使用业务幂等键;记录副作用结果;恢复前核验外部状态;不确定时转人工。
追问六:怎么证明校验有效
用结构、依赖、业务和运行时四类错误集逐题回放,检查错误发现层、误放行、失效范围和重复副作用,不虚构总分。

计划、状态和副作用必须可对齐,才谈得上安全重规划。
怎样向面试官解释计划校验与重规划
LLM Planner 生成的是候选计划,不是执行授权,因为它可能漏掉必要步骤、依赖成环、引用不存在的工具、使用无来源参数或包含越权动作。我会先让计划符合结构化 Schema,再分层校验:字段与类型、依赖图、工具和参数来源、业务必需步骤、用户权限、风险与预算、每个节点的完成条件。通过后也不整份脚本一次跑完,而是只释放前置依赖已满足的节点,工具结果验证后更新状态。运行中单个工具失败、而已有结果仍可信时,沿依赖图只重规划受影响子图;用户目标改变、关键状态不可信或工具能力整体变化时,才全量重建。计划版本、状态版本和副作用记录分开保存,写操作用业务幂等键并在恢复前核验外部结果。验证时用结构错误、依赖错误、越权计划和运行时变化做回放,检查是否误放行、是否错误扩大失效范围,以及是否重复执行。
谈重规划前,先准备这些项目证据
如果简历写了“支持动态重规划”,下面这些材料应当能被当场展开:
- 一份真实但脱敏的计划 Schema。
- 结构、依赖、工具、权限和预算各层校验规则。
- 计划版本与状态版本的存储方式。
- 一次局部重规划的失效范围说明。
- 一次全量重建的判断依据。
- 写操作的幂等与副作用核验方案。
- 一组非法计划与环境变化回归样本。
如果你的项目没有实际 Checkpoint、执行记录或故障回放,就明确说这是设计方案。能让模型列出漂亮步骤并不难,难的是证明每一步可执行、变化后不重复、失败时知道该保留什么、推翻什么。