恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Harness工程实战:构建生产级Agent循环与上下文管理

  • 首页
  • 资讯中心
  • /
  • Harness工程实战:构建生产级Agent循环与上下文管理

相关资讯

Harness工程实战:从线上事故到长时运行Agent的稳定性设计 2026/10/15 22:31:52
Java Swing连连看源码解析:二维数组与路径搜索算法实战 2026/10/15 22:31:52
SAP STO自动化配置全链路实战指南 2026/10/15 22:31:52

最新资讯

AI时代个人量化交易:从想法到实盘的全流程实战指南
Flutter ThemeData深度解析:从视觉宪法到企业级主题工程化
JMeter Beanshell脚本实战:动态参数、Token传递与业务断言
用户研究ROI量化:从成本中心到价值证明
Spark多源社交媒体情感分析系统实战指南
LBP纹理特征原理与Matlab实战:环形采样、旋转不变性与均匀模式

今日推荐

AI视频生成的时间一致性难题与时空建模演进
基于bbox的PDF文档解析:多栏重排与水印过滤实战
探矿数据进RAG前的清洗全攻略:TXT、Word、PDF、网页四类文档处理实践

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Harness工程实战:构建生产级Agent循环与上下文管理

发布时间:2026/10/15 22:31:52
Harness工程实战:构建生产级Agent循环与上下文管理 1. 从一次线上事故说起为什么我们需要认真对待 Harness 工程去年年底我参与的一个自动化代码修复项目上线第三周就翻车了。现象很典型Agent 在本地跑得好好的一放到长时运行环境里跑到第 40 多轮就开始胡言乱语明明前面已经修好的文件被它反复改回去日志里还出现了大量重复的工具调用。当时团队第一反应是模型不行换了更大的模型结果只是把崩溃点从第 40 轮推迟到了第 70 轮。真正的问题根本不在模型而在于我们那套“裸奔”的 Agent 循环——没有上下文管理、没有沙箱隔离、没有验证环节、没有长时运行的恢复机制。这件事之后我才真正意识到Harness 工程这个词虽然听起来有点抽象但它描述的恰恰是决定一个 Agent 系统能不能从 Demo 走向生产的那层“外壳”。所谓 Harness直译是“挽具、约束装置”在 Agent 语境里它指的是包裹在模型之外的一整套运行时基础设施循环控制、上下文组织、工具调用、沙箱执行、结果验证、状态持久化、错误恢复。模型是马Harness 是挽具和缰绳马再强壮挽具不行车照样翻。这篇文章我想把 Harness 工程拆成几个能落地的模块来讲Agent 循环怎么设计才不失控、上下文怎么组织才不爆、沙箱怎么隔离才安全、验证怎么做才可信、长时运行怎么撑住不崩。适合正在做 Agent 应用、自动化任务、代码生成、流程编排的开发者参考也适合刚接触这块、想知道“为什么我的 Agent 跑不长”的朋友。我会尽量把每个决策背后的“为什么”讲清楚而不是只丢一堆配置。2. Agent 循环从 while(true) 到可控状态机2.1 最朴素的循环长什么样为什么它一定会出问题几乎所有 Agent 教程的第一段代码都是这样的把用户输入塞进消息列表调用模型如果模型返回工具调用就执行工具、把结果追加回消息列表然后再次调用模型直到模型不再调用工具为止。用伪代码写出来大概是这样messages [{role: user, content: task}] while True: response model.chat(messages) messages.append(response) if not response.tool_calls: break for call in response.tool_calls: result execute(call) messages.append({role: tool, content: result})这段代码能跑但它埋了至少四个雷。第一没有终止条件兜底模型如果陷入“调用工具—看到结果—再调用同一个工具”的死循环这个 while 会一直转下去烧钱烧到你自己发现。第二没有轮次预算长任务里模型可能在第 200 轮才收敛但你的上下文早就爆了。第三没有状态快照进程一挂前面所有轮次的工作全丢。第四没有错误分类工具报错和模型逻辑错误混在一起你根本不知道该重试还是该终止。我踩过的坑是早期版本里工具执行抛异常我直接把异常字符串塞回消息列表结果模型看到“ConnectionError”之后开始疯狂重试同一个调用因为它以为只是临时故障。实际上那次是参数格式永久性错误重试一万次也没用。这就是没有错误分类的代价。2.2 一个可控循环应该具备的五个要素把上面那些雷一个个拆掉我总结出一个生产级 Agent 循环至少要包含五个要素缺一个都会在长时运行里暴露出来。轮次预算与时间预算。给循环设一个硬上限比如最多 50 轮、最多 10 分钟。超了就强制进入收尾流程让模型基于当前已有信息给出阶段性结论而不是直接掐断。这个预算不是拍脑袋定的要根据任务复杂度估简单问答 3 到 5 轮代码修复类 20 到 40 轮复杂调研类可能上百轮那就得配合上下文压缩一起用。状态机而非裸循环。把循环的每个阶段显式建模成状态PLANNING规划、ACTING执行工具、OBSERVING处理结果、VERIFYING验证、DONE结束、FAILED失败。状态之间的转移有明确条件这样你才能在日志里一眼看出 Agent 卡在哪个阶段。我现在的做法是每次状态转移都打一条结构化日志包含轮次、状态、耗时、token 消耗排查问题时直接按状态过滤。终止条件的多重判定。不能只靠“模型不再调用工具”这一个条件。要同时检查模型是否显式声明完成、是否达到轮次上限、是否连续 N 轮没有产生有效进展、是否触发了不可恢复错误。我一般设“连续 3 轮工具调用结果高度相似”作为停滞信号触发后强制让模型总结当前进展。错误分类与重试策略。把工具错误分成三类瞬时错误网络抖动、限流可以指数退避重试参数错误格式不对、字段缺失不重试直接把错误信息反馈给模型让它修正参数致命错误权限不足、资源不存在直接终止并上报。这个分类逻辑要写在 Harness 层不能指望模型自己判断。检查点与恢复。每完成一个状态转移就把当前消息列表、已执行工具记录、中间产物落盘。进程重启后能从最近检查点恢复而不是从头再来。这一点在长时运行里是刚需后面第 5 节会展开讲。2.3 循环控制里的参数怎么定一个可参考的计算过程很多人问我轮次预算到底设多少。我的经验公式是轮次预算 ≈ 任务预估步骤数 × 2.5。乘 2.5 是因为模型经常需要“试探—修正”的额外轮次。比如一个代码修复任务我预估需要读 3 个文件、改 2 个文件、跑 1 次测试大概 6 个步骤那轮次预算设 15 轮比较稳妥。时间预算则要看单轮平均耗时。如果单轮平均 8 秒含模型推理和工具执行15 轮就是 120 秒那时间预算设 180 秒留出缓冲。这两个预算要联动任何一个先到都触发收尾。实测下来把轮次和时间双预算都设上之后失控烧钱的情况基本绝迹了。注意轮次预算不要设得太紧。我见过有人为了省钱把预算压到刚好够用结果模型每次都在收尾阶段被迫中断产出质量断崖式下跌。宁可多给 30% 的余量让模型有空间自我修正。3. 上下文工程让 Agent 在有限窗口里记住该记的3.1 上下文为什么会爆爆了之后会发生什么Agent 循环每跑一轮消息列表就长一截模型的思考、工具调用的参数、工具返回的结果全都堆在里面。一个读文件的工具调用返回内容可能就有几千 token。跑个二三十轮轻松突破十万 token。这时候要么超出模型窗口直接报错要么触发截断而截断是最危险的——它可能把最早的任务描述截掉模型瞬间“失忆”开始做一些莫名其妙的事。我遇到过一次特别典型的情况Agent 在修一个 bug前面 30 轮都在正常推进第 31 轮突然开始重新读最开始那个文件然后把已经改好的代码又改了回去。查日志发现上下文超限后系统自动截断了最前面的消息而任务描述和“已经完成哪些修改”的记录正好在被截断的部分。模型失去了任务锚点只能根据最近的几条消息瞎猜。3.2 三层上下文结构锚点层、工作层、归档层解决这个问题的核心思路是不是所有信息都值得留在窗口里但关键信息一个都不能丢。我把上下文分成三层来管理。锚点层永远保留不参与压缩。内容包括原始任务描述、硬性约束比如“不要修改测试文件”、当前进度摘要。这一层通常控制在 500 token 以内是整个 Agent 的“北极星”。工作层是最近若干轮的完整消息保留原始细节。一般保留最近 5 到 8 轮因为模型对近期信息的依赖最强工具返回的具体内容、报错信息都在这里。归档层是更早的历史经过压缩后以摘要形式存在。压缩不是简单截断而是让模型自己总结“前面 20 轮做了什么、产出了什么、遇到了什么问题”。这个摘要会追加到锚点层后面。具体实现上我一般这样组织消息列表def build_context(anchor, archive_summary, recent_messages, budget): messages [] messages.append({role: system, content: anchor}) if archive_summary: messages.append({role: system, content: f历史进展摘要{archive_summary}}) messages.extend(recent_messages) # 如果还是超预算从 recent_messages 头部开始丢但锚点层不动 while count_tokens(messages) budget and len(recent_messages) 2: recent_messages.pop(0) messages rebuild(...) return messages3.3 压缩时机与压缩策略的选择压缩不是每轮都做那样太浪费。我的做法是设一个水位线比如窗口的 70%。超过 70% 才触发压缩把最老的那批消息比如前 10 轮拿出来做摘要。这样既控制了频率又留出了缓冲空间。压缩策略有两种增量摘要和全量重摘要。增量摘要是每次只总结新溢出的那部分追加到已有摘要后面成本低但容易累积误差全量重摘要是把锚点层加所有历史重新总结一遍质量高但贵。我的选择是日常用增量每压缩 5 次做一次全量重摘要来“纠偏”。实测下来这个组合在成本和准确性之间平衡得不错。实操心得压缩摘要的 prompt 里一定要明确要求“保留具体的文件路径、函数名、变量名和已做的修改”否则模型总结时会把这些关键细节抽象掉导致后续轮次找不到目标。我早期就是吃了这个亏摘要写得像周报全是“完成了部分修改”一点用没有。3.4 工具结果的裁剪别把整个文件塞进上下文上下文爆炸的一大元凶是工具返回的原始数据。读一个文件返回 5000 行跑一次测试返回 2000 行日志这些全塞进去几轮就满了。我的处理原则是工具返回结果在进入上下文之前先裁剪。读文件类工具只返回相关片段。怎么判断相关可以用简单的关键词匹配也可以让模型先给出“我要看哪几行”工具只返回那个范围。跑测试类工具只返回失败用例的摘要和关键堆栈通过的用例折叠成一行统计。搜索类工具返回前 N 条结果加摘要不要返回全文。这个裁剪逻辑放在 Harness 层对模型透明。模型看到的就是裁剪后的精简结果它不需要知道原始数据有多大。这样单轮 token 消耗能降下来 60% 以上长时运行的轮次上限直接翻倍。4. 沙箱与验证让 Agent 的手别伸太长让它的活别太糙4.1 沙箱隔离的三个层次Agent 要执行工具工具可能碰文件系统、跑命令、发网络请求。如果不加隔离一个失控的 Agent 能把你整个环境搞乱。沙箱隔离我一般分三个层次来做。进程级隔离是最基础的。每个工具调用在独立子进程里跑设 CPU 和内存上限超了就杀。这样即使工具代码有死循环或者内存泄漏也不会拖垮主进程。Python 里可以用resource模块设RLIMIT_CPU和RLIMIT_AS简单有效。文件系统级隔离是防止 Agent 乱改文件的关键。我的做法是给每个任务分配一个独立的工作目录Agent 只能在这个目录及其子目录里读写。所有文件路径在进入工具之前先做规范化然后检查是否在工作目录内。这个检查不能省我见过 Agent 用../../跳出目录去改系统文件的案例。网络级隔离视任务而定。如果任务不需要联网直接禁掉网络访问最安全。如果需要联网走白名单只允许访问必要的域名。这一层在 Harness 里通过配置控制不同任务用不同策略。4.2 验证环节Agent 说“我完成了”不算数Agent 有个通病它特别容易自我感觉良好。改完代码说“已修复”实际上测试根本没跑写完文档说“已完成”实际上格式全乱。所以验证环节必须独立于 Agent 的自我声明用客观标准来判定。我的验证设计分三层。第一层是工具级验证每个工具执行完立刻检查返回码和输出格式不符合预期就标记为失败。第二层是任务级验证任务完成后跑一组预设的检查比如代码任务跑测试、文档任务跑格式校验、数据任务跑一致性检查。第三层是交叉验证对于关键产出用一个独立的模型实例或者规则引擎再检查一遍避免 Agent 自己既当运动员又当裁判。验证不通过怎么办不能简单打回让 Agent 重做那样容易陷入“改—验—改”的死循环。我的做法是验证失败时把具体的失败信息哪个测试挂了、哪一行格式不对作为反馈塞回上下文让 Agent 针对性修复同时限制修复轮次比如最多 3 轮超过就上报人工。4.3 一个验证配置的实例以代码修复任务为例我的验证配置大概长这样验证层级检查项失败处理最大重试工具级文件写入返回码、语法解析立即反馈给模型修正2任务级单元测试通过率、lint 检查反馈失败用例定向修复3交叉验证独立模型审查 diff标记可疑改动人工复核1这张表不是拍脑袋来的是踩坑踩出来的。早期我没设工具级验证结果 Agent 写文件时路径拼错返回码是失败但它没检查继续往下走最后整个任务基于一个不存在的文件展开全盘皆输。加上工具级验证之后这类低级错误在第一轮就被拦住了。注意验证本身也要有超时。我遇到过测试用例里有死循环验证环节卡住整个任务挂起。现在所有验证步骤都包在超时控制里超时按失败处理。5. 长时运行让 Agent 撑过几小时甚至几天5.1 长时运行到底难在哪短任务跑几分钟很多问题暴露不出来。一旦任务拉长到几小时甚至跨天下面这些问题就会集中爆发。状态丢失进程重启、机器迁移、网络中断任何一次意外都会让前面的工作归零。资源漂移跑久了内存缓慢增长、临时文件堆积、连接池耗尽。上下文退化即使有压缩跑几百轮之后摘要也会越来越模糊模型逐渐失去方向感。外部依赖变化任务依赖的接口改了、文件被别的进程动了Agent 却还按老样子操作。我在一个跨天的数据整理任务里深刻体会过这些。任务跑到第 8 小时机器例行维护重启因为没做检查点前面 8 小时白干。第二次加了检查点但没做资源清理跑到第 12 小时临时文件把磁盘写满了。第三次才把该补的都补上。5.2 检查点设计存什么、存多频、怎么恢复检查点的核心是存够恢复所需的最小状态。我一般存这几样当前轮次和状态机状态、锚点层上下文、归档摘要、最近 N 轮消息、已执行工具的完整记录、工作目录的文件快照或者用版本控制记录 diff、待办事项列表。存多频我的策略是状态转移时必存工具执行后选存。状态转移比如从 ACTING 到 VERIFYING是天然的分界点必须存。工具执行后如果产生了重要产物比如写入了文件也存一次。这样即使崩溃最多丢失一轮的工作。恢复的时候先加载检查点重建消息列表然后检查工作目录的实际状态和记录是否一致。不一致的话比如文件被外部改了要么回滚到检查点状态要么把差异作为新信息塞给模型让它重新评估。我倾向于后者因为回滚可能丢失外部有价值的改动。5.3 资源清理与健康检查长时运行必须配一个后台的健康检查线程定期做几件事清理超过一定时间的临时文件、检查内存和磁盘使用率、验证关键外部依赖是否可达、检查 Agent 是否陷入停滞比如连续多轮没有文件写入或状态变化。停滞检测特别有用。我设的规则是如果连续 5 轮既没有工具调用成功、也没有状态转移就判定为停滞触发一次“强制反思”——让模型基于当前上下文重新规划或者直接上报。这个机制救过我好几次有一次 Agent 卡在一个永远返回空结果的搜索工具上停滞检测把它拉了出来。5.4 长时运行的日志与可观测性跑几小时的任务出问题时你不可能从头看日志。所以日志必须结构化包含时间戳、轮次、状态、事件类型、耗时、token 消耗、关键参数。我一般用 JSON Lines 格式每行一个事件方便用命令行工具过滤和统计。关键指标要实时监控每轮平均耗时、token 消耗速率、工具成功率、验证通过率、检查点写入频率。这些指标异常时能提前预警。比如 token 消耗速率突然翻倍可能是上下文压缩失效了工具成功率下降可能是外部依赖出问题了。有了这些信号你就能在任务彻底崩掉之前介入。6. 常见问题与排查技巧实录6.1 典型问题速查表现象可能原因排查方向处理方式Agent 反复调用同一工具工具返回结果没被正确理解或陷入死循环看最近几轮工具调用参数是否相同加停滞检测强制反思或终止上下文超限报错压缩水位线设太高或工具返回未裁剪统计每轮 token 增量降低水位线加强工具结果裁剪任务跑到一半失忆锚点层被压缩或截断检查锚点层是否完整保留锚点层设为不可压缩验证一直不通过反馈信息不够具体模型无法定位看验证失败信息是否包含具体位置细化验证输出限制修复轮次检查点恢复后行为异常工作目录状态与记录不一致对比文件快照和实际文件把差异作为新信息反馈给模型长时运行内存持续增长临时对象未释放或消息列表未清理监控内存曲线检查消息列表长度定期清理用生成器替代列表累积6.2 几个不那么常见但很致命的坑工具调用的幂等性问题。有些工具比如“追加写入文件”重复执行会产生副作用。如果 Agent 因为重试机制把同一个调用执行了两次文件里就会出现重复内容。我的处理是给每个工具调用生成唯一 ID执行前先查记录已执行过的直接返回缓存结果。这个幂等层在 Harness 里做对模型透明。时间相关的逻辑陷阱。Agent 如果依赖“当前时间”做判断长时运行跨天后可能行为突变。比如一个定时任务判断“今天是工作日”跨到周末后逻辑就错了。我的做法是把时间作为显式参数传给工具而不是让工具自己取系统时间这样时间基准可控。并发任务的相互干扰。如果多个 Agent 共享工作目录一个改文件另一个读很容易读到中间状态。要么给每个 Agent 独立目录要么加文件锁。我倾向于独立目录简单可靠最后再合并。6.3 我个人的调试习惯遇到 Agent 行为异常我第一件事不是改代码而是把最近 20 轮的完整上下文 dump 出来人肉读一遍。十有八九问题就藏在某轮的工具返回里——可能是一个被忽略的报错可能是一段被截断的关键信息。读完再决定是改 Harness 还是改 prompt。第二件事是复现。把 dump 出来的上下文喂给同一个模型看能不能复现异常。能复现就是逻辑问题不能复现可能是环境或时序问题。这个二分法能快速缩小排查范围。第三件事是加日志再跑。如果前两步没定位到就在可疑环节加详细日志重跑一次。我一般会加工具调用的完整参数和返回、上下文压缩前后的 token 数、状态转移的触发条件。跑一次基本就水落石出了。这套 Harness 工程的东西说到底就是让 Agent 从“能跑”变成“能一直跑、跑得稳、跑得对”。模型能力固然重要但真正决定生产可用性的往往是外面这层看起来不起眼的挽具。我现在的习惯是每接一个新 Agent 任务先花半天把 Harness 的骨架搭好后面省下的调试时间远超这半天。这个投入产出比做过长时运行任务的人应该都懂。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号