1. 为什么"能跑通的代码"和"能交付的工程"之间隔着一道鸿沟如果你最近半年深度用过任何一款 AI 编程助手,大概率经历过这样的场景:你让它写一个功能,它三下五除二吐出一大段代码,你复制粘贴进去,跑起来了,心里一阵爽。然后第二天你想加个新功能,或者改一个边界条件,你发现它开始胡言乱语——要么把之前的逻辑改崩,要么引入一堆你根本没要求的依赖,要么干脆把整个文件重写一遍,把你昨天调好的细节全抹掉了。这不是模型不够聪明的问题。这是工作流缺失的问题。我把它类比成装修:你请了一个手艺很好的师傅,但你每次只跟他说"帮我把这面墙刷一下",他确实能刷得很好。可当你今天让他刷墙、明天让他改水电、后天让他装柜子,而他每次进门都失忆,不知道之前干了什么、不知道整体图纸长什么样,那这个房子迟早要出问题。AI Coding 的现状就是这样——单点能力极强,但缺乏一个承载上下文、约束行为、串联步骤的"工程化外壳"。这个外壳,就是标题里说的Agentic Harness Workflow 框架。Harness 这个词在工程语境里是"线束、约束装置、测试夹具"的意思,它不负责产生智能,它负责把智能装进一个可控的轨道里。Agentic 指的是让 AI 具备自主执行多步任务的能力。Workflow 则是把整个开发过程拆成有明确输入输出的阶段。三者合起来,核心目标只有一个:把 AI Coding 从"聊天式的一次性生成"变成"可复现、可回滚、可协作的工程化流程"。这篇文章适合谁看?如果你只是偶尔用 AI 写个正则、改个报错,那可能用不上这么重的东西。但如果你正在做以下任何一件事,这篇内容会非常对路:你在团队里推动 AI 辅助开发,但发现每个人用法五花八门,产出质量参差不齐;你在做需要多轮迭代的中大型项目,AI 每次改代码都像在赌博;你想把 AI 接入 CI/CD 或者自动化流水线,但不知道如何保证它的输出稳定;你自己就是那个"被 AI 改崩代码"改到心态爆炸的开发者。接下来我会从框架的核心构成讲起,拆解每个环节为什么这么设计,然后给出一套可以照着搭的最小可用流程,最后聊聊我在实际落地中踩过的坑和总结出的经验。全程不涉及任何具体平台的绑定,讲的是通用的工程思路。2. Harness 框架的四层结构:从"对话"到"流水线"的拆解要理解 Agentic Harness Workflow,先得把它的骨架看清楚。我把它拆成四层,从下往上分别是上下文层、约束层、编排层、验证层。这四层不是随便分的,每一层都在解决一个具体的失效模式。2.1 上下文层:解决"AI 每次都在失忆"的问题最底层是上下文层。AI 编程最大的痛点之一就是上下文窗口是有限的,而项目是无限的。你不可能每次把整个代码库塞进去,那样既慢又贵,而且模型在超长上下文里的注意力会稀释,反而抓不住重点。上下文层的核心任务是:在每次调用 AI 之前,动态组装出"这次任务真正需要的那部分信息"。这包括几个部分:项目级上下文:技术栈、目录结构、编码规范、依赖清单。这部分相对稳定,可以做成一个"项目画像"文件,每次带上。任务级上下文:当前要做的这个功能或修复,涉及哪些文件、哪些接口、哪些数据结构。这部分是动态检索出来的。历史级上下文:之前几轮做了什么决策、改了什么、为什么这么改。这部分最容易丢,也最致命。我见过太多人只做第一层,把项目结构一贴就开始让 AI 干活,结果 AI 不知道昨天已经决定不用某个库了,又给你引进来。上下文层做得好不好,直接决定了 AI 是"越用越懂你"还是"每次从零开始"。一个实用的做法是维护一个context/目录,里面放project.md(项目画像)、decisions.md(决策记录)、current-task.md(当前任务)。每次调用前,用一个简单的脚本把这几份文件拼成 prompt 的前缀。别小看这个动作,它能把 AI 的"返工率"降一大截。2.2 约束层:解决"AI 自由发挥改崩代码"的问题第二层是约束层。如果说上下文层是给 AI"喂信息",那约束层就是给 AI"立规矩"。AI 编程最让人抓狂的行为是什么?我列几个你肯定遇到过:你让它改一个函数,它顺手把整个文件重写了;你让它加个日志,它给你引入了一个新的日志库;你让它修个 bug,它把不相关的代码也"优化"了一遍;你让它用现有的工具函数,它自己又造了一个轮子。这些行为的根源是:AI 默认在"最大化完成任务",而不是"最小化改动范围"。约束层的作用就是把这个默认行为掰过来。约束层通常包含几类规则:约束类型具体内容解决什么问题改动范围约束只允许修改指定文件/函数防止顺手改崩无关代码依赖约束禁止引入新依赖,除非明确批准防止依赖膨胀风格约束遵循现有命名、注释、错误处理风格防止风格割裂输出格式约束必须以 diff 形式输出,而非整文件方便审查和回滚禁止行为约束不得删除现有测试、不得改公共接口防止破坏性改动这些约束不是写在文档里就完事了,而是要注入到每一次调用的 prompt 里,并且最好做成可配置的规则文件。比如你可以写一个rules.yaml,里面定义当前任务允许改动的文件白名单、禁止的操作类型,然后在组装 prompt 时自动带上。提示:约束层最容易犯的错是"约束太松等于没约束,约束太紧 AI 没法干活"。我的经验是,先松后紧——一开始只约束"改动范围"和"禁止新依赖"这两条最关键的,等流程跑顺了再逐步加细。2.3 编排层:解决"多步任务无法串联"的问题第三层是编排层,这是整个框架里最像"工作流"的部分。前面两层是静态的准备,编排层是动态的执行。一个真实的开发任务,从来不是"一步生成"能搞定的。它通常包含:理解需求 → 定位相关代码 → 设计方案 → 写代码 → 写测试 → 跑测试 → 修失败 → 提交。AI 如果只在"写代码"这一步发力,其他步骤全靠人肉衔接,那效率提升是有限的。编排层要做的是:把一个大任务拆成有明确输入输出的步骤,每一步都定义好"谁来做、用什么上下文、产出什么、如何验证"。这里的"谁"可以是 AI,也可以是人,还可以是脚本。举个具体的例子。假设任务是"给用户模块加一个手机号登录功能",编排层可以拆成:需求澄清步(AI 辅助):读需求文档,输出一份"我理解的需求 + 待确认问题清单",人来确认。代码定位步(脚本 + AI):用关键词检索出相关的用户模块文件,AI 判断哪些需要改。方案设计步(AI):基于定位结果,输出改动方案,包括要改哪些文件、加哪些接口、数据结构怎么变。编码步(AI):按方案逐个文件生成 diff。测试步(AI + 脚本):生成测试用例,跑测试,收集失败信息。修复步(AI):根据失败信息修复,回到第 5 步,直到通过。提交步(脚本):生成 commit message,提交。注意第 5、6 步形成了一个循环,这个循环是编排层最有价值的地方——它让 AI 具备了"自我纠错"的能力,而不是生成完就撒手不管。编排层的实现方式可以很轻,不一定非要上什么重型框架。一个 YAML 文件定义步骤,一个 Python 脚本按顺序执行,每步调用 AI 或脚本,把产出存到临时目录,就够用了。关键不在于工具多高级,而在于步骤边界是否清晰、每步的输入输出是否明确。2.4 验证层:解决"AI 说完成了但其实是错的"的问题最上层是验证层。AI 有一个非常危险的特点:它非常擅长用自信的语气说出错误的话。它说"我已经完成了修改",你一看,改的是另一个文件;它说"测试通过了",你一看,它把测试断言改松了。验证层的职责是:不信任 AI 的任何自我报告,一切以客观信号为准。客观信号包括:代码能否编译/通过静态检查;测试是否真的通过(而且测试本身没被篡改);diff 是否在允许的改动范围内;是否引入了新的依赖或新的警告。验证层最好做成自动化的门禁。也就是说,AI 的产出必须通过这一层才能进入下一步,通不过就打回去重做。这跟 CI 的思路是一样的——把"信任"换成"验证"。我在实际项目里,验证层至少包含三道检查:第一道是语法/类型检查,第二道是单元测试,第三道是 diff 范围检查(确认没改白名单外的文件)。这三道过了,才允许提交。别嫌麻烦,这三道检查拦下来的问题,比你事后 debug 花的时间少得多。3. 把框架跑起来:一套最小可用的落地流程讲完结构,接下来是实操。我不会给你一个"完美框架",而是给一套你今天下午就能搭起来跑的最小流程。这套流程的核心思想是:先用最土的办法把闭环跑通,再逐步优化。3.1 目录结构:先约定好"东西放哪"任何工程化流程的第一步都是约定目录。我推荐的结构是这样的:project/ ├── src/ # 你的源码 ├── tests/ # 测试 ├── .harness/ # 框架的工作目录 │ ├── context/ │ │ ├── project.md # 项目画像:技术栈、结构、规范 │ │ ├── decisions.md # 决策记录:做过哪些关键决定 │ │ └── current.md # 当前任务描述 │ ├── rules.yaml # 约束规则 │ ├── workflow.yaml # 编排步骤定义 │ ├── runs/ # 每次运行的产出 │ │ └── 2024-xx-xx-xx/ # 按时间戳分目录 │ └── prompts/ # 各步骤的 prompt 模板 └── ...这个结构的关键点是.harness/runs/目录。每一次 AI 参与的运行,所有中间产出都落盘到这个目录里。这样做的好处是:出问题了可以回溯,可以看到 AI 每一步到底看到了什么、产出了什么。我踩过的最大的坑就是早期没做落盘,AI 改崩了代码,我完全不知道它是基于什么上下文做出的决策,只能从头再来。3.2 项目画像文件:花半小时写,省几十小时project.md是整个框架里性价比最高的一个文件。它不需要多复杂,把下面这些写清楚就行:项目是干什么的,一句话;技术栈和主要依赖,列出来;目录结构说明,每个顶层目录放什么;编码规范:命名风格、错误处理方式、日志方式、注释要求;常用命令:怎么跑测试、怎么跑 lint、怎么启动本地环境;已知的坑:哪些地方容易出问题,哪些模块是历史遗留别乱动。我实测下来,认真写一份project.md,大概花半小时到一小时。但它能让 AI 的输出质量提升一个档次,因为它不用再猜你的项目长什么样了。很多人抱怨 AI 不懂自己的项目,其实是因为从来没告诉过它。注意:project.md要定期更新。项目演进后如果这个文件还是旧的,AI 会基于过时信息做决策,反而更危险。我的做法是每次大的架构调整后,顺手更新一下这个文件。3.3 约束规则文件:用 YAML 把"不许干的事"写死rules.yaml是约束层的落地。一个简单的例子:task: name: "add-phone-login" allowed_files: - "src/user/*.py" - "tests/user/*.py" forbidden_actions: - "delete_test" - "modify_public_api" - "add_dependency" output_format: "diff" max_files_changed: 5这个文件在每次调用 AI 时被读进来,拼进 prompt。同时,验证层也会读它,用来检查 AI 的产出是否越界。规则文件是"约束"和"验证"之间的桥梁——约束告诉 AI 别越界,验证检查 AI 有没有越界。这里有个经验:allowed_files尽量用通配符而不是精确路径,否则维护成本太高。但forbidden_actions要尽量具体,因为模糊的禁止项 AI 理解不了。比如你写"不要乱改",AI 不知道什么叫乱改;你写"不得删除 tests 目录下的任何文件",它就懂了。3.4 编排脚本:一个循环把"生成-验证-修复"串起来编排层我用一个 Python 脚本实现,核心逻辑就是一个循环:def run_workflow(task): context = load_context(task) rules = load_rules(task) for step in workflow_steps: prompt = build_prompt(step, context, rules) output = call_ai(prompt) save_output(step, output) if step.has_validation: result = validate(output, rules) if not result.passed: # 进入修复循环 output = repair_loop(output, result, context, rules) context = update_context(context, output) return final_output这个脚本本身不复杂,复杂的是build_prompt和validate这两个函数。build_prompt负责把上下文、规则、当前步骤的指令拼成一段清晰的 prompt;validate负责跑检查。我特别想强调repair_loop这个设计。当验证失败时,不要直接把失败信息丢给 AI 让它"再试一次",而是要把失败的具体信息 + 原始任务 + 当前产出一起给它,让它做针对性的修复。我试过直接说"测试没过,再改改",AI 经常乱改一通;而把具体的报错栈、失败的断言、期望值 vs 实际值都给它,修复成功率会高很多。3.5 验证门禁:三道检查缺一不可验证层我前面提了三道检查,这里展开说一下怎么落地。第一道:语法/类型检查。这个最简单,直接调用项目现有的 lint 和 type check 命令就行。比如 Python 项目跑ruff check和mypy,JS 项目跑eslint和tsc --noEmit。这一步能拦下大量低级错误。第二道:单元测试。跑测试有个坑:要防止 AI 篡改测试。所以验证层要先检查测试文件有没有被改动,如果改了,要么拒绝,要么人工审查。我一般把测试文件也放进allowed_files里,但会额外加一条规则:测试文件的改动必须单独标记出来供人确认。第三道:diff 范围检查。这一步是检查 AI 实际改动的文件是否都在allowed_files白名单里。如果它改了白名单外的文件,直接打回。这个检查用git diff --name-only就能实现,非常简单但极其有效。三道检查都过了,才允许进入提交步骤。这套门禁跑下来,AI 产出的"可用率"能从大概五六成提升到八成以上。4. 实战中最容易翻车的几个地方框架搭起来只是开始,真正难的是让它稳定运行。下面这几个坑,是我和身边同行反复踩过的,写出来帮你省点时间。4.1 上下文不是越多越好,而是要"精准"新手最容易犯的错是:既然上下文重要,那我就把所有能塞的都塞进去。结果 prompt 变得巨长,AI 反而抓不住重点,而且成本飙升。我做过一个对比实验:同一个任务,一次给 AI 塞了 8000 字的上下文(整个模块的代码 + 所有相关文档),另一次只给 1500 字(精准检索出的相关函数 + 任务描述)。结果后者的一次通过率反而更高。原因是长上下文里充满了干扰信息,模型在"大海捞针"时容易分心。所以上下文层的核心不是"多",而是"准"。怎么做到准?我的做法是:先用关键词检索缩小范围,再让 AI 判断哪些是真正相关的,最后只把相关的部分拼进 prompt。这个"检索-判断-筛选"的过程本身也可以让 AI 来做,但要有明确的筛选标准。4.2 约束太死会让 AI"摆烂"约束层有个反直觉的坑:约束太严,AI 会开始敷衍。比如你把allowed_files限制得特别死,AI 发现它想改的文件不在白名单里,它不会告诉你"我需要改这个文件",而是会在允许的范围内硬凑一个方案,结果就是打补丁式的烂代码。我的应对办法是:给 AI 一个"申请例外"的出口。在 prompt 里明确告诉它,如果它认为必须修改白名单外的文件,可以输出一个EXCEPTION_REQUEST块,说明理由。然后编排层捕获这个请求,交给人来决策。这样既保住了约束,又不会让 AI 憋着乱来。4.3 修复循环要有次数上限,否则会死循环前面说的repair_loop很好用,但如果不设上限,AI 可能陷入"改 A 崩 B,改 B 崩 A"的死循环。我遇到过最夸张的一次,AI 在同一个测试上反复修了十几轮,每轮都换个方式错。所以修复循环必须设上限,我一般设 3 次。3 次还修不好,就停下来,把当前状态、失败信息、AI 的修复尝试都记录下来,交给人来处理。这个"停下来"的动作很重要,它避免了无谓的 token 消耗,也避免了 AI 在错误方向上越走越远。4.4 决策记录比代码本身更值钱decisions.md这个文件,我一开始觉得可有可无,后来发现它是整个框架里最被低估的部分。AI 编程的一个隐性成本是:同样的决策会被反复讨论。比如"为什么这个模块不用某个流行的库",如果没记录,下次 AI 又会建议用那个库,你又得解释一遍。而有了决策记录,每次调用时带上,AI 就知道"哦,这个已经决定过了,不用再提"。决策记录的写法很简单,就是流水账:日期、决策内容、原因、影响范围。不用写得多正式,关键是持续记。我现在的习惯是,每次和 AI 讨论出一个重要决定,就顺手记一行。积累下来,这份文件成了项目的"记忆",AI 越用越顺手。4.5 别指望 AI 一次做对,要设计"可回滚"的流程最后一个坑,也是最根本的一个认知:AI 编程的本质是概率性的,它永远不可能 100% 一次做对。所以整个框架的设计前提,不是"如何让 AI 不出错",而是"如何让 AI 出错时,代价最小"。这就引出了"可回滚"的设计。具体做法包括:每次 AI 改动前,先git stash或者建一个临时分支;所有 AI 产出以 diff 形式保存,方便对比和回滚;验证不通过的产出,绝不合并到主分支;关键步骤前打 tag,出问题可以快速回到已知good状态。我现在的流程里,AI 的每一次改动都是在一个独立的临时分支上进行的,验证通过后才合并。这样即使 AI 把代码改得面目全非,我一个git checkout就回来了,心态非常稳。5. 从"能用"到"好用":几个进阶优化方向最小流程跑通之后,如果你想让这套框架更上一层楼,下面几个方向值得投入。5.1 把常用步骤做成可复用的"技能"当你发现某些步骤反复出现时(比如"生成测试""写 commit message""更新文档"),可以把它们抽成独立的"技能"模块。每个技能有自己的 prompt 模板、上下文需求、验证规则。这样编排层就可以像搭积木一样组合技能,而不是每次从头写 prompt。技能化的好处是一致性。同一个技能,无论谁调用、在什么任务里调用,行为都是一致的。这对团队协作特别重要——它把"某个人的 prompt 技巧"变成了"团队的资产"。5.2 用历史运行数据来优化 prompt.harness/runs/目录里积累的运行记录,是一座金矿。你可以分析:哪些步骤的失败率最高?哪些 prompt 模板容易让 AI 跑偏?哪些约束规则从来没被触发过(说明可能多余)?我做过一次简单的统计,发现"方案设计步"的返工率最高,原因是 prompt 里对"方案要包含哪些内容"定义得不够清楚。后来我把方案模板细化成"改动文件清单 + 接口变化 + 数据结构变化 + 风险点"四块,返工率明显下降。这种优化,只有靠数据才能发现,拍脑袋是想不出来的。5.3 人机分工的边界要动态调整框架跑久了,你会发现有些步骤 AI 做得比人好,有些步骤人必须介入。这个边界不是固定的,而是随着模型能力提升和项目熟悉度变化而移动的。我的经验是:从"人审所有产出"开始,逐步放开那些 AI 稳定做对的步骤。比如一开始每个 diff 我都要看,后来发现"生成测试"这一步 AI 做得很好,就改成只抽查;而"方案设计"这一步涉及架构决策,我始终保留人工确认。这个动态调整的过程,本质上是在用信任度换效率,但前提是你有验证层兜底。5.4 把框架本身也纳入版本管理最后一点,.harness/目录本身也要纳入 git 管理。因为你的 prompt 模板、约束规则、编排脚本,都是会演进的。把它们版本化,你才能知道"这次 AI 表现变差,是不是因为我昨天改了某条规则"。我甚至会给.harness/目录单独写一个简短的 CHANGELOG,记录每次调整的原因和效果。这份记录和decisions.md配合起来,构成了整个框架的"元记忆"——它不仅记录项目怎么做的,还记录"我们是怎么学会做这个项目的"。6. 我个人的一点体会这套框架我从去年开始折腾,中间推翻重来过两次。最大的体会是:Agentic Harness Workflow 的价值,不在于让 AI 写得更快,而在于让 AI 写得更"可控"。快是显而易见的,但快而不稳,在真实项目里是负资产。你省下的那点编码时间,会在 debug、回滚、解释"为什么代码变成这样"上成倍还回去。而一旦你把上下文、约束、编排、验证这四层搭起来,AI 就从"一个聪明但不可靠的实习生"变成了"一个听话且可追溯的工程助手"。另一个体会是:这套东西没有终点。模型在进化,项目在变化,你的框架也得跟着调。别指望一次搭好就一劳永逸。把它当成一个持续迭代的工程实践,而不是一个装好就忘的工具,心态会好很多。如果你现在就想动手,我的建议是:别一上来就搞全套。先写一份project.md,再定两条最关键的约束(改动范围 + 禁止新依赖),然后手动跑几次"生成-验证-修复"的循环,感受一下哪里卡。等你对流程有感觉了,再逐步把它脚本化、自动化。先跑通闭环,再谈优化,这个顺序别搞反。
1. 为什么"能跑通的代码"和"能交付的工程"之间隔着一道鸿沟如果你最近半年深度用过任何一款 AI 编程助手,大概率经历过这样的场景:你让它写一个功能,它三下五除二吐出一大段代码,你复制粘贴进去,跑起来了,心里一阵爽。然后第二天你想加个新功能,或者改一个边界条件,你发现它开始胡言乱语——要么把之前的逻辑改崩,要么引入一堆你根本没要求的依赖,要么干脆把整个文件重写一遍,把你昨天调好的细节全抹掉了。这不是模型不够聪明的问题。这是工作流缺失的问题。我把它类比成装修:你请了一个手艺很好的师傅,但你每次只跟他说"帮我把这面墙刷一下",他确实能刷得很好。可当你今天让他刷墙、明天让他改水电、后天让他装柜子,而他每次进门都失忆,不知道之前干了什么、不知道整体图纸长什么样,那这个房子迟早要出问题。AI Coding 的现状就是这样——单点能力极强,但缺乏一个承载上下文、约束行为、串联步骤的"工程化外壳"。这个外壳,就是标题里说的Agentic Harness Workflow 框架。Harness 这个词在工程语境里是"线束、约束装置、测试夹具"的意思,它不负责产生智能,它负责把智能装进一个可控的轨道里。Agentic 指的是让 AI 具备自主执行多步任务的能力。Workflow 则是把整个开发过程拆成有明确输入输出的阶段。三者合起来,核心目标只有一个:把 AI Coding 从"聊天式的一次性生成"变成"可复现、可回滚、可协作的工程化流程"。这篇文章适合谁看?如果你只是偶尔用 AI 写个正则、改个报错,那可能用不上这么重的东西。但如果你正在做以下任何一件事,这篇内容会非常对路:你在团队里推动 AI 辅助开发,但发现每个人用法五花八门,产出质量参差不齐;你在做需要多轮迭代的中大型项目,AI 每次改代码都像在赌博;你想把 AI 接入 CI/CD 或者自动化流水线,但不知道如何保证它的输出稳定;你自己就是那个"被 AI 改崩代码"改到心态爆炸的开发者。接下来我会从框架的核心构成讲起,拆解每个环节为什么这么设计,然后给出一套可以照着搭的最小可用流程,最后聊聊我在实际落地中踩过的坑和总结出的经验。全程不涉及任何具体平台的绑定,讲的是通用的工程思路。2. Harness 框架的四层结构:从"对话"到"流水线"的拆解要理解 Agentic Harness Workflow,先得把它的骨架看清楚。我把它拆成四层,从下往上分别是上下文层、约束层、编排层、验证层。这四层不是随便分的,每一层都在解决一个具体的失效模式。2.1 上下文层:解决"AI 每次都在失忆"的问题最底层是上下文层。AI 编程最大的痛点之一就是上下文窗口是有限的,而项目是无限的。你不可能每次把整个代码库塞进去,那样既慢又贵,而且模型在超长上下文里的注意力会稀释,反而抓不住重点。上下文层的核心任务是:在每次调用 AI 之前,动态组装出"这次任务真正需要的那部分信息"。这包括几个部分:项目级上下文:技术栈、目录结构、编码规范、依赖清单。这部分相对稳定,可以做成一个"项目画像"文件,每次带上。任务级上下文:当前要做的这个功能或修复,涉及哪些文件、哪些接口、哪些数据结构。这部分是动态检索出来的。历史级上下文:之前几轮做了什么决策、改了什么、为什么这么改。这部分最容易丢,也最致命。我见过太多人只做第一层,把项目结构一贴就开始让 AI 干活,结果 AI 不知道昨天已经决定不用某个库了,又给你引进来。上下文层做得好不好,直接决定了 AI 是"越用越懂你"还是"每次从零开始"。一个实用的做法是维护一个context/目录,里面放project.md(项目画像)、decisions.md(决策记录)、current-task.md(当前任务)。每次调用前,用一个简单的脚本把这几份文件拼成 prompt 的前缀。别小看这个动作,它能把 AI 的"返工率"降一大截。2.2 约束层:解决"AI 自由发挥改崩代码"的问题第二层是约束层。如果说上下文层是给 AI"喂信息",那约束层就是给 AI"立规矩"。AI 编程最让人抓狂的行为是什么?我列几个你肯定遇到过:你让它改一个函数,它顺手把整个文件重写了;你让它加个日志,它给你引入了一个新的日志库;你让它修个 bug,它把不相关的代码也"优化"了一遍;你让它用现有的工具函数,它自己又造了一个轮子。这些行为的根源是:AI 默认在"最大化完成任务",而不是"最小化改动范围"。约束层的作用就是把这个默认行为掰过来。约束层通常包含几类规则:约束类型具体内容解决什么问题改动范围约束只允许修改指定文件/函数防止顺手改崩无关代码依赖约束禁止引入新依赖,除非明确批准防止依赖膨胀风格约束遵循现有命名、注释、错误处理风格防止风格割裂输出格式约束必须以 diff 形式输出,而非整文件方便审查和回滚禁止行为约束不得删除现有测试、不得改公共接口防止破坏性改动这些约束不是写在文档里就完事了,而是要注入到每一次调用的 prompt 里,并且最好做成可配置的规则文件。比如你可以写一个rules.yaml,里面定义当前任务允许改动的文件白名单、禁止的操作类型,然后在组装 prompt 时自动带上。提示:约束层最容易犯的错是"约束太松等于没约束,约束太紧 AI 没法干活"。我的经验是,先松后紧——一开始只约束"改动范围"和"禁止新依赖"这两条最关键的,等流程跑顺了再逐步加细。2.3 编排层:解决"多步任务无法串联"的问题第三层是编排层,这是整个框架里最像"工作流"的部分。前面两层是静态的准备,编排层是动态的执行。一个真实的开发任务,从来不是"一步生成"能搞定的。它通常包含:理解需求 → 定位相关代码 → 设计方案 → 写代码 → 写测试 → 跑测试 → 修失败 → 提交。AI 如果只在"写代码"这一步发力,其他步骤全靠人肉衔接,那效率提升是有限的。编排层要做的是:把一个大任务拆成有明确输入输出的步骤,每一步都定义好"谁来做、用什么上下文、产出什么、如何验证"。这里的"谁"可以是 AI,也可以是人,还可以是脚本。举个具体的例子。假设任务是"给用户模块加一个手机号登录功能",编排层可以拆成:需求澄清步(AI 辅助):读需求文档,输出一份"我理解的需求 + 待确认问题清单",人来确认。代码定位步(脚本 + AI):用关键词检索出相关的用户模块文件,AI 判断哪些需要改。方案设计步(AI):基于定位结果,输出改动方案,包括要改哪些文件、加哪些接口、数据结构怎么变。编码步(AI):按方案逐个文件生成 diff。测试步(AI + 脚本):生成测试用例,跑测试,收集失败信息。修复步(AI):根据失败信息修复,回到第 5 步,直到通过。提交步(脚本):生成 commit message,提交。注意第 5、6 步形成了一个循环,这个循环是编排层最有价值的地方——它让 AI 具备了"自我纠错"的能力,而不是生成完就撒手不管。编排层的实现方式可以很轻,不一定非要上什么重型框架。一个 YAML 文件定义步骤,一个 Python 脚本按顺序执行,每步调用 AI 或脚本,把产出存到临时目录,就够用了。关键不在于工具多高级,而在于步骤边界是否清晰、每步的输入输出是否明确。2.4 验证层:解决"AI 说完成了但其实是错的"的问题最上层是验证层。AI 有一个非常危险的特点:它非常擅长用自信的语气说出错误的话。它说"我已经完成了修改",你一看,改的是另一个文件;它说"测试通过了",你一看,它把测试断言改松了。验证层的职责是:不信任 AI 的任何自我报告,一切以客观信号为准。客观信号包括:代码能否编译/通过静态检查;测试是否真的通过(而且测试本身没被篡改);diff 是否在允许的改动范围内;是否引入了新的依赖或新的警告。验证层最好做成自动化的门禁。也就是说,AI 的产出必须通过这一层才能进入下一步,通不过就打回去重做。这跟 CI 的思路是一样的——把"信任"换成"验证"。我在实际项目里,验证层至少包含三道检查:第一道是语法/类型检查,第二道是单元测试,第三道是 diff 范围检查(确认没改白名单外的文件)。这三道过了,才允许提交。别嫌麻烦,这三道检查拦下来的问题,比你事后 debug 花的时间少得多。3. 把框架跑起来:一套最小可用的落地流程讲完结构,接下来是实操。我不会给你一个"完美框架",而是给一套你今天下午就能搭起来跑的最小流程。这套流程的核心思想是:先用最土的办法把闭环跑通,再逐步优化。3.1 目录结构:先约定好"东西放哪"任何工程化流程的第一步都是约定目录。我推荐的结构是这样的:project/ ├── src/ # 你的源码 ├── tests/ # 测试 ├── .harness/ # 框架的工作目录 │ ├── context/ │ │ ├── project.md # 项目画像:技术栈、结构、规范 │ │ ├── decisions.md # 决策记录:做过哪些关键决定 │ │ └── current.md # 当前任务描述 │ ├── rules.yaml # 约束规则 │ ├── workflow.yaml # 编排步骤定义 │ ├── runs/ # 每次运行的产出 │ │ └── 2024-xx-xx-xx/ # 按时间戳分目录 │ └── prompts/ # 各步骤的 prompt 模板 └── ...这个结构的关键点是.harness/runs/目录。每一次 AI 参与的运行,所有中间产出都落盘到这个目录里。这样做的好处是:出问题了可以回溯,可以看到 AI 每一步到底看到了什么、产出了什么。我踩过的最大的坑就是早期没做落盘,AI 改崩了代码,我完全不知道它是基于什么上下文做出的决策,只能从头再来。3.2 项目画像文件:花半小时写,省几十小时project.md是整个框架里性价比最高的一个文件。它不需要多复杂,把下面这些写清楚就行:项目是干什么的,一句话;技术栈和主要依赖,列出来;目录结构说明,每个顶层目录放什么;编码规范:命名风格、错误处理方式、日志方式、注释要求;常用命令:怎么跑测试、怎么跑 lint、怎么启动本地环境;已知的坑:哪些地方容易出问题,哪些模块是历史遗留别乱动。我实测下来,认真写一份project.md,大概花半小时到一小时。但它能让 AI 的输出质量提升一个档次,因为它不用再猜你的项目长什么样了。很多人抱怨 AI 不懂自己的项目,其实是因为从来没告诉过它。注意:project.md要定期更新。项目演进后如果这个文件还是旧的,AI 会基于过时信息做决策,反而更危险。我的做法是每次大的架构调整后,顺手更新一下这个文件。3.3 约束规则文件:用 YAML 把"不许干的事"写死rules.yaml是约束层的落地。一个简单的例子:task: name: "add-phone-login" allowed_files: - "src/user/*.py" - "tests/user/*.py" forbidden_actions: - "delete_test" - "modify_public_api" - "add_dependency" output_format: "diff" max_files_changed: 5这个文件在每次调用 AI 时被读进来,拼进 prompt。同时,验证层也会读它,用来检查 AI 的产出是否越界。规则文件是"约束"和"验证"之间的桥梁——约束告诉 AI 别越界,验证检查 AI 有没有越界。这里有个经验:allowed_files尽量用通配符而不是精确路径,否则维护成本太高。但forbidden_actions要尽量具体,因为模糊的禁止项 AI 理解不了。比如你写"不要乱改",AI 不知道什么叫乱改;你写"不得删除 tests 目录下的任何文件",它就懂了。3.4 编排脚本:一个循环把"生成-验证-修复"串起来编排层我用一个 Python 脚本实现,核心逻辑就是一个循环:def run_workflow(task): context = load_context(task) rules = load_rules(task) for step in workflow_steps: prompt = build_prompt(step, context, rules) output = call_ai(prompt) save_output(step, output) if step.has_validation: result = validate(output, rules) if not result.passed: # 进入修复循环 output = repair_loop(output, result, context, rules) context = update_context(context, output) return final_output这个脚本本身不复杂,复杂的是build_prompt和validate这两个函数。build_prompt负责把上下文、规则、当前步骤的指令拼成一段清晰的 prompt;validate负责跑检查。我特别想强调repair_loop这个设计。当验证失败时,不要直接把失败信息丢给 AI 让它"再试一次",而是要把失败的具体信息 + 原始任务 + 当前产出一起给它,让它做针对性的修复。我试过直接说"测试没过,再改改",AI 经常乱改一通;而把具体的报错栈、失败的断言、期望值 vs 实际值都给它,修复成功率会高很多。3.5 验证门禁:三道检查缺一不可验证层我前面提了三道检查,这里展开说一下怎么落地。第一道:语法/类型检查。这个最简单,直接调用项目现有的 lint 和 type check 命令就行。比如 Python 项目跑ruff check和mypy,JS 项目跑eslint和tsc --noEmit。这一步能拦下大量低级错误。第二道:单元测试。跑测试有个坑:要防止 AI 篡改测试。所以验证层要先检查测试文件有没有被改动,如果改了,要么拒绝,要么人工审查。我一般把测试文件也放进allowed_files里,但会额外加一条规则:测试文件的改动必须单独标记出来供人确认。第三道:diff 范围检查。这一步是检查 AI 实际改动的文件是否都在allowed_files白名单里。如果它改了白名单外的文件,直接打回。这个检查用git diff --name-only就能实现,非常简单但极其有效。三道检查都过了,才允许进入提交步骤。这套门禁跑下来,AI 产出的"可用率"能从大概五六成提升到八成以上。4. 实战中最容易翻车的几个地方框架搭起来只是开始,真正难的是让它稳定运行。下面这几个坑,是我和身边同行反复踩过的,写出来帮你省点时间。4.1 上下文不是越多越好,而是要"精准"新手最容易犯的错是:既然上下文重要,那我就把所有能塞的都塞进去。结果 prompt 变得巨长,AI 反而抓不住重点,而且成本飙升。我做过一个对比实验:同一个任务,一次给 AI 塞了 8000 字的上下文(整个模块的代码 + 所有相关文档),另一次只给 1500 字(精准检索出的相关函数 + 任务描述)。结果后者的一次通过率反而更高。原因是长上下文里充满了干扰信息,模型在"大海捞针"时容易分心。所以上下文层的核心不是"多",而是"准"。怎么做到准?我的做法是:先用关键词检索缩小范围,再让 AI 判断哪些是真正相关的,最后只把相关的部分拼进 prompt。这个"检索-判断-筛选"的过程本身也可以让 AI 来做,但要有明确的筛选标准。4.2 约束太死会让 AI"摆烂"约束层有个反直觉的坑:约束太严,AI 会开始敷衍。比如你把allowed_files限制得特别死,AI 发现它想改的文件不在白名单里,它不会告诉你"我需要改这个文件",而是会在允许的范围内硬凑一个方案,结果就是打补丁式的烂代码。我的应对办法是:给 AI 一个"申请例外"的出口。在 prompt 里明确告诉它,如果它认为必须修改白名单外的文件,可以输出一个EXCEPTION_REQUEST块,说明理由。然后编排层捕获这个请求,交给人来决策。这样既保住了约束,又不会让 AI 憋着乱来。4.3 修复循环要有次数上限,否则会死循环前面说的repair_loop很好用,但如果不设上限,AI 可能陷入"改 A 崩 B,改 B 崩 A"的死循环。我遇到过最夸张的一次,AI 在同一个测试上反复修了十几轮,每轮都换个方式错。所以修复循环必须设上限,我一般设 3 次。3 次还修不好,就停下来,把当前状态、失败信息、AI 的修复尝试都记录下来,交给人来处理。这个"停下来"的动作很重要,它避免了无谓的 token 消耗,也避免了 AI 在错误方向上越走越远。4.4 决策记录比代码本身更值钱decisions.md这个文件,我一开始觉得可有可无,后来发现它是整个框架里最被低估的部分。AI 编程的一个隐性成本是:同样的决策会被反复讨论。比如"为什么这个模块不用某个流行的库",如果没记录,下次 AI 又会建议用那个库,你又得解释一遍。而有了决策记录,每次调用时带上,AI 就知道"哦,这个已经决定过了,不用再提"。决策记录的写法很简单,就是流水账:日期、决策内容、原因、影响范围。不用写得多正式,关键是持续记。我现在的习惯是,每次和 AI 讨论出一个重要决定,就顺手记一行。积累下来,这份文件成了项目的"记忆",AI 越用越顺手。4.5 别指望 AI 一次做对,要设计"可回滚"的流程最后一个坑,也是最根本的一个认知:AI 编程的本质是概率性的,它永远不可能 100% 一次做对。所以整个框架的设计前提,不是"如何让 AI 不出错",而是"如何让 AI 出错时,代价最小"。这就引出了"可回滚"的设计。具体做法包括:每次 AI 改动前,先git stash或者建一个临时分支;所有 AI 产出以 diff 形式保存,方便对比和回滚;验证不通过的产出,绝不合并到主分支;关键步骤前打 tag,出问题可以快速回到已知good状态。我现在的流程里,AI 的每一次改动都是在一个独立的临时分支上进行的,验证通过后才合并。这样即使 AI 把代码改得面目全非,我一个git checkout就回来了,心态非常稳。5. 从"能用"到"好用":几个进阶优化方向最小流程跑通之后,如果你想让这套框架更上一层楼,下面几个方向值得投入。5.1 把常用步骤做成可复用的"技能"当你发现某些步骤反复出现时(比如"生成测试""写 commit message""更新文档"),可以把它们抽成独立的"技能"模块。每个技能有自己的 prompt 模板、上下文需求、验证规则。这样编排层就可以像搭积木一样组合技能,而不是每次从头写 prompt。技能化的好处是一致性。同一个技能,无论谁调用、在什么任务里调用,行为都是一致的。这对团队协作特别重要——它把"某个人的 prompt 技巧"变成了"团队的资产"。5.2 用历史运行数据来优化 prompt.harness/runs/目录里积累的运行记录,是一座金矿。你可以分析:哪些步骤的失败率最高?哪些 prompt 模板容易让 AI 跑偏?哪些约束规则从来没被触发过(说明可能多余)?我做过一次简单的统计,发现"方案设计步"的返工率最高,原因是 prompt 里对"方案要包含哪些内容"定义得不够清楚。后来我把方案模板细化成"改动文件清单 + 接口变化 + 数据结构变化 + 风险点"四块,返工率明显下降。这种优化,只有靠数据才能发现,拍脑袋是想不出来的。5.3 人机分工的边界要动态调整框架跑久了,你会发现有些步骤 AI 做得比人好,有些步骤人必须介入。这个边界不是固定的,而是随着模型能力提升和项目熟悉度变化而移动的。我的经验是:从"人审所有产出"开始,逐步放开那些 AI 稳定做对的步骤。比如一开始每个 diff 我都要看,后来发现"生成测试"这一步 AI 做得很好,就改成只抽查;而"方案设计"这一步涉及架构决策,我始终保留人工确认。这个动态调整的过程,本质上是在用信任度换效率,但前提是你有验证层兜底。5.4 把框架本身也纳入版本管理最后一点,.harness/目录本身也要纳入 git 管理。因为你的 prompt 模板、约束规则、编排脚本,都是会演进的。把它们版本化,你才能知道"这次 AI 表现变差,是不是因为我昨天改了某条规则"。我甚至会给.harness/目录单独写一个简短的 CHANGELOG,记录每次调整的原因和效果。这份记录和decisions.md配合起来,构成了整个框架的"元记忆"——它不仅记录项目怎么做的,还记录"我们是怎么学会做这个项目的"。6. 我个人的一点体会这套框架我从去年开始折腾,中间推翻重来过两次。最大的体会是:Agentic Harness Workflow 的价值,不在于让 AI 写得更快,而在于让 AI 写得更"可控"。快是显而易见的,但快而不稳,在真实项目里是负资产。你省下的那点编码时间,会在 debug、回滚、解释"为什么代码变成这样"上成倍还回去。而一旦你把上下文、约束、编排、验证这四层搭起来,AI 就从"一个聪明但不可靠的实习生"变成了"一个听话且可追溯的工程助手"。另一个体会是:这套东西没有终点。模型在进化,项目在变化,你的框架也得跟着调。别指望一次搭好就一劳永逸。把它当成一个持续迭代的工程实践,而不是一个装好就忘的工具,心态会好很多。如果你现在就想动手,我的建议是:别一上来就搞全套。先写一份project.md,再定两条最关键的约束(改动范围 + 禁止新依赖),然后手动跑几次"生成-验证-修复"的循环,感受一下哪里卡。等你对流程有感觉了,再逐步把它脚本化、自动化。先跑通闭环,再谈优化,这个顺序别搞反。