ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

Agent Harness 实战:从 Anthropic 到 DeepSeek 的工程底座解析

Agent Harness 实战:从 Anthropic 到 DeepSeek 的工程底座解析

这两年只要一聊到 Agent,关注点基本都扎在模型本身上——今天又发了什么新模型,benchmark 涨了几个点,谁家的上下文窗口又扩了一倍。但我是真把 Agent 从 demo 推到生产环境跑过的人,感受最深的一点是:模型只是大脑,真正把大脑的聪明转化为稳定生产力的,是外面那一整套“身体系统”。而业界给这套系统起了个名字,叫 Harness。

这篇文章想做的,是把 Harness 这个越来越重要的概念彻底讲透:从 Anthropic 长时任务设计的工程实践,到 Google AX 带火的声明式调度,再到我自己落地 DeepSeek Harness 项目和 Skill 插件体系时踩过的那些坑。不管你是刚开始学 Agent 开发,还是已经在做 Agent 框架与编排,这篇文章应该都能给你一些能直接抄作业的东西。

1. Harness 到底是什么:模型是大脑,Harness 是身体

1.1 Agent 与 Harness 的区别:一句话说清

很多新手上来就问 Agent 和 Harness 到底啥关系。我常用一个类比:Agent 是一个员工,Harness 是他所在的整家公司。员工再聪明,也得有办公桌、电脑、门禁卡、项目管理系统、同事协作流程,才能把活儿干出来。对应到技术里:

  • 模型是员工的脑子,负责思考;
  • Agent 是员工这个角色本身,负责自主决策、发起行动;
  • Harness 则是员工所处的基础设施——工具怎么调用、上下文怎么管理、任务怎么调度、干到一半崩了怎么恢复、哪些事能干哪些不能干,全由 Harness 决定。

所以你看网上那些 Agent 项目,抛开模型能力不谈,真正拉开差距的其实是 Harness。同一个 Claude 或 DeepSeek 模型,有人搭出来的 Agent 只能聊两句就乱,有人搭出来的能连续跑一小时的深度研究任务还不跑偏。差别不在模型,在 Harness。

1.2 Harness 的五大核心能力

拆开看,一个合格的 Agent Harness 至少要管五件事:

第一,工具网关。Agent 说“我要调用某某工具”,Harness 负责解析这句话、做参数校验、执行调用、把结果回填到上下文。这层很像后端里的 API 网关——Agent 不能直接裸调各种系统,所有进出都得过一道统一出口。好处是你能在工具层统一做鉴权、限流、重试、日志。

第二,上下文工程。这是最容易被低估的一层。模型上下文窗口就那么长,你不能什么都往里塞。Harness 要决定:哪些历史对话保留,哪些压缩成摘要,哪些信息压根不该进上下文。我见过太多 Agent 项目死在上下文溢出上——跑半小时后模型开始胡说八道,就是因为上下文里塞了太多垃圾,真正的关键信息被稀释了。

第三,任务调度与状态保持。长时任务最怕什么?怕做了一半进程崩了。Harness 要负责把任务状态持久化,让 Agent 干到一半也能断点续跑,而不是每次崩溃都从头再来。

第四,记忆系统。跨会话记忆怎么存、怎么查、怎么更新。不是简单把历史聊天记录全存起来,而是要有结构化设计:哪些该留,哪些该丢,哪些该进长期记忆库。

第五,安全与权限。Agent 能读哪些文件、能跑哪些命令、能访问哪些网络资源,全在 Harness 这一层管控。没有这层,Agent 就是一个没有刹车的车,工具越多越危险。

1.3 为什么说是“新护城河”

护城河这个说法,我以前也觉得夸张。但 2025 年做 Agent 做久了你会发现:模型能力越来越趋同,API 谁都能调,真正的差异就是外围系统。就像移动互联网时代,底层芯片大家都差不多,真正拉开体验差距的是操作系统和 App 生态。

Anthropic 也好,Google 也好,现在都在往 Harness 层砸资源,这信号已经很明显了。模型本身你很难有壁垒,但 Harness 层的工程积累——任务设计模式、调度框架、工具协议、技能插件体系——这些东西是时间堆出来的,是真正的护城河。

