跳到正文

AGENT PROJECT INTERVIEW · Q02 / 25

Agent 规划应该写在 Prompt 里,还是固定在业务代码里?

从灵活性、风险、可审计性和维护成本出发,拆解 Agent Planner、固定业务流程和混合规划架构,讲清哪些决策能交给模型。

作者与复核:吴师兄内容依据:公开 Agent 教程、项目题资料与工程推导查看关联教程 →查看吴师兄公开作品 →

25 道题目Q02
本页内容17 节

30 秒先说结论

当任务路径无法提前枚举、允许探索且每一步都有可靠反馈时,可以让 LLM 生成局部计划;当步骤固定、涉及权限、合规或不可逆操作时,应由代码或状态机控制。常见做法是混合规划:程序定义阶段、工具白名单、参数边界、预算和停止条件,Planner 只输出结构化子任务,执行前再做可行性、权限和依赖校验。

面试官问:“你们的 Agent 是怎么规划的?行业流程都写在 Prompt 里吗?”

这道题最容易出现两个极端答案。

一种说法是:“全部让大模型自己拆任务,这样最灵活。”另一种说法是:“模型不可靠,所以所有步骤都写死。”前者忽略安全与确定性,后者又把 Agent 做成了披着模型外衣的固定流程。

生产系统更常见的答案在中间:代码定义不可越过的边界和主流程,模型只在不确定、可验证、可回退的局部做规划。真正的难点在于规划权放在哪一层,以及模型给出的计划如何进入执行系统;一句“请逐步思考”解决不了这两个问题。

先给出 30 秒回答

当任务路径无法提前枚举、允许探索,而且每一步都有可靠反馈时,可以让 LLM 生成局部计划;当步骤固定、涉及权限、合规、金额或不可逆操作时,应由代码、规则或状态机控制。常见做法是混合规划:程序先固定阶段、工具白名单、参数边界、预算和停止条件,Planner 只输出结构化子任务,执行前还要检查计划依赖、工具是否存在、用户是否有权限以及动作是否需要人工确认。这样既保留模型处理长尾问题的能力,又不把业务控制权交给概率输出。

回答里至少要出现“局部规划”“结构化计划”“执行前校验”和“业务边界”四件事。否则很容易停留在 Prompt 技巧层面。

先理解:Prompt 规划到底做了什么

Prompt 规划不是模型突然学会了项目管理,而是开发者通过任务描述、角色、可用工具、限制条件和输出格式,让模型产生下一步建议或一组子任务。

常见规划实现会告诉模型目标,让它思考、决定、行动、观察;也可以让一个 Planner 生成子任务,再交给 Executor 执行。这些方式能够处理不确定问题,但“由模型规划”并不等于“无需框架”。开发者仍然提前决定了谁负责规划、它能看到什么、能调用什么、输出长什么样。

例如一个教学资料调研任务,用户只给出主题和输出要求。搜索什么关键词、先看哪一类资料、发现信息缺口后往哪个方向补充,很难完全提前写死。这部分可以交给 Planner。每拿到一批资料后,Planner 根据现有证据决定下一步,模型的灵活性才真正产生价值。

反过来,如果业务规定必须先校验身份,再确认资源状态,之后才允许提交动作,那么顺序不是“建议”,而是制度。即使模型能生成看起来合理的捷径,也不能采用。

规划控制权不应只有两个极端

规划层的目标不是追求最大自由,而是在可控边界里使用模型处理不确定性。

哪些内容适合写进 Prompt

目标和当前状态的解释

模型需要知道用户想完成什么、已经完成哪些步骤、当前有哪些约束。自然语言目标常常包含模糊表达,模型擅长做初步理解和拆解。

但状态不能只靠一段不断增长的对话历史。更稳妥的方式是把关键状态结构化,例如当前阶段、已完成子任务、缺失字段、可用工具和剩余预算。Prompt 负责把这些状态解释给模型,不负责凭空创造状态。

难以枚举的局部策略

搜索查询怎么改写、资料冲突时先补哪个来源、工具返回空结果后是换关键词还是请求用户澄清,这些选择会随环境变化,适合让模型提出候选。

局部策略的共同特点是:失败通常可逆;候选动作数量有限;执行结果能够观察;系统可以在预算耗尽时安全停止。

自然语言组织和解释

计划不仅要给机器执行,有时还要给用户看。模型可以把结构化子任务解释成易懂步骤,说明为什么需要补充信息,或者总结当前进度。

但用户可见的解释不能替代机器可执行的计划。只有一段散文式“第一步、第二步”,执行器很难稳定解析,也无法检查依赖和权限。

多个低风险候选之间的选择

例如系统已经通过权限过滤,只剩三个只读工具,模型可以结合任务语义选择一个。工具候选必须先由后端确定,模型不能自己发明不存在的 API。

