
Agentic 工程现在真正值得讨论的不是让 Agent 生成更多的输出而是让 Agent 学会拒绝输出。这不是一句反常识的口号而是我在接触多轮自动化任务、代码修改型 Agent、数据加工流程之后得出的实际感受很多系统从“跑不通”到“跑得通”靠的不是把模型换大、把提示词写长而是把“哪些结果不该被放行”这件事提前设计进流程里。这篇文章想把这个判断拆开讲清楚包括为什么生成型优化会失效、拒绝优先的结构是什么样的、落地时看哪些指标以及新手和生产环境应该选择什么配置。Agentic 工程和传统程序开发的差别很大。传统程序是确定性逻辑输入合法执行路径明确输出可预期。Agent 程序不是这样输入是模糊的自然语言任务中间步骤由模型自己决定工具调用一个接一个最终结果还要经过一层判断才能确认“这个任务真的做完了”。所以 Agent 系统的难点从来不是把某个环节做出来而是每个环节都可能出错而且出错方式比普通程序更隐蔽。少生成、慢生成、拒绝生成经常比多生成、快生成、完整生成更安全。我见过很多团队评估 Agent 时只看一个问题它能不能自动完成一个端到端任务。能完成就继续不能完成就换模型、加 few-shot、加长上下文。但自动化稳定之后真正的风险才开始出现Agent 会以极高的置信度执行错误动作会把“生成了一段看起来合理的文本”误认为“完成了真实世界的操作”。这时候最需要的机制不是提高生成能力而是建立一整套能让输出被拦截、被拒绝、被送回重做的工程屏障。1. Agentic 工程的核心矛盾生成容易验证很难1.1 生成能力已经溢出可信执行才是瓶颈先明确一个概念。Agentic 工程不是指用提示词调用一次大模型而是指让大模型在受控环境中自主完成多步任务比如调用代码解释器、操作文件、执行命令、调用业务 API、汇总结果。这类系统真正的高风险点不在模型推理而在行动。一个语言模型生成一段代码很容易生成一句“任务已完成”更容易。但它有没有真正读取文件、有没有实际执行测试、有没有检查输出目录、有没有在失败后停下来而不是继续补一段虚构结果才是 Agent 系统能不能用于生产的区别。这部分能力不会因为模型的推理水平提高而自动解决只能靠工程手段解决。所以我对这个标题的理解是把 Agent 当成“一个努力输出的东西”方向就错了。它应该被当成“一个随时准备停下来的执行器”。系统设计者优化的是过滤机制、停止条件、校验链路而不是最大化解码长度、工具调用次数和完整度。1.2 “会说话”不等于“会办事”“会办事”不等于“办对了”区分三层能力很重要。第一层是生成。模型能写出步骤、写出代码、写出答案这是当前模型最擅长的。第二层是执行。Agent 能调用工具、操作文件、运行命令这是 Agent 框架层解决的问题。第三层是判断。Agent 需要决定哪些动作不该执行、哪些结果不该返回、哪些情况必须停下来问人。大部分项目卡在第三层。原因是第三层没有现成模型可以直接负责它需要工程规则来兜底。比如“遇到任何删除操作都必须停下来确认”“测试未通过时不允许提交结果”“输出涉及用户隐私字段时直接丢弃”“上下文不足时明确说不知道而不是补全一个答案”这些都是拒绝策略。判断能力越弱系统就越容易给人一种“已经很智能”的错觉因为生成结果太流畅了。但只要有一次错误输出没有拦截整个任务的代价就可能超过它之前所有正确输出节省的人力。拒绝是 Agent 的可信执行里最便宜的兜底机制。2. 过度生成在实际场景里是怎么造成事故的2.1 代码类 Agent改动范围失控的典型场景代码助理类 Agent 是最常见的应用场景。用户说“把项目里过时的接口调用清理掉”Agent 如果只按字面理解就会搜索所有相关代码然后一次性大范围替换。结果可能是更新了不该更新的注释、顺手改了格式、把不同模块里语义不同的同名变量一起替换了甚至在没有跑测试的情况下直接标记为完成。这类事故很少是模型“不聪明”造成的更多是系统没有约束动作范围。真正应该发生的是先搜索定位到具体文件列出待改动清单逐项标注理由请用户确认再小步执行每步都跑一次测试。任何一步失败就停下来。所以代码类 Agent 的工程重点不是让它写多少代码而是让它在边界之外拒绝行动。改动面多大需要确认、哪些目录只读、哪些分支不允许推送、测试失败后禁止继续提交每一条都是拒绝规则。2.2 数据任务里最常见的“自信用错”数据处理类 Agent 更危险因为它的输出看起来精确。比如让 Agent 从一批表格里提取某些字段并统计如果它遇到缺失值、编码错误或语义歧义最容易出现的行为是“猜一个合理值继续算”而不是停下来报告数据质量问题。结果是输出完整、数字合理但前提假设是错的。正确的 Agent 行为应该是发现数据异常先记录字段含义不明确先输出假设并请求确认必要情况下直接判定“这个任务当前不可执行”。拒绝不执行本身就是有价值的输出因为它把风险暴露在流程早期。我一般跟团队说数据类 Agent 的第一产出物不是最终报表而是数据质量说明。如果这个环节没有明确的停止机制后面再智能都会变成事故放大器。2.3 成本视角一次错误输出的代价等于 N 次正确输出为什么拒绝值得被当作核心优化目标因为 Agent 系统运行成本不只是 token 费用。错误输出会产生连锁成本人工审查需要时间错误操作需要回滚下游任务需要重跑用户对系统的信任会下降。一次错误输出可能让数十次正确输出积攒的信任清零。如果系统设计成“尽量生成、少打扰人”那它在低风险任务里体验确实好但一旦出错代价是堆叠式的。反过来如果系统主动拒绝、频繁请求确认表面上看效率变低了但实际上每一次通过的输出都更接近可用状态。对生产系统来说宁可多在中间环节停下来也不要让错误一路畅通地到达终点。真正贵的不是“多问一次”而是“错到底才发现”。3. Agent 要拒绝的不是“不做”而是“不可验证地做”3.1 把确认、校验、拦截拆成三个独立环节很多 Agent 设计把安全检查写在提示词里让模型“自己注意安全”。这种做法在简单任务里有效在复杂流程里不可靠。更好的做法是把控制逻辑移动到工程层从三个环节分别把关。确认环节负责解决意图问题。Agent 在行动前重复一遍它理解的用户意图、执行范围、预期产物和风险点用户可以修改或确认。这一步看起来多余却是打断“自说自话执行”的最有效手段。校验环节负责解决结果问题。Agent 完成一个动作后系统必须运行自动校验比如测试是否通过、输出模式是否合法、文件是否生成、结果是否为空。校验不通过时不允许进入下一步也不允许把中间结果当最终结果返回。拦截环节负责解决边界问题。敏感操作、高风险目录、网络请求、删除动作、推送发布等都要设置独立开关。开关默认关闭只有具备权限的人或明确的策略才能打开。三个环节分开日志也分开出事时能快速定位问题出在意图理解、结果质量还是权限配置。3.2 最小动作原则小步多次优于一次性大改让 Agent 学习一种工作习惯一次只解决一个问题尽量使用最小化的改动。这不是为了慢而是为了可追溯。改动越小每个中间结果的校验成本越低出现问题时回滚范围越窄。批量任务尤其要遵循这个原则。很多 Agent 工具支持一次处理一百个文件但这种批量能力应该放在流程稳定之后不应该放在最前面。最开始我只建议跑一条、跑三条、跑十条例行任务确认每一条的输出差异都在可接受范围内再放开批量。如果 Agent 倾向于在一次请求里做很多动作工程上要主动拆分。一个任务拆成“搜索、过滤、草拟、确认、执行、验证”六个子步骤比让模型自由发挥更稳定。每个子步骤都能独立判断是否继续这就是拒绝优先的落地形态。3.3 人工确认点是决策器不是审批负担很多人优化 Agent 时喜欢把人工确认点减到最少觉得“全自动”才算成功。但人工确认点真正的作用是处理低概率但高成本的错误这跟审批流程是两回事。一个好的确认点应该提供足够清晰的上下文。不是单纯问“是否确认继续”而是给用户看到 Agent 当前理解、待执行动作、可能影响的范围、预估风险。这样用户几秒钟就能做出决定。如果确认点设计得让用户还要去查日志、翻源码才能判断那这个确认点就是失败的需要先把信息整理好再问人。我见过一个比较好用的节奏主动考虑被动执行。Agent 可以提出完整方案但动作要等用户明确指令或策略放行后才执行。这个过程的人工操作次数并不一定多因为大多数策略可以通过规则前置放行只有规则覆盖不到的才转人工。4. 把“拒绝优先”落进实际工程流程4.1 先写验证器再写生成器这是我最想强调的一点。很多 Agent 项目都是先让模型生成结果再考虑怎么校验。正确的顺序应该反过来先把验证器写出来再让模型生成。验证器长什么样取决于任务。代码任务里是单元测试、编译检查和静态检查数据处理里是字段完整性、类型合法性、空值和异常值统计文本任务里是格式约束、关键词约束和长度边界。验证器不需要一开始就很完善但至少要能判断三件事结果是否为空、结果是否符合结构约束、结果是否与输入产生明显冲突。有了验证器之后Agent 的提示词里就可以写清楚只有通过验证的结果才算完成。验证失败时要么重新执行要么明确返回失败原因不能生成一个“看起来像成功”的答案。这个逻辑放在工程层以后模型会产生一种行为倾向它知道后续会校验所以编造概率会降低不确定时会倾向于说明问题。4.2 给 Agent 足够明确的停止条件Agent 任务失败最典型的现象不是停止而是硬着头皮继续。任务已经做不下去模型还在生成步骤、补全文件、尝试新路径。根因是缺少停止条件。在设计任务模板时要显式写下几种允许停止的情况必要条件缺失比如找不到目标文件、字段不存在、依赖未安装校验结果不通过且尝试重试次数达到上限发现执行结果与预期目标冲突上下文已经无法支撑完整执行继续部分执行会产生误判需要更高权限或者依赖外部信息才能继续。这些规则应该在提示词里也应在编排层必要时用代码硬性终止。比如任务超过一定步骤数或者超过一定时间就自动进入“待人工处理”状态而不是让模型继续尝试。一个明确说“我无法继续因为测试日志显示 NPM 包不存在”的 Agent比一个硬编一个包版本继续跑完流程的 Agent 可靠得多。下面是停止条件比较推荐的一种规范化写法方便把决策规则收敛到一处。[AGENT_STOP_RULES] - IF 输入缺少关键参数 AND 无法自行获取 - STOP_REASONINSUFFICIENT_INPUT - IF 校验器返回 FAIL 且重试 3 次 - STOP_REASONVALIDATION_FAILED - IF 计划改动范围超过用户预期边界 - STOP_REASONSCOPE_EXCEEDED - IF 需要执行 forbidden_actions 中的动作 - STOP_REASONPERMISSION_DENIED - ELSE - CONTINUE注意这不是标准代码只是一份通用规则样例。实际字段名和判断顺序要依据你自己的框架来定但要让模型和人都能看懂同一份停止语义。4.3 用沙箱和最小权限兜住危险动作Agent 最终要执行真实世界里的动作所以权限必须小于用户自身而不是等于用户。这一点经常被忽略。本地开发场景里可以给 Agent 配置独立的运行目录让它只能访问指定的工作目录需要联网时走代理或单独的网络环境涉及读写的接口默认只给读权限写权限按任务临时授权。云端任务则需要考虑服务账号的权限边界不让 Agent 使用具有全局权限的密钥。沙箱的目标不是挡住故意的恶意而是挡住误操作和幻觉导致的无意破坏。模型可能在某次工具调用里把路径写错或者在拼接命令时多了一层目录切换。没有权限边界这种小错误直接变成生产事故有了权限边界最多只是任务失败然后回到停止条件。4.4 一个可照着走的最小落地工作流如果你要在一个新场景里上 Agent我建议按下面这套顺序推进。定义任务边界。明确输入是什么、输出是什么、哪些动作属于范围外。范围外的事情直接拒绝不要试图由 Agent 自主判断是否要做。写三个最基础的校验器输出不为空、结构满足要求、关键指标与输入不冲突。设计停止条件清单。至少解决“没数据时怎么办”“校验失败时怎么办”“缺少权限时怎么办”。跑一条最小任务。只测一个成功路径观察 Agent 是否会按边界执行。人为注入一个错误。故意给 Agent 一个包含异常数据的输入看它是否停下来而不是硬编结果。检查日志。确认 Agent 每次拒绝、暂停、请求确认都有记录且记录里能找到出处。逐步放开范围。每次放开一个权限或增加一个动作类型都要跑一遍回归验证。这套步骤不酷但很有效。它的核心思路是把“最坏情况”前置先用低风险任务测试高风险路径再逐步扩大信任边界。5. 怎么判断 Agent 真的“懂拒绝”5.1 只看任务成功率远远不够衡量 Agent 时最容易犯的错是只统计端到端成功率。比如一百个任务里有九十个完成了就觉得系统很好。但一次错误执行带来的破坏可能超过十次正确执行积累的价值。更合理的做法是同时统计生成的置信度、动作的危险度和结果的校验通过率。成功不是终点校验通过才是。如果一个任务完成但校验失败那它在工程意义上应该被记为失败。5.2 一组更实用的验收指标下面这些指标比“是否完成”更有参考价值。指标计算方式关注点动作拦截率被规则拦截的动作数 / 总动作数拦截规则是否真的在工作停止准确率主动停止且理由合理次数 / 总停止次数Agent 是理性停止还是乱停假阴性率输出质量问题但未被校验发现次数 / 总输出数校验器覆盖是否够假阳性率正确输出被拦截次数 / 总输出数拒绝策略是否过于保守人工确认后修改率用户修改 Agent 方案的次数 / 总确认次数确认点提供的上下文是否有效回滚率需要回滚的操作次数 / 执行总次数执行动作是否被允许得过宽我自己比较看重的是“人工确认后修改率”。如果这个比例很高说明 Agent 提的方案跟用户预期差得远确认点只是在走形式并没有真正提升确认效率。理想状态是多数情况下用户只看一眼就能确认少数情况下需要修改最坏情况是用户发现 Agent 在反复提交明显不该执行的方案。5.3 Agent 的行为日志比最终文档重要很多人验收 Agent 项目时只看一份最终汇报看完觉得很完整但不知道系统在过程中做了什么。拒绝对 Agent 工程来说行为是全部。所以日志设计要有标准每个动作都要记录触发理由、工具名称、输入摘要、输出摘要、结果状态每次拒绝都要记录拒绝类型、停止原因、重试次数每次确认都要记录确认人、确认时间和上下文快照。这样出问题时才能回答“为什么 Agent 会做这件事”而不是靠猜。一个值得坚持的做法是让 Agent 每次任务都输出一份行为卡片里面不是自然语言总结而是结构化字段。至少包含任务 ID、已执行动作、被拒绝动作、校验结果、停止原因。这个卡片既是调试材料也是审计证据更是后续优化提示词和规则的依据。6. 新手配置和生产配置应该差多少6.1 学习阶段怎么配如果你刚开始尝试 Agentic 工程不需要一开始就上重规则。先保证三点。环境上使用独立工作目录不直接操作真实业务代码或生产数据库权限上只授予读操作和轻量测试权限流程上强制每个高风险动作之前人工确认。提示词里写清楚边界、失败场景和停止条件但这个阶段校验器可以非常简陋比如只要输出结构正确、非空、能打开即可。重点是让流程跑通并体会“什么情况下 Agent 会错误地继续执行”。学习阶段适合用默认策略跑简单样例。你可以故意设计几个坑比如让 Agent 读取不存在的文件、修改只有只读权限的文件、处理含空值的表格。观察它是否停下来还是直接生成一个合理的假结果。这类测试能快速暴露系统在拒绝能力上的缺陷。6.2 生产阶段怎么配一旦任务要进入生产环境配置就需要升级。至少要考虑这些变化权限上按任务最小授权不共用长期密钥敏感系统使用独立服务账号。校验上验证器不仅检查结构还要维护数据质量基线例如字段枚举范围、数值区间、重复记录检测等。停止条件要配置成机器可读规则不只是提示词。流程上对高风险动作执行双人确认或策略审批。日志要集中存储并做审计方便回溯。生产阶段还应该做演练。平时跑任务时随机注入几类错误场景确认 Agent 能稳定停在预期位置不会绕过限制。这种演练频率不用太高但每次改动规则或升级模型后都应该做一次。6.3 配置差异速览维度学习阶段生产阶段运行环境本地独立目录隔离沙箱/预发布环境权限读为主写低频最小化授权敏感操作单独审批校验结构校验结构校验 数据质量基线 回归集停止条件提示词说明提示词 编排层硬规则 超时终止人工确认手动确认所有风险动作白名单自动化 异常转人工日志本地文本日志结构化日志、审计追踪、告警测试几条冒烟样例错误注入 回归测试 灰度放量新手不要盲目套用生产配置否则会被大量拦截规则淹没连基本流程都调不通。生产也不要停留在新手阶段否则 Agent 权限越大事故越大。判断标准很简单任务是否能长期反复跑、失败时能不能快速定位、被拒绝的动作能不能被人工接管。7. 常见误区和排查链路7.1 误区让 Agent “注意安全”就等于让它会拒绝提示词里写“注意安全”“不要做危险操作”本质上还是在生成端想办法。模型看到这句话确实会短暂倾向于更谨慎但遇到复杂上下文、多轮对话和上下文过长时这种倾向会衰减。真正可靠的拒绝需要外部规则、权限控制、校验结果和人工确认点来配合。提示词只能表达意向工程才能形成约束。7.2 误区Agent 拒绝得越多就越好拒绝策略本身也有成本。拒绝过多正确任务无法推进用户体验变差人工确认点和审批流成了新的瓶颈。好的系统应该是分层结构常规动作自动执行超出预期的动作触发确认明确禁止的动作直接拦截。拒绝的粒度要跟风险匹配风险低的动作不需要每步都问。如果发现拦截率过高不要急着加规则先看停止原因分布。很多时候问题出在任务描述太模糊、输入格式不完整或者停止条件太宽泛。给 Agent 更明确的输入信息往往比放宽拦截规则更有效。我在实际项目里经常发现Agent 频繁“不知道该怎么办”的时候提示词里其实没写清楚“什么算完成”。7.3 排查顺序从现象一路往上查当 Agent 出现错误行为或异常停止时按下面这个顺序排查比到处改提示词更高效。先看现象。Agent 还在跑还是已经停了是卡在等待确认、报错退出还是返回了错误结果。这个阶段只记录不做修改。再看输入。核对任务描述、输入文件、环境变量和上下文里有没有脏数据、歧义表述、缺失字段。大量 Agent 行为异常都是输入问题。三看规则。把停顿和拦截记录翻出来核对停止条件是否误触发权限范围是否过窄以及确认点是不是消息格式不规范导致误判。四看校验。校验器本身是否是可靠。如果校验器没有发现结果错误比如没有检查输出目录是否生成文件Agent 就会认为自己完成了。五看生成。到了这一步才把注意力放到模型能力上换模型、调温度、补 few-shot 示例。多数时候你会发现不需要这一步问题在前面已经找到。我反复遇到的情况是最后发现不是模型判断错误而是校验器没写完整导致 Agent 在缺少某个前置文件的情况下照常产出结果。一旦把“output 目录必须存在且文件非空”这类校验加进去问题立刻消失。7.4 一套可以留作自检的排错问题清单如果任务表现异常先问自己这几个问题Agent 是否知道当前阶段属于哪个流程节点如果上下文里没有明确的阶段标记它很容易把中间状态误认为最终状态。输入里是否存在多个意图或多种数据格式Agent 往往只会按最常见的那一种理解然后忽略其他情况。失败路径是否真的被测试过很多项目只测成功路径失败场景完全没有覆盖。是否有可以绕开确认的操作通道比如某个工具函数支持批量删除Agent 只要调用批量接口就能绕过单条确认这是典型的权限漏洞。日志里能看出 Agent 为什么选择某条路径吗如果看不到说明日志设计还有缺陷先补日志再优化模型。结尾说回“Agentic engineering optimizes for rejecting output, not generating it”这句话。它真正想表达的不是让 Agent 不要干活而是让 Agent 的每一次行动都经过“可验证”这道门槛。生成的输出只是候选能通过校验、在权限边界内、符合停止条件的结果才算真正完成。Agentic 工程成熟与否要看它拦截了多少错误输出而不是看它产生了多少文本和动作。我个人的建议是如果你想尝试这一类系统先别急着追求全自动。从一条最小任务开始把验证器、停止条件、权限边界各建一层然后故意给系统喂一个错误场景看它有没有停下来。如果它能清晰地说出自己的判断依据并且停下来等待人工确认那这个 Agent 才算具备进入生产的基本条件。如果它还在自信地生成一套漂亮的结果那说明工程还差得远。踩过几次之后就会发现稳定不是生成出来的是拒绝出来的。