ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Agent失控?Harness才是企业智能体落地的骨架

Agent失控?Harness才是企业智能体落地的骨架 如果你最近在关注 AI Agent 方向应该会频繁刷到一个词Harness。从 DeepSeek Harness 到 Codex Harness再到各种 agent harness 的开源项目几乎每隔几天就有一个新包装冒出来。我第一次看到这词的时候心里想的是这又是给 Agent 套壳的营销概念吧等自己真动手把一个会用工具的 Agent 放到业务环境里跑起来才发现 Harness 不是壳而是决定 Agent 能不能在企业场景里活下去的骨架。这篇不是科普贴是我从“裸调大模型做 Agent”到“自己搭 Harness”再到“把通用能力收敛成业务智能体”这段过程里的真实记录。适合正在琢磨 Agent 落地、想搞明白 Harness 到底解决了什么问题的团队参考。我会把 Harness 和 Agent 的区别、企业为什么不能直接套用通用方案、以及我自己搭内部 Harness 时的设计和踩坑经历都摊开来讲。1. 为什么突然都在聊 Harness从 Agent 失控说起1.1 通用 Agent 的典型失控现场先说一个让我印象极其深刻的案例。年初的时候我接了个需求让 Agent 自动处理客服工单分类给每个工单打上“售后、退款、技术咨询、投诉”之类的标签然后推给对应组。听起来很常规吧我一开始也这么想直接把一个能调用工具的大模型接进来给了它三个工具查询订单系统、发送邮件、访问 CRM 客户信息。结果上线第一周就出了不少问题。最常见的状况是Agent 在工单里查不到某个订单号的时候不是停下来问用户而是会对着同一个查询工具反复重试一次任务最多能触发几十次工具调用token 费用翻了五六倍。还有更离谱的它会自己“脑补”结果明明订单系统返回的是“not found”它却在最后输出里写“该订单已找到状态为已发货”。这不是模型能力不行是运行方式有问题。大家最初做 Agent 的时候都习惯把 Prompt 写得天花乱坠你是谁、你要做什么、你有哪些工具、你要遵循什么规则。但大模型本质上是一个概率引擎它不是在执行流程而是在“预测下一个 token”。对话场景里这种自由发挥是优势一旦把它放到需要确定性、可审计、可回滚的业务系统里自由就成了危险源。所以那段时间我最大的体会是一个 Agent 出问题往往不是模型不够聪明而是缺少一套约束框架。你给了它手却忘了给它一条“什么时候可以动手、什么时候必须停下”的规矩它当然会乱来。1.2 Agent 不是不够聪明是缺少约束框架现在网上大家聊得火热的 Harness 工程本质上就是在补这个缺。它负责回答几个看似基础、但裸 Agent 一直没解决好的问题模型在什么状态下可以调用工具一次任务最多允许调用多少次工具工具调用失败了是重试、换一个工具还是直接终止并转人工模型的输出如何判定为“完成”谁来验收整个任务花了多少钱、跑了多少轮有没有预算上限出问题之后能不能把每一步回放出来找到责任点这些问题放在传统软件开发里都是常识但到了大模型这里很多人下意识觉得“模型自己能搞定”。实际上模型自己搞不定。ReAct 循环让模型推理、行动、观察结果再推理本身没问题但它缺边界、缺停机条件、缺恢复策略。Harness 就是把这些给补上规定模型什么时候能干什么参数有哪些限制失败后走什么分支预算用完了怎么办。如果说 Agent 是发动机那 Harness 就是整车。单有发动机你也能看着它转起来但只有配上方向盘、刹车、仪表盘、安全带它才能真正上路载客。这个类比我后面会展开讲因为不少团队到现在还停在“发动机转起来就算成功”的阶段。2. Harness 和 Agent 到底差在哪2.1 一个类比发动机和整车网上关于“Harness 和 Agent 区别”的讨论特别多但很多文章写得绕。我用一个更直白的类比Agent 是发动机Harness 是整车。发动机解决的是“动力从哪来”的问题对应 Agent 解决的是“理解和行动能力从哪来”。但一辆车能安全开到目的地靠的不光是发动机还需要方向盘来定方向、刹车来止损、仪表盘来反馈状态、车灯来照路、安全带和气囊来兜底。这些“外部装置”加起来就是 Harness。具体到技术上方向盘对应工具路由和意图收敛模型不能自己想调什么就调什么只能在 Harness 给定的工具范围内做选择。刹车对应终止条件和熔断任务超出轮数或金额上限立刻停止。仪表盘对应可观测性每一步状态、每次模型调用、每次工具返回值都要被记录。安全带对应权限校验和审批高危操作必须经过额外确认不能由模型独自决定。没有 Harness 的 Agent 就像只有发动机的裸车动力强劲但你不敢让客户坐上去。企业环境里坐车的可是真实业务、真实数据、真实钱。2.2 一张表说清楚 Harness 干的主要事我整理过一张对比表给团队和老板讲 Harness 和裸 Agent 的差别时非常有用能力维度裸 Agent模型 工具Harness 加持的业务智能体工具调用模型自行选择参数全靠提示词约束工具白名单 输入 Schema 校验 参数范围限制进程控制模型自己决定是否继续明确状态机 最大轮数 失败重试策略记忆管理历史全量塞进上下文窗口容易爆短期窗口 摘要压缩 长期存储按需加载权限管控提示词里写“不要越权”实际很难执行平台层做身份、角色、操作级校验可观测性靠人工翻日志慢慢捞结构化事件流 全链路回放 离线评测成本控制跑完了才知道花了多少钱每一步有 Token 预算超额自动熔断完成判定模型说“做完了”就是做完了工具执行结果校验 业务规则断言通过才算数这张表后来成了我每次做分享的保留内容。你可以看到右边这一列没有一项是“模型能力更强”但它恰好是企业在真实系统里最关心的东西。我经常跟人说Agent 决定一个任务“能不能干”Harness 决定它“能不能被信任着干”。2.3 为什么通用 Agent 直接落地企业会出问题通用 Agent 的核心理念是“什么都能聊、什么都能试”但企业真实系统最怕的就是“什么都敢干”。一个接入内部订单系统、CRM、邮件服务的通用 Agent一次幻觉操作就可能把错误数据写进核心表或者把营销邮件发给错误客户。这类事故一旦发生信任就没了项目大概率被叫停。还有一个很现实的问题通用 Agent 的打磨方向是“对话体验丝滑”它追求的是“用户问什么都能接住话”。但业务智能体的要求是另一套东西流程走得对、步骤可追溯、结果可解释、责任可落到人。这两者的评价体系完全不同。你用“对话好不好”来衡量一个退款智能体肯定衡量不出来它靠不靠谱。所以我的观点一直很明确通用 Agent 适合做个人助手、写作、编程辅助这类容错率高的场景一旦要进入企业业务流程就必须有一个自己的 Harness 把它包起来。这个 Harness 不是限制发挥而是把“无限可能性”压成“有限可控的操作空间”让模型在可接受的边界内发挥能力。边界画得越清楚业务智能体越能放开手脚做事——这听起来反直觉但实际跑下来确实是这样。3. 企业为什么需要自己的 Harness从通用 Agent 到业务智能体3.1 业务智能体不是“用了大模型的聊天机器人”先明确一个概念业务智能体到底是什么我的定义是在特定业务领域内能理解目标、拆解步骤、调用企业系统工具、按业务规则完成闭环任务、并且对结果负责的程序实体。它有三个核心特征第一有明确的职责边界。客服智能体只处理客服域的事它不需要会写代码数据分析智能体只做取数和分析它不需要会开退款。边界清楚权限才能清楚出问题的面才小。第二懂得企业自己的业务口径和规则。比如“VIP 客户的定义是什么”“退款超过多少金额需要审批”“什么情况下可以发补偿券”。这些规则写在 Harness 里由代码强制执行而不是靠模型“心情好就遵守”。第三能对结果负责。业务智能体的每一次判断、每一次工具调用、每一次最终输出都要能回溯、能解释。这需要 Harness 提供完整的事件记录和评测机制。之前看到有人在热搜里问“agent 开发到底是做什么的”其实就是做上面这些事的把大模型的能力嵌进一个带着业务规则、权限边界和可观测性的运行框架里。模型是大脑Harness 是身体业务智能体才是那个能上班干活的人。3.2 为什么非要有自己的 Harness而不是直接套现成框架很多人会问网上那么多开源的 Harness、Agent 框架DeepSeek Harness、Codex Harness、各种 agent harness直接拿来用不就行了我的答案很直接可以参考但要落地到自己的业务你大概率需要一个自己的 Harness。原因有四条数据主权和私有化。企业内部的知识库、客户数据、订单信息都属于高敏数据不能随便丢给一个公共 Agent 服务去处理。自己的 Harness 跑在自己的基础设施上才能控制数据流向走企业内部的安全审计。领域决策链路不一样。不同企业的审批链、风控规则、错误处理方式千差万别。A 公司的退款流程是“先审单、后退款、再通知”B 公司可能是“先冻结、再人工确认、最后原路退回”。通用框架不可能把这些差异都内置进去只有自己的 Harness 能把企业规则写成确定性的代码逻辑。权限体系不对等。企业有组织架构、角色、数据权限不同岗位的人能看的、能操作的东西不一样。通用 Agent 不理解“这个人是财务还是客服”它只会按提示词走。自己的 Harness 要把人的权限映射成 Agent 的操作权限做到“什么样的人触发什么样的智能体拥有什么样的工具列表”。成本与绩效可统计。业务智能体上线后公司要评估它值不值这个月处理了多少工单、成功率多少、平均耗时多少、省了多少人力。这需要 Harness 从一开始就提供可统计、可评测的框架而不是等项目跑了一个月再来补数据。顺带说一句DeepSeek Harness 这类开源方案的思路很好它把很多 Agent 运行时的常见问题比如上下文管理、工具编排、会话控制都做了工程化封装网上安装教程也多得很。但你要明白这类方案解决的是“通用 Agent 的基础运行问题”它不了解你的客户、你的审批流、你的数据权限。把它当作起点没问题当作终点就会踩坑。3.3 哪些场景最值得先做自己的 Harness结合我自己的实践有四个场景非常适合最早做企业自己的 Harness、沉淀业务智能体客服工单分诊与回复。工单分类规则相对固定历史数据充足结果好衡量非常适合作为第一个业务智能体。Harness 里只需要定义读工单、查订单、判断分类、拟回复草稿、转人工这几步。数据查询与报表生成。把“用户问数据 - 写 SQL - 查库 - 生成解读”这个流程固化下来由 Harness 控制查询权限和结果格式能极大释放数据分析师的时间。内部知识库问答加轻量操作。比如 HR 问答、IT 帮助台不仅能回答问题还能在权限允许范围内直接发起流程比如重置密码、提交请假申请。这里 Harness 的价值是“能答的答能做的做不能动的坚决不碰”。代码辅助审查与自动化修复。研发团队可以把代码仓库、静态扫描工具、CI 流程接进 Harness让智能体做初步审查、生成修复建议甚至在小范围内自动提交修复 PR。由于每一步都有记录出问题可以快速回滚。你会发现这四个场景的共同点就是高频重复、规则相对明确、结果可回放、责任可追溯。这正是 Harness 最擅长发挥价值的地方。先挑一个这样的场景做深做透比铺开一堆“万能助手”要靠谱得多。4. 从零搭一个内部 Harness 的实操思路4.1 先别写框架先把状态机画明白我的第一个建议是不要一上来就选框架、搭环境先把你希望智能体完成的任务拆成一个状态机。状态机这个词听起来拗口其实就是把你脑子里的流程“画出来”第一步干什么这一步做完能去哪个分支每个分支在什么条件下触发。拿客服工单处理举例可以定义这些状态入参校验 - 意图识别 - 信息收集 - 决策/审批 - 执行 - 反馈 - 终止。每个状态要回答四个问题输入是什么比如“信息收集”的输入是“意图已识别但缺少订单号”模型在这里要做什么调用工具直接输出还是问用户问题有哪些出口成功进入下一状态失败重试还是转人工超时和最大重试次数是多少我落地的时候直接用 Python 字典定义状态机结构类似下面这样states { intent: {next: [collect, ask], max_steps: 1}, collect: {next: [decide], max_steps: 5}, decide: {next: [execute, approval], requires_permission: True}, execute: {next: [feedback], max_retries: 2}, feedback: {next: [done]}, }这里有个关键点状态机的迁移不归模型管归代码管。模型只在每个状态内做“局部决策”比如在 collect 状态里决定“调用哪个工具来获取信息”但“这个信息够了没有、下一步是执行还是审批”由 Harness 的代码根据业务规则判断。这能有效防止模型满嘴跑火车把流程带偏。为什么要这么做因为状态迁移一旦交给模型你就失去了确定性。企业流程讲究可预测同一个输入进来不管模型今天是哪个版本、温度参数是多少流程主干都应该走得一样。状态机就是那条主干道模型只是在每个路口帮你选择走哪条匝道。4.2 工具接入用 MCP 统一出口工具是业务智能体的“手”但手多了也麻烦。早先我们接工具都是一对一写胶水代码查订单写一套查 CRM 写一套发邮件又写一套。后来工具一多就发现模型经常搞混工具参数而且每个工具的错误返回格式都不一样解析逻辑越写越乱。后来我用 MCPModel Context Protocol模型上下文协议把工具接入统一了。简单说MCP 就是给“模型和工具之间”定了一个标准接口不管背后是 REST API、数据库还是内部服务统一封装成带标准输入输出格式的工具模型侧只用记住“工具名 参数”不用关心底层实现。每个工具注册时我会写明四个东西名称和描述、输入 Schema、权限等级、超时时间。类似这样tools: - name: query_order description: 根据订单号查询订单状态 input_schema: order_id: string permission: read timeout_ms: 5000 - name: refund_order description: 发起订单退款 input_schema: order_id: string amount: number permission: high_risk requires_approval: true这样做的最大好处是Harness 可以在调用工具前做一次参数校验比如 order_id 必须是 20 位以内的字符串、amount 必须大于 0非法参数直接拦下压根不给模型尝试的机会。这比“模型自己想办法把参数拼对”稳妥太多了。另外要注意工具描述要写得像“给一个认真但缺乏业务常识的新同事看”一样。比如“query_order根据订单号查询订单状态订单号通常在用户发来的文本里是一串数字或字母组合”。描述越具体模型选错工具的概率越低。4.3 权限与安全智能体能不能做“危险操作”权限这块是我吃过亏以后才彻底重视起来的此处必须先说一句重话权限做在提示词里等于没做必须做在执行层。你写在 Prompt 里的“不要调用删除接口、不要发送邮件”在大模型眼里只是“参考建议”不是硬性约束。上下文一长、历史信息一多它真的会忘。我的做法是把工具按风险等级分成三类只读类查询订单、查库存、查用户信息。这类操作风险低模型可自主调用。普通执行类修改草稿、更新备注、生成报表。有一定影响但可回滚模型可调用但会记录全量日志。高危类退款、删数据、给外部发邮件、变更合同状态。这类操作模型只能“发起申请”Harness 会生成一个审批待办由对应角色的人在系统里确认后才能继续执行。执行高危操作前Harness 还要做硬校验。比如模型发起退款Harness 会先检查订单是否存在订单归属人是不是发起会话的用户退款金额有没有超过该角色的单笔限额用户角色是否满足退款操作白名单。任何一项不满足直接拒绝不给兜圈子。还有一个非常重要的设计工具列表按会话角色动态生成。一个普通客服人员的会话里根本就不应该出现“给用户发营销邮件”这个工具只有营销运营角色触发的智能体会话才看得到相关工具。这样不是靠模型自觉而是从源头上缩小可操作面。我自己的体会是Harness 的权限设计要遵循最小权限原则能给只读就不给读写能不暴露高危工具就不暴露。4.4 上下文与记忆设计业务智能体的上下文管理比大多数人想象的要复杂。很多人一开始就是“所有历史都塞给模型”结果上下文窗口越来越满响应越来越慢费用越来越高最后模型还开始胡言乱语。我踩过这个坑之后把记忆分成了三层短期记忆指当前任务内的对话和工具返回结果。Harness 会限制它的长度比如最多保留最近 10 轮对话和最近 5 次工具调用超过之后就做裁剪。中期记忆指当前任务的关键信息摘要。每当上下文快要塞满时Harness 会调用一次大模型把前面的对话和工具结果压缩成一段结构化摘要比如“客户反馈订单丢失已查到订单号 ORD20240001状态为已签收客户要求补发”。长期记忆指跨任务的业务知识比如“这个客户上次投诉过物流慢偏好电话沟通”“这个供应商的结算周期是 30 天”。这类记忆存在数据库里按需加载只有模型在处理相关任务时才把它注入上下文。这里很容易理解错的一点是记忆系统的目标不是“让模型记住所有东西”而是“Harness 负责决定哪些该记、哪些该忘”。模型本身不是一个可靠的存储介质你把历史交给它记忆它就会用概率去“猜”历史而不是“查”历史。正确的做法是Harness 用确定性的数据结构保存事实模型每一次需要历史信息时都通过检索去拿而不是从上下文里翻旧账。4.5 评估与回放没有评测就谈不上上线如果只让我选一个 Harness 里最重要的模块我会选评估与回放。没有这套机制你根本不知道模型换了一个版本之后业务会变成什么样。我每次跑任务都会让 Harness 输出一份完整的事件记录里面包含session_id、经过的每个状态、每次大模型调用的模型名/token 数/延迟、每次工具调用的工具名/参数/返回状态/耗时、最终输出、以及业务规则校验结果。类似这样{ session_id: sess_20241101_001, states: [intent, collect, decide, execute, feedback], llm_calls: [ {model: gpt-4o, tokens: 1200, latency_ms: 800} ], tool_calls: [ {tool: query_order, status: success, cost_ms: 120} ], final_output: 已通知用户补发, passed_rules: true }有了这套记录我就可以做两件非常重要的事。第一离线回放。每次要升级模型或改 Prompt 之前先在历史数据上回放一遍看完成率、工具调用有效率、失败率有没有变化。第二建立固定测试集。挑 200 个典型任务作为回归集每次改动都跑一遍用统一的评分标准打分防止“按下葫芦浮起瓢”。评估维度上我一般看四个指标任务完成率业务规则校验通过的比例、工具调用有效率有效调用次数除以总调用次数太低说明模型在盲目尝试、失败恢复率第一次失败后能通过重试或切换策略成功完成的比例、单任务平均成本token 数加工具调用费用。这四个指标一出来业务智能体的健康度基本一目了然。5. 踩坑实录几个值得写进周报的教训5.1 事件日志被大模型刷爆第一个让我头疼的问题是日志量失控。早期我把每次大模型调用的完整上下文都写进日志方便事后排查。结果一天下来日志存储吃掉了几个 GB。Agent 任务稍微一多日志系统直接报警。后来我调整了策略正常任务只记录结构化摘要包括输入输出的关键字段、token 数、调用的工具、耗时只有被标记为“异常”或“需要人工复核”的会话才保留全量原始记录。日志的目的是定位问题不是为了备份数据。你要保留的是够你回答“这单为什么失败”的最小信息集。5.2 工具返回格式永远比想象的脏另一个高频坑是工具返回格式“不干净”。比如我们的订单系统接口偶尔会在 JSON 前面多一段日志前缀或者在字段之间混进 markdown 的代码块标记。大模型在解析这种脏数据时经常出错然后它会选择重试继续调用工具继续解析失败白白烧掉不少 token。我的解决办法是两层第一在工具接入层加一个清洗函数把原始返回统一转成标准 schema解析失败就返回一个明确的错误码而不是把脏字符串原样丢给模型第二重试次数设上限超过之后自动转人工不允许模型无限重试。记住一句话重试是计划内的兜底不是计划外的烧钱。每次重试都是真金白银要给它设置上限。5.3 权限做在提示词里等于没做前面说了权限要放在执行层这里我讲一个真实翻车现场。当时有个智能体要处理“客户申请发票”的任务我在提示词里明确写了“不能调用删除发票接口”。结果有一次模型在上下文很长的情况下居然真的调用了删除接口虽然被接口层的权限校验拦下来了但那次把我和团队都吓出一身冷汗。后来查原因发现模型在几百行上下文之后注意力早就涣散了最初提示词里的那条禁令它根本没“记住”。这件事之后我们所有高危操作都接到了执行层接口本身做了权限校验工具列表按角色动态生成模型根本看不见它不该调用的工具。不要把安全寄托在模型的“自觉”上这句话值得写进每个 Agent 开发团队的手册里。5.4 流式输出和“完成”信号是两码事做业务智能体的时候产品经理经常跑来问用户那边已经看到模型输出一大段话了为什么后台还显示任务“执行中”这里的问题出在界面上流式输出的文字结束和整个任务的完成是两个完全不同的概念。模型输出一段话可能只是表示“我把分析和建议说完了”但后续可能还有工具调用、审批流程、外部系统通知要执行。我在 Harness 里单独定义了三种终态正常完成工具执行结果校验通过、需确认进入人工审批、异常终止超时或重试失败。界面上的“完成”信号只由 Harness 判定不参考模型输出里有没有出现“好的已帮您完成”之类的话。模型说的是“说完了”Harness 管的是“做完了”两件事必须分开对待。5.5 回放评估里最难的不是对错是评分标准最后再讲一个容易被低估的难点评估业务智能体时“评分标准”比“评估工具”重要得多。我最初让一个 GPT 模型给另一个模型的答案打分打了几百条之后发现同一个答案今天打 8 分、明天打 6 分波动非常大。GPT 打分受温度参数、上下文长度、甚至问题顺序的影响都很大。后来我把评分拆细了格式是否合规、关键字段是否完整、业务规则是否通过、成本是否在预算内。能写成断言的用断言比如“退款金额必须等于申请金额”“邮件正文不能为空”“严禁出现‘不好意思我无法处理’之外的拒绝话术”。只有少量边界 case 才交给模型评分加人工抽审。评分标准越接近“代码逻辑”评估结果越稳定业务线才敢真的信你。5.6 常见问题速查表现象可能原因排查办法Agent 反复重试同一个工具工具返回格式解析失败或参数生成有误查看工具调用记录里的 status 和 error 字段检查清洗函数上下文一长就出现幻觉工具名历史信息过载模型注意力涣散压缩上下文按角色动态收敛工具列表任务显示“完成”但结果错误终态判定只看了模型输出增加业务规则校验完成信号由 Harness 判定成本突然飙升多次失败重试 超长历史记录设置每步 token 预算、最大轮数、重试上限模型不遵守提示词里的权限约束提示词不是硬性约束把权限下沉到工具注册层和接口层写在最后先有边界再谈智能从“通用 Agent”到“业务智能体”我的核心体会是真正难的不是模型能力而是围绕模型搭建的那套运行机制。你需要的不是一个更聪明的模型而是一个知道什么时候该让模型发挥、什么时候该用代码硬约束的 Harness。我踩过的最多坑全部是“约束不足”造成的问题几乎没有一次是“模型能力不够”带来的。如果团队准备开始做这件事我的建议是先挑一个高频、规则明确的场景做一个最小的 Harness——一个状态机、三个工具、一条审批规则、一套回放日志就够了。先让智能体在窄边界里把事做对、做稳、可评估再一步步扩大它的自由度和工具范围。边界画得越清楚之后的扩展才越有底气。这个顺序反了大概率会像我早期一样被各种失控现场折腾到怀疑人生。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进