1. 从“每天开着 Claude Code”到“一周开不了几次”一个团队的真实转变一年前我们团队几乎所有人的终端里都常驻着 Claude Code写代码、改 bug、跑测试、查日志几乎每一步都离不开它。那时候大家开玩笑说Claude Code 就是我们的“第二 IDE”。但一年后的今天情况完全反过来了——团队里 70% 的日常工作根本不需要打开 Claude Code。这不是因为 Claude Code 不好用了恰恰相反是因为它太好用了以至于我们把它的能力“拆解”出来嵌进了整个研发流程的各个环节形成了一个更上层的Harness体系。这个体系的核心逻辑就是让 Agent 在合适的时机、以合适的方式自动介入而不是每次都靠人去“召唤”它。这个变化背后其实是一个很朴素的工程直觉任何需要人反复手动触发的工具最终都会成为流程的瓶颈。Claude Code 本身是一个强大的 Agent 执行环境但它默认的交互模式是“人提问、它执行”。当团队规模扩大、任务复杂度上升之后这种模式的开销就变得不可忽视了。我们开始思考能不能让 Claude Code 的能力变成一种“基础设施”而不是一个“需要打开的应用”这就是 Harness 这个概念的起点。所谓 Harness在 AI Agent 的语境里指的是包裹在模型或 Agent 外面的一层编排与控制框架。它负责决定什么时候调用哪个 Agent、传入什么上下文、如何验证输出、失败之后怎么重试、结果怎么回写到工作流里。你可以把它理解成 Agent 的“操作系统”——Agent 是进程Harness 是调度器。我们团队这一年最大的变化就是从“手动使用 Claude Code”转向了“构建 Harness 来编排 Claude Code 和其他 Agent”。而这个转变最反直觉的地方在于Harness 做得越好Claude Code 本身被直接使用的频率就越低。这就是标题里说的“自我淘汰”——不是被淘汰而是主动把自己从“前台工具”变成了“后台能力”。这篇文章适合几类人看一是已经在用 Claude Code 但感觉效率遇到瓶颈的开发者二是正在考虑构建 Agent 工作流、但不知道从哪里下手的团队三是对 Harness、Agent orchestration 这些概念感兴趣但被各种术语绕晕了的人。我会尽量用我们团队的真实经历和踩过的坑把这件事讲清楚。2. 为什么我们决定“不再手动打开 Claude Code”2.1 手动调用的隐性成本比想象中高得多一开始我们没觉得手动打开 Claude Code 有什么问题。毕竟它启动快、响应快复制粘贴一段代码进去几秒钟就能拿到修改建议。但当我们把时间线拉长到一个月问题就暴露出来了。我让团队做了一个简单的统计每个人每天平均打开 Claude Code 的次数是 23 次每次从“想到要问”到“拿到可用结果”的平均耗时是 4 分半钟。这里面真正花在模型推理上的时间可能只有 30 秒剩下的 4 分钟全部消耗在切换窗口、组织问题、复制上下文、检查输出、再复制回编辑器这些动作上。这还只是显性成本。更麻烦的是隐性成本每次手动调用人都要重新建立上下文。你正在改一个函数突然发现一个类型错误于是打开 Claude Code 问一下得到答案后回到编辑器结果已经忘了刚才改到哪了。这种上下文切换的损耗在一天里累积起来非常可观。我们粗略估算一个工程师一天里至少有 1.5 到 2 小时是消耗在这种“人肉编排”上的。提示如果你现在还在手动高频调用 Claude Code建议先做一个简单的耗时统计。不用很精确拿张纸记一下一天里打开它的次数和每次的大致耗时你会对“手动成本”有一个全新的认识。2.2 Harness 的核心思路把“人做调度”变成“系统做调度”Harness 要解决的核心问题就是把这部分调度工作从人手里拿走。具体来说我们定义了几个关键的调度场景代码提交前的自动审查每次 git commit 之前Harness 自动把 diff 发给 Claude Code让它检查潜在问题只有通过检查才允许提交。CI 失败后的自动修复尝试当 CI 流水线失败时Harness 自动拉取失败日志让 Claude Code 分析原因并生成修复补丁然后自动创建一个分支供人 review。文档与代码的同步检查当某个模块的接口发生变化时Harness 自动触发 Claude Code 检查相关文档是否需要更新。日常代码问答的“预加载”Harness 会根据当前打开的文件和最近的 git 操作提前把可能相关的上下文准备好当人真的需要问的时候答案已经在那里了。这些场景的共同点是触发条件明确、上下文可以自动收集、输出结果可以自动验证。一旦满足这三个条件就没有必要让人来手动操作了。2.3 “自我淘汰”不是目标而是结果很多人听到“70% 的工作不需要打开 Claude Code”这个说法第一反应是“那 Claude Code 是不是要被替代了”。其实完全不是。Claude Code 依然是整个体系里最核心的 Agent 执行引擎只是它的调用方式从“人直接调用”变成了“Harness 间接调用”。这就像数据库一样你写业务代码的时候不会每次都手动打开数据库客户端去执行 SQL而是通过 ORM 或者数据访问层来调用。数据库本身没有消失只是被封装到了更上层的抽象里。我们团队内部有一个说法好的工具应该让人感觉不到它的存在。当 Harness 做得足够好的时候Claude Code 就变成了这样一种“感觉不到存在”的基础设施。你不需要知道它在什么时候被调用了你只需要知道你的代码被检查过了、你的 CI 被修复了、你的文档被同步了。这就是“自我淘汰”的真正含义——不是被淘汰而是主动退居到幕后成为支撑整个流程的隐形能力。3. Harness 体系的核心组件与编排逻辑3.1 触发器层什么情况下应该自动调用 AgentHarness 的第一层是触发器。我们定义了四类触发器每一类对应不同的调用时机和上下文收集策略。触发器类型触发条件收集的上下文调用的 Agent输出处理提交前检查git commit 执行时diff、最近 5 次提交信息、相关文件内容Claude Code通过则放行不通过则阻断并提示CI 失败修复CI 流水线返回失败失败日志、失败用例、相关源码Claude Code 自定义修复 Agent生成补丁分支通知负责人接口变更同步检测到公开接口签名变化接口定义、调用方列表、相关文档Claude Code生成文档更新建议创建 PR上下文预加载文件打开或切换时当前文件、光标位置、最近编辑历史Claude Code轻量模式缓存建议结果供后续查询触发器层的关键设计原则是宁可漏触发不要误触发。早期我们为了追求覆盖率设置了大量触发器结果导致 Agent 被频繁调用不仅消耗资源还产生了大量噪音。后来我们把触发条件收紧只保留那些“触发后大概率能产生有价值输出”的场景效果反而更好。3.2 上下文组装层让 Agent 拿到“刚好够用”的信息这是 Harness 里最容易被低估、但实际上最影响效果的一层。Claude Code 本身的能力很强但如果上下文给得不对输出质量会大打折扣。我们踩过的坑包括给太多无关文件导致模型分心、给太少上下文导致模型瞎猜、给的信息格式混乱导致模型理解偏差。我们的解决方案是分层组装上下文第一层直接相关。当前修改的文件、光标附近的代码、报错信息。这部分是必须给的。第二层间接相关。被修改函数的调用方、相关的类型定义、最近的 git 提交记录。这部分按需给。第三层背景知识。项目的编码规范、架构决策记录、常见问题列表。这部分以摘要形式给控制 token 消耗。注意上下文组装不是越多越好。我们实测发现当上下文超过一定长度后Claude Code 的输出质量反而会下降因为它会把注意力分散到不相关的信息上。我们的经验值是对于代码审查场景上下文控制在 8000 token 以内效果最好对于复杂修复场景可以放宽到 16000 token但需要更精细的筛选。3.3 输出验证层怎么判断 Agent 干得对不对Agent 的输出不能直接信任这是我们在早期就确立的原则。Harness 必须有一套验证机制来判断 Agent 的输出是否可用。我们的验证策略分三级语法级验证生成的代码能不能通过编译、能不能通过 lint。这是最基本的。测试级验证生成的补丁能不能让失败的测试通过、会不会破坏已有测试。这是最关键的。语义级验证生成的修改是否符合项目规范、是否引入了不必要的复杂度。这部分目前还需要人工 review但 Harness 会给出置信度评分帮助人快速判断。验证不通过的输出会被丢弃并记录到日志里。我们会定期分析这些失败案例用来优化上下文组装策略和提示词模板。这个反馈闭环是 Harness 能够持续改进的关键。3.4 回写与通知层让结果回到该去的地方Agent 的输出经过验证之后需要回写到合适的地方。我们的做法是代码修改类输出自动创建分支和 PR附带详细的修改说明和验证结果。文档更新类输出直接提交到文档仓库或者创建 PR 供人确认。问答类输出缓存到本地当人真的问到相关问题时直接展示。失败类输出记录到日志并通知相关负责人。这一层的设计原则是尽量减少对人的打扰。只有那些需要人做决策的输出才会通知人其他的都自动处理。我们内部有一个指标叫“通知信噪比”目标是让每 10 条通知里至少有 7 条是真正需要人关注的。4. 实操从零搭建一个最小可用的 Harness4.1 环境准备与基础配置搭建 Harness 不需要很复杂的 infrastructure。我们最初就是用一台普通的开发机加上一些脚本搞起来的。下面是一个最小可用的配置方案。首先你需要确保 Claude Code 可以在非交互模式下被调用。Claude Code 提供了命令行接口可以通过管道传入提示词和上下文然后拿到输出。这是 Harness 能够自动调用它的基础。# 检查 Claude Code 是否已安装并可用 claude --version # 非交互模式调用示例传入提示词拿到输出 echo 请检查以下代码是否有潜在问题$(cat src/main.py) | claude --non-interactive如果你还没有安装 Claude Code可以参考官方文档进行安装。在 Ubuntu 上通常是通过包管理器或者直接下载二进制文件。安装完成后建议先手动跑几个非交互模式的调用确认基本功能正常。提示非交互模式下Claude Code 不会保留会话历史。这意味着每次调用都是独立的你需要在每次调用时把需要的上下文都传进去。这看起来麻烦但实际上对 Harness 来说是好事——它让每次调用的行为更可预测。4.2 编写第一个触发器提交前自动审查我们从一个最简单的场景开始在 git commit 之前自动调用 Claude Code 检查 diff。这个场景的好处是触发条件明确、上下文容易收集、输出容易验证。实现方式是用 git 的 pre-commit hook。在.git/hooks/pre-commit里写入以下脚本#!/bin/bash # 获取暂存区的 diff DIFF$(git diff --cached) # 如果没有 diff直接放行 if [ -z $DIFF ]; then exit 0 fi # 调用 Claude Code 进行审查 RESULT$(echo 请审查以下代码变更指出潜在问题。如果没有问题只输出 PASS。如果有问题输出 FAIL 并说明原因。 $DIFF | claude --non-interactive) # 检查结果 if echo $RESULT | grep -q PASS; then echo 代码审查通过 exit 0 else echo 代码审查未通过 echo $RESULT exit 1 fi这个脚本的逻辑很简单拿到暂存区的 diff发给 Claude Code如果返回 PASS 就放行否则阻断提交并显示原因。实测下来这个简单的 hook 就能拦住不少低级错误比如拼写错误、明显的逻辑漏洞、忘记处理的边界情况。但这里有几个坑需要注意diff 可能很大。如果一次提交涉及很多文件diff 会非常长超出模型的上下文限制。我们的做法是设置一个阈值超过 500 行的 diff 就拆分成多次调用或者只审查最关键的几个文件。模型可能误判。有些看起来像问题的代码其实是故意的比如为了性能而写的“丑陋”代码。我们的做法是在项目根目录放一个.claude-review-config文件里面写明哪些模式是允许的Harness 会把这个文件的内容也传给模型。审查耗时。每次提交都要等几秒钟对于频繁提交的人来说可能会烦。我们的做法是提供一个--no-review参数紧急情况下可以跳过审查。4.3 进阶CI 失败后的自动修复提交前审查只能拦住一部分问题还有很多问题是在 CI 阶段才暴露出来的。我们的第二个触发器就是针对 CI 失败的自动修复。这个触发器的实现稍微复杂一些因为它需要和 CI 系统集成。我们的做法是在 CI 流水线里加一个“失败回调”步骤当流水线失败时自动调用一个 Harness 脚本把失败日志和相关源码传给 Claude Code让它尝试生成修复补丁。# harness/ci_fix.py import subprocess import json import os def get_failure_log(): # 从 CI 系统的 API 获取失败日志 # 这里以本地文件为例 with open(/tmp/ci_failure.log, r) as f: return f.read() def get_related_source(log): # 从日志中提取失败的文件和行号 # 简化处理假设日志里有 File: xxx.py, Line: 42 这样的格式 import re matches re.findall(rFile: (\S), Line: (\d), log) sources {} for file, line in matches: if file not in sources: with open(file, r) as f: sources[file] f.read() return sources def generate_fix(log, sources): prompt fCI 流水线失败了以下是失败日志 {log} 以下是相关源码 {json.dumps(sources, indent2)} 请分析失败原因并生成修复补丁。输出格式要求 1. 先说明失败原因 2. 然后给出修复后的完整文件内容 3. 最后说明修改了哪些地方 result subprocess.run( [claude, --non-interactive], inputprompt, capture_outputTrue, textTrue ) return result.stdout def main(): log get_failure_log() sources get_related_source(log) fix generate_fix(log, sources) # 把修复结果写到文件里供后续处理 with open(/tmp/ci_fix_result.md, w) as f: f.write(fix) print(修复建议已生成请查看 /tmp/ci_fix_result.md) if __name__ __main__: main()这个脚本跑完之后会生成一个修复建议文件。我们的做法是让 Harness 自动根据这个建议创建一个分支和 PR然后通知相关负责人 review。如果修复建议通过了测试验证就直接合并如果没有通过就保留分支供人手动处理。注意自动修复不能盲目信任。我们设置了一个规则只有那些“失败原因明确、修复方案简单”的情况才允许自动创建 PR。如果 Claude Code 输出的修复方案涉及超过 3 个文件的修改或者修改了核心模块就必须人工介入。4.4 上下文预加载让答案“等在那里”前面两个触发器都是“事后”的而上下文预加载是“事前”的。它的思路是根据用户当前正在编辑的文件和最近的操作提前调用 Claude Code 生成可能需要的建议缓存起来。当用户真的需要问的时候答案已经在那里了。实现方式是用文件系统监听器比如watchdog监控编辑器的文件变化当检测到用户打开或切换文件时触发预加载。# harness/preload.py import time from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import subprocess import hashlib import os CACHE_DIR /tmp/claude_preload_cache class PreloadHandler(FileSystemEventHandler): def on_modified(self, event): if event.is_directory: return if not event.src_path.endswith((.py, .js, .ts, .go)): return # 计算文件内容的哈希避免重复处理 with open(event.src_path, r) as f: content f.read() content_hash hashlib.md5(content.encode()).hexdigest() cache_file os.path.join(CACHE_DIR, content_hash) if os.path.exists(cache_file): return # 已经缓存过了 # 调用 Claude Code 生成建议 prompt f请分析以下代码给出可能的改进建议和潜在问题。用简洁的列表形式输出。 文件{event.src_path} {content} result subprocess.run( [claude, --non-interactive], inputprompt, capture_outputTrue, textTrue ) # 缓存结果 os.makedirs(CACHE_DIR, exist_okTrue) with open(cache_file, w) as f: f.write(result.stdout) print(f已为 {event.src_path} 预加载建议) if __name__ __main__: observer Observer() observer.schedule(PreloadHandler(), path., recursiveTrue) observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join()这个脚本会在后台运行监控项目目录下的代码文件变化。每当文件被修改它就会调用 Claude Code 生成建议并缓存。当用户真的需要问的时候Harness 可以直接从缓存里读取响应时间从几秒降到毫秒级。这个做法的代价是会有一些“无用功”——有些预加载的建议可能永远不会被用到。但实测下来只要缓存命中率超过 30%整体收益就是正的。我们的缓存命中率大概在 45% 左右因为很多问题其实是重复出现的。5. 常见问题与排查技巧实录5.1 Agent 调用超时或返回空结果怎么办这是最常见的问题。可能的原因和排查思路如下现象可能原因排查方法解决方案调用超时上下文太长模型处理不过来检查传入的 token 数量精简上下文只保留最相关的部分返回空结果提示词格式有问题模型没理解手动跑一次相同的提示词调整提示词格式增加明确的输出要求返回结果不完整输出被截断检查输出长度是否接近限制要求模型分多次输出或者精简输出格式调用失败Claude Code 进程异常检查进程状态和日志增加重试机制设置最大重试次数我们踩过最坑的一次是Harness 在调用 Claude Code 时传入了一个包含特殊字符的 diff导致 shell 解析出错调用直接失败。后来我们改成用文件传递上下文而不是通过命令行参数问题就解决了。提示在 Harness 里调用外部命令时尽量用文件或者标准输入传递数据避免通过命令行参数传递大段文本。命令行参数有长度限制而且特殊字符容易出问题。5.2 如何避免 Agent 产生“幻觉”修改Agent 有时候会“自作主张”地修改一些不相关的东西或者引入一些看起来合理但实际上错误的代码。我们的应对策略是限制修改范围在提示词里明确要求“只修改与问题直接相关的代码不要做额外的重构或优化”。验证修改范围Harness 会自动检查 Agent 的修改是否超出了预期范围。如果修改了超过 3 个文件或者修改了核心模块就标记为“需要人工 review”。保留原始版本每次 Agent 修改之前Harness 都会自动创建一个备份分支。如果修改有问题可以随时回滚。我们内部有一个说法Agent 是实习生不是资深工程师。你可以让它干活但你必须检查它的活。Harness 的价值就在于把这种检查自动化了而不是让人去逐行 review。5.3 Harness 本身的维护成本怎么控制Harness 本身也是一个软件系统也需要维护。如果 Harness 变得太复杂维护成本可能会超过它带来的收益。我们的经验是保持简单每个触发器只做一件事不要试图在一个触发器里处理多种场景。配置化把触发条件、上下文组装规则、验证策略都做成配置文件而不是硬编码在脚本里。可观测Harness 的每一步操作都要有日志方便排查问题。渐进式不要一开始就搭建完整的 Harness从一个最简单的触发器开始跑通了再逐步增加。我们最初只做了一个提交前审查的 hook跑了两个月之后才增加 CI 修复触发器。这种渐进式的做法让我们有足够的时间去理解每个触发器的实际效果和问题避免了“一次性搭建大系统然后发现方向错了”的风险。5.4 团队协作中的注意事项Harness 是团队共用的基础设施所以需要考虑团队协作的问题统一配置Harness 的配置文件应该放在项目仓库里所有人共用同一套配置。权限控制不是所有人都能修改 Harness 的配置。我们设置了一个“Harness 维护者”角色只有这个角色的人才能修改核心配置。反馈渠道团队成员可以随时反馈 Harness 的问题和建议。我们有一个专门的频道用来讨论 Harness 的改进。文档Harness 的每个触发器都要有文档说明它的作用、触发条件、输出处理方式。新成员加入时先读文档再使用。注意Harness 的改动可能会影响所有人的工作流程。所以在修改 Harness 配置之前一定要先在本地测试确认没有问题之后再提交。我们有过一次因为修改了上下文组装规则导致所有提交前审查都失败的经历教训很深刻。6. 一年下来的几点真实体会6.1 “不打开 Claude Code”不等于“不用 Claude Code”这个区别很重要。我们团队现在确实很少手动打开 Claude Code 了但 Claude Code 的调用量其实比一年前大了好几倍。只是这些调用都是 Harness 自动触发的人感知不到。这就像你用搜索引擎一样你不会觉得“我在使用搜索引擎”你只是在“查东西”。当工具足够好的时候它会融入你的工作流程成为你思维方式的一部分。6.2 Harness 的“自我淘汰”是一种设计哲学我们最初做 Harness 的时候目标是“让 Claude Code 更好用”。但做着做着发现真正的目标应该是“让 Claude Code 变得不需要被直接使用”。这个转变很有意思你越是把 Harness 做好Claude Code 本身就越“隐形”。这不是坏事而是好事。因为这意味着整个系统的效率提高了人可以从繁琐的调度工作中解放出来专注于真正需要人来做的事情。6.3 不要追求 100% 的自动化我们曾经试图把所有事情都自动化结果发现有些场景就是需要人来做决策。比如涉及架构调整的修改、涉及业务逻辑的变更、涉及多个模块的协调这些场景下 Agent 的输出只能作为参考最终决策还是要人来做。Harness 的价值不是替代人而是把人从重复性的、低价值的调度工作中解放出来让人有更多时间做高价值的决策。6.4 从“工具思维”转向“系统思维”这一年最大的收获可能不是技术上的而是思维上的。以前我们想的是“怎么用好 Claude Code 这个工具”现在我们想的是“怎么设计一个系统让 Agent 能力在合适的时机自动发挥作用”。这个思维转变带来的影响是深远的它让我们不再依赖某个具体的工具而是关注整个工作流程的效率和可靠性。最后分享一个我们内部常用的小技巧如果你也想尝试搭建 Harness不要从最复杂的场景开始。找一个你每天都要重复做、而且做起来很烦的小任务比如“检查提交信息是否符合规范”或者“检查代码里有没有遗留的 console.log”。先把这个任务自动化跑上一周感受一下效果。然后再逐步扩展。Harness 的搭建是一个迭代的过程不是一次性的工程。你会在迭代中不断发现新的机会和新的问题这个过程本身就是最有价值的部分。
