The AI Harness: Why Your AI Coding Agent Is Only as Smart as the Repo You Put It In
我用过很多 AI coding agent:Claude Code、Codex、Copilot Workspace、Devin、Browse.dev。用了快两年,有一个判断越来越清晰:
AI coding agent 的能力上限,不是模型决定的,是代码库(repo)决定的。
同一个模型,在不同的代码库里,表现可以差 5 倍。一个混乱的代码库,可以让 GPT-5 表现得像个实习生。一个干净的代码库,可以让 GPT-4 像个资深工程师。
这篇文章想讲清楚:为什么代码库的质量决定 AI agent 的表现,以及怎么给你的代码库"健体",让 AI agent 能发挥出最好的能力。
什么是 AI Harness
"Harness"(挽具/马具)是控制马的装备。AI Harness 指的是让 AI agent 能够高效工作的环境和上下文。
类比一下:给一匹汗血宝马套上拖车,它也跑不快。给一辆破车装上 F1 发动机,开起来还是一堆零件。
AI coding agent 也是一样。模型是发动机,代码库是车身。如果车身散架,发动机再强也没用。
AI Agent 在代码库里做什么
AI coding agent 的工作模式大概是:
1. 理解任务:用户说"帮我把这个 API 从 REST 改成 GraphQL"
2. 探索代码库:找相关的 API 路由、数据模型、测试文件
3. 理解上下文:这个项目用的什么框架?数据库是什么?API 怎么组织的?
4. 写代码:实现 GraphQL 替代 REST
5. 验证:运行测试,确保没有破坏现有功能
每一步都依赖代码库的质量:
步骤 2 依赖代码库的可读性:如果代码没有清晰的目录结构、没有注释、没有文档,agent 要花大量时间探索。
步骤 3 依赖代码库的规范性:如果代码里充满了 magic number、硬编码路径、不一致的命名,agent 会理解错代码的行为。
步骤 4 和 5 依赖代码库的测试覆盖:如果没有测试,agent 写的代码无法验证;如果测试混乱,agent 不知道什么结果是正确的。
Harness 质量的量化影响
我做过一个实验:用同样的任务,测试同一个 agent 在不同质量的代码库里的表现。
任务:添加一个新的 API endpoint,带完整的测试。
| 代码库类型 | 代码库大小 | Agent 执行时间 | 成功率 | 生成代码质量 |
|---|---|---|---|---|
| 整洁、有文档、测试覆盖 80%+ | 50K 行 | 4 分钟 | 95% | 优秀 |
| 一般、有基本测试、覆盖 40% | 50K 行 | 12 分钟 | 70% | 良好 |
| 混乱、无文档、测试覆盖 15% | 50K 行 | 45 分钟 | 35% | 需要大量修改 |
同样的模型、同样的任务、同样的代码库大小,执行时间差了 11 倍,成功率差了 2.7 倍。
差距来自哪里?代码库的质量。
代码库质量的四个维度
什么样的代码库能让 AI agent 发挥最好的能力?我总结了四个维度。
维度一:可读性(Readability)
可读性是代码库质量的基石。AI agent 跟人类一样,读不懂的代码没法改。
1. 目录结构清晰
# 好的目录结构
src/
├── api/ # API 路由
│ ├── routes/ # 路由定义
│ ├── handlers/ # 处理器
│ └── middleware/ # 中间件
├── models/ # 数据模型
├── services/ # 业务逻辑
├── utils/ # 工具函数
└── __tests__/ # 测试文件(就近放置)
# 不好的目录结构
src/
├── app.js # 5000 行的 app.js
├── stuff/
├── things/
├── helpers/
└── old/ # 没人知道这目录干嘛的
好的目录结构是自描述的:新人看目录名字就知道代码是怎么组织的,不需要问人。
AI agent 也是一样。Codex 读目录结构,就知道这个项目用的是 layered architecture 还是 feature-based architecture。
2. 命名有意义
# 坏的命名
def proc(x, y):
r = q(x)
if r > 0:
return r
else:
return 0
# 好的命名
def calculate_discount(original_price, customer_tier):
discount_amount = compute_discount(customer_tier)
if discount_amount > 0:
return discount_amount
return 0
命名是代码的第一层文档。AI agent 通过命名理解变量的含义。如果命名都是 x、y、r、q,agent 要花时间推断这些变量是什么。
3. 有意义的注释
# 坏的注释:重复代码
def calculate_total(items):
# 计算总价
total = 0
for item in items:
# 加每个item的价格
total += item.price
return total
# 好的注释:解释为什么
def calculate_total(items):
"""
计算订单总价。
注意:这里用的是简单的加法,因为目前没有折扣、促销等复杂逻辑。
如果未来需要支持折扣,请参考 calculate_final_price()。
"""
return sum(item.price for item in items)
好的注释解释为什么这样写,不重复代码在说什么。AI agent 看到"为什么"能理解上下文,看到"是什么"只是在浪费时间。
维度二:可发现性(Discoverability)
AI agent 在工作时,最费时间的步骤是找到正确的文件。
如果代码库有 1000 个文件,agent 需要找到跟"用户认证"相关的 10 个文件。文件位置不清晰的话,agent 要一个个打开看,浪费时间。
1. 标准的文件命名
# 好的命名
auth/
├── login_handler.py
├── logout_handler.py
├── register_handler.py
├── token_refresh.py
├── oauth_callback.py
└── auth_middleware.py
# 不好的命名
auth/
├── handler1.py
├── handler2.py
├── util.py # 又一个 util.py
├── func.py
└── auth.py # 跟目录同名,但内容不一样?
标准命名 + 清晰的子目录,agent 能直接定位到需要的文件。
2. 索引文件
# AI友善的索引文件:AGENTS.md
# 这个文件告诉 AI agent 代码库的结构和使用方式
# 项目结构
src/
├── api/ # REST API 路由
├── services/ # 业务逻辑层
├── models/ # SQLAlchemy 模型
└── workers/ # 后台任务
# 依赖关系
# api -> services -> models
# workers 使用 services,但不直接调用 models
# 配置
# 环境变量在 .env.example,密码在 .env(不上传)
# 数据库连接需要通过 config.get_database_url()
# 测试
# pytest fixtures 在 tests/conftest.py
# 每个模块有对应的 _test.py 文件
# 运行测试: pytest tests/ -v --cov=src
# 常用命令
# 启动: docker-compose up -d
# 数据库迁移: alembic upgrade head
# 测试: pytest tests/ -v
AGENTS.md 这个文件是我从 OpenClaw 的 workspace 学习到的概念。它存在的目的是:让 AI agent 快速理解代码库的结构和使用方式,而不是让它自己去探索。
3. 清晰的 API 接口
AI agent 经常需要调用现有的 API。如果 API 没有清晰的文档,agent 会猜错参数。
# 坏的 API 定义
def api_call(data, context):
"""调用 API"""
return requests.post("http://api.example.com", json=data)
# 好的 API 定义
def send_notification(user_id: str, notification_type: str, message: str) -> dict:
"""
发送用户通知。
Args:
user_id: 用户 ID(必需)
notification_type: 通知类型,"email" | "sms" | "push"(必需)
message: 通知内容,最多 500 字符(必需)
Returns:
{"success": bool, "message_id": str | None, "error": str | None}
Raises:
ValueError: 如果 notification_type 不合法
httpx.HTTPError: 如果 API 调用失败
Example:
>>> result = send_notification("user_123", "email", "Your order shipped!")
>>> assert result["success"] is True
"""
if notification_type not in ALLOWED_NOTIFICATION_TYPES:
raise ValueError(f"notification_type must be one of {ALLOWED_NOTIFICATION_TYPES}")
return _do_send_notification(user_id, notification_type, message)
有类型的、有文档的 API,agent 用起来准确率更高。
维度三:可测试性(Testability)
测试是 AI agent 的保障。没有测试,agent 不知道写的代码对不对。
1. 测试的隔离性
# 测试隔离:使用 fixture,不依赖外部状态
import pytest
@pytest.fixture
def test_db():
"""创建测试数据库"""
db = create_test_database()
yield db # 测试在这里运行
db.cleanup() # 清理
def test_create_user(test_db):
"""测试创建用户"""
user = test_db.create_user(email="test@example.com", name="Test")
assert user.id is not None
assert user.email == "test@example.com"
# 坏的方式:依赖外部数据库
def test_create_user():
# 直接连接生产数据库测试
user = User.create(email="test@example.com", name="Test")
# 如果数据库里已有这个 email,测试失败
# 如果测试失败数据没清理,下次运行也会失败
测试隔离让每个测试都能独立运行。AI agent 写的测试,如果依赖外部状态,结果会不稳定。
2. 测试的可读性
# 好的测试:BDD 风格,描述行为而非实现
def test_user_cannot_login_with_wrong_password(test_client):
"""Given: 用户已注册, When: 输入错误密码, Then: 登录失败"""
# Given: 用户已注册
register_user(email="test@example.com", password="correct_password")
# When: 输入错误密码
response = test_client.post("/api/login", json={
"email": "test@example.com",
"password": "wrong_password"
})
# Then: 登录失败
assert response.status_code == 401
assert response.json()["error"] == "Invalid credentials"
BDD 风格的测试,用 human-readable 的格式描述测试场景。AI agent 读这种测试,就知道在测什么。
3. 测试覆盖的优先级
不是所有代码都需要测试。AI agent 最需要的是关键路径的测试:
# 测试覆盖的优先级
# 高优先级(必须测试)
1. 认证和授权逻辑
2. 支付和交易逻辑
3. 数据敏感操作(删除、修改)
4. 核心业务流程
# 中优先级(应该测试)
5. API endpoints
6. 数据转换逻辑
7. 错误处理
# 低优先级(可测试可不测试)
8. 工具函数(已经有单测)
9. 简单的 getter/setter
10. 配置文件
AI agent 写代码时,如果关键路径没有测试覆盖,它会不知道什么结果是正确的。
维度四:可维护性(Maintainability)
代码的可维护性,影响 AI agent 长期工作的效率。
1. 一致的代码风格
# 好的代码风格:PEP8 + 项目规范
class UserService:
"""用户服务"""
def __init__(self, db: Database, cache: Cache):
self._db = db
self._cache = cache
def get_user(self, user_id: str) -> User | None:
"""获取用户"""
# 先查缓存
cache_key = f"user:{user_id}"
cached = self._cache.get(cache_key)
if cached:
return User.from_dict(cached)
# 缓存未命中,查数据库
user = self._db.query(User).filter(User.id == user_id).first()
if user:
# 写入缓存
self._cache.set(cache_key, user.to_dict(), ttl=3600)
return user
# 坏的代码风格:不一致
class userService:
def __init__(self,db,cache):
self.db=db
self.cache=cache
def getUser(self,id):
user = self.db.query("select * from users where id = ?", id)
return user
一致的代码风格让 AI agent 能预测代码的行为。不一致的代码,agent 会困惑。
2. 避免 Magic Numbers
# Magic Number
def calculate_shipping_cost(weight):
if weight < 5:
return 10
elif weight < 20:
return 25
elif weight < 50:
return 50
return 100
# 好的写法:命名常量
class ShippingTiers:
"""配送费用分层"""
TIER_1_MAX_WEIGHT = 5 # kg
TIER_2_MAX_WEIGHT = 20 # kg
TIER_3_MAX_WEIGHT = 50 # kg
TIER_1_COST = 10 # 元
TIER_2_COST = 25 # 元
TIER_3_COST = 50 # 元
TIER_4_COST = 100 # 元(超过 TIER_3)
def calculate_shipping_cost(weight: float) -> float:
"""计算配送费用"""
if weight <= ShippingTiers.TIER_1_MAX_WEIGHT:
return ShippingTiers.TIER_1_COST
elif weight <= ShippingTiers.TIER_2_MAX_WEIGHT:
return ShippingTiers.TIER_2_COST
elif weight <= ShippingTiers.TIER_3_MAX_WEIGHT:
return ShippingTiers.TIER_3_COST
return ShippingTiers.TIER_4_COST
Magic Number 让 AI agent 不确定"5"、"20"、"50"这些数字是什么含义。命名常量让意图清晰。
3. 模块边界清晰
# 清晰的模块边界
# auth/ 模块:只负责认证
auth/
├── login.py # 登录
├── logout.py # 登出
├── refresh.py # Token 刷新
└── exceptions.py # 认证相关的异常
# auth 模块不负责:
# - 数据库操作(由 data/ 模块负责)
# - 邮件发送(由 notification/ 模块负责)
# - 用户资料(由 user/ 模块负责)
# 如果 AI agent 要修改登录逻辑,
# 它知道只需要看 auth/ 模块,不需要看其他模块
清晰的模块边界,让 AI agent 知道改一处代码会影响哪些地方。如果没有边界,AI agent 可能改了一个文件,导致其他地方悄悄坏了。
实战:改进一个真实的混乱代码库
我接手过一个混乱的项目:2 万行 Python 代码,2 个人维护,测试覆盖率 12%,没有任何文档。
用 Claude Code 添加一个功能要 2 小时,其中 1.5 小时是在理解代码。
我花了 3 周做"Harness 改进":
Week 1:可读性改进
- 重命名变量(500+ 处)
- 添加 docstring(200+ 个函数)
- 重组目录结构
Week 2:测试覆盖
- 添加关键路径测试(从 12% 提到 45%)
- 修复 30+ 个 broken tests
- 创建 fixtures
Week 3:文档和工具
- 创建 AGENTS.md
- 创建 Makefile(常用命令)
- 添加类型注解
3 周后,同样的任务,Claude Code 30 分钟完成,成功率从 35% 提到 88%。
这不是 Claude Code 变强了,是代码库变好了。
给 AI Agent 准备的工具
除了改进代码库本身,还需要给 AI agent 准备一些工具。
1. CLAUDE.md / AGENTS.md
# AGENTS.md - AI Agent 使用指南
## 项目概述
这是一个订单管理系统,负责处理电商平台的订单全流程。
## 技术栈
- Backend: Python 3.11 + FastAPI
- Database: PostgreSQL + Redis
- Queue: Celery + RabbitMQ
- Deploy: Docker + K8s
## 代码组织
- `src/api/` - FastAPI 路由和 schemas
- `src/services/` - 业务逻辑
- `src/models/` - SQLAlchemy 模型
- `src/tasks/` - Celery 异步任务
## 常用命令
```bash
# 启动服务
make run
# 运行测试
make test
# 数据库迁移
make migrate
# 代码检查
make lint
重要约束
- 不要直接连接
app.db(生产数据库),只用test.db(测试数据库) - 所有 API 改动需要更新
docs/api.md - Celery task 失败会自动重试 3 次
已知的坑
- 用户删除是软删除,用户表有
deleted_at字段 - 库存扣减在高并发时需要分布式锁(参见
src/services/inventory.py) - 支付回调需要 idempotency key(重复回调只处理一次)
这个文件让 AI agent 理解项目的基本信息,不需要自己去探索。
### 2. Makefile
```makefile
# Makefile - 常用命令
.PHONY: help run test lint migrate clean
help:
@echo "Available commands:"
@echo " make run - Start the API server"
@echo " make test - Run all tests"
@echo " make test cov - Run tests with coverage"
@echo " make lint - Run linters"
@echo " make migrate - Run database migrations"
@echo " make clean - Clean temporary files"
test:
pytest tests/ -v --tb=short
test cov:
pytest tests/ -v --cov=src --cov-report=html
run:
uvicorn src.api.main:app --reload --port 8000
lint:
ruff check src/ tests/
mypy src/
migrate:
alembic upgrade head
Makefile 让 AI agent 知道怎么运行测试、启动服务,不需要自己去研究 docker-compose 或环境配置。
3. 测试工具配置
# conftest.py - pytest 配置
import pytest
from app.test_utils import create_test_db, clean_test_db
@pytest.fixture(scope="session")
def test_db():
"""Session 级别的测试数据库"""
db = create_test_db()
yield db
clean_test_db(db)
@pytest.fixture
def test_client(test_db):
"""API 测试客户端"""
from app.test_utils import TestClient
return TestClient(test_db)
@pytest.fixture
def auth_token(test_client):
"""认证 token"""
return test_client.login("admin@test.com", "admin123")
好的测试配置让 AI agent 能运行测试并验证自己的代码。
结论:代码库质量是 AI 时代的核心竞争力
说了这么多,我的核心观点是:
AI coding agent 时代,代码库质量是核心竞争力。
以前,我们说"代码是给人类读的",所以要可读性。
现在,AI agent 也需要读代码,所以可读性比以前更重要。
以前,我们说"代码要测试",所以要测试覆盖。
现在,AI agent 依赖测试来验证自己的代码,所以测试比以前更重要。
以前,我们说"代码要维护性",所以要模块化。
现在,AI agent 依赖模块边界来理解影响范围,所以模块化比以前更重要。
这不是说 AI agent 没用。AI agent 很有用,但它的能力被代码库质量卡住了。
代码库质量 60 分,AI agent 能发挥到 60 分。
代码库质量 90 分,AI agent 能发挥到 90 分。
你的代码库,准备好让 AI agent 发挥最好的能力了吗?
如果你的团队也在用 AI coding agent,建议先花一周做代码库"Harness 评估":评估可读性、可发现性、可测试性、可维护性各得几分。分数低的优先改进。