哪些内容必须写进代码或状态机

身份、权限和数据范围

用户能否访问某条记录、某个租户的数据是否隔离、工具是否允许执行写操作,都必须由后端检查。Prompt 中写“不得越权”只能起提醒作用,不能成为安全控制。

不可跳过的业务步骤

教学合同审核场景中,高风险条款出现后必须进入人工复核;教学退款场景中,状态变更前必须完成身份与订单校验。这些步骤要进入固定 Workflow 或状态机。

参数硬边界和资源预算

最大结果数、允许的日期范围、单任务最大工具次数、总耗时、上下文预算等,应由程序限制。模型可以建议参数,但不能突破服务端约束。

不可逆动作和最终提交

写库、发消息、修改配置或创建真实业务动作,需要幂等、二次确认、审计和回滚方案。模型可以准备草稿或 Dry-run 结果,真正提交由确定性系统控制。

计划的状态迁移

“某子任务已完成”应该由工具结果和验证规则更新,而不是模型自己说完成。状态机要知道任务处于待执行、执行中、等待用户、等待审批、成功、失败还是取消。

什么应该写进 Prompt,什么应该写进代码

模型负责建议与解释,系统负责事实、权限、状态和副作用。

混合规划的完整工程链路

一个可控的 Planner 不应该直接持有所有工具执行权。可以把链路拆成六步。

第一步:状态整理

系统先把用户目标、业务状态、已知事实、缺失信息、权限范围和剩余预算整理成结构化输入。原始用户文本仍可保留,但关键判断不能只依赖自由文本。

如果用户说“还是按上次的方式处理”,系统要先从有权限的历史状态中找到“上次”对应什么。找不到就请求澄清,而不是让模型猜。

第二步:Planner 生成结构化计划

计划至少要包含子任务 ID、目标、依赖、候选工具、输入来源、完成条件和失败后的建议动作。下面是教学示例,用于说明字段边界,不是生产代码:

{
  "goal": "比较两份资料中的准入要求",
  "steps": [
    {
      "id": "read_a",
      "depends_on": [],
      "tool": "read_document",
      "success_condition": "返回资料 A 的条款与来源位置"
    },
    {
      "id": "compare",
      "depends_on": ["read_a", "read_b"],
      "tool": "compare_evidence",
      "success_condition": "列出相同项、差异项和缺失项"
    }
  ]
}

重点不在字段名,而在计划必须可检查。散文计划只能供人阅读,结构化计划才能进入校验、执行和回放。

第三步:计划校验

校验器检查:工具是否真实存在;依赖是否形成死循环;必需步骤是否缺失;参数来源是否明确;完成条件是否可以观测;计划是否超过预算。

有些校验可以用规则完成。例如工具名必须来自注册表,依赖图不能有非法环,高风险动作必须包含审批节点。语义层面的计划是否合理,可以再使用模型或人工辅助,但不能只让同一个 Planner 自己给自己打勾。

第四步:权限与风险检查

计划合法不等于用户有权执行。系统根据身份、租户、工具风险等级和数据范围,过滤计划中的动作。若动作需要审批,状态进入等待确认,而不是继续自动执行。

第五步:一次只执行可控的一步

Executor 读取当前可执行节点,调用真实工具,记录请求、参数摘要、耗时、结果和错误。不要一口气把整份模型计划当脚本跑完,否则中途状态变化时无法及时调整。

第六步:观察结果并更新计划

工具结果进入状态。若完成条件满足,标记当前节点完成;若返回空结果、权限变化或新约束,Planner 只能在允许的范围内重新规划。达到预算、连续失败或高风险边界时,系统停止自动执行。

一份计划进入执行器前的链路

Planner 提出建议,校验器与执行器决定这份建议是否能够安全落地。

混合规划最常见的失败方式

失败一:把业务知识全部塞进 Prompt

需求一变就改长 Prompt,看起来灵活,实际上权限、规则和提示词纠缠在一起。模型版本或措辞变化后,同一规则可能被不同解释,也很难审计某次执行使用了哪版制度。

应对方式是把稳定规则做成代码、配置或规则服务,Prompt 只接收当前有效、与任务有关的约束摘要。规则版本要进入 Trace。

失败二:计划只是一段自然语言

模型生成“先查询,再比较,最后总结”,但没有子任务 ID、依赖、工具和完成条件。执行器只能再次让模型解释这段话,系统逐渐变成多层概率输出。

应对方式是定义计划 Schema,并对解析失败、字段缺失、非法工具和不可验证完成条件分别返回结构化错误。

失败三:Planner 同时负责审批和执行

模型提出动作、判断动作合法、执行动作、再宣布成功,整个链路没有独立检查。它一旦理解错目标,后面每层都会跟着错。

应对方式是分离职责:Planner 生成候选;Policy 检查权限;Executor 执行;Verifier 根据工具结果判断完成。

