ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Agent三层架构实战:Harness、Loop与Graph生产级落地指南

Agent三层架构实战:Harness、Loop与Graph生产级落地指南 做了快三年 Agent 工程我最大的体会是现在圈里讨论 Agent大部分还停留在“提示词写多好、工具怎么拼”的层面真正生产级的东西没人讲。你随便搜一下“Agent 框架”出来的教程十个有九个是单循环 demo——模型调一次工具、看一次结果、再调一次跑了三五个来回就完事。这种项目在本地跑没问题一旦丢到线上用户并发一上来、任务复杂度一上来立刻就是事故现场工具乱调用、上下文爆掉、Agent 陷入死循环烧 token最要命的是出了问题你连日志都翻不明白。后来我慢慢理清楚了一件事Agent 工程化本质上就是一个三层架构问题——Harness管运行环境Loop管核心循环Graph管任务编排。这三层各司其职才是把 Agent 从“能跑的 demo”变成“能扛生产的系统”的关键。这篇文章我就把这三层掰开揉碎讲清楚每一层到底在解决什么问题、关键配置怎么落以及我在真实生产环境中踩过的一系列坑。不管你是刚开始做 Agent 开发还是已经在线上跑着 Agent 项目但经常被幺蛾子困扰这篇都应该能给你一些直接的参考。1. 三层架构的整体拆解Harness、Loop、Graph 分别解决什么问题1.1 为什么必须是“三层”我见过太多团队在做 Agent 时第一步就是急着写 prompt、接模型、调工具恨不得一天之内把 demo 跑出来。这种热情我能理解但它恰恰是整个工程失败的开端。因为 Agent 和传统软件有个本质区别传统代码的逻辑是确定的if 就是 ifelse 就是 else但 Agent 的逻辑是不确定的同一个 prompt 配上同一个上下文模型这次可能走分支 A下次可能走分支 B。这个不确定性一旦叠加到真实业务里单层结构根本兜不住。这里需要先把视角拉高一点。一个真实业务里的 Agent比如客服场景它要面对的是多轮对话、多系统查询、多个工具来回调用还要处理用户情绪的波动和信息的残缺。如果所有逻辑都压在一个循环里模型的能力边界就成了系统的能力边界——模型记不住那么多状态工具调用多了会选错权限管控更是无从谈起。Harness、Loop、Graph 这三层拆开来看就是分别解决这三座大山的Harness解决的是“环境”问题。模型怎么接入、工具怎么注册、权限怎么设、上下文怎么管理、日志怎么留这些都属于 Harness 的范畴。你可以把它理解成 Agent 的厂房和安全生产制度。Loop解决的是“心跳”问题。Agent 不是一个一次性的计算函数它的本质是一个循环看情况、想方案、做动作、看结果再继续。这个循环怎么转、什么时候停、怎么防止它转疯掉是 Loop 层的事。Graph解决的是“导航”问题。复杂任务不能靠一条直线走到底得有分支、有并行、有兜底、有回退。这些结构化控制逻辑就是 Graph 层的职责。我在实际项目里最深的感受是这三层缺一不可但绝大多数翻车事故要么是“只有 Loop 没有 Graph”任务一复杂就全乱套要么是“Harness 边界没划清楚”工具的权限和上下文管理一团浆糊。所以先把这三层的概念吃透后面写代码才有方向。1.2 三层架构的职责边界速览先给一张表把每层的核心职责、类比和不做它的后果列清楚后面每一层我们再详细拆。层级核心职责一句话类比不考虑它的后果Harness环境与安全模型接入、工具注册、权限沙箱、上下文管理、日志回放工厂厂房 安全生产制度工具乱调用、上下文爆炸、出问题无法复盘Loop核心循环感知-规划-行动-观察循环控制与终止判断流水线上的工人作业循环死循环烧 token、重复操作、任务发散Graph任务编排把复杂任务拆成有向图控制分支、并行、回退车间里的传送带与调度中控步骤间无法衔接、状态传递混乱、并行任务做不了这个分层也对应着三种不同的工程能力要求Harness 偏基础设施和安全Loop 偏算法和控制论Graph 偏系统架构和状态管理。一个人很难三层都精通但这三层的概念必须都懂否则你连 Agent 出问题该找哪个层都不知道。1.3 分层的一个关键收益可测试、可回退、可观测分层带来的最大好处不是代码好看了而是工程上可追责了。单循环的 Agent 就像一个只有一根弦的吉他弦断了整首曲子就没法弹你还不知道是哪根弦的问题。三层架构就不一样Loop 层出问题比如死循环、不收敛你可以在不碰 Harness 和 Graph 的情况下单独修循环策略Graph 层出问题比如某条分支走错了、状态没传下去你可以在不动循环逻辑的情况下单独调图和状态。更重要的是可回退。生产环境里模型会更新、prompt 会改动、工具接口会升级任何一个环节出问题都可能导致 Agent 行为漂移。有了清晰的层级边界你可以做分层回退模型升级出问题退回上一版模型工具变更出问题单独摘掉那个工具的路由循环策略改坏了恢复上一版 Loop 参数。这种从容是单层结构永远给不了的。2. Harness 层Agent 的躯干与安全边界2.1 Harness 和 Agent 不是一回事先说一个被问烂但每次都有人搞混的问题Harness 到底是不是 Agent不是。Agent 是那个做决策的实体它负责想“我下一步该做什么”Harness 是承载和约束它的系统它负责让 Agent 的每一步动作都能安全、可控、可记录地完成。Agent 是驾驶员Harness 是安全带、仪表盘、行车记录仪和交通规则的总和。驾驶员技术再好没有安全带和记录仪上路也是裸奔。同样Agent 的推理能力再强没有 Harness 约束在生产环境里就是一颗随时会爆炸的不定时炸弹。这个区分很重要因为它直接决定了你在项目里怎么分配精力。很多人把精力全砸在 prompt 调优上觉得模型推理强了就万事大吉结果线上工具被误调用、敏感接口没人拦、上下文越积越长最后模型直接失忆这些问题没有一个是增强推理能解决的全是 Harness 的活。2.2 Harness 的核心组成与实际配置那一个合格的 Harness 到底要装哪些东西我按生产优先级排个序。第一模型接入层。这是最基础的部分但现在不少团队用的是多模型路由。什么意思就是生产环境不能只绑一家模型得有一个抽象层能根据任务类型、成本、延迟动态选择模型。日常简单问答走便宜快的模型复杂推理走强模型出了问题还能随时切换备用模型。这里面的重点是一个统一的调用接口让上层 Loop 不关心底下到底是 DeepSeek 还是别的开源模型。第二工具注册与白名单机制。Agent 要干活就得调工具但工具不能是“拿来主义”。每个工具在接入前必须有明确的 schema 定义入参是什么、出参是什么、调用权限是什么。我更建议做一层显式的白名单而不是靠模型自觉。模型说“我要调删除接口”Harness 直接拦下来问这个接口的调用权限你有没有没有就拒绝。不要觉得这碍事我见过太多因为没做工具白名单Agent 在生产环境里误调了写接口、把数据搞脏的惨案。第三上下文管理。这是 Harness 层最容易被人忽略但最影响体验的部分。模型上下文窗口是有限的而用户的对话会越来越长工具返回结果也经常一大坨。如果没有上下文管理你会有两个直接后果一是 token 消耗成倍增长成本失控二是上下文被无关信息塞满模型注意力稀释回答质量直线下降。上下文管理通常有几种策略截断把最早的对话丢掉、摘要把历史对话压缩成摘要、关键信息提取只保留工具返回里的关键字段。这几个策略需要在 Harness 层做成可配置的而不是在每个 prompt 里手动拼。我见过一个团队用了一个很巧妙的分层方案短期记忆用原始对话长期记忆用摘要库工具结果只在当轮保留跨轮只保留提炼后的状态。第四权限与沙箱。如果你的 Agent 能联网、能执行代码、能写文件那权限就是生死线。代码执行要放到沙箱文件系统要限定目录网络请求要走白名单域名。这块没有捷径就是严格。第五日志与回放。生产环境里 Agent 出了错最怕的是“为什么错”完全不可追溯。所以 Harness 层必须把模型输入输出、工具调用入参出参、每一步耗时和 token 消耗全部落日志。最好能做到“回放”把某一次会话的完整轨迹重现一遍方便你和团队复盘到底哪一步出了问题。第六技能和插件管理。这几年社区里很流行把特定任务的提示词和工作流打包成 Skill 或插件比如 DeepSeek Harness 生态里的各种实用插件、Claude 的 Agent Skills 等。这个思路我认可但工程上要注意技能包的加载、版本管理和内网部署要做成统一的机制。社区里有人问“怎么把 DeepSeek Harness 附带的 skill 部署到内网服务器”答案其实就一句话把技能描述成标准 JSON 或 YAML 清单放进 Harness 的配置中心用统一的注册接口加载而不是散落在各个业务代码里。2.3 开源 Harness 方案的实践参考现在市面上的 Harness 实现不少有偏重模型路由的有偏重工具调用的也有把安全做得很重的。我个人推荐你不管选什么方案都先看三件事第一它怎么管理工具权限第二它怎么处理上下文溢出第三它怎么记录完整链路日志。这三件事做不好其他功能再花哨都是白搭。社区里 DeepSeek Harness 是不少人拿来做二次开发的起点因为它的插件机制比较灵活技能包的注册和加载做得很清爽。用它的时候有几个经验插件尽量少装只装真正用得上的每多一个插件就多一层上下文和误调用的风险技能包的 prompt 要内聚不要写得冗长否则会占用模型宝贵的注意力。另外提一句现在也有团队用 Rust 写 Agent 的 Harness 层核心理由就两个一是内存安全二是并发性能。如果你的 Agent 要面对高并发请求Rust 确实是值得考虑的方向但代价是开发效率低一些。我的建议是团队里没有熟 Rust 的人别硬上先用成熟的 Python 方案跑通业务性能瓶颈出现了再谈重构。3. Loop 层Agent 的核心循环机制3.1 Agent 循环的完整链路如果说 Harness 是 Agent 的身体那 Loop 就是 Agent 的心脏。几乎所有的 Agent 框架核心都是同一个模式ReAct也就是 推理Reason 行动Act 的交替循环。这个循环的完整链路是这样的。第一步Agent 接收外部输入可能是用户的话也可能是上游系统传来的任务第二步模型进行推理决定下一步要做什么第三步如果需要调用工具就发工具请求拿到工具返回的结果第四步模型根据工具结果再推理看任务是否完成如果没完成就回到第二步继续直到满足终止条件。用伪码写出来就是def agent_loop(task, max_rounds10): state initialize_state(task) for round in range(max_rounds): thought model_think(state) # 感知 规划 if thought.finished: # 终止判断 return thought.answer result harness_call_tool(thought) # 行动经 Harness state observe(result) # 观察并更新状态 return state.fallback_answer # 超轮数兜底这个循环看起来简单但坑全在细节里。最典型的坑就是“模型以为自己完事了其实没完事”。模型生成一句“好的我已经帮你完成了退换货申请”但实际上工具根本没有被调用过。这种情况在评估的时候不会暴露因为评估集里你预设了标准答案一上生产就原形毕露用户的工单根本没提交成功。3.2 循环控制别让 Agent 停不下来Loop 层最核心的工程问题就一个字停。什么时候该停下来什么时候必须强行停这两个问题想不清楚Agent 就是个 token 黑洞。我自己的实践中会从四个维度去控制循环最大轮数。所有 Agent 循环都必须有硬性上限。不要天真地以为模型会自己收敛模型有时会就一个简单的动作反复确认来回七八轮不推进。我的默认值是工具类任务 10 轮以内如果超过 10 轮还没完成说明任务本身有问题或者工具返回有问题这时候不如直接转人工。终止条件。除了轮数上限还要有语义层面的终止判断。模型要能显式输出一个“完成”信号而不是只在回答里说“done”。这个信号要结构化比如在输出格式里强制要求 final_answer 字段没有这个字段就认为没完成继续循环。Token 预算。每一轮循环都会消耗 token而且工具返回有时候特别大。我建议在 Harness 里设一个全局 token 预算整个会话累计消耗超过预算就强制触发摘要压缩或终止。这个指标一定要监控因为成本失控是生产事故里最常见的。自反馈与反思节点。现在很多框架会在主循环里加一个“反思”步骤让模型在行动之后先自我评估一次结果质量再决定继续还是收尾。这能明显提升任务完成率代价是每轮多一次模型调用。我的建议是简单任务不要用反思只有复杂任务才启用否则延迟和成本都扛不住。3.3 循环层的调优实战在真实项目里Loop 层调优是花时间最多的部分。我分享三个高频问题的调试经验。第一个问题死循环。模型反复调用同一个工具每次返回都一样但它就是不终止。这种情况通常是终止条件写得太宽或者模型自己的状态里没有“这个动作已经做过了”的标记。解决办法是在 state 里维护一个已执行工具摘要在每次推理前注入进去明确告诉模型“你已经调用过查询接口了结果是 X请基于这个结果做下一步判断”。这一招在大多数场景都有效。第二个问题任务发散。模型做着做着跑偏了本来在查订单突然开始介绍公司的退货政策。这种情况的本质是原始任务目标在长循环中被稀释了。解决办法是把原始目标和已完成步骤摘要始终固化在上下文的前置位置你可以理解成给模型立一个“任务锚点”不管循环到第几轮锚点都清晰可见。第三个问题重复劳动。模型反复调用同一个查询接口拿到的数据一样但还是一次次去查。这通常是中间状态管理没做好。工具返回结果不应该只是被丢进上下文吃 token而应该被结构化提取并储存在 state 里。后续模型如果要同一个数据直接从 state 里取而不是再调一次工具。4. Graph 层从单循环到结构化编排4.1 什么时候必须上 Graph并不是所有 Agent 都需要 Graph。一个查询天气、写段文案的简单 Agent单 Loop 就足够了硬上 Graph 反而是过度设计。但以下几种情况你不用 Graph 一定会出事。第一任务是多步骤的且步骤之间有依赖关系。比如“查订单状态 → 判断是否满足退款条件 → 执行退款 → 生成工单 → 通知用户”每一步依赖上一步的结果不能在同一个朴素的循环里碰运气。第二任务需要分支判断。比如售后流程用户说要退款你得先判断是未发货还是已发货不同情况走不同分支。这种逻辑如果用自然语言塞给模型“如果...就...否则...”模型在多步执行后很容易漏判。第三任务需要人工介入。审批环节、高风险操作、用户确认这些不能全部交给模型自动决策需要在流程图里设置一个“human-in-the-loop”节点流程走到这里暂停等人确认再继续。第四任务需要并行处理。比如你要让 Agent 同时去三个系统拉数据再汇总单 Loop 只能一个一个串行执行效率太差而且中途状态容易乱。4.2 Graph 的节点类型与状态管理Graph 层的本质是把 Loop 从“一条路走到黑”变成“一张图任意走”。现在成熟方案里比如 LangGraph核心抽象就两个节点和边。节点是在干什么边是下一步往哪走。节点的类型我按用途分一下LLM 节点让模型做一次推理可以包含或不包含工具调用。工具节点执行一个具体的工具调用入参来自上游状态出参写回状态。条件节点根据当前状态走向不同分支。这类节点我建议用代码写判断而不是让模型自己决定走哪条路——确定性逻辑就该交给代码别交给概率。并行节点把多个互不依赖的子任务同时派发出去全部完成后再聚合。子图节点把一个完整的子任务封装成子图在主图中作为一个节点引用。子图内部可以再有自己的 Loop 和分支实现任意层级的嵌套。这几种节点的存在意味着你要把 Agent 的编排从“prompt 里告诉模型怎么做”升级成“代码里确定流程prompt 只负责每个节点内的推理”。这是一次重要的思维转变流程是代码的推理是模型的各管各的别混。状态管理是 Graph 层最容易踩坑的地方。每个节点都要往共享状态里写数据、读数据如果状态结构设计不好下游节点拿不到上游的数据整个流程就断了。我的建议是定义好全局 State 的数据结构每个字段标明写入者和读取者必要时给字段加校验。这会明显提高系统的可靠性和可调试性。举一个真实的坑我们曾经在一个多 Agent 协作的图里让一个 Agent 把客户信息写进 State 的 guest_info 字段另一个 Agent 却去读 customer 字段结果流程跑了一半发现下游拿到的永远是空。当时排查了半天最后发现是字段命名不统一。这种问题在单 Loop 里几乎不会出现但一上 Graph 就是家常便饭。所以 State 的 schema 要当成接口契约来管理变更要走评审不要随手加字段。4.3 条件分支与动态子图的落地实践Graph 里最灵活也最难控制的是动态分支。我的经验是能用静态图解决的问题就不上动态图。静态图在开发时就把所有可能的路径画好了每条边上的条件都是确定的最大的优点是可测试、可预测。动态图虽然看起来智能但路径不可预知意味着你没法穷举测试场景。那什么时候得上动态图你的 Agent 要面对的任务类型是开放式的比如一个通用的代码生成 Agent它可能要写文件、要跑测试、要装依赖、要修改代码每一步的下一步完全取决于上一步的结果。这种场景静态图画不出来必须动态扩展。但在生产落地时我会给动态图加两层保险一层是节点类型白名单只允许创建预定义的节点类型避免失控另一层是最大节点数限制超过就终止并转人工。这两层保险我建议所有用动态图的团队都加上。另外提一个容易被忽略的点循环在 Graph 里怎么表达。很多人在 Graph 里遇到“某一步失败需要重试两三次”这种需求第一反应是在循环里套循环结果状态一乱重试完都不知道回到哪个节点。我的做法是把重试逻辑封装成一个子图子图内部是一个带最大次数的 Loop外部看起来就只是一个普通的子图节点。这样主流程的边和状态都不会被循环逻辑污染调试起来也清爽得多。5. 三层架构的生产化落地流程5.1 从需求到三层架构的每一步理解了三层架构之后真正的挑战是怎么把它落到自己的项目里。我建议你按下面的顺序走每一步都有明确产出不要跳步。第一步需求分析。先把任务类型拆清楚这个 Agent 要做几类事每类事的步骤是确定的还是开放式的需要调用哪些工具哪些操作需要人工审批这一步的产出是一份“任务类型清单 边界说明”。第二步确定复杂度级别。根据需求分析的结果判定是纯单 Loop 就能解决还是要上 Graph。判断标准很简单——任务步骤是否超过 5 步、是否有不确定分支、是否有并行需求三个里面中两个就上 Graph。第三步设计 Harness。明确模型接入方式单模型还是多模型路由、工具白名单、权限策略、上下文管理方案、日志规范。这一步的产出是 Harness 配置清单。第四步实现 Loop。先把最核心的循环跑通配上最大轮数、终止条件、token 预算。不要一开始就堆技能和反思先把主干跑通再优化。第五步搭建 Graph。从上往下画主流程识别分支和并行节点定义全局 State 的 schema注意字段命名统一。第六步评估与灰度。准备一个覆盖主要任务类型的评估集跑完看完成率和质量达到预期再灰度上线。5.2 关键参数和生产配置参考这里我给一套我在生产里用得比较稳的参数模板你可以根据自己的场景调整但方向不会错。配置项建议值说明最大循环轮数8-12简单任务 8复杂任务 12超过转人工全局 Token 预算2 万-5 万 token/会话超过触发摘要压缩或强制终止工具超时10 秒工具 10 秒无响应直接报错回退反思节点启用条件任务步骤 5 或首次质量分 0.7简单任务不启用保证延迟可控上下文历史保留轮数最近 6 轮 摘要原始信息太久远就摘要化人工审批触发条件关键操作白名单外、金额超阈值写操作必须走审批这些数值不是拍脑袋定的。最大循环轮数定在 8-12是我统计过线上会话的实际轮数分布绝大多数正常任务在 6 轮内结束超过 8 轮的要么是任务本身有问题要么是模型在绕圈再给它 100 轮也是浪费。全局 token 预算同理正常业务会话很少超过 3 万 token超出基本可以断定进入了死循环或工具结果失控。5.3 可观测性三层都要有“仪表盘”生产环境里最烦的不是出 bug而是出了 bug 你找不到证据。所以我在每一层都强制做可观测性指标缺一个都不能放线上。Harness 层要统计模型调用延迟、token 消耗、工具调用成功率、上下文裁剪次数、沙箱拦截次数。这些指标能直接告诉你系统最脆弱的环节在哪。Loop 层要统计平均循环轮数、死循环发生率、终止方式分布正常完成 / 超轮数终止 / token 超限终止、每轮平均花费。如果平均轮数突然从 5 涨到 8说明最近有什么改动影响了模型的收敛性。Graph 层要统计节点执行次数、分支走向分布、并行节点耗时、失败回退率。这些指标能让你看到真实业务里用户任务到底怎么流动的哪些分支很少走、哪些节点总出问题决策起来就有依据了。我强烈建议从项目第一天就引入链路追踪每个节点执行都生成一个 trace ID把这一个节点相关的模型输入输出、工具请求、状态变更全部串起来。再配合日志回放功能线上出问题时你能像放电影一样把整个会话回放一遍。这个投入产出比是所有基础设施里最高的。6. 常见问题排查与避坑实录6.1 高频故障速查表把这些年在三层架构里踩过的典型问题整理成一个速查表遇到类似的情况可以先对着查。现象可能的层排查思路Agent 反复调用同一个工具不退出Loop检查 state 是否记录了已执行动作检查终止条件是否被触发流程走到中间发现下游拿到的数据是空Graph检查 State 字段命名是否统一、上游节点是否真的写入了该字段模型上下文越来越乱回答开始失忆Harness检查上下文管理策略是否做了截断/摘要是否残留了太多工具返回Agent 误调用了不该调用的工具Harness检查工具白名单和权限边界确认模型是否有权限发起该调用同一个任务不同次运行结果差异很大Graph检查是否存在动态分支是否该把确定性逻辑从模型判断改为代码判断整个会话 token 消耗异常大增Loop先看轮数是否增加再看工具返回体积确认是否缺少状态存储或摘要改了一版 prompt 后线上行为异常Harness用日志回放对比改动前后的完整轨迹定位行为漂移点并发高时系统响应变慢甚至崩溃Harness检查沙箱资源隔离和模型并发调度确认是否存在资源争抢还有一个很典型的报错值得单独提一下“self referencing loop detected”。这个错误本质上是状态序列化时出现了循环引用——某个状态对象里有一处字段指向了自身日志系统序列化定位到它时就卡死了。排查思路很简单在把状态写入日志之前先做一步深拷贝或只保留可序列化字段不要直接把内存里的复杂对象丢给日志组件。6.2 避坑经验与上手建议最后聊几个项目里的心得体会这些不是文档会写的全是踩出来的。第一不要让模型决定所有流程。这是我和很多团队反复强调的一点。能写在代码里的确定性逻辑就写在代码里模型只负责真正需要语义理解的推理。否则你把一个简单的“if 金额大于 1000 走审批”交给模型判断它有可能在特定上下文里给你判反了。第二评估集一定要早建。我见过太多团队模型上线全靠“感觉还行”这是最危险的事。你至少要做到每次改 prompt、改循环策略、改 Graph 结构都在固定评估集上跑一遍对比完成率、质量分、平均轮数、token 消耗。没有这个对比你根本不知道你的改动是优化还是回退。第三插件和技能不要贪多。每次往 Harness 里加一个新技能都意味着模型的上下文多一份负担、工具选择多一份干扰。我习惯的做法是一个 Agent 的技能数量控制在 5 个以内多余的下线或放进按需加载的二级菜单。第四人工兜底永远要有。不管你的 Agent 做得多么智能都必须预留一个“转人工”出口。轮数超限转人工、置信度太低转人工、关键操作转人工。这不是对 Agent 能力的否定而是对生产环境负责。上线前和业务团队约定好转人工的触发场景和对接流程比出事故后再补救强一百倍。第五Harnass 的安全红线一票否决。工具权限、数据隔离、沙箱策略这些方面宁可过度约束绝不图省事放开。模型调用代码执行工具这种事一句话都嫌多——直接默认不允许真有需求走特殊审批通道。根据我个人这几年的体会三层架构与其说是一个技术规范不如说是一个思维框架。它让你在设计 Agent 的时候不自觉地先问三个问题它跑在什么环境里、它怎么循环、它怎么编排。这三个问题想清楚了Agent 就不会是一个黑盒而是一个条理分明的系统。最后再分享一个小窍门如果你刚开始做 Agent先别急着上 Graph 和动态分支。拿一个最简单但真实的任务把 Harness 和 Loop 这两层跑扎实再逐步把 Graph 引进来。很多人一上来就搞一个巨大复杂的图结果每个节点都是草台班子线上运行一塌糊涂。从简单开始每一层做到扎实再慢慢往上加复杂度这才是 Agent 工程最稳的路子。
返回列表