1. 从模型崇拜到系统思维:为什么现在要聊 Harness
过去两年,我接触过不少做机器人方向的朋友,大家见面第一句话往往是"你用的哪个模型"。VLA 模型、LLM 规划器、端到端策略网络,谁的参数大、谁的榜单分数高,谁就站在话题中心。但真正把机器人从实验室推到产线、推到真实场景里的人,心里都清楚一件事:模型只是整个系统里的一环,而且往往不是最脆弱的那一环。
我踩过最典型的一个坑,是早期做一个桌面抓取任务。当时选了一个当时榜单上表现很好的 VLA 模型,离线评测成功率能到八成多,结果一上真机,成功率直接掉到三成。排查了两周才发现,问题根本不在模型本身,而在整个执行链路:视觉输入的时序对齐有偏差、动作输出的频率和底层控制器不匹配、异常情况下没有重试和回退机制。模型没变,但把外围这套东西理顺之后,成功率回到了七成以上。
这就是 Harness 这个概念的价值所在。所谓 Harness,直译是"挽具、约束框架",在机器人和 Agent 领域,它指的是包裹在模型外面、负责把模型能力真正落地成可靠行为的那一整套系统:输入输出适配、状态管理、工具调用、错误恢复、安全约束、日志观测。模型决定"能不能做",Harness 决定"做得稳不稳、能不能复现、出问题能不能查"。
这篇文章想聊的,就是怎么从"追更强的模型"这个惯性里跳出来,转向"搭更好的系统"。我会把机器人 Harness 和物理 Agent Harness 放在一起对比,拆解它们的核心组成、关键设计取舍、实操落地步骤,以及我在真实项目里踩过的坑。不管你是刚入门机器人学习的新手,还是已经在做 Agent 开发的工程师,都能从里面找到可以直接抄作业的部分。
2. 先把概念理清楚:Agent、Harness、VLA、LLM 到底是什么关系
2.1 四个高频词的真实边界
很多人被这几个词绕晕,其实用一句话就能理清它们的分工。我习惯用"开车"来类比:LLM 是大脑里负责思考和决策的部分,VLA 是能同时看路和动手的驾驶员,Agent 是"驾驶员加一整套行为规范"这个角色,而 Harness 是方向盘、油门、刹车、仪表盘这一整套让驾驶可控的物理与逻辑接口。
具体来说,LLM 是纯语言/文本空间的大模型,擅长推理、规划、生成结构化指令,但它本身不接触物理世界。VLA 是视觉-语言-动作模型,输入图像和语言指令,直接输出动作序列,它是"感知加决策加执行"的耦合体。Agent 是一个更上层的概念,指具备自主感知、规划、行动、反思能力的智能体,它可能由 LLM 驱动,也可能由 VLA 驱动,甚至两者混合。Harness 则是把上面这些能力组织起来、约束起来、观测起来的那层工程系统。
这里有个常见误区:很多人以为"Agent 就是 LLM 加个循环"。实际上,一个能用的 Agent,模型部分可能只占三成代码量,剩下七成全是 Harness 的活:怎么管理上下文、怎么调用工具、怎么处理失败、怎么防止它做出危险动作。我见过太多 demo 惊艳、一上生产就崩的 Agent 项目,问题几乎都出在这七成上。
2.2 Harness 和 Agent 的区别,一句话说透
热搜里有个词叫"harness 和 agent 区别",这个问题问得特别好。我的理解是:Agent 是"谁在做这件事",Harness 是"这件事被怎么组织和约束"。Agent 是主体,Harness 是环境加规则加工具的总和。
举个具体例子。你让一个 Agent 去"把桌上的杯子拿起来"。Agent 负责理解这个指令、规划出"移动到杯子附近、闭合夹爪、抬起"这几步。而 Harness 负责的是:把摄像头图像按正确频率喂给模型、把模型输出的动作转成底层控制器能懂的指令、检测夹爪有没有真的闭合、如果没夹住就触发重试、整个过程记录日志方便回放。没有 Harness,Agent 就是个只会空想的脑袋;没有 Agent,Harness 就是一堆没有灵魂的管道。
2.3 为什么"更好的系统"比"更强的模型"更值得投入
我做过一个粗略的统计。在我参与过的机器人项目里,把模型从 A 换成更强的 B,端到端成功率平均提升大概 10 到 15 个百分点。但把 Harness 从"能跑"优化到"健壮",成功率提升经常能到 30 个百分点以上,而且稳定性、可复现性、可维护性的提升是数量级的。
原因很简单:模型的能力上限受限于训练数据分布,而真实世界的长尾情况是无穷的。Harness 的价值在于,它能把模型在分布内的能力稳定发挥出来,同时在分布外的情况下优雅降级、安全退出、留下可分析的痕迹。一个 80 分的模型配一套 90 分的 Harness,实际表现往往好过一个 95 分的模型配一套 50 分的 Harness。
3. 机器人 Harness 的核心组成与设计取舍
3.1 感知层 Harness:让输入干净且对齐
感知层 Harness 要解决的核心问题是:模型看到的,和真实世界发生的,是不是同一件事。这里面最容易被忽视的是时间对齐。摄像头有曝光延迟,深度相机有处理延迟,关节编码器有采样延迟,如果这些数据没有统一的时间戳对齐,模型拿到的就是"时空错乱"的输入。
我在一个机械臂项目里就吃过这个亏。视觉帧和关节状态差了大概 40 毫秒,单看没问题,但在快速移动时,模型基于"旧"的关节状态去规划"新"的动作,就会产生系统性偏差。后来我们引入统一时钟源,所有传感器数据打上同一时间基准的时间戳,再做插值对齐,问题才解决。
具体做法上,我推荐几个实操要点。第一,所有传感器数据进缓冲区时强制打时间戳,用单调时钟而不是系统时钟,避免时间跳变。第二,设定一个固定的控制周期,比如 50 赫兹,每个周期从缓冲区取最近的数据做插值,而不是来一帧处理一帧。第三,对视觉输入做基本的质量检查,比如亮度异常、运动模糊、遮挡检测,不合格的帧直接丢弃并触发重采,而不是硬喂给模型。
提示:时间对齐这件事,离线评测时几乎看不出来,因为离线数据往往是已经对齐好的。一定要在真机上验证,而且要专门设计快速运动的测试用例。
3.2 动作层 Harness:从模型输出到物理执行
动作层 Harness 是模型和物理世界之间的翻译官加安全员。模型输出的动作可能是归一化的、可能是关节空间的、可能是末端位姿的,而底层控制器要的是具体的、带限幅的、带速度约束的指令。这中间的转换、限幅、平滑、安全检查,全是 Harness 的活。
我一般会在这层做四件事。第一是坐标和单位转换,把模型输出统一到控制器期望的表示。第二是限幅,包括位置限幅、速度限幅、加速度限幅,防止模型输出一个离谱的值把机械臂甩出去。第三是平滑,对动作序列做低通滤波或者样条插值,避免抖动。第四是安全检查,比如工作空间边界检查、碰撞预判、力矩上限检查,任何一项不通过就拒绝执行并进入安全状态。
这里有个经验:限幅参数不要拍脑袋定。我见过有人直接把速度限幅设成电机最大值,结果模型一激动就触发过流保护。合理的做法是先设一个保守值,比如最大速度的 30%,跑通之后再逐步放开,同时监控电流和温度。
3.3 状态与记忆 Harness:让 Agent 记得住、想得起
Agent 要完成多步任务,就必须有状态管理。这层 Harness 负责维护任务进度、历史动作、环境变化、失败记录。没有它,Agent 每步都是"失忆"的,只能做单步反应,做不了长程规划。
我的做法是用一个结构化的状态对象,而不是把历史全塞进上下文。状态对象里包含:当前子任务、已完成步骤、关键观测、失败次数、剩余预算。每次调用模型时,只把和当前决策相关的状态摘要喂进去,而不是把几十轮历史全灌进去。这样既省 token,又避免模型被无关信息干扰。
记忆这块还有个坑:不要把原始图像序列全存下来当记忆,存储爆炸不说,检索也慢。我一般存的是压缩后的语义摘要,比如"在第 3 步检测到目标位置偏移约 5 厘米",需要细节时再回查原始日志。
3.4 工具与技能 Harness:Agent 的手脚怎么接
Agent 要干活,就得有工具。工具层 Harness 负责注册、发现、调用、超时、重试、结果解析。这块和纯软件 Agent 的思路类似,但机器人场景多了物理约束:工具调用可能改变物理世界状态,不能随便重试。
比如"抓取"这个工具,失败了不能无脑重试,因为物体可能已经被碰倒了。我的做法是给每个工具标注"幂等性"和"副作用等级"。幂等的、无副作用的工具可以自动重试;有副作用的工具失败后必须重新感知环境再决策。这个标注看起来麻烦,但能避免很多"越重试越糟"的情况。
3.5 安全与观测 Harness:出事了能查、能停、能恢复
安全层是底线,观测层是眼睛。安全层要有独立的急停通道,不能依赖主控制循环,因为主循环可能卡死。观测层要记录足够的信息,包括每步的输入、输出、耗时、状态、异常,而且日志要能按时间线回放。
我特别想强调日志的结构化。早期我用纯文本日志,排查问题时靠 grep,效率极低。后来改成结构化日志,每条记录带时间戳、模块名、事件类型、关键字段,配合一个简单的回放工具,排查效率提升了好几倍。这个投入绝对值得。
4. 物理 Agent Harness 的独特挑战
4.1 不可逆性:物理世界没有 Ctrl+Z
软件 Agent 做错了,回滚一下就行。物理 Agent 做错了,杯子碎了就是碎了。这个不可逆性决定了物理 Agent Harness 必须比软件 Harness 保守得多。
我的原则是:任何可能造成不可逆后果的动作,执行前必须做一次独立的可行性检查。这个检查不依赖主模型,而是一个轻量的、规则化的安全模块。比如抓取前检查物体是否在可达空间、夹爪是否张开、路径上是否有障碍。这个检查可能误报,但宁可误报也不能漏报。
4.2 实时性:延迟就是错误
物理 Agent 对延迟极其敏感。模型推理慢 100 毫秒,在慢速任务里无所谓,在动态任务里可能就是失败。Harness 要做的,是把推理延迟和控制在时间上解耦。
常见做法是异步推理加动作缓冲。控制循环以固定高频运行,从动作缓冲区取指令执行;推理在另一个线程跑,算完一批动作就塞进缓冲区。这样即使推理偶尔卡顿,控制也不会断。缓冲区长度要权衡:太短容易断供,太长则响应迟钝。我一般设成覆盖 2 到 3 个推理周期。
4.3 部分可观测:你永远看不到全部
真实世界的传感器有盲区、有噪声、有遮挡。Harness 要处理这种部分可观测性,做法包括:维护一个对环境的信念状态、主动触发探索动作、在信息不足时选择保守策略。
我常用的一个技巧是"不确定性门控":当模型对当前决策的置信度低于阈值时,不直接执行,而是先做一个信息收集动作,比如换个视角看一眼。这个逻辑放在 Harness 层,比让模型自己学会"该看的时候看"要可靠得多。
4.4 硬件异构:一套 Harness 适配多种本体
做机器人项目很难只碰一种硬件。今天机械臂,明天移动底盘,后天可能是个复合体。如果 Harness 和具体硬件绑死,每换一次硬件就要重写一遍,成本极高。
我的做法是抽象出一层"本体接口",定义统一的感知输入格式和动作输出格式,具体硬件通过适配器接入。这样上层 Harness 和 Agent 逻辑不用改,只换适配器就行。这个抽象早期会多花点时间,但长期看省下的重复劳动非常可观。
5. 从零搭一套可用的 Harness:实操步骤
5.1 环境准备与依赖选型
先说环境。机器人 Harness 通常跑在 Linux 上,实时性要求高的部分可能需要实时内核。我的建议是开发阶段用普通内核,部署阶段再上实时内核,避免过早引入复杂性。
依赖选型上,通信中间件我一般用 ROS 2 或者更轻量的方案。ROS 2 生态成熟、工具链全,但有一定学习成本;如果项目简单,直接用共享内存加自定义消息队列也够用。模型推理这块,Python 生态最方便,但关键路径上如果延迟敏感,可以考虑用 C++ 重写热点。
这里给一个我常用的目录结构参考:
harness/ perception/ # 感知层:传感器接入、时间对齐、预处理 action/ # 动作层:转换、限幅、平滑、安全检查 state/ # 状态层:任务状态、记忆、上下文管理 tools/ # 工具层:技能注册、调用、重试 safety/ # 安全层:独立急停、边界检查 observability/ # 观测层:结构化日志、回放 adapters/ # 本体适配器:不同硬件的统一接口 config/ # 配置文件:参数、阈值、限幅5.2 感知层搭建:时间对齐与质量门控
感知层的第一步是统一时钟。我一般用一个单调时钟作为全局时间基准,所有传感器回调进来第一件事就是打时间戳。然后维护一个滑动窗口缓冲区,每个控制周期从窗口里取数据做插值。
质量门控这块,我列几个常用的检查项:图像亮度均值是否在合理区间、拉普拉斯方差是否低于模糊阈值、深度图有效像素比例是否达标、点云是否有点数突变。任何一项不通过,就标记这一帧为低质量,触发重采或者降级使用。
注意:质量门控的阈值一定要用真实数据统计出来,不要照搬网上的值。不同相机、不同光照,阈值差别很大。
5.3 动作层搭建:限幅、平滑与安全检查
动作层的核心是一个处理管线:原始动作进,安全动作出。我一般按这个顺序处理:坐标转换、单位统一、位置限幅、速度限幅、加速度限幅、低通滤波、工作空间检查、碰撞预判、最终输出。
限幅参数的计算,我举个具体例子。假设机械臂最大关节速度是 180 度每秒,我一般把模型输出的速度限幅设成 60 度每秒,也就是三分之一。为什么是三分之一?因为要给加速度限制留余量,还要给突发情况留反应时间。跑稳之后再逐步往上调,每次调 10%,观察一周。
平滑这块,一阶低通滤波简单够用,截止频率设成控制频率的十分之一左右。如果动作抖动特别厉害,可以上样条插值,但会增加延迟,要权衡。
5.4 状态层搭建:结构化状态与上下文裁剪
状态对象我一般用字典或者数据类实现,字段包括:任务 ID、当前子任务、已完成步骤列表、关键观测摘要、失败计数、剩余时间预算、当前环境快照引用。
上下文裁剪的逻辑是:每次调用模型前,根据当前子任务,从状态对象里挑出相关字段,组装成一个精简的提示。我一般控制在几百 token 以内,而不是把整个历史塞进去。这个裁剪逻辑本身也是 Harness 的一部分,需要精心设计。
5.5 工具层搭建:注册、调用与重试策略
工具注册我用装饰器的方式,每个工具函数标注名称、参数 schema、幂等性、副作用等级、超时时间。调用时统一走一个调度器,负责参数校验、超时控制、重试决策、结果解析。
重试策略我按副作用等级分三档:无副作用工具自动重试三次;低副作用工具重试一次并记录;高副作用工具不自动重试,失败后触发重新感知和重新决策。
5.6 安全与观测层搭建:独立急停与结构化日志
安全层我强烈建议独立于主循环。用一个单独的线程或者进程监控关键指标,比如关节力矩、电流、温度、工作空间越界,一旦触发阈值,直接走硬件急停通道,不经过主控制逻辑。
观测层的结构化日志,我用 JSON Lines 格式,每行一条记录,字段包括时间戳、模块、事件、关键数据。配合一个简单的回放脚本,可以按时间线重现整个执行过程。这个工具在排查偶发问题时价值巨大。
6. 常见问题与排查技巧实录
6.1 模型离线好、真机差,怎么查
这是最高频的问题。我的排查顺序是:先查时间对齐,再查动作限幅,再查状态管理,最后才怀疑模型。
具体做法:录一段真机执行日志,把模型输入和真机实际状态对齐后可视化。如果发现输入和实际状态有明显时间偏移,就是对齐问题。如果输入没问题但动作执行不到位,就是动作层问题。如果单步都对但多步任务失败,就是状态管理问题。
6.2 Agent 陷入死循环怎么办
死循环通常有三个原因:状态没有正确更新、失败后没有改变策略、工具返回的结果没有被正确解析。
我的做法是加一个"进展检测"机制:每隔几步检查任务状态是否有实质推进,如果没有,强制触发策略切换或者退出。同时给每个任务设一个最大步数预算,超了就安全退出并上报。
6.3 推理延迟导致控制断供
这个问题的解法是异步推理加动作缓冲,前面提过。补充一个细节:缓冲区要能检测"即将断供",提前触发降级策略,比如切换到更快的备用模型,或者执行一个安全的保持动作。
6.4 工具调用失败后越重试越糟
这就是前面说的副作用问题。解法是给工具标注副作用等级,高副作用的工具不自动重试。另外,重试前一定要重新感知环境,不能基于旧状态重试。
6.5 常见问题速查表
| 现象 | 可能原因 | 排查方向 | 解决思路 |
|---|---|---|---|
| 离线好真机差 | 时间对齐偏差 | 对齐日志可视化 | 统一时钟、插值对齐 |
| 动作抖动 | 输出未平滑 | 检查滤波参数 | 加低通滤波、调截止频率 |
| 多步任务失败 | 状态未更新 | 检查状态对象 | 结构化状态、上下文裁剪 |
| 死循环 | 无进展检测 | 检查步数预算 | 加进展检测、强制退出 |
| 控制断供 | 推理延迟 | 检查推理耗时 | 异步推理、动作缓冲 |
| 越重试越糟 | 副作用未标注 | 检查工具标注 | 副作用分级、重试前重感知 |
| 偶发失败难复现 | 日志不结构化 | 检查日志格式 | 结构化日志、回放工具 |
6.6 几个我踩过的坑
第一个坑是过早优化模型。项目初期我花大量时间调模型,结果发现瓶颈在 Harness,白费功夫。后来我改成先把 Harness 搭稳,再优化模型,效率高很多。
第二个坑是忽视日志。早期觉得日志麻烦,出问题全靠猜。后来被一个偶发问题折磨了一周,痛定思痛上了结构化日志,才发现问题一目了然。
第三个坑是安全层和主循环耦合。有一次主循环卡死,急停也失效了,差点出事。后来把安全层独立出来,才睡得着觉。
7. 模型选型与 Harness 的配合策略
7.1 LLM 规划器加 VLA 执行器的组合
现在比较主流的架构是 LLM 负责高层规划,VLA 负责底层执行。LLM 把"把桌子收拾干净"拆成"拿起杯子、放到架子上、拿起盘子、放到水槽",VLA 负责每个子任务的具体动作。
这个组合的关键在于接口设计。LLM 输出的子任务描述要足够具体,VLA 才能执行;同时要足够抽象,不限制 VLA 的发挥。我一般用"目标状态加约束"的方式描述子任务,比如"杯子在架子上,夹爪不碰其他物体"。
7.2 纯 VLA 端到端的适用场景
纯 VLA 端到端适合任务单一、环境稳定的场景,比如固定工位的分拣。它的优势是延迟低、链路短,劣势是泛化差、难调试。如果任务变化频繁,还是分层架构更合适。
7.3 模型能力不足时 Harness 怎么补
模型能力不足,Harness 可以从几个方面补:一是加规则化的兜底逻辑,处理模型搞不定的边界情况;二是加主动探索,信息不足时先收集信息;三是加多模型投票,关键决策用多个模型交叉验证。
我做过一个项目,主模型在某些光照下表现差,我就在 Harness 层加了一个光照检测,光照异常时切换到备用模型,整体成功率提升明显。
8. 一些实操心得与后续扩展方向
聊了这么多,最后分享几个我个人的体会。第一,Harness 的投入回报是复利的。你在一套 Harness 上花的功夫,换硬件、换模型、换任务都能复用,而模型调优的收益往往是一次性的。第二,可观测性不是可选项。没有好的日志和回放,你就是在盲人摸象。第三,安全层要独立,这是底线,不能省。
后续扩展上,我觉得有几个方向值得投入。一是 Harness 的自动化测试,用仿真环境批量跑回归,把 Harness 的健壮性量化出来。二是 Harness 的配置化,把限幅、阈值、重试策略都做成配置,不同场景快速切换。三是 Harness 和模型训练的闭环,把真机执行中 Harness 记录的成功和失败案例,反哺给模型做微调,形成数据飞轮。
这个方向我还在持续摸索,有新的心得再和大家分享。如果你也在做类似的事情,欢迎交流踩坑经验,毕竟 Harness 这东西,坑都是相似的,经验是可以互相抄的。