社区天天讨论哪个模型 SWE-bench 分高、哪个代码能力强。我做了一个对照实验:固定模型不变,只改变它的运行环境(Harness),代码质量差了 3 倍。决定 AI 编程效果的不是模型,是 Harness。
一个反直觉的现象
上周我让 DeepSeek V3 帮我写一个 Express 中间件。直接在普通聊天窗口里给它需求,它写出来的代码能跑,但风格和项目完全不搭——变量命名用了 camelCase(项目是 snake_case),错误处理用了 try-catch(项目统一用 error middleware),甚至导入路径都是猜的。
然后我在 Claude Code 里给了完全相同的需求,同样用 DeepSeek V3(通过 API 网关切过去的)。这次它写出来的代码风格完全一致——snake_case、error middleware、正确的导入路径、甚至注释风格都对了。
同一个模型,同一个需求,输出质量天差地别。
差异在哪?在模型周围的那套系统——业界现在叫它 Harness。
Harness Engineering 是什么
Harness 是 AI Agent 的"运行时环境"。它不是模型本身,而是模型周围的一切:系统提示词、可用工具、项目上下文、编码规范、记忆系统、错误恢复策略。
一个类比:模型是发动机,Harness 是整辆车。同一台发动机装在拖拉机和跑车里,性能体验完全不同。
Harness 的组成:
├── 系统提示词(角色定义、行为约束)
├── 项目上下文(CLAUDE.md / .cursorrules / 代码库索引)
├── 工具集(MCP Server、文件操作、Shell 命令)
├── 上下文管理策略(窗口大小、历史压缩、注入时机)
├── 记忆系统(跨 session 的知识持久化)
└── 错误恢复(重试、降级、自我修正循环)
2026 年 AI 编程工具的竞争,已经从模型层转移到了 Harness 层。Claude Code、Cursor、Codex 底层都能接多种模型,真正的差异化在 Harness 的设计上。
实验设计:同一模型,三种 Harness
我固定使用 DeepSeek V3,准备了三种 Harness 配置,让它完成同一组编码任务。
三种配置
配置 A:裸模型(Bare)
- 只有基础的系统提示:"你是一个编程助手"
- 没有项目上下文、没有工具、没有记忆
- 相当于在普通聊天窗口里写代码
配置 B:标准 Harness(Standard)
- 系统提示包含角色定义和基础规范
- 接入了文件读写和 Shell 工具
- 手动给它 2-3 个相关文件作为上下文
- 没有 CLAUDE.md、没有代码库索引、没有记忆
配置 C:完整 Harness(Full)
- 详细的 CLAUDE.md(编码风格、架构规范、禁止模式)
- 完整的 MCP 工具链(文件、Shell、Git、搜索)
- 代码库索引(Agent 能自主浏览项目结构)
- 上下文管理(滚动窗口 + 历史压缩)
- 跨 session 记忆(记得之前的决策和偏好)
# 三种配置的代码差异只在系统提示和工具注册
# 模型完全相同:DeepSeek V3,temperature 0.3
# 配置 A:裸模型
messages_a = [
{"role": "system", "content": "你是一个编程助手。"},
{"role": "user", "content": task_prompt}
]
# 配置 B:标准 Harness
messages_b = [
{"role": "system", "content": STANDARD_SYSTEM_PROMPT},
{"role": "user", "content": f"项目相关文件:\n{context_files}\n\n任务:{task_prompt}"}
]
# 配置 C:完整 Harness
# 通过 Agent 框架执行,自动注入 CLAUDE.md、工具、记忆
agent.execute(task_prompt, tools=full_mcp_tools, memory=persistent_memory)
任务集
10 个编码任务,覆盖不同复杂度:
| 编号 | 任务 | 复杂度 |
|---|---|---|
| T1 | 写一个字符串工具函数 | 低 |
| T2 | 实现一个 Express 中间件 | 低 |
| T3 | 写一个数据库迁移脚本 | 中 |
| T4 | 实现分页查询 API(含参数校验) | 中 |
| T5 | 写一个 WebSocket 消息处理器 | 中 |
| T6 | 实现带重试的 HTTP 客户端 | 中 |
| T7 | 写一个定时任务调度器 | 中高 |
| T8 | 实现 JWT 认证中间件(含刷新逻辑) | 中高 |
| T9 | 写一个事件发布/订阅系统 | 高 |
| T10 | 实现乐观锁的并发更新逻辑 | 高 |
评分维度(每项 1-5 分)
| 维度 | 评估标准 |
|---|---|
| 正确性 | 代码逻辑对不对,能不能跑 |
| 风格一致性 | 命名、缩进、注释风格是否和项目统一 |
| 架构适配 | 是否遵循项目的分层、模式和约定 |
| 边界处理 | 错误处理、空值检查、参数校验 |
| 可维护性 | 代码是否清晰、模块化、易于修改 |
实验结果
总分对比
| 配置 | 平均总分(/25) | 相对裸模型 |
|---|---|---|
| A 裸模型 | 10.3 | 基线 |
| B 标准 Harness | 17.8 | +73% |
| C 完整 Harness | 22.1 | +115% |
完整 Harness 的代码质量是裸模型的 2.1 倍。 如果只看风格一致性和架构适配两个维度,差距超过 3 倍。
各维度详细数据
| 维度 | 裸模型 (A) | 标准 (B) | 完整 (C) |
|---|---|---|---|
| 正确性 | 3.4 | 4.1 | 4.5 |
| 风格一致性 | 1.2 | 3.2 | 4.7 |
| 架构适配 | 1.1 | 2.9 | 4.5 |
| 边界处理 | 2.4 | 3.6 | 4.2 |
| 可维护性 | 2.2 | 4.0 | 4.2 |
三个关键发现:
发现 1:正确性差距最小。 裸模型也能写出基本正确的代码(3.4/5)。模型本身的编码能力已经很强了。差距主要在"正确但不适合这个项目"上。
发现 2:风格一致性差距最大。 裸模型只有 1.2 分(几乎完全不符合项目风格),完整 Harness 达到 4.7 分。这就是为什么裸用模型写的代码"看着就不对"——风格不是错,是不一致。 而 CLAUDE.md 里的编码规范直接解决了这个问题。
发现 3:标准 Harness 已经覆盖了大部分收益。 从 A→B 的提升(+73%)远大于 B→C 的提升(+24%)。这意味着你不需要一个完美的 Harness,一个"够用"的 Harness 就能拿到大部分收益。
按任务复杂度拆分
| 复杂度 | 裸模型 | 标准 | 完整 | A→C 提升 |
|---|---|---|---|---|
| 低 (T1-T2) | 13.5 | 19.0 | 22.0 | +63% |
| 中 (T3-T6) | 10.5 | 18.0 | 22.5 | +114% |
| 中高 (T7-T8) | 9.0 | 17.5 | 22.0 | +144% |
| 高 (T9-T10) | 7.0 | 15.5 | 21.0 | +200% |
任务越复杂,Harness 的价值越大。 简单任务裸模型也能应付(提升 63%),高复杂度任务 Harness 带来 3 倍提升。这很好理解——简单函数不需要太多上下文,复杂系统设计严重依赖对项目架构的理解。
消融实验:哪个 Harness 组件最重要
完整 Harness 有 5 个组件。我逐个关闭,看每个组件对总分的贡献:
| 关闭的组件 | 总分 | 相比完整 Harness |
|---|---|---|
| 无(完整 Harness) | 22.1 | 基线 |
| 关闭记忆 | 21.3 | -3.6% |
| 关闭上下文管理 | 20.5 | -7.2% |
| 关闭 MCP 工具 | 18.9 | -14.5% |
| 关闭代码库索引 | 17.2 | -22.2% |
| 关闭 CLAUDE.md | 15.1 | -31.7% |
CLAUDE.md(项目规范文件)是最重要的单一组件。 关掉它之后质量暴跌 31.7%。这一个文件告诉模型:项目用什么命名规范、什么架构模式、什么是禁止的——没有它,模型只能靠猜。
第二重要的是代码库索引(-22.2%)——让 Agent 能自主浏览项目结构,而不是靠你手动喂文件。
记忆和上下文管理的影响相对小(-3.6% 和 -7.2%),因为我的测试任务是单次执行的。如果是多轮迭代开发,记忆的价值会大得多。
实战建议:最小可用 Harness
如果你现在还在裸用模型写代码(聊天窗口直接问),做两件事就能拿到 70% 以上的收益:
第一步:写一份 CLAUDE.md(20 分钟)
# Project Rules
## 编码规范
- 变量命名: snake_case
- 函数命名: camelCase
- 文件命名: kebab-case
- 缩进: 2 空格
- 分号: 不加
## 架构约定
- 分层: router → controller → service → repository
- 错误处理: 不用 try-catch,统一走 error middleware
- 数据校验: 在 controller 层用 zod 校验
- 数据库: 用 drizzle ORM,不写裸 SQL
## 禁止
- 不要用 any 类型
- 不要用 console.log 做日志(用 pino)
- 不要在 service 层直接访问 request 对象
这份文件不需要写得很长。30 行就够了,关键是把"我们项目里绝对不做的事"写清楚。 模型不知道你的约定,你不说它就会用它训练数据里最常见的模式。
第二步:让 Agent 能浏览代码库
给 Agent 配一个文件读取工具,让它在写代码之前先看看项目里现有的同类文件是怎么写的。
# 在 Agent 的系统提示里加一句
"在写任何代码之前,先用工具查看项目中同类文件的实现方式,
确保你的代码风格和现有代码一致。"
这句话让模型从"凭空创作"变成"参考现有代码"——风格一致性会大幅提升。
效果估算
| 投入 | 预期质量提升 |
|---|---|
| 写 CLAUDE.md(20 分钟) | +50-60% |
| 加文件浏览工具(10 分钟) | 再 +15-20% |
| 总计 30 分钟 | +70-80% |
30 分钟的一次性投入,之后每次 AI 编码都受益。这个 ROI 比换模型高得多——升级到 Opus 4.7 的提升大约 10-15%,但花费多了 5 倍以上。
对模型选型的影响
这个实验改变了我对模型选型的看法。
以前我觉得"写代码就要用最好的模型"。现在我的策略是:先把 Harness 搭好,再选模型。 一个好的 Harness + 中端模型,效果好于一个差的 Harness + 旗舰模型。
实测数据验证这个判断:
| 组合 | 总分(/25) |
|---|---|
| DeepSeek V3 + 完整 Harness | 22.1 |
| Opus 4.7 + 裸模型 | 13.8 |
DeepSeek V3(5/MTok)裸用的质量。便宜 18 倍的模型,靠 Harness 反超了。
当然,最佳组合是旗舰模型 + 完整 Harness。但如果预算有限,先投入 Harness 的 ROI 远高于升级模型。有需要的时候把关键任务路由到旗舰模型就行——我自己日常编码走 DeepSeek,架构决策切 Opus 4.7,都在 TheRouter 上一个 Key 搞定的,切模型改个字符串的事。
常见问题
Q: CLAUDE.md 和 .cursorrules 有什么区别? A: 格式不同,目的一样——都是给 AI 编程工具看的项目规范文件。CLAUDE.md 是 Claude Code 的约定,.cursorrules 是 Cursor 的约定。内容可以互相复制,核心都是编码规范 + 架构约定 + 禁止列表。不管用什么工具,写一份这样的文件是收益最高的单一优化。
Q: Harness Engineering 和 Prompt Engineering 的区别? A: Prompt Engineering 优化的是"怎么跟模型说话"(单次输入)。Harness Engineering 优化的是"模型运行在什么环境里"(系统级)——包括工具、上下文、记忆、错误恢复整套运行时。Prompt 是 Harness 的一个子集。2026 年的共识是:只优化 prompt 远远不够。
Q: 消融实验里记忆影响最小(-3.6%),那记忆不重要? A: 单次任务里确实不重要。但连续开发多天的场景下,记忆的价值会显著上升——Agent 记得你之前做的技术决策、踩过的坑、偏好的方案。这个实验是单任务的,低估了记忆在真实工作流里的价值。