失败四:所有任务都进入昂贵规划

一个明确的单步查询也先让模型生成五步计划,会增加响应时间和上下文。规划不是越多越好。

可以先用规则或轻量分类判断:单步确定任务直接进入对应工具;需要多步和动态路径时再启动 Planner。

失败五:计划失效后从头重来

外部结果变化或某个工具失败后,系统丢掉全部已完成工作,重新生成整份计划。这样容易重复调用、增加成本,写操作还可能产生副作用。

应保留已验证的节点结果,只重规划受影响的局部;若状态可信度不足,再明确进入全量重建。局部与全量重规划的边界要有记录。

怎样验证 Prompt 规划真的带来价值

建立三类任务

第一类是路径固定的常规任务,主要验证混合方案不会为了规划增加无谓步骤。第二类是中途会出现空结果、冲突或缺失信息的动态任务,验证 Planner 能否改变路径。第三类是高风险任务,验证模型即使提出越权计划也会被系统拦截。

所有场景均应使用脱敏或教学数据。没有真实项目授权时,不要用生产写操作做实验。

分层判断计划质量

计划质量不是一个“看起来合理”的总分。至少分别检查:目标是否保持;必要步骤是否覆盖;依赖是否正确;工具是否存在;参数来源是否明确;完成条件是否可验证;是否包含越权或高风险动作。

执行后再看任务是否完成、发生几次重规划、哪些计划被规则拒绝、人工在哪些节点介入。不能用最终答案碰巧正确,倒推整份计划都是正确的。

做计划变更回放

当 Prompt、模型、工具描述或规则版本变化时,使用同一批任务重新生成计划,并比较结构差异。重点关注新增或丢失的必要步骤、工具选择变化、审批节点变化和预算变化。

回放记录应保留输入状态、计划版本、模型版本、校验错误和最终执行轨迹。这样出现退化时,才能确认是 Planner 变了,还是业务规则或工具变了。

对照纯 Workflow

动态任务中,混合规划可能减少人工配置的长尾路径;固定任务中,纯 Workflow 可能更快、更稳。评估应该允许这种结论,而不是把所有指标都设计成证明 Agent 更好。

需求频繁变化时,Prompt 一定比代码好维护吗

不一定。

Prompt 修改快,但它可能同时影响多个行为,回归边界不清;代码修改慢一些,却能通过类型、单元测试和明确分支控制影响范围。真正降低维护成本的不是把规则翻译成自然语言,而是把变化来源分开管理。

可以把系统拆成三类变化:

  1. 业务制度变化:进入规则或配置,带版本和审核。
  2. 工具能力变化:进入工具注册表和 Schema,处理兼容性。
  3. 长尾策略变化:进入 Planner Prompt,并通过固定任务集回归。

如果每次需求变化都只能重写一段大 Prompt,说明模块边界仍然不清晰。

规划控制权还要落实到数据和接口

很多设计在架构图上分清了 Planner 和 Workflow,落到代码里又重新混在一起:Planner 返回一段文本,Executor 从文本中猜工具和参数,业务代码再根据关键词决定是否放行。这样的接口没有真正边界。

可以为 Planner 单独定义输入和输出契约。输入只包含本轮需要的目标、当前状态、允许工具、硬约束和剩余预算;输出只允许候选子任务、依赖、参数来源和完成条件。敏感凭证、内部错误堆栈和不属于当前用户的数据,不应因为“帮助模型规划”而进入 Prompt。

计划进入系统后要有独立身份和版本。Prompt 版本变化、模型变化、工具 Schema 变化或业务规则变化,都可能让相同输入产生不同计划。Trace 至少要能回答:这份计划由哪个模型和哪版 Prompt 生成;它基于哪个状态版本;经过哪些规则;哪一版工具定义被允许;最终哪些节点实际执行。

Prompt 变更不能绕过发布流程

Prompt 看起来只是文字,但它改变的是控制策略。修改“优先调用哪个工具”“信息不足时是否继续搜索”“何时请求确认”,都可能改变真实行为。因此规划 Prompt 应像代码一样评审、版本化和回归,而不是在线上临时改一句就结束。

回归时不要只看最终答案。比较计划节点、必要步骤覆盖、工具选择、权限拒绝、人工节点和预算变化。若新 Prompt 让输出更流畅,却漏掉审批步骤,仍然是不合格变更。

业务规则也不要复制进多个 Prompt

同一条权限或合规规则若散落在 Router、Planner、Reflector 多个 Prompt 中,更新时容易出现版本不一致。确定规则应有单一事实来源,由后端统一执行;Prompt 只接收任务所需的规则摘要或结果。

计划失败必须有可理解的错误契约