2. Anthropic 长时任务设计:从开放式对话到工程级任务

2.1 长时任务的第一性问题

Anthropic 这轮最值得学习的就是长时任务(Long-running Tasks)的设计思路。先聊明白问题在哪,再聊他们怎么解决。

长时任务有三个第一性难题:

上下文注意力陷阱。你的任务从第 1 分钟跑到第 60 分钟,早期收集的信息还在上下文里,但模型对它们的注意力会衰减。研究论文里叫“Lost in the Middle”——中间位置的信息最容易被忽略。所以靠“把所有东西都堆在上下文里”来支撑长时任务,必死。

状态会丢失。Agent 不是一个常驻进程,它每执行一步都是“读上下文 → 推理 → 调工具 → 拿结果 → 再读上下文”。任何一步崩溃、超时、被杀掉,整个状态就没了。你以为是“让 Agent 干活”,实际是“让一个失忆症患者连续工作一小时”。

调用链错误累积。一次长任务里 Agent 可能要调几十次工具,每次都有失败概率。如果单次成功率是 95%,连续 30 次调用的成功率只有 21%。你以为在跑任务,其实是在掷骰子。

2.2 Claude Code 的 Harness 工程实践

Anthropic 的 Claude Code 是我见过最典型的 Harness 实践样板,它把这些难题逐个用工程手段解掉了。

工作树 + 待办清单机制。Claude Code 不是让 Agent 靠着上下文裸奔,而是维护一个任务状态文件,把大任务拆成待办列表,每完成一项就更新一次。即使中间中断,重新启动后 Agent 读一下状态文件就知道干到哪了——这就是 Checkpoint 机制,简单但极其有效。

定期落盘。Claude Code 里 Agent 会阶段性把重要结论、文件清单、下一步计划写进项目里的任务文档。这个过程表面看是“Agent 在记笔记”,本质是 Harness 层的状态持久化。我自己的项目里也复刻了这个思路,每完成一步就把中间结果写到磁盘,实测中断恢复的成功率提升非常明显。

代码回退能力。Agent 改代码改到一半把项目搞坏了怎么办?Claude Code 的 Harness 里有版本回退能力——执行任务前对工作区做快照,Agent 搞砸了可以一键回滚。这也是热词里很多人搜“deepseek harness 代码回退”的原因。说白了,给 Agent 配了后悔药。

2.3 Agent Skills 机制拆解

再聊一个和我实操关系最密切的:Agent Skills。

Anthropic 提出 Skills 的核心理念,是技能模块化——以后你想让 Agent 做一件事,不用在系统提示词里写一大堆指令,而是定义成一个 Skill 包,按需加载。一个 Skill 包的结构通常是:

my-skill/ ├── SKILL.md # 技能说明文档,告诉 Agent 这个技能怎么用 ├── scripts/ # 可执行的脚本或代码 ├── references/ # 参考文档,Agent 在需要时按需读取 └── assets/ # 其他资源文件

关键设计在于:SKILL.md 是入口,Agent 先用它了解“这个技能是干什么的”,真正动手时才去加载 scripts 和 references。这比把全部技能细节都塞进系统提示词,上下文开销小了几个量级。

这点对长时任务的帮助极大。没有 Skills 的 Agent,提示词越长、任务越长,越容易迷失。有了 Skills,Agent 像是拥有一个工具箱,需要用哪个工具时再去翻说明书,而不是把整套工具箱背在身上。

我在 DeepSeek Harness 里部署技能插件时,就是套用这套规范来组织技能包,很顺手。

3. Google AX 的声明式调度:一场 Agent 编排范式的转变

3.1 命令式编排的痛点

说完了 Anthropic 的长时任务,再来看 Google AX 带来的另一个思路转变:声明式调度。

在此之前,大多数 Agent 编排是命令式的。什么意思?就是你用代码把每一步写死:

# 命令式编排:开发者手工控制每一步 agent.run("搜索相关资料") agent.run("整理搜索结果为大纲") agent.run("按大纲撰写正文") agent.run("检查文章质量")

