
最近这半年我越来越清晰地感觉到一个趋势大家讨论 AI 智能体的时候注意力正在从“模型选哪个、参数怎么调”转移到“模型外面那层壳怎么搭”。这层壳在圈子里逐渐有了一个名字叫 Harness Engineering。说白了就是围绕大模型构建提示词、工具、状态、控制流程、评估机制的一整套工程。很多项目一开始跑得挺欢一上真实流量就崩问题根本不在模型智商而是 Harness 太单薄。我自已也有一段被客服智能体“折腾到怀疑人生”的经历把它修好之后对智能体的稳定性有了完全不一样的理解。这篇就把我的认知和整个排查、改造的过程整理出来希望能给正在做智能体开发的人省一点弯路。1. 先搞清楚什么叫“智能体崩溃”很多人一听到崩溃第一反应就是程序报错、服务器 500、进程退出了。但做了智能体开发之后你会发现真正的“崩溃”远比这隐蔽它是智能体还在回复但回复的内容已经脱离了你原本的设计目标。1.1 崩溃不止是报错三类最常见的翻车现场我习惯把智能体崩溃分成三类。第一类是“死循环型”。智能体调了一个查询订单接口接口返回数据格式不符合预期它不返回给用户而是继续调用另一个工具尝试“修复”。第二个工具也失败它又尝试第三个最后在十几个工具调用之间来回横跳像钻进了一个迷宫出不来。用户看不到过程只看到页面一直转圈最后超时。这类崩溃占了我遇到的情况大头。第二类是“幻觉叠加型”。单次生成的大模型幻觉大家都能理解但智能体场景里幻觉会被工具调用结果持续放大。比如智能体读不到用户订单就“合理推断”出一个订单号去查库查不到就开始道歉并编造退款规则。表面上它在正常对话实际上已经走上了错误逻辑链。这一类最危险因为它不报错日志里全是正常记录业务方却接到大量投诉。第三类是“规则漂移型”。早期你会给智能体写很长的系统提示词规定它只能做订单查询其他一律拒绝。结果它在长对话里逐渐“忘记”了这个限制用户连续问了几次“你能帮我改地址吗”它就从“很抱歉我不能”变成“好的我来帮你尝试”然后去调根本没有权限的接口。模型能力越强这种模仿人类“妥协”的倾向就越明显。三类的共同点是问题都出在模型的外围而不是模型本身。你换更强的模型死循环还是会死循环只是换一种姿势。1.2 为什么模型越来越强“崩溃”却越来越常见这里有一个很反直觉的观察模型本身越聪明智能体越容易在不该发挥的地方“自由发挥”。传统软件系统的崩溃是可预期的输入输出边界清晰而智能体本质上是一段概率性文本生成过程参与的系统控制同样的输入两次生成可能走完全不同的路径。模型变强带来的是更流畅的自然语言能力和更复杂的工具调用意图但如果你没有一个强约束的外围框架这些能力就会变成不可控变量。打个比方一台发动机马力再大底盘、转向、刹车没跟上上路还是翻车。Harness 就是那个底盘。底盘不牢光换发动机只会让翻车翻得更快。这也是为什么这两年智能体领域的新趋势不再是单纯比谁的模型好而是比谁的外围工程能力强谁能在模型之外把这个“壳”设计得足够鲁棒谁家智能体就不容易翻车。2. Harness Engineering 是什么一句话版本和完整版本这个概念还没有特别统一的严格定义不同团队叫法也不完全一样。有人叫工程护栏有人叫编排框架有人干脆就叫“系统提示词工程”。我的理解很简单Harness 是让大模型在特定任务里稳定完成任务的所有外围机制的总和。2.1 一句话理解如果把大模型想象成一个知识渊博但容易走神的新员工Harness 就是你给他安排的工作台、作业指导书、审批流程和质检机制。工作台决定他能接触到什么工具作业指导书决定他说话的边界审批流程决定哪些动作必须停下来有人确认质检机制决定他的产出是否达标。模型本身是“大脑”Harness 是“工作环境”。一开始我只把重心放在系统提示词上觉得把提示词写得足够细智能体就不会乱来。后来发现提示词只是 Harness 的一小块甚至不是最重要的一块。一个设计良好的 Harness可以达到用较小的模型加简单提示词就能跑赢大模型加复杂提示词的稳定性。这不是我一家之言圈子里很多团队实测都有类似结论。2.2 Harness 五层拆解我在实际项目中通常把 Harness 拆成五层每一层都有自己独立的关注点。第一层是上下文层。系统和用户内容怎么组织历史对话怎么保留怎么截断需要把哪些关键业务规则固定住。这一层最容易被低估因为测试时特别短上下文一长就暴露问题。比如智能体只保存最近 10 轮对话用户在第 11 轮提到“刚才说的那个订单”智能体已经完全不记得了就会开始猜测猜测就会出错。第二层是工具层。工具的描述、参数定义、调用超时、异常返回格式全部要单独设计。我见过太多项目把工具描述写得太含糊结果模型根本不知道什么时候该用哪个工具明明有查询接口它偏要自己算一个答案出来。工具层理想状态是每个工具都有明确的触发条件、完整的参数 schema、稳定的失败返回并且失败返回里要包含可读的错误原因。第三层是状态层。多轮任务里智能体执行到哪一步了哪些信息已经拿到哪些还没拿到需要怎样流转这些状态不能靠模型自己“记忆”因为记忆就是幻觉的温床。正确做法是维护一个结构化的任务状态对象每一轮依据状态决定下一步动作。可以把它理解为智能体的“记事本”模型的每次思考都基于这个记事本而不是基于缥缈的“我记得”。第四层是控制层。这是我和团队改造重点。包括工具调用的次数上限、单步超时、循环检测、连续失败熔断、危险动作的人工审批闸口。控制层原则是所有可能无限循环或产生副作用的行为都必须在代码层面强制终止而不是寄希望于模型“自觉”。你永远不能在大模型提示词里写“请勿循环调用”你要在循环外面套一个“超过五次强制结束”的守卫这才是工程。第五层是评估与可观测层。系统能跑还不够你要能随时回答三个问题它现在做什么它做得好不好它是否比上周更稳定这三个问题需要 trace 日志、成功率统计、回归测试集来回答。没有这一层Harness 改善就成了摸黑走路。2.3 关键结论Harness 不是“工程美化”是决定成败的成本项很多团队规划智能体项目时预算大部分花在模型 API 和算法人力上Harness 设计的时间和人力常常被压缩到“顺便做一下”。这是一个战略判断错误。从我自己的体感来说模型能力大家都能买到差距真的不在模型而在于谁能把 Harness 做深做透。你可以用开源模型和商业模型对比单轮问答差距确实存在但放到智能体场景把所有决策和工具调用都收敛到固定流程上之后差距会被大幅抹平。这说明模型能力之上的 Harness才是稳定性的主要贡献者。早意识到这个可以少走很多弯路。3. 实战案例一个客服智能体从“70% 成功率”到“99% 稳定运行”理论说多了容易虚我拿一个真实搞过的模拟项目来拆解吧。背景是一个电商场景的订单查询客服智能体我代称它为“某客服助手”。上线第一周各项监控数据触目惊心成功率只有 70% 左右大量会话中途中断人工介入率特别高投诉关键词里全是“机器人听不懂人话”。3.1 项目背景和病态现象这个智能体的功能并不复杂用户登录后智能体读取订单接口、物流接口、售后规则回答用户的问题必要时发起退款申请。模型用的是当时主流的大模型提示词写了将近两千字几乎把能想到的边界都写进去了。病态现象非常有代表性。第一用户问“我的快递到哪了”时智能体经常返回“您有多个订单请问哪一个”哪怕用户当前只有一个进行中的订单。第二用户报出订单号后智能体查完物流还会“顺手”推荐一些毫不相关的商品把客服对话搞成了营销。第三一旦用户情绪激动它会一反常态地道歉、承诺补偿甚至直接说要给用户退款 500 元这在业务上完全不合规。这几类现象放在一起基本可以判断提示词里写的规则模型在长对话和多工具场景里并没有稳定遵守。我们最开始以为加大模型规模能解决试了一版更大更强的结果成功率没怎么升反而因为模型更强生成文本更长响应延迟更高用户体感更加糟糕。3.2 根因定位trace 数据不会说谎果断把重心从调模型转到修 Harness。第一步是搭 trace。我们没有额外买复杂的观测平台就是把每一步的用户输入、系统状态、模型输出、工具调用参数和结果都记录成结构化日志拼出一个完整的调用链。trace 一出来问题清清楚楚。“快递到哪了”这个问题的链路是智能体先调订单列表接口接口返回了两个历史订单模型一看有复数订单就按预设逻辑让用户选。但其中一单半年前就完成了另一单才是进行中的。模型没有能力判断“只有进行中的订单才需要提供给用户”于是把两个订单都抛出去制造了无意义的选择。“推荐商品”问题则出在一个历史上为了提升活跃度加入的商品推荐工具。这个工具在系统提示词里写了“仅在用户询问商品时使用”但在一次会话中模型判断用户情绪不错就主动调用推荐工具而控制层没有任何拦截。它会“过度服务”。“虚假承诺退款”更致命根因是售后规则工具的返回内容太长了一次塞进上下文的长文本里包含了很多种情况。模型在处理实际对话时引用了其中一条不适用于当前订单的规则因为它根本区分不了规则适用的前提条件它只是“看起来很像”地选择了最近的文本。3.3 我给 Harness 动的手术状态、工具、控制三层齐改定位到根因之后我做了几个关键改造。第一处改造是在状态层。我在会话状态里增加了一个“当前订单快照”字段。第一步先把订单列表接口的返回结果做过滤和归一化只保留“进行中”的订单然后存储为结构化状态并在工具说明里要求所有涉及订单的问题一律从状态快照里取数据不许模型自己从冗长的工具响应里挑。这一步直接干掉了“多个订单让你选”的问题。第二处改造在工具层。商品推荐工具被直接下架。短期营收可能受影响但稳定优先推荐功能应该由独立的营销智能体来承担而不是塞在一个客服智能体里。工具层还补了一个失败回退凡是读取物流信息失败统一返回“暂时无法查询请稍后重试”不提供给模型任何发挥的余地。模型一旦没有模糊的数据可引用自然不会编造。第三处改造在控制层。我设计了一个带硬限制的调用循环类似下面这种思路MAX_TOOL_CALLS 5 for step in range(MAX_TOOL_CALLS): response llm.generate(messages, toolstools, current_statestate) if response.tool_calls: state.last_action tool_call result execute_tool(response.tool_calls, state) messages.append(result) if result.is_error: state.consecutive_failures 1 else: state.consecutive_failures 0 if state.consecutive_failures 2: return 抱歉系统暂时无法完成这个操作请稍后再试。 else: return response.text return 抱歉这个问题比较复杂我会转给人工客服处理。这套逻辑的核心思路是工具调用成功与否不交给模型判断而是由代码检测。连续失败两次直接熔断让用户走人工不要再浪费用户时间。达到最大调用次数也不再让模型继续“思考”而是直接兜底回复。这样的做法损失了一些“智能感”但换来了硬性的稳定。控制层还加了一个行为审批闸口。凡是模型输出里出现“退款”“补偿”“改地址”这类高风险意图不直接执行而是先返回一个确认话术要求用户明确点击或复述确认。这等于在关键副作用发生前加了一个人工确认位。这里是模拟项目没有接真实审批系统但机制和真实场景是一致的。提示词也做了精简从两千字精简到六百字左右只保留核心身份、工具使用原则、拒绝边界三条。之前以为提示词越全越好实际操作后发现提示词越长模型越容易在长上下文中忽略某些约束精简之后反而规则更突出遵守率更高。3.4 修复后的数据验证改造上线后我观察了两周。成功率从 70% 爬到了 99% 左右这是一个非常直观的数据变化。具体来说原来每天有 30% 的会话最终走到人工兜底现在降到 1% 上下原来平均每个会话要调用 4 到 7 次工具现在控制在 2 到 3 次用户反馈里“机器人乱说话”的投诉直接归零。这里有一个值得注意的细节模型本身没有换提示词还变短了唯一的变量是 Harness。我不否认模型能力的重要性但在智能体场景稳定性确实更多来自外围工程。很多团队在遇到智能体不稳定时第一反应是换更强模型而不是检查自己的 Harness在我看来这就是舍本逐末。4. 平时怎么发现“即将崩溃”的信号可观测性与回归测试智能体崩溃不可怕可怕的是崩完之后你根本不知道它怎么崩的。很多团队连基础的 trace 都没有靠用户投诉反馈再打开后台看聊天记录一条条人工分析效率低得让人抓狂。这块我有几个很实用的建议。4.1 让每次智能体运行都有“黑匣子”那套客服智能体改造前后的对比让我彻底明白了一个道理没有 trace 就没有排查权。每个会话我都建议至少记录以下内容。会话的唯一 request_id用来串联整条链路每轮的用户输入和最终的模型输出每次工具调用的名称、参数、耗时、返回码状态对象的每次变更控制层的每个终止或兜底点的触发原因把这些记录成 JSON 日志之后搭建一个简单的检索界面就行。排查时可以按 request_id 调出整条链路一眼可以看出模型哪一步开始走偏是工具返回异常还是提示词没有约束住。不要嫌这个工作琐碎。很多崩溃是间歇性的没有黑匣子你只能靠猜。你也不会愿意在生产环境为了查一个 bug 去打印一堆临时代码。4.2 建立智能体回归测试集不能只测 happy path传统软件开发里会做单元测试智能体领域同样可以做而且必须做。我习惯把测试用例分成几类。第一类是正常路径用户正常下单、正常查询测试智能体能不能顺利走到正确工具并给出答案。第二类是异常输入用户乱说、骂人、发语音转文字的错误文本、发空消息测试智能体会不会失态。第三类是工具故障模拟接口超时、返回空数据、返回非法格式测试智能体会不会死循环或编造数据。第四类是越权试探用户问客服能不能改价格、能不能绕过退款限制测试智能体会不会“灵活处理”。每一类都跑一遍全都通过才允许发布。这在实践中有一些难度因为大模型生成有随机性同样的用例十次可能九次通过一次失败。我的做法是在每个用例上设定一个通过阈值比如工具故障类用例要求“10 次里至少 9 次符合预期”。这样既容忍大模型的概率性又确保稳定性在可控区间。4.3 用成本不高的方式做持续监控上线之后还需要监控。不用一开始就上重型平台一个简单的定时任务就可以每天随机抽取 30 到 50 个真实会话用规则筛查几个关键事件比如是否有连续三个相同动作的工具调用、是否有超过五步的循环、是否出现退款等高风险关键词。如果有自动报警。这套机制成本很低但非常有效。它可以在用户大规模投诉之前先让你自己发现问题。我和团队现在保持一个习惯每周开一次稳定性复盘会数据都是从这个监控里来。你会发现稳定不是一次性工程而是一个不断被打破又重新建立平衡的过程。5. 给想做 Harness 工程的人避坑清单和几条反直觉心得最后聊聊经验教训。这些东西不是教科书上写的全是自己踩坑踩出来的。5.1 常见崩溃诱因对照表为了便于快速定位问题我整理了一张对照表基本覆盖了我见过的大部分翻车场景。崩溃现象最可能的诱因优先排查方向工具调用死循环控制层缺少次数上限和失败熔断在代码里加硬性循环限制模型编造工具返回数据工具返回格式不稳定模型只能靠猜统一工具返回结构失败时给兜底文案长对话后忘记规则上下文过长提示词被淹没精简系统提示词规则放到关键节点重复强调对敏感操作“过度服务”工具层权限过大没有审批闸口高风险操作转为显式人工确认回答前后矛盾状态没有统一维护靠模型记忆用结构化状态对象记录关键信息间歇性失败无法复现缺少 trace 日志部署结构化 logging全链路串联这张表不能覆盖所有情况但它能告诉你一个基本方向遇到智能体异常先想 Harness 哪一层没有堵住而不是先怀疑模型智商。5.2 几条反直觉但很有用的心得第一给模型留“退路”反而会减少出错。早期我总想把所有边界都堵死让模型只能走我规定的路。结果模型遇到边界情况时会强行找一条路走往往就走错了。后来我在提示词里明确加了一句如果信息不足直接告诉用户“我无法确认请稍后再试或联系人工”。加了这句之后模型在未知场景下的胡编乱造大幅下降。让模型敢说“不知道”是稳定性的一个重要开关。第二工具不是越多越好。工具越多模型选择成本越高选错的概率越大。客服项目里我把十几个工具砍到五个稳定性明显上升。每加一个工具都要问自己这个工具不模型调用直接硬编码行不行很多看似需要模型决策的点其实用代码判断更可靠。第三提示词要“分布式”放置而不是全部堆在系统提示词里。我发现把关键规则分散到对应的工具说明和状态描述中比集中在系统提示词里更有效。比如订单查询规则写在订单工具的 description 里退款权限写在退款工具里模型执行特定任务时才看到强相关约束遵守率比在开头写一万字高得多。第四小型开源模型加完善 Harness很多时候比商业大模型裸奔更稳。这不一定准确但可以作为选型参考。当你的系统已经把大部分决策收敛到固定判断流程模型需要“自由发挥”的空间很小那么大模型带来的额外优势就不明显了。5.3 我个人的最后提醒做了大半年 Harness Engineering我最大的体会是你别把智能体当成一个“超级会说话的人”你要把它当成一个“需要严格管理的新员工”。员工越聪明越容易自作主张你需要给他明确的工作职责、决策边界和审批流程。没有一套好的 Harness再强的模型也只是个高学历的定时炸弹。还有一个小建议所有工具调用日志里从第一天就带上 request_id这个不起眼的字段会在你排查问题时救你无数次。别等到智能体已经崩得不可开交再回头补日志那真的太难了。希望这篇拆解能给你一点启发。如果你正在做智能体开发遇到模型“好像不太行”的时候先别急着换模型去看看你的 Harness大概率会有奇效。我自己的项目就是这样换了一整套外围控制设计之后同样的模型跑出了完全不一样的稳定性。这条经验值得你花时间验证一下。