校验器不要只返回 invalid plan。应区分结构错误、工具不存在、参数缺失、依赖冲突、越权、超预算和需要人工确认。Planner 只有收到准确、可公开的错误类型,才可能做有边界的修复。

错误契约也方便统计:若大量计划因同一个工具描述不清而失败,应该修改工具 Schema;若大量请求缺少用户参数,应该提前澄清;若经常越权,可能是候选工具过滤位置错误。不能把所有问题都归为“模型能力不够”。

一个适合面试展示的混合规划样本

可以选一条没有真实副作用的教学任务,展示三份材料:第一份是控制表,标出固定阶段、Planner 节点和人工节点;第二份是结构化计划及校验结果;第三份是工具返回后状态如何变化。

展示时要主动说明哪些是教学设计,哪些由自己真实实现。若只完成 Planner 和 Mock Executor,就不要说已经具备生产审批、状态恢复或多租户权限。面试官更看重边界是否诚实,而不是模块名称是否齐全。

面试官会怎样连续追问

追问一:为什么不用全 Prompt

因为权限、合规、状态迁移和不可逆动作要求确定性与审计,Prompt 不能成为安全边界。模型只处理可验证、可回退的局部规划。

追问二:为什么不用全部硬编码

当任务路径依赖实时反馈、长尾情况难以穷举时,完全硬编码会产生大量分支和维护成本。Planner 可以在受限候选中生成局部计划。

追问三:模型计划违反规则怎么办

计划先经过 Schema、工具存在性、依赖、预算和权限校验;越权动作被拒绝或转审批,错误信息进入状态后再决定是否重规划。

追问四:怎样防止模型漏掉必要步骤

把必要步骤写进 Workflow 模板或验证规则,而不是仅在 Prompt 里提醒。计划校验时检查必需节点是否存在。

追问五:Planner 与 Executor 为什么要分开

分开后可以独立校验计划、限制权限、替换执行方式,并清楚定位是规划错误还是工具错误。模型建议不再等同于真实执行。

追问六:你怎么评估维护成本

记录每类需求变化修改了哪一层、影响多少任务、回归失败在哪、需要多少人工处理。没有真实记录时只说明评估方法,不填结论数字。

混合规划上线前检查

一份能生成计划的 Prompt 只是起点,计划契约、权限和回放才构成工程闭环。

Prompt 与代码怎样分工:一段面试回答

Agent 的规划逻辑不应该全部写进 Prompt,也不应该全部硬编码。我会按确定性和风险分层:步骤固定、必须审计、涉及权限或不可逆操作的主干,用代码、规则或状态机控制;路径无法提前枚举、每一步又有可靠反馈的局部任务,才交给 LLM Planner。工程上,Planner 不直接执行工具,而是输出包含子任务、依赖、候选工具和完成条件的结构化计划。系统先检查 Schema、工具是否存在、依赖和预算,再做用户权限与风险校验,之后 Executor 一次执行一个节点,把结果写回状态。工具为空、约束变化时可以局部重规划;连续失败、越权或超预算就停止并转人工。验证时我会同时准备固定任务、动态任务和高风险任务,比较纯 Workflow 与混合规划,并保存计划版本、校验失败和执行 Trace。这样保留的是受控灵活性,而不是把业务控制权交给模型。

Prompt 与代码分工,项目里要留下哪些证据

回答前请确认自己能提供:

  1. 一张固定主干、模型规划点和人工节点分开的流程图。
  2. 一份真实但脱敏的计划结构,而不是只展示 Prompt。
  3. 必需步骤、工具、依赖、权限和预算的校验规则。
  4. 一条计划漏步、越权或失效的失败样本。
  5. Prompt、规则、工具和模型的版本记录。
  6. 纯 Workflow 与混合规划使用同一任务集的对照方法。

如果尚未实现计划校验或状态机,就把它说成下一步设计,不要把一段能生成步骤的 Prompt 包装成完整 Planner。工程化的分界线不在模型能不能列计划,而在系统能不能判断这份计划何时可信、何时拒绝、何时停止。

INTERVIEW FOLLOW-UPS

面试官会怎样继续追问?

这些追问会继续检查方案取舍、验证方法和项目事实。
  1. Q01

    怎样判断一个规划决策应该交给 Prompt,还是写进代码?

  2. Q02

    模型生成的计划要经过哪些校验,才能进入执行器?

  3. Q03

    业务需求频繁变化时,硬编码和 Prompt 各自怎样维护版本?

  4. Q04

    如果规划结果违反权限或遗漏必要步骤,系统如何兜底?

PROJECT CHECK

换成你的项目,这几件事能否说清楚?

  • 列出固定主干、模型决策点和人工检查点
  • 为计划定义结构化 Schema 与允许的工具集合
  • 记录计划版本、校验失败和重新规划原因
  • 准备一条计划越界或漏步的失败样本
用自己的项目经历练一次