这种写法的问题很明显:Agent 行为的自由度被杀死了,你说“先搜索再整理”,但实际场景里 Agent 可能发现搜索到的资料不够,应该先补一次搜索再整理——命令式流程没法灵活变通。反过来,如果你完全不写编排,让 Agent 自由发挥,它又可能跑偏。

命令式的另一个大坑是:编排逻辑和业务流程纠缠在代码里,没法统一观测和治理。十几个 Agent 项目,各自写各自的流程控制,一旦出问题,排查起来头大。

3.2 声明式调度的核心:只声明目标,把执行交给运行时

Google AX(Agent Experience)的核心思路是反过来的——声明式。你不告诉 Agent 每一步怎么走,你只声明“我要什么结果、有哪些约束、依赖哪些资源”,剩下的事交给调度运行时去规划。

举个例子,同样写一篇文章,声明式会这样写:

task: name: "撰写技术博客" goal: "产出一篇关于 Harness 的深度技术文章" constraints: max_steps: 20 allowed_tools: ["web_search", "file_write", "code_execute"] dependencies: - task: "搜集参考资料" - task: "梳理文章大纲" success_criteria: - "文章字数不少于 3000" - "包含实操案例"

运行时收到这个声明后,自己去拆解步骤、规划流程、执行、判断是否达到成功标准,不达标就重试或调整策略。这里的差别就像“手绘流程图”和“跟导航说出目的地”的区别。

我把这个思路落地到自己项目里后,最大的感受是:Agent 终于像 Agent 了,而不是一个被 if-else 绑住手脚的脚本机器。它能自主决定“先搜什么、哪个资料更重要、什么时候该写代码验证”,而我又没有失去对全局的控制权——约束条件还在运行时手里。

3.3 声明式调度带来的工程收益

声明式不只是一个理念,它落地后的工程收益是实打实的。

第一个收益是可观测性。因为流程定义和执行引擎分离了,你可以在执行层统一埋点,记录每一个任务的进度、每一步的耗时、成功失败状态。命令式代码里想做到这一点,你得在各个业务编码点手动埋日志,工作量大还容易漏。

第二个收益是自动恢复。声明式任务因为明确声明了目标和依赖,失败后引擎可以根据目标自动重试,或者跳过非关键依赖降级处理。命令式代码想做到这点,你得手写一堆重试和降级逻辑。

第三个收益是可复用性。流程定义是配置,不是代码,所以同一个任务定义可以在不同 Agent、不同项目之间复用。换了模型、换了执行环境,声明式定义不用改。这对 Agent 框架与编排的演进意义很大。

4. 实操复盘:DeepSeek Harness 部署与 Skill 体系落地

4.1 环境准备与安装(含常见安装失败处理)

理论说了这么多,实操才是这篇文章的重头戏。我拿 DeepSeek Harness 当例子,完整复盘一遍从部署到技能落地的过程。

首先明确一点:DeepSeek Harness 是一个典型的开源 Agent Harness 项目,做深度研究、代码生成、多步任务都够用。安装时先确认环境,Python 版本要跟上项目要求(我这边用的 3.11+),Node 环境也建议备好,因为不少插件和 Web 端组件依赖它。

安装步骤大致是:

  1. 从仓库拉取项目代码;
  2. 创建虚拟环境并安装 Python 依赖;
  3. 按模板配置模型 API 密钥和基础参数;
  4. 启动 Web 服务或命令行入口,验证是否能正常对话。

这里我要特别提一个高频报错——很多人在启动时遇到failed to load plugins web boot: 1 entry did not activate这类插件加载失败问题。我排查下来的经验是:别急着怀疑插件本身,先看入口文件路径和依赖完整性。插件系统启动时会扫描每个插件目录,期望的入口文件没找到、依赖没装完、入口函数没有正确导出注册,都会导致 entry 激活失败。把日志级别调到 debug,看它具体卡在哪个插件的哪个文件上,比瞎猜快得多。

4.2 Skill 与插件体系实战:内网部署的完整路径

Skill 体系的部署是很多人卡住的地方。我按照前文说的 Anthropic Skills 规范,把技能包组织好了之后,最关键的问题变成了:怎么部署到内网服务器上。

