去年年底给一个客户做AI Coding落地评审,他们内部已经用Agent写了一个微服务原型,demo跑得挺顺,代码生成速度也快。但评审会上CTO只问了一个问题:“这个Agent从需求到上线,中间哪一步掉了,你能定位吗?怎么恢复?”全场安静了。因为那个Agent是一个巨大的Prompt包,所有流程都揉在一起,一旦中途出错,只能重来。这就是典型的“有Agent,没有Harness”的窘境。
后来我带团队重新搭了一套AI Coding的Harness工程体系,核心思路就是:不让Agent自己决定整条开发链路的走向,而是由Harness控制流程,把能力切成一个个可编排、可测试、可复用的Skill,用8个Skill把从需求澄清到上线压测的完整链路串起来。这篇文章就把这套东西掰开讲讲清楚,包括Harness和Agent到底什么关系、8个Skill各自干什么、Skill脚本怎么开发、链路怎么编排、全量压测怎么做,以及企业落地时最容易翻车的几个细节。适合正在做AI Coding工具链、或者想把AI编程从“demo能跑”推向“生产可用”的团队参考。
1. 为什么企业级AI Coding需要一个Harness,而不是一个能打的Agent
先厘清一个概念。很多人听到Harness,第一反应是“又一个AI框架”。其实Harness这个词在软件工程里早就有了,叫“测试夹具”或者“执行环境”。在AI Coding的场景里,Harness指的是包裹在模型和Agent外面的一层工程控制逻辑:它负责Agent的启动、上下文注入、Skill调度、工具调用、结果校验、失败重试、审计留痕。换句话说,Agent负责“想”,Harness负责“管”。
1.1 先理清楚Harness、Agent、Skill到底各管哪一段
我习惯用一句话区分三者:Agent是大脑,Skill是手脚,Harness是神经系统和肌肉骨骼。
- Agent:负责理解任务、拆解决策、调用工具。它是“思考者”。
- Skill:一个被封装好的、可复用的能力单元,比如“生成单元测试”“画架构图”“做代码审查”。它是“执行者”。
- Harness:负责把Agent和Skill组合到一起,定义执行顺序、状态流转、上下文管理、异常处理。它是“管理者”。
从这个角度看,市面上很多“AI编程神器”其实只做了Agent层,Skill是零散写在Prompt里的,Harness根本没有。结果就是:换个场景就得重新调Prompt,出错了不知道卡在哪一步,也没法对关键节点做人工审批。这就是单体Agent在企业级链路里的最大问题。
1.2 单体Agent在企业链路里的三个软肋
我拆过不少团队的AI Coding流程,发现单体Agent模式普遍有三个软肋:
第一是状态不可控。一个长任务的Agent要经过需求理解、代码生成、测试、修复等多个步骤,每一步都是不同模型调用,中间状态如果只存在Agent的上下文里,一旦上下文溢出或者中断,整个任务就得从头来。企业级项目里一个模块的生成可能要跑十几分钟,中途崩掉重来的成本完全不可接受。
第二是能力不可复用。同一个团队里,A项目沉淀的“代码评审经验”在B项目里根本用不上,因为都写在Agent的Prompt里,没法单独抽出来。这就像把每个工具的功能全写在洗衣机说明书里,换台洗衣机就全废了。
第三是安全不可审计。单体Agent发起的所有工具调用都混在一起,没有清晰的日志边界。评审的时候问“刚才这个删除文件的动作是哪个节点触发的”,没人能回答。这在企业里是硬伤,尤其是涉及生产环境操作、数据库变更的时候。
1.3 我的选型判断:什么时候该上Harness工程
不是说所有场景都要上Harness。个人写脚本、跑一次性任务,单体Agent完全够用,甚至效率更高。但一旦出现下面几个信号,就应该考虑Harness工程了:
- 开发链路需要多人协作、多角色审批;
- 同一个能力要在多个项目中复用;
- 任务失败需要精确到某个环节重跑;
- 需要对AI的每一次操作留痕审计;
- 模型不是固定一个,而是要根据任务类型切换(比如需求分析用一个模型,代码生成用另一个)。
我们这次落地的项目,就是同时踩中了这五个信号,所以才决定从“一个Agent干到底”改成“Harness编排 + 8个Skill分工”。
2. 全链路8个Skill的完整拼图与职责边界
定Skill之前,我先把“全链路”拆了一遍。企业里一个功能从想法到上线,至少要经历:需求澄清、技术设计、任务拆分、代码编写、代码审查、测试验证、文档沉淀、性能验证这八个环节。正好对应我们设计的8个Skill。
2.1 从需求到上线的八个关卡
这八个关卡不是随便拍的,是从软件开发流程里归纳出来的。每个关卡都有明确的输入、输出和验收标准,这样才能被Skil化——如果一件事说不清输入输出,就没法做成技能包。
| 关卡 | Skill名称 | 核心职责 | 关键输出 |
|---|---|---|---|
| 1 | taste-skill | 需求澄清与质量判断 | 用户故事、验收标准、需求边界 |
| 2 | archify-skill | 架构设计与技术选型 | 模块划分、技术方案、架构图 |
| 3 | split-skill | 任务拆解与依赖分析 | 任务列表、依赖关系、执行顺序 |
| 4 | codex-skill | 编码实现与规范落地 | 可运行的代码、单测骨架 |
| 5 | review-skill | 代码审查与边界检查 | 审查意见、修复建议 |
| 6 | test-skill | 测试用例生成与补齐 | 单测、集成测试用例 |
| 7 | doc-skill | 文档编排与知识沉淀 | 设计文档、接口文档、变更日志 |
| 8 | loadtest-skill | 链路全量压测 | 压测报告、瓶颈分析、优化建议 |
每个Skill的边界必须清楚,不能重叠。比如taste-skill只管需求澄清,不负责技术方案;codex-skill只按需求和设计写代码,不负责判断架构对不对。边界清楚的好处是,后续优化某个Skill时不会影响其他环节。
2.2 Skill 1-2:需求澄清与架构设计
第一个Skill,taste-skill,是最容易被忽略但最关键的。它的核心不是“读懂需求”,而是“判断需求质量”。很多大模型拿到一句话需求就直接开写,结果做出来的东西根本不是用户要的。taste-skill要做的是:把一句话需求拆成完整用户故事,列出业务规则,标记出模糊点,生成验收标准。我们给它内置了一个“需求质量评分表”,低于60分的直接打回,要求补充信息,而不是硬做。
第二个Skill,archify-skill,负责把需求翻译成技术方案。它会根据项目现状(已有的代码库结构、技术栈、依赖)输出模块划分建议、数据模型设计、接口定义、以及关键技术选型的对比分析。这个Skill我们接入了drawio-skill的能力,可以直接生成架构图,方便评审会上贴出来讨论。
这里有个经验:架构设计是AI最容易“一本正经地胡说八道”的环节。所以archify-skill的输出不是最终结论,而是给架构师看的“初版方案”,必须有人工确认环节,才能进入下一步。
2.3 Skill 3-5:任务拆解、编码实现、代码评审
split-skill把archify-skill输出的技术方案拆成一个一个可执行的任务单元。每个任务单元包含:改动范围、涉及文件、依赖的前置任务、验收方式。我们要求拆出来的任务必须能“独立提交”,也就是说每个任务做完都不破坏主分支。这里面的关键点是依赖分析——两个任务如果改同一个文件,就会冲突,split-skill必须把它们串行化或者提前做接口隔离。
codex-skill是写代码的主力。它可以对接不同的模型后端,我们实际用了混合策略:简单CRUD逻辑用轻量模型,复杂业务逻辑用更强的模型。Skill内部封装了团队编码规范,包括命名、注释语言、异常处理方式、日志格式,所有生成代码必须先过一遍格式化和静态检查,不过关就自动迭代修改,最多重试三次。
review-skill做的是“AI审查AI”的活。它站在资深工程师的角度对codex-skill生成的代码做审查,重点看几个维度:是否有多余的公共代码可以抽取、异常处理是否完善、边界条件是否覆盖、有没有明显的安全隐患。审查意见会按严重级别分P0/P1/P2,P0级问题会直接阻断提交流程,强制修改后才能继续。
2.4 Skill 6-8:测试生成、文档编排、回归压测
test-skill不是一个简单的“生成单测”工具。它会结合需求文档里的验收标准来生成测试用例,保证每条验收标准都有对应的测试覆盖。我们观察到一个现象:AI生成的代码,单测覆盖率往往虚高——很多assert是无效断言,根本没测到核心逻辑。所以test-skill里专门加了一个“断言质量检查”,会分析每个测试用例是否真的触达了目标分支。
doc-skill在传统流程里常被省略,但在AI Coding流程里非常关键,因为代码生成速度太快,如果文档跟不上,后期维护就是灾难。它会在代码合入后自动更新设计文档、接口文档、README、变更日志。文档生成不是简单地把代码注释拼接起来,而是从代码变更中提取“为什么这么改”的上下文,这部分输入来自archify-skill的设计决策和review-skill的审核意见。
loadtest-skill是链路全量压测的兜底关卡。它会对整个系统生成压测方案,包括造数据脚本、并发模型、监控指标,并执行一轮全链路压测。压测结果会输出瓶颈分析报告,比如“数据库连接池不够”“某个接口慢查询”等,问题会回流给codex-skill修复。
2.5 每个Skill的输入输出契约表
做好Skill有一个前提:输入输出必须结构化。我们给每个Skill都定义了契约,运行时Harness负责校验数据完整性,不满足契约就不调用。
| Skill | 必填输入 | 输出格式 | 后续消费方 |
|---|---|---|---|
| taste-skill | 原始需求、业务背景 | 用户故事+验收标准(JSON) | archify-skill |
| archify-skill | 用户故事、验收标准、代码库结构 | 技术方案+架构图 | split-skill |
| split-skill | 技术方案、团队约定 | 任务列表+依赖关系 | codex-skill |
| codex-skill | 任务单元、编码规范、相关代码上下文 | 代码diff、单测骨架 | review-skill |
| review-skill | 代码diff、审查规范 | 审查意见(P0/P1/P2) | codex-skill / test-skill |
| test-skill | 代码diff、验收标准 | 测试用例、覆盖率报告 | doc-skill |
| doc-skill | 设计决策、代码变更、审查意见 | 文档更新 | 知识库 |
| loadtest-skill | 可运行系统、压测配置 | 压测报告、瓶颈分析 | codex-skill / 运维 |
这份契约表是全链路的核心资产,比任何一段Prompt都值钱。它让整个流程从“玄学”变成了“工程”。
3. Skill开发的工程化套路:从一段Prompt到一个可复用技能包
定完8个Skill的职责边界,接下来就是怎么把每个Skill做成真正可复用的技能包。这一步是Harness工程里体力活最大、但收益也最明显的部分。
3.1 Skill的本质是“可调用的最小能力单元”
很多人在刚开始做Skill的时候容易犯一个错误:把Skill当成一个“大Prompt”。比如写一个2000字的Prompt,告诉模型“你是一个资深架构师,请根据需求输出方案”——这不是Skill,这只是换了个说话风格。
真正的Skill应该像一个函数:它有明确的入参、出参、异常处理和版本号。模型只是Skill内部的执行引擎,Skill本身是围绕模型封装的一层工程代码。这层工程代码包括:
- 元信息:名称、版本、作者、适用场景、依赖的其他Skill;
- 上下文构造函数:如何从全局上下文中截取本Skill需要的信息,控制Token开销;
- 执行业务逻辑:调用模型或工具的入口,包括重试策略、超时设置;
- 输出解析器:把模型返回的原始文本解析成结构化数据,校验字段完整性;
- 自检逻辑:对输出做质量检查,不达标就触发内部重试。
3.2 一个标准Skill脚本的结构拆解
拿我们的taste-skill举个例子。它的目录结构是这样的:
skills/ ├── taste-skill/ │ ├── SKILL.md │ ├── schema/ │ │ └── input.json │ ├── templates/ │ │ ├── user_story.md │ │ └── acceptance_criteria.md │ ├── scripts/ │ │ ├── main.py │ │ └── quality_check.py │ └── version.txtSKILL.md是技能包的入口描述文件,里面用YAML声明了基本信息和执行参数,核心部分长这样:
name: taste-skill version: 1.4.0 description: > 将模糊需求澄清为可验收的用户故事和验收标准。 内置需求质量评分,低于阈值时主动返问。 input_schema: schema/input.json output_schema: schema/output.json max_retries: 2 context_budget: 4000 dependencies: - utils/common-validator hooks: on_start: scripts/main.py --phase analyze on_retry: scripts/main.py --phase clarifyscripts/main.py是实际执行体,核心逻辑是“判断需求质量”和“引导澄清”。它分成几个阶段:先让模型从原始需求中提取业务规则,识别模糊点;然后根据模糊点列表决定是主动返问,还是直接生成用户故事草稿;最后把结果交给quality_check.py计算质量分,低于60分就触发再澄清一轮。
这种“模型+脚本”的组合方式,比单纯写Prompt稳得多。因为脚本可以做循环、条件判断、调用外部工具,而Prompt只能做一步到底。
3.3 调试Skill的三种手段
Skill开发最花时间的不是写第一个能跑的版本,而是后续的调试和优化。我调试Skill主要靠三个手段:
第一是输入输出快照。每个Skill调用结束后,Harness会把输入、输出、模型中间思考过程、Token消耗全部存成快照。出问题时可以直接回放,看是输入上下文给的不够,还是模型理解错了,还是输出解析器写崩了。这套快照机制是整个调试体系的基石,没有它你就是在盲调。
第二是最小化回归集。每个Skill都维护一组典型的输入样例,比如taste-skill里就有十几个需求样本,覆盖“一句话需求”“伪需求”“需求边界模糊”“需求与现有系统冲突”等典型场景。每次改完Skill,先把这组回归集跑一遍,看有没有把原本好的表现改坏。
第三是对比A/B输出。同一个输入,让新旧两个版本的Skill分别跑,人工对比输出质量差异。这是Skill版本升级时最直接的验证方式,比看指标数字直观得多。
3.4 技能包的版本管理与复用
Skill也是代码,必须纳入版本管理。我们用的是Git仓库管理,每个Skill目录就是一个独立仓库,用语义化版本号标记。主Harness的配置里明确锁死每个Skill的版本区间,避免“上游更新了Skill,下游流程突然行为变化”的事故。
复用这块,我们做了一个内部的“技能市场”,所有团队都可以把自己沉淀的Skill发布上去,包含说明文档和回归集。其他团队引入新Skill时必须先跑一遍该Skill自带的最小回归集,通过后才能接入全链路。这个机制帮我们沉淀了不少价值很高的内部Skill,比如针对特定数据库方言的代码生成优化、针对公司内部框架的架构设计模板。
4. 把8个Skill串成一条流水线:Harness编排实例
Skill是零件,Harness才是组装这些零件的那条流水线。这一节重点讲编排逻辑和链路压测方法。
4.1 用状态机思维定义Skill的上下游
企业级流程必须状态清晰。我们把全链路定义成一组状态,每个Skill的执行结果都会把流程推进到下一个状态:
需求澄清 → 技术方案 → 任务拆分 → 编码 → 审查 → 测试 → 文档 → 压测 → 完成执行中允许回跳:比如编码完成后审查发现P0问题,状态回退到编码;压测发现性能瓶颈,状态回到编码修复。Harness里维护一个状态机引擎,只有状态转移合法才允许继续,防止出现“还没审查就压测”的乱序操作。
这套状态机设计还有一个好处:可以在任何状态设置人工审批断点。比如我们规定,需求澄清结果必须人工确认才能进入架构设计;技术方案必须架构师签字才能进入任务拆分。审批断点不是摆设,它是企业流程和AI流程之间的安全阀。
4.2 一次典型迭代的完整编排流程
下面是我们实际跑一个“订单列表接口支持分页查询”需求时,Harness的完整编排过程:
- taste-skill接收原始需求,输出用户故事和验收标准。Harness将结果推送到IM机器人,需求负责人一键确认。
- 进入archify-skill,结合现有代码库结构输出技术方案。Harness自动用drawio-skill生成架构图,附加到方案里。架构师确认后进入下一步。
- split-skill把任务拆成“修改实体类”“新增查询接口”“补充DTO”“前端适配”四个任务单元,按文件依赖排序,标记为串行/并行。
- 两个并行任务直接分配给codex-skill的不同执行实例,各自生成代码diff。Harness自动合并diff并跑静态检查。
- review-skill对合并后的代码进行审查,发现了一个“分页参数未做最大限制”的P1问题,Harness触发codex-skill修复,重新走审查,通过。
- test-skill根据验收标准生成测试用例,覆盖分页边界条件(页码为0、页大小超过上限等),并执行单测。
- doc-skill自动更新接口文档、变更日志,并在代码库上生成一条独立分支。
- 分支合并后,loadtest-skill跑一轮针对该接口的压测,验证在每秒500并发下P95延迟低于200ms。压测通过后,Harness创建合并请求,通知人工Reviewer把关,最终合入主干。
整个流程从20分钟到40分钟不等,取决于代码复杂度。相比之下,纯人工流程至少大半天。
4.3 链路全量压测怎么做
“全链路压测”这个词经常被误解,有人以为就是跑一轮Jmeter叫压测。但全链路压测的关键在于:从入口到出口,所有组件都在真实负载下联调,并且有全链路追踪。
loadtest-skill的做法分四步:
- 第一步,达到参数解析。它会自动读取系统配置,识别压测涉及的服务节点、数据库、缓存、消息队列。
- 第二步,造数与隔离。在测试环境生成一批模拟数据,并标记这些数据的特征,避免污染生产或影响真实统计。
- 第三步,梯度压测。从100并发开始,每次翻倍,直到系统开始出现错误或延迟明显上升,记录拐点。
- 第四步,瓶颈分析。压测过程中采集每个节点的耗时、GC情况、慢查询日志,生成报告,指出最薄弱的环节。
报告会自动回传给codex-skill,作为修复的依据。比如之前一次压测发现“分页查询在大数据量下走了全表扫描”,loadtest-skill直接定位到慢SQL,codex-skill根据报告生成加索引的修复方案。
4.4 失败回滚与人工断点
Harness必须有失败回滚机制,不然AI越能干,出问题时越可怕。我们实现了两个级别的回滚:
- 环节级回滚:某个Skill失败后,只重跑那一个环节,不需要从头开始。比如test-skill生成的用例没跑过,Harness会调用codex-skill先修代码,再调test-skill重新生成用例,而不是回到需求澄清阶段。
- 状态快照回滚:每个状态的关键产物都会做快照,回滚时可以直接恢复某个SKill产出的上一版本。快照存储在独立的存储里,防止模型调用过程中的上下文污染导致数据丢失。
人工断点的设计原则是:AI能自主决策的尽量不打断人类,但涉及外部系统变更、代码合入、生产环境操作的步骤必须有审批。我们实际上把“人工确认”也做成了一个特殊节点,Harness会在IM群发审批卡片,等责任人点“同意”才会往下走。这样既保留AI流程的高效,又守住企业的合规底线。
5. 企业落地时最容易翻车的五个细节
这套Harness工程跑起来之后,我也踩了不少坑。下面这五个细节,是任何想落地AI Coding全链路的企业绕不开的坎。
5.1 模型选型不是越强越好
一开始我图省事,8个Skill全部用同一个大模型。后来发现有些环节用大模型纯属浪费——比如doc-skill生成变更日志,轻量模型完全够用,响应还快。反过来,archify-skill这种要高强度推理的环节,用轻量模型效果就很拉胯。现在我们的策略是三级分档:需求理解和架构设计用强推理模型,写代码和审查用代码能力强但成本中等的模型,文档和标格式化用低成本模型。Harness的Skill配置里可以指定model_engine,按环节切换。
5.2 上下文窗口的预算管理
AI Coding链路里最大的隐性成本是Token消耗。很多Skill在执行时会把整个代码库都塞进上下文,结果一次调用烧掉几万Token,还因为上下文过长导致长时间停顿。解决思路是给每个Skill设置上下文预算,比如codex-skill执行时只注入本次任务相关的文件、接口定义、当前代码库结构摘要,而不是全部代码。这个工作由Harness的上下文管理器负责,它维护一个“项目索引”,按需加载编码相关内容。
5.3 Skill之间的输出互相污染
Skill之间传递数据时,最容易出的问题是“脏数据”。比如taste-skill输出的验收标准里有一句“响应时间不超过500ms”,到了codex-skill居然被误读成业务规则,导致代码里写死了超时逻辑。这种问题的根源是Skill之间传递的结构化数据不够严格。解决办法是把每个Skill的输出做成强类型定义,并让下游Skill的输入校验器严格检查字段白名单,不认识的字段一律忽略。数据契约的意义就在这里——宁可截断,不能污染。
5.4 权限与安全边界
AI Coding的权限管理比传统开发更复杂,因为AI的操作不仅是写代码,还会调用各种工具。我们的原则是:AI能做的事,必须是工具允许范围内最小集合。比如codex-skill只允许操作代码库里特定目录,不允许访问密钥管理服务;loadtest-skill只允许在测试环境执行压测,不允许连接生产环境。Harness里有一个权限控制插件,对每个Skill声明了可调用的工具白名单位,越权调用直接拦截并告警。
5.5 让团队接受“AI同事”的过程管理
技术问题都好解决,真正难的是让团队接受一个“AI同事”。推行的时候遇到最大的阻力不是模型能力不够,而是工程师觉得“AI生成的代码风格不像人类写的”。为了解决这个问题,我们特意做了一个风格定制层,把团队的代码风格规则(命名、注释、格式化、设计模式偏好)做成一套配置,注入到codex-skill的上下文中。后来工程师们的反馈是:AI写出的代码越来越像团队里资深工程师写的,这说明风格定制层起了作用。
另外,推行节奏也有讲究。我们没有一步到位,而是先让AI只做“任务拆解+代码骨架生成”,人工审查填充细节;等团队信任了,再逐步放开codex-skill独立写代码、test-skill自动执行测试,最后才接入loadtest-skill这类的生产前置环节。每一步都留一个后门,可以让人类随时接管。
整套Harness工程从搭框架到8个Skill全部上线,前后花了大约两个月。最值得的投入不是那套编排引擎,而是每个Skill背后的输入输出契约和回归集。它们让AI Coding从“炫技”变成了“可控的流水线”。如果你也想在企业里推AI Coding,我的建议非常简单:不要急着让Agent写更多代码,先把你自己的研发流程拆成可以用Skill表达的关卡,再把关卡串起来,让AI在每一个关卡里当好“员工”,而不是当好“老板”。