从只有大模型到完备 Harness:7 个组件缺一不可
上周我让 Agent 帮我写了一篇博客。
它从我的 wiki 里读了 5 篇历史文章做去重分析,生成初稿后自己跑了一轮对抗性评审打了 18 分,然后用 Gemini 生了一张配图、resize 到 1360px 以下、压缩成 948KB 的 PNG,再跑了一遍中文排版修复,最后 commit 推到 GitHub,等 CI 构建完成后自己验证了上线 URL。
整个过程我做了三件事:选了一个标题方向,补了两处内容,说了三次「发布」。
这套流水线跑了 4 篇博客(#290 到 #293),每篇都是这个流程。它不是 demo,是真实的生产管线。
但我回头看这套东西的时候,发现一个问题: 我搭出来的不是一个 Agent,是一个 Harness。
一个被忽视的事实:Agent 交付靠的不是模型
我在 让钉钉机器人自己开发自己 里说过一句话:「自主性的瓶颈在环境接入,不在模型能力。」
这句话当时说的是 Agent 修自己的 Bug。但其实它适用于所有 Agent 场景。
最近有一篇讲 Harness 的文章把这个问题说得很透:
大模型解决的是智能问题。Harness 解决的是交付问题。
什么叫 Harness?它是 Agent 的业务运行底座——把模型、工具、知识、记忆、策略、观测和配置组织起来,让 Agent 能在真实业务场景里稳定、安全、可控地完成任务。
没有 Harness,Agent 只能回答「应该怎么做」。有了 Harness,Agent 才能真的去查、去判断、去调用工具、去执行、去记录、去复盘。
这篇文章列出了 Harness 的 7 个组件:
| # | 组件 | 解决的问题 |
|---|---|---|
| 1 | 模型网关 | 什么任务用什么模型 |
| 2 | 工具注册表 | Agent 能用哪些工具 |
| 3 | 知识库引擎 | 从哪拿业务知识 |
| 4 | 记忆系统 | 记住上下文和偏好 |
| 5 | 策略引擎 | 规则和红线怎么强制 |
| 6 | 可观测性 | Agent 干得怎么样 |
| 7 | 配置管理 | 怎么持续调教不发版 |
读完这张表,我回头审视自己在钉钉上搭的这套系统,发现——7 个组件全都有,而且全是钉钉 + dws 原生能力撑起来的,没有一行胶水代码。
钉钉 + dws:一张完备的 Harness 映射表
下面我把这 7 个组件逐一映射到我在钉钉上实际跑通的工程实现。每个组件我都会给出:它在我的系统里长什么样,用了什么 dws 命令,以及如果缺了它会怎样。
组件 1:模型网关——异构 Agent 各司其职
我的系统里有两个 Agent,配了不同的模型:
| Agent | 模型 | 定位 |
|---|---|---|
| OpenCode Agent | GLM 5.2 | 写代码、跑测试、改 Bug |
| Hermes Agent | Qwen 3.7 Max | 知识库、长上下文、写博客、记忆 |
这不是随意分配的。GLM 5.2 的代码生成能力强但上下文窗口小,适合确定性的编码任务。Qwen 3.7 Max 上下文长、中文好,适合需要读大量材料的分析和写作任务。
模型网关的核心原则是: 该用好模型的地方不要省,该用便宜模型的地方不要浪费,能用规则解决的地方就别麻烦大模型。
在钉钉上,这两个 Agent 通过消息总线协作(见 两个 Agent 的钉钉对话)。我在群里 @ Hermes 让它写一篇博客,它写到需要跑代码的时候会把任务转给 OpenCode。这不是一个 Agent 内部切模型,而是 两个 Agent 在 IM 里协作——模型网关变成了消息路由。
缺了它会怎样? 所有任务都打给最贵的模型。成本飙升,响应变慢,而且很多简单任务(比如查群列表、发通知)根本不需要大模型。
组件 2:工具注册表——dws 的 163 条指令
dws CLI 就是我的工具注册表。当前版本(v1.0.52-beta.2)提供了 163 条指令,覆盖钉钉全部核心能力:
┌──────────────────────────────────────────────┐
│ dws 工具注册表 │
├──────────┬───────────────────────────────────┤
│ chat │ 群聊/消息/机器人/公告/群管理 │
│ calendar │ 日历日程/会议室/闲忙 │
│ contact │ 通讯录/用户/部门/人员关系 │
│ doc │ 钉钉文档管理 │
│ drive │ 钉盘文件管理 │
│ mail │ 邮箱/邮件收发 │
│ oa │ OA 审批/同意/拒绝/撤销 │
│ todo │ 待办任务管理 │
│ wiki │ 知识库/空间管理/节点管理 │
│ aitable │ AI 表格操作 │
│ minutes │ AI 听记/会议纪要 │
│ dev │ 开发者能力/connect/事件订阅 │
└──────────┴───────────────────────────────────┘
每条指令都有 --help 自描述、--format json 结构化输出、--dry-run 预览——这三个 flag 让 Agent 能自主探索工具能力,不需要人提前教它每个参数。
比如我要让 Agent 给 FDE 教练发消息,它不需要知道 FDE 教练的 openDingTalkId。它自己跑 dws contact user search --keyword 「FDE 教练」 查到 ID,再跑 dws chat message send。工具注册表不只是「有工具」,还要让 Agent 能自己发现工具。
缺了它会怎样? Agent 只能聊天,不能操作任何业务系统。你让它帮你安排会议,它只能说「建议你打开日历看看」,而不是真的帮你查空闲时间、发邀请。
组件 3:知识库引擎——wiki + 博客 corpus + memory
我的知识库分三层:
┌─────────────────────────────────────────┐
│ 知识库三层架构 │
├─────────────────────────────────────────┤
│ Layer 1: ~/wiki/ │
│ raw/notes/ — 原始素材(会议记录、 │
│ 文章、数据报告) │
│ concepts/ — 结构化概念页面 │
│ entities/ — 实体页面(人、工具) │
│ │
│ Layer 2: ~/Projects/blog2/content/post/ │
│ 历史博客 corpus(293 篇) │
│ Agent 写新文章前必须读、做去重分析 │
│ │
│ Layer 3: Hermes persistent memory │
│ 用户偏好、环境配置、常用联系人 │
│ 跨 session 持久化 │
└─────────────────────────────────────────┘
知识库不是 RAG 这么简单。Layer 1 是原始素材库,Agent 用 search_files 和 read_file 按关键词检索。Layer 2 是已发布的知识,Agent 写新博客前必须扫最近的文章做去重——这是我在 人机协同的核心不是 Chat,是 Feedback Loop 里讲的「Agent 必须记住你」。Layer 3 是 Hermes 的 memory 系统,存的是偏好和事实,不是知识条目。
缺了它会怎样? Agent 每次从零开始。它不知道你已经写过「异构多 Agent 协作」,会再写一篇角度几乎一样的文章。它不知道你喜欢 Claude 风格的配图,每次都要你重新说。
组件 4:记忆系统——Hermes memory + session_search
记忆系统和知识库的区别:知识库是「可检索的资料」,记忆是「当前上下文 + 长期偏好」。
Hermes 的记忆分两层:
- 持久记忆(memory tool):跨 session 生效。存的是「用户喜欢简洁回复」「dws 用 id_ed25519 密钥」「FDE 教练的 openDingTalkId 是 xxx」这种稳定的事实和偏好。
- 会话记忆(session_search):可以搜过去的对话记录。比如我上周和幕山聊了什么,Agent 能搜出来做会议准备。
记忆系统的关键设计不是「记什么」,而是「 不记什么 」。我在 skill 里明确写了:不记 PR 编号、commit SHA、临时 TODO 状态——这些一周后就过期了。记太多会污染上下文,还会把 A 任务的设定带到 B 任务里。
缺了它会怎样? 你每次和 Agent 交互都要重新自我介绍。它不记得你上周让它跟进的那个项目,不记得你讨厌「随着 AI 的发展」这种开头。Feedback Loop 断裂。
组件 5:策略引擎——渐进信任 + 通知分级 + 超时机制
策略引擎是 Harness 7 个组件里最容易被低估的。我的系统里策略引擎管三件事:
渐进信任三级模型:
┌─────────────────────────────────────────┐
│ 渐进信任三级模型 │
├──────────┬──────────────────────────────┤
│ Level 1 │ 每步确认 │
│ 新任务 │ Agent 做完每件事都汇报 │
├──────────┼──────────────────────────────┤
│ Level 2 │ 异常确认 │
│ 已验证 │ 常规自动执行,异常才求助 │
├──────────┼──────────────────────────────┤
│ Level 3 │ 定期汇报 │
│ 充分信任 │ 完全自主,只给周报 │
└──────────┴──────────────────────────────┘
通知优先级分级: 只在需要人决策时通知,常规执行只写日志。我早期配 Hermes 的时候它每完成一个小任务都来找我,一天二十多条消息。三天后我就不看了。
超时机制: Agent 问用户一个问题(question 工具),60 秒没回答就自动 reject,防止会话卡死。这是我在 #293 里加的第一个改进——因为我自己就是那个「没看见问题导致 Agent 卡了一夜」的用户。
缺了它会怎样? Agent 要么太激进(自作主张发了一封邮件给全公司),要么太保守(每一步都来问你,比你自己做还慢)。更危险的是卡死——没有超时机制,一个未回答的 question 就能让整个管线停摆。
组件 6:可观测性——event-watcher + 钉钉消息流
可观测性是我在 #293 里重点讲的组件。核心是 event-watcher:一个独立进程连 opencode serve 的 SSE 事件流,把 Agent 执行中的事件实时转发到钉钉。
opencode serve (agent 会话)
│ SSE /global/event
▼
event-watcher ──转发──> 钉钉
事件类型:
- 工具调用(执行中/完成)
- 会话完成(模型、轮数、tokens、缓存命中)
- question 提问
这解决了 Harness 文章里说的那个问题:「没有可观测性,就没有 Agent 运营。因为你不知道它哪里好,哪里坏,哪里浪费成本,哪里反复出错。」
在钉钉上看 Agent 的执行轨迹,比在任何 dashboard 上都直观——因为它和你的其他工作消息在同一个界面里。你不需要切到一个专门的监控后台,刷钉钉的时候顺便就能看到 Agent 在干什么。
而且这条消息流本身就是测试信号。在 用 Agent 在钉钉上跟进团队周度任务 里,我让 Agent 从 16 个人的单聊消息里提取任务进展——真实使用产生的消息流,就是最好的回归测试集。
缺了它会怎样? Agent 出了问题你只能猜。它说「已完成」,你不知道它到底跑了哪些步骤、用了多少 token、中间有没有报错。出了问题也没有日志可查。
组件 7:配置管理——dws skills + cron + profiles
配置管理让 Agent 可以持续调教而不需要改代码。我的系统里有三种配置机制:
- dws skills:Agent 的能力说明书。每个 skill 是一个 SKILL.md 文件,定义了意图表、命令用法、注意事项。改 skill 就是改 Agent 的行为,不需要重新训练或改代码。
- cron jobs:定时任务配置。比如每周一自动跑一次「16 个高管的任务跟进」,不需要人手动触发。
- profiles:多组织配置。同一个 dws 可以切换钉钉、阿里巴巴、Raspberry Pi 三个组织,每个组织有独立的认证和上下文。
配置管理的本质是: 把「这次我要什么」和「Agent 长期是什么」分开。 你的写作风格是长期记忆,但「这篇文章面向 CEO 还是工程师」是本次配置。好的配置管理让你不需要每次都重新教 Agent。
缺了它会怎样? 每次使用 Agent 都要从头调教。换个场景就要改 prompt,换个组织就要重新登录。Agent 变成了「一次性工具」而不是「持续进化的同事」。
7/7:一张完备性审计表
把上面的映射汇总成一张审计表。你可以用这张表来检查自己的 Agent 系统:
| 组件 | 问题 | 钉钉/dws 实现 | 缺了会怎样 |
|---|---|---|---|
| 模型网关 | 什么任务用什么模型? | OpenCode (GLM 5.2) + Hermes (Qwen 3.7 Max) 异构路由 | 成本飙升,简单任务用贵模型 |
| 工具注册表 | Agent 能用哪些工具? | dws 163 条指令,–help 自描述 | Agent 只能聊天,不能操作业务系统 |
| 知识库引擎 | 从哪拿业务知识? | wiki 三层架构 + 博客 corpus + search_files | 每次从零开始,重复已写过的内容 |
| 记忆系统 | 记住上下文和偏好? | Hermes memory + session_search | 每次都重新自我介绍 |
| 策略引擎 | 规则红线怎么强制? | 渐进信任 + 通知分级 + 60s 超时 | 太激进或太保守,会话卡死 |
| 可观测性 | Agent 干得怎么样? | event-watcher SSE→钉钉 + 消息流 | 出问题只能猜,没有日志可查 |
| 配置管理 | 怎么持续调教? | dws skills + cron + profiles | 每次从头调教,换场景就废 |
7 个组件缺任何一个,Agent 都会在某个环节崩掉。不是「可能崩」,是一定崩。
为什么是钉钉而不是 LangChain
有人会说:LangChain、CrewAI、AutoGen 这些框架也能搭 Harness,为什么要绑定一个 IM 平台?
区别在于 胶水 vs 底座。
框架搭的是胶水——你用代码把 LLM、工具、记忆、策略粘在一起。胶水越多,接口越多,出问题的地方越多。每次升级一个组件,你都要检查胶水有没有开裂。
IM 平台提供的是底座——消息路由、事件订阅、群管理、用户认证、文件存储,这些都是平台原生能力。底座越厚,你要搭的胶水越少。
具体到 dws:
- 消息路由 = 模型网关。你在群里 @ Agent A,Agent A 可以 @ Agent B。模型路由变成了消息路由,不需要你自己写 dispatcher。
- event 订阅 = 可观测性。单聊/@/群聊消息事件、已读、撤回、贴表情——这些事件 Agent 原生就能监听,不需要你自己埋点。
- 群管理 = 策略引擎。Agent 作为群成员,权限受群规则约束。它不能发消息给不在群里的人,不能修改不是它创建的群公告。平台级的权限控制比你自己写的策略引擎更可靠。
框架给你的是 能力。底座给你的是 约束。能力你自己也能加,约束只有平台能给。而 Harness 的核心价值恰恰是约束——让 Agent 不乱来。
从「能用」到「完备」
回到开头的场景:Agent 帮我写博客、生成配图、排版修复、commit 推送、验证上线。
这套流水线能跑,不是因为模型强——GLM 5.2 和 Qwen 3.7 Max 都不是最强的模型。它能跑,是因为 7 个组件都到位了:模型路由(异构 Agent)、工具(dws 163 条指令)、知识(wiki + 博客 corpus)、记忆(Hermes memory)、策略(渐进信任 + 超时)、观测(event-watcher)、配置(skills + cron)。
缺一个就跑不起来。 没有知识库,它会写出和旧文重复的内容。没有策略引擎,它会半夜给你发 20 条消息。没有可观测性,它说「已完成」你不知道它到底干了什么。没有配置管理,你每次都要重新教它你的写作风格。
这才是 AI 钉钉基建的真正含义:
AI 钉钉基建 = AI-Ready 的工作流数据 × 人-Agent 的原生协同
左边「AI-Ready 的工作流数据」是知识库引擎 + 工具注册表——让 Agent 能读懂和操作系统里的数据。右边「人-Agent 的原生协同」是模型网关 + 记忆 + 策略 + 观测 + 配置——让 Agent 能在 IM 里像一个同事一样工作。
乘号的意思是: 两边都要完备,缺一边就不成立。
所以,如果你的 Agent 项目总是卡在「demo 能跑但上线就崩」,不要急着换模型。先拿那张 7 组件审计表,逐条检查:你的 Harness 完备吗?
你的 Agent 有策略引擎吗?有可观测性吗?有配置管理吗?
如果答案是「没有」或「临时拼了一个」——那问题不在模型,在 Harness。
你在搭 Agent 系统的时候,踩过哪个组件的坑?欢迎留言讨论。