内网部署的完整路径一般是这样的:

  1. 把 Skill 目录整个拷贝到 Harness 的 skills 目录下(或配置里指定技能包的搜索路径);
  2. 确认技能包目录结构符合规范——SKILL.md 必须存在,scripts 目录下的脚本要有执行权限;
  3. 在 Harness 的配置文件里注册或启用这个技能;
  4. 重启服务,让技能加载器重新扫描。

这里有一个特别容易踩的坑:内网服务器没有外网访问能力,所以技能里如果用了在线依赖或者需要拉取远程模型的数据,就废了。我当时的做法是:所有技能脚本尽量只依赖 Python 标准库,需要外部数据时把参考文件提前下载好放进 references 目录。这相当于把技能做成一个“离线可执行”的自治包,内网部署就非常顺。

另一个经验是权限控制。Skill 本质上是让 Agent 获得了执行某些操作的能力,所以这个能力的边界必须在 Harness 层画清楚。我自己会给技能设定一个工作目录白名单,Agent 的读写操作只能在白名单范围内进行。没有这层约束,Agent 一通操作下来可能把服务器上的东西改得面目全非。

4.3 代码回退机制与任务断点续跑

前文提到的代码回退,实操时我是这样实现的:每次任务启动前,对工作区做一次 Git 快照(commit 或 stash),任务结束后如果检查发现结果不可用,就执行一次硬回退,把工作区恢复到任务开始前的状态。

# 任务启动前保存现场 git add -A && git commit -m "checkpoint before agent task" # 如果任务翻车,回退现场 git reset --hard HEAD~1

这个操作成本很低,但价值极大。我实际跑过一个让 Agent 重构代码的任务,它干了十几分钟,改了几十个文件,最后跑测试全红——如果没有回退能力,这十几分钟的破坏就得手工恢复。有了快照,一条命令就回到原点,让 Agent 换个策略重跑。

断点续跑的逻辑类似。长任务执行中我会让 Agent 每完成一个阶段就把结果写入磁盘(比如更新任务进度文件),同时把当前状态记录为一个 checkpoint。即使中途断掉,重新启动时 Agent 读一下 checkpoint 就知道干到哪、下一步该干什么。这和 Anthropic 的任务文件设计是一个思路——让状态离开上下文,落到磁盘上。

4.4 Harness + RPA 的落地思路

说到落地,最近很多人问 Harness 怎么和 RPA 结合。我的理解是:RPA 负责“手”,Harness 负责“脑”。

典型的落地架构是:Harness 里的 Agent 负责任务拆解和决策,然后通过消息队列或 HTTP 回调,把结构化指令下发给 RPA 客户端;RPA 执行完 UI 操作后,把结果回传给 Agent,Agent 解析后决定下一步动作。

这里的关键是通信协议的设计。最好不要让 Agent 直接返回一段“自然语言指令”给 RPA,那解析起来想哭。我用的方案是定义一套 JSON 指令协议,包含操作类型、目标元素、参数、超时等字段,RPA 那边只按协议执行,执行结果也按协议回传。这样两边解耦,Agent 换模型、RPA 换工具,都不影响整体链路。实操下来这个组合能覆盖大量“既要智能决策又要操作业务系统”的场景。

5. 常见问题排查实录

5.1 插件加载失败与入口未激活

这类报错在前面提过一次,这里把完整的排查思路整理出来。报错的核心是“entry did not activate”,意思是有插件入口没有成功激活。按照经验,依次排查以下四个环节:

  1. 目录结构和入口路径:插件清单里写了入口文件,实际文件不存在或者路径不对,必然报错。先把入口文件是否存在确认了再说别的。
  2. 依赖完整性:入口文件里 import 的模块装了吗?版本对不对?很多插件会用到第三方库,内部版本和插件要求不一致时,报错信息往往不直观。
  3. 导出注册函数:插件框架一般要求入口文件导出特定名称的注册函数。你没导出、或者函数名不对,框架扫到了文件但激活不了。
  4. 权限问题:内网服务器上常见的坑——入口文件没有执行权限,或者插件目录在只读文件系统里。

这套排查顺序我用过太多次了,每次都有效。核心心得是:插件系统报错基本都是这四类,从最便宜的动作开始查,别上来就怀疑框架本身。

5.2 API 连接类报错的通用排查思路

跑 Agent 项目的人大概率见过unable to connect to开头的报错。这类问题的原因大致分三类,排查思路也按顺序走:

第一类:目标服务本身不可用或网络不通。先确认服务状态是否正常,再检查本地到目标的网络连通性、DNS 解析、TLS 握手,逐层排查。这一步就纯粹是标准网络调试。

第二类:认证和配置信息不对。API Key 过期、配置环境变量没生效、请求头格式不对,都会表现为连接阶段的报错。排查方法是直接手工发一个最小 HTTP 请求复现,确认认证信息有没有问题。

第三类:网关或路由配置导致模型身份不匹配。如果你走网关或路由接入模型服务,可能遇到类似doesn't look like an anthropic model: expected a gateway model route的报错。这个报错的本质是网关返回的模型元数据和客户端预期不一致——客户端通过网关做模型路由时,网关返回的模型头信息与 SDK 校验规则对不上,从而拒绝继续。

这类问题的解决方向有两条:一是回到网关侧,确认模型路由是否指向预期模型,也就是网关配置里 model route 的映射关系;二是如果业务对稳定性要求高,生产环境优先使用官方 SDK 直连通道,或与网关服务商确认透传方式一致。我的建议始终是:网关方案可以尝试,但如果身份校验类报错反复出现,就别在绕过校验上花心思了,用匹配的官方通道才是干净的解法。

5.3 并发场景下 Agent 扛压的一些做法

“AI Agent 怎么扛并发”是近期问得最多的问题之一。先说一个基本的认知:Agent 的并发和普通 Web 服务的并发不一样,Agent 每次调用模型都要消耗 Token,而且每个 Agent 会话都有独立的上下文状态,所以并发瓶颈主要在 Token 消耗和上下文管理,而不是单纯的线程数量。

我自己用的做法是:

  1. 任务队列化:不直接“同时跑 100 个 Agent”,而是把任务推入队列,控制并发水位(比如同时最多跑 5 个),避免模型 API 被限流。
  2. Token 预算制:给每个任务设定 Token 上限,快到上限时强制 Agent 收敛产出,防止单个任务把资源耗尽。
  3. 指数退避重试:API 限流或超时后,不立刻重试,而是按指数退避策略重试三次。这个在长时任务里尤其重要。

5.4 Agent 记忆与上下文管理技巧

最后聊一个贯穿所有 Agent 项目的话题:记忆。

很多人问“Agent 记忆”是不是就是把聊天历史全存下来。我的回答是:如果你全存,上下文很快就爆。我实际用的方法是三层记忆模型:

  • 工作记忆:当前任务的上下文,保持在上下文窗口内,任务结束就清空。
  • 项目记忆:跟当前项目相关的规范、结论、偏好,存在项目目录的文件或向量库里,需要时检索加载。
  • 长期记忆:跨项目可复用的用户偏好、通用知识,存在独立的记忆库中。

每次对话开始时,Harness 根据当前项目从记忆库里检索相关片段注入上下文,而不是把整个记忆库全倒给模型。这样既保证了记忆的持久性,又不吞噬上下文窗口。

6. 实操心得与最后的小建议

把该聊的都聊完了,最后说几句真实体会。

Harness 这个词听上去像学术概念,但实际上它就是每一个 Agent 项目里“那些看不见但撑起全局的工程底座”。你自己写 Agent 的时候,哪怕不用任何框架,也一定要想明白这五层——工具怎么管、上下文怎么管、任务怎么管、状态怎么存、权限怎么控。模型可以随时换,但这五层是你真正沉淀下来的积累,也是你项目里真正的护城河。

还有一个我踩了几次坑之后总结出来的小技巧:一切从最小的 Harness 起步。不要一开始就设计一套复杂的调度引擎和插件规范,先把“调用工具→更新状态→落盘检查点”这个最小闭环跑通,再逐步加声明式调度、Skill 加载、RPA 对接。我见过太多人一开始就把架构设计得很宏大,结果连最小任务都跑不稳。架构是长出来的,不是一开始画出来的。先让你的 Agent 稳定地跑完一个三十分钟的任务,再谈护城河。

RELATED READING

延伸阅读

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