芥末
发布于 2026-04-02 / 0 阅读
0
0

从 Claude Code 反推 AI 编码 Agent 的工程架构

AI 编码工具真正难的地方,不是让大语言模型生成一段代码,而是让它在真实工程里安全、连续、可回滚地工作。

真实工程不是一段孤立的函数。它有目录结构、历史代码、依赖管理、测试脚本、构建命令、代码规范、权限边界和团队约定。AI 如果只根据用户一句话直接写代码,很容易遇到几类问题:

  • 不知道项目真实结构,生成不存在的文件路径;
  • 忽略已有抽象,重复造轮子;
  • 修改范围过大,难以 review;
  • 执行危险命令,比如删除文件、覆盖配置、访问敏感路径;
  • 没有运行测试,错误直到合并后才暴露;
  • 上下文越聊越长,模型开始遗忘关键约束。

Harness Engineering(驾驭工程)要解决的就是这个问题:给 AI 编码 Agent 套上一组工程化缰绳,让模型能调用工具、理解项目、修改代码、验证结果,同时把风险限制在可控范围内。

Claude Code 这类 AI 编码工具可以看作一个典型样本。它的核心不是单次代码补全,而是一个围绕“大语言模型 + 工具系统 + 上下文管理 + 权限控制”的循环执行框架。

AI 编码 Agent 和普通聊天机器人的区别

普通聊天机器人主要处理文本输入和文本输出。AI 编码 Agent 面对的是一个动态工作区:它需要读文件、搜索代码、执行命令、生成补丁、观察报错,再根据结果继续调整。

两者的差异可以这样理解:

能力维度普通聊天机器人AI 编码 Agent
输入用户消息用户目标、代码仓库、文件内容、命令输出、历史操作
输出文本回答解释、计划、代码补丁、命令调用、测试结果
状态对话上下文对话上下文 + 工作区状态 + 工具执行结果
风险回答不准确改坏代码、泄露密钥、执行危险命令
关键机制提示词设计上下文工程、工具路由、权限控制、执行闭环

AI 编码 Agent 的目标不是“一次回答正确”,而是通过多轮观察和修正,逐步把工程状态推进到目标状态。

整体架构:模型只负责推理,Agent 负责驾驭环境

一个可用的 AI 编码 Agent 通常由几层组成:

flowchart LR
    U[用户目标] --> UI[CLI / IDE / Web 入口]
    UI --> O[Agent Orchestrator<br/>调度器]

    O --> C[Context Builder<br/>上下文构造器]
    C --> R[(代码仓库)]
    C --> M[Memory / Rules<br/>项目规则与历史摘要]

    O --> L[LLM<br/>大语言模型]
    L --> O

    O --> T[Tool Router<br/>工具路由器]
    T --> P[Permission Gate<br/>权限网关]

    P --> F[文件工具<br/>read/write/edit]
    P --> S[搜索工具<br/>grep/index]
    P --> SH[命令工具<br/>shell/test/build]
    P --> G[Git 工具<br/>diff/status]

    F --> R
    S --> R
    SH --> W[工作区环境]
    G --> R

    F --> O
    S --> O
    SH --> O
    G --> O

这里最重要的设计原则是:大语言模型不直接操作系统和文件,所有外部动作都必须经过 Agent 的工具层。

模型可以提出“读取某个文件”“搜索某个符号”“运行测试”“修改某段代码”的意图,但真正执行这些动作的是工具系统。工具系统再经过权限网关判断是否允许执行、是否需要用户确认、是否要截断输出、是否要记录审计日志。

这层隔离非常关键。没有工具层,模型就只能聊天;没有权限层,模型就可能变成不受控的脚本执行器。

核心循环:感知、计划、行动、观察

AI 编码 Agent 的工作方式接近一个循环:

flowchart TD
    A[接收用户目标] --> B[收集上下文]
    B --> C[生成计划]
    C --> D{需要工具吗}
    D -- 是 --> E[调用工具]
    E --> F[获得观察结果]
    F --> G{目标完成了吗}
    G -- 否 --> B
    G -- 是 --> H[给出变更说明和验证结果]
    D -- 否 --> H

这个循环可以拆成四个动作:

  1. 感知:读取代码、搜索符号、查看配置、理解错误输出。
  2. 计划:决定改哪些文件、按什么顺序改、要运行哪些验证命令。
  3. 行动:通过工具执行文件编辑、命令运行、代码搜索。
  4. 观察:把工具返回结果放回上下文,让模型继续判断下一步。

一个典型修复流程如下:

sequenceDiagram
    participant User as 用户
    participant Agent as Agent 调度器
    participant Ctx as 上下文构造器
    participant LLM as 大语言模型
    participant Tool as 工具系统
    participant Repo as 代码仓库

    User->>Agent: 修复登录接口 500 错误
    Agent->>Ctx: 收集路由、控制器、日志、测试信息
    Ctx->>Repo: 读取相关文件
    Repo-->>Ctx: 返回代码片段
    Ctx-->>Agent: 组装上下文
    Agent->>LLM: 请求分析和计划
    LLM-->>Agent: 需要查看认证中间件
    Agent->>Tool: 搜索 auth middleware
    Tool->>Repo: grep / index search
    Repo-->>Tool: 返回匹配结果
    Tool-->>Agent: 返回观察结果
    Agent->>LLM: 继续推理
    LLM-->>Agent: 生成补丁和测试命令
    Agent->>Tool: 应用补丁、运行测试
    Tool-->>Agent: 返回 diff 和测试结果
    Agent-->>User: 汇报修改点、验证结果、剩余风险

真正的工程能力来自这个闭环,而不是来自某一次模型输出。

上下文工程:给模型刚好够用的信息

大语言模型的上下文窗口有限,即使窗口很大,也不应该把整个仓库塞进去。上下文越杂,模型越容易被无关内容干扰;上下文越少,又会缺少关键约束。

上下文工程的目标是:把完成任务必需的信息放进去,把无关信息挡在外面。

上下文通常包含什么

上下文类型作用示例
用户目标明确任务边界“把支付回调改成幂等处理”
项目规则约束代码风格和工具链代码规范、测试命令、目录约定
相关文件提供真实实现controller、service、repository、test
搜索结果定位符号和调用关系函数定义、引用位置、配置项
命令输出反馈真实环境状态测试失败日志、构建错误
已做修改防止重复操作当前 diff、已编辑文件列表
安全限制限制危险行为禁止访问密钥、禁止删除目录

一个粗糙的 Agent 会把“用户问题 + 全仓库代码”直接发给模型。一个工程化 Agent 会先判断任务类型,再逐步加载上下文。

渐进式加载比一次性全量加载更稳

可以把上下文加载分成几层:

flowchart TD
    A[用户目标] --> B[读取项目规则]
    B --> C[生成初步搜索关键词]
    C --> D[搜索文件和符号]
    D --> E[读取最相关文件片段]
    E --> F[让模型制定修改计划]
    F --> G{信息够吗}
    G -- 不够 --> H[继续定向读取]
    H --> F
    G -- 够 --> I[生成补丁或调用工具]

这种方式有几个好处:

  • 模型先理解任务,再决定要看什么;
  • 上下文不会被无关文件污染;
  • 每次工具调用都有明确目的;
  • 读文件和改文件之间有可审计的路径。

一个上下文构造器的简化实现

下面的 TypeScript 伪代码展示了上下文构造器的基本思路。重点不是具体 API,而是“先筛选,再组装,再控制预算”。

type UserTask = {
  goal: string;
  repoPath: string;
};

type ContextItem = {
  kind: "rule" | "file" | "search" | "diff" | "command";
  title: string;
  content: string;
  priority: number;
};

type ContextBudget = {
  maxTokens: number;
};

async function buildContext(task: UserTask, budget: ContextBudget): Promise<string> {
  const items: ContextItem[] = [];

  const rules = await readProjectRules(task.repoPath);
  items.push({
    kind: "rule",
    title: "Project Rules",
    content: rules,
    priority: 100,
  });

  const keywords = extractSearchKeywords(task.goal);
  const matches = await searchRepository(task.repoPath, keywords);

  items.push({
    kind: "search",
    title: "Search Results",
    content: formatSearchResults(matches),
    priority: 80,
  });

  const candidateFiles = rankFilesByRelevance(matches, task.goal);
  for (const file of candidateFiles.slice(0, 8)) {
    const snippet = await readRelevantSnippet(file, task.goal);
    items.push({
      kind: "file",
      title: file.path,
      content: snippet,
      priority: file.score,
    });
  }

  const currentDiff = await gitDiff(task.repoPath);
  if (currentDiff.trim()) {
    items.push({
      kind: "diff",
      title: "Current Diff",
      content: currentDiff,
      priority: 90,
    });
  }

  return packByPriority(items, budget.maxTokens);
}

这里有几个细节值得关注:

  • readProjectRules 通常读取类似 CLAUDE.mdAGENTS.mdREADME.md、代码规范文档一类的项目规则文件;
  • searchRepository 不应该只做文件名搜索,还要支持符号、字符串、配置项搜索;
  • readRelevantSnippet 最好读取函数级或类级片段,而不是整份大文件;
  • packByPriority 要处理 token 预算,优先保留任务目标、规则、相关代码和当前 diff。

工具系统:把模型意图变成受控动作

AI 编码 Agent 的工具不是普通函数调用,而是一组受控能力。每个工具都应该有清晰的输入、输出、权限要求和错误格式。

一个文件读取工具可以这样描述:

{
  "name": "read_file",
  "description": "读取工作区内的文本文件",
  "input_schema": {
    "type": "object",
    "properties": {
      "path": {
        "type": "string",
        "description": "相对于工作区根目录的文件路径"
      },
      "start_line": {
        "type": "number",
        "description": "起始行号,从 1 开始"
      },
      "end_line": {
        "type": "number",
        "description": "结束行号"
      }
    },
    "required": ["path"]
  },
  "permission": "read_workspace"
}

一个命令执行工具需要更严格:

{
  "name": "run_command",
  "description": "在工作区内执行命令,默认不允许访问网络和工作区外路径",
  "input_schema": {
    "type": "object",
    "properties": {
      "command": {
        "type": "string"
      },
      "timeout_ms": {
        "type": "number"
      },
      "reason": {
        "type": "string",
        "description": "说明为什么需要执行该命令"
      }
    },
    "required": ["command", "reason"]
  },
  "permission": "execute_command"
}

reason 字段不是装饰,它能帮助权限层和用户判断命令是否合理。例如运行 npm test 和运行 rm -rf . 都是 shell 命令,但风险完全不同。

权限体系:让 AI 能做事,但不能越界

AI 编码 Agent 必须有权限边界。权限设计太宽,风险不可控;权限设计太窄,Agent 会退化成只能给建议的聊天工具。

一种实用做法是把权限拆成几个级别:

权限级别允许行为典型工具是否需要确认
只读读取文件、搜索代码、查看 git 状态read_filegrepgit status通常不需要
工作区写入修改工作区内文件、应用补丁edit_fileapply_patch可按配置决定
安全命令执行测试、格式化、类型检查npm testgo testcargo fmt通常不需要或首次确认
高风险命令删除文件、安装依赖、修改环境rmpip installnpm install需要确认
网络访问调用外部接口、下载依赖curl、包管理器需要确认
敏感信息读取密钥、环境变量、凭据.env、SSH key默认禁止

权限判断可以做成一个独立流程:

flowchart TD
    A[模型请求调用工具] --> B[解析工具类型和参数]
    B --> C{路径在工作区内吗}
    C -- 否 --> X[拒绝执行]
    C -- 是 --> D{是否命中敏感文件}
    D -- 是 --> X
    D -- 否 --> E{命令是否高风险}
    E -- 是 --> F[请求用户确认]
    F --> G{用户允许吗}
    G -- 否 --> X
    G -- 是 --> H[执行工具]
    E -- 否 --> H
    H --> I[记录日志并返回结果]

权限系统至少要覆盖四类风险。

1. 路径越界

文件工具必须限制在工作区根目录内。即使模型传入 ../../.ssh/id_rsa,工具层也应该规范化路径后拒绝。

import path from "node:path";

function assertInsideWorkspace(workspaceRoot: string, inputPath: string) {
  const resolved = path.resolve(workspaceRoot, inputPath);
  const root = path.resolve(workspaceRoot);

  if (!resolved.startsWith(root + path.sep) && resolved !== root) {
    throw new Error(`Path escapes workspace: ${inputPath}`);
  }

  return resolved;
}

2. 敏感文件访问

.env、私钥、云厂商凭据、生产配置等文件不应该默认暴露给模型。即使某个任务看起来需要环境变量,也应该先让用户手动确认,或者只提供经过脱敏的键名。

const blockedPatterns = [
  /\.env(\..*)?$/,
  /id_rsa$/,
  /id_ed25519$/,
  /credentials\.json$/,
  /kubeconfig$/,
  /\.npmrc$/,
];

function isSensitivePath(filePath: string) {
  return blockedPatterns.some((pattern) => pattern.test(filePath));
}

3. 危险命令

命令不能只按字符串黑名单处理,因为 shell 组合方式太多。更稳的做法是分层控制:

  • 默认工作目录固定在 workspace;
  • 默认禁用网络;
  • 默认禁用交互式命令;
  • 限制超时时间;
  • 对删除、移动、权限修改、包安装等行为要求确认;
  • 对输出做截断和脱敏。
命令类型示例处理方式
测试npm testpytestgo test ./...可允许
静态检查npm run linttsc --noEmit可允许
格式化prettier --write .cargo fmt可允许,但最好展示影响范围
删除rm -rfgit clean -fdx必须确认
安装依赖npm installpip install需要确认
网络请求curlwget需要确认或禁用
权限修改chmodchown需要确认

4. 输出泄露

命令输出也可能包含敏感信息。Agent 返回给模型前,可以做一层脱敏处理:

function redactSecrets(output: string) {
  return output
    .replace(/AKIA[0-9A-Z]{16}/g, "[REDACTED_AWS_KEY]")
    .replace(/ghp_[A-Za-z0-9_]{30,}/g, "[REDACTED_GITHUB_TOKEN]")
    .replace(/-----BEGIN [A-Z ]+PRIVATE KEY-----[\s\S]+?-----END [A-Z ]+PRIVATE KEY-----/g, "[REDACTED_PRIVATE_KEY]");
}

脱敏不能替代权限控制,但可以降低日志和模型上下文里的泄露风险。

代码修改:优先生成小补丁,而不是整文件重写

AI 编码 Agent 修改代码时,最怕“大面积重写”。重写越多,review 成本越高,也越容易引入无关变化。

更稳的方式是让模型生成结构化补丁:

diff --git a/src/auth/session.ts b/src/auth/session.ts
index 7a1c9a2..3b2f8c1 100644
--- a/src/auth/session.ts
+++ b/src/auth/session.ts
@@ -18,7 +18,11 @@ export async function getSession(userId: string) {
   const cached = await cache.get(cacheKey);
   if (cached) return JSON.parse(cached);
 
-  const session = await db.session.findFirst({ where: { userId } });
+  const session = await db.session.findFirst({
+    where: { userId, revokedAt: null },
+    orderBy: { createdAt: "desc" },
+  });
+
   if (!session) return null;
 
   await cache.set(cacheKey, JSON.stringify(session), 300);

补丁式修改有几个优势:

  • 变更范围清楚;
  • 容易做冲突检测;
  • 可以在应用前展示给用户;
  • 可以通过 git diff 审计;
  • 失败后更容易回滚。

一个安全的修改流程通常是:

flowchart TD
    A[生成修改计划] --> B[读取目标文件]
    B --> C[生成最小补丁]
    C --> D[应用补丁]
    D --> E[查看 git diff]
    E --> F[运行格式化 / 测试]
    F --> G{验证通过吗}
    G -- 是 --> H[汇报变更和验证结果]
    G -- 否 --> I[读取错误输出]
    I --> J[生成修复补丁]
    J --> D

这里的关键不是让模型“相信自己写对了”,而是让测试、类型检查和构建命令提供外部反馈。

规划机制:任务越复杂,越需要显式计划

简单任务可以直接改,例如修正拼写、补一个类型、改一处配置。复杂任务应该先拆计划,否则模型很容易在多个文件之间跳来跳去,最后留下半成品。

一个可执行计划应该满足三点:

  1. 每一步都有明确产物;
  2. 每一步都能被观察或验证;
  3. 中间失败时可以停下来,不会把工程状态推到不可控位置。

例如“给订单模块增加取消接口”可以拆成:

步骤动作验证方式
定位模块搜索订单 controller、service、路由找到现有创建、查询接口
理解约定读取相邻接口实现和测试确认错误码、权限、返回格式
修改业务逻辑增加取消方法,处理状态流转单元测试覆盖成功和失败分支
暴露接口增加路由和请求校验接口测试或集成测试
更新文档补充 API 示例文档 diff 可检查

计划不是为了写得漂亮,而是为了降低失控概率。Agent 每完成一步,就能根据真实反馈更新后续动作。

项目规则:把团队约定显式交给 Agent

很多 AI 编码错误来自“默认假设”。例如模型不知道项目使用 pnpm 还是 npm,不知道测试命令是什么,不知道异常应该抛业务错误还是 HTTP 错误,也不知道团队禁止直接访问数据库。

项目可以用一个规则文件告诉 Agent:

# Agent Instructions

## Project
- Runtime: Node.js 20
- Package manager: pnpm
- Main framework: Fastify
- ORM: Prisma

## Commands
- Install: pnpm install
- Type check: pnpm typecheck
- Test: pnpm test
- Lint: pnpm lint

## Coding Rules
- Do not access Prisma client directly in controllers.
- Put business logic in `src/modules/*/service.ts`.
- Use `AppError` for business errors.
- Add or update tests for behavior changes.

## Safety
- Do not read `.env*` files.
- Do not run database migration commands unless explicitly requested.

这类规则文件越具体,Agent 越容易遵守。空泛的“写高质量代码”没有什么帮助,明确的目录、命令、禁止事项和错误处理约定才有用。

记忆系统:长期规则和短期任务要分开

AI 编码 Agent 需要记住信息,但不能把所有历史都塞进上下文。可以把记忆分成三类:

记忆类型生命周期示例使用方式
项目规则长期技术栈、测试命令、目录规范每次任务加载
任务状态短期当前计划、已修改文件、失败测试当前任务内维护
历史摘要中期最近一次重构的背景、未完成事项按相关性检索

长期规则应该人工维护,短期任务状态由 Agent 自动维护,历史摘要要谨慎使用。历史信息如果不准确,会比没有记忆更危险。

一种简单的任务状态结构如下:

{
  "task_id": "fix-login-500",
  "goal": "修复登录接口 500 错误",
  "plan": [
    {
      "step": "定位登录接口实现",
      "status": "done"
    },
    {
      "step": "修复 session 查询逻辑",
      "status": "done"
    },
    {
      "step": "运行认证模块测试",
      "status": "running"
    }
  ],
  "touched_files": [
    "src/auth/session.ts",
    "src/auth/session.test.ts"
  ],
  "last_observation": "1 个测试失败:should reject revoked session"
}

有了任务状态,Agent 不需要靠模型“记忆力”维持流程,调度器可以把关键状态稳定地送回上下文。

反馈系统:测试、类型检查和 lint 是 Agent 的眼睛

AI 编码 Agent 不应该只给出“已完成”的文字说明。更可信的输出应该包含:

  • 修改了哪些文件;
  • 每个文件改了什么;
  • 运行了哪些命令;
  • 命令结果是什么;
  • 哪些验证没有运行,原因是什么;
  • 还有哪些风险需要人工确认。

验证链路可以按成本从低到高排列:

flowchart LR
    A[格式检查] --> B[类型检查]
    B --> C[单元测试]
    C --> D[集成测试]
    D --> E[构建]
    E --> F[端到端测试]

不同项目的验证命令不同,但思路一样:先运行便宜、反馈快的检查,再运行成本高的检查。Agent 如果修改了一个 TypeScript 函数,通常先跑 tsc --noEmit 或相关单测;如果修改了构建配置,再跑完整构建更合适。

示例命令可以写进项目规则:

pnpm typecheck
pnpm test src/auth/session.test.ts
pnpm lint

如果测试失败,失败输出应该回到上下文,进入下一轮修复,而不是直接把错误甩给用户。

适合和不适合交给 AI 编码 Agent 的任务

AI 编码 Agent 很适合处理上下文明确、验证手段清楚、修改范围可控的任务;如果需求模糊、业务决策重、缺少测试,风险会明显上升。

任务类型适合程度原因
修复类型错误错误位置明确,验证反馈直接
补单元测试可参考已有测试风格,结果可运行
小范围重构中高需要控制 diff,适合分步执行
接口参数调整中高影响面可通过搜索和测试验证
大规模架构迁移需要人工拆分阶段,不能一次交给 Agent
业务规则设计中低需要产品和领域判断
生产事故处置时间压力大,权限敏感,需要人工主导
涉密配置修改容易触碰凭据和环境风险

更稳的使用方式是把大任务拆成多个小任务,让 Agent 在每个小任务里完成“理解上下文、修改代码、运行验证、汇报 diff”的闭环。

生产化实践:可观测、可回滚、可评估

把 AI 编码 Agent 用在真实工程里,除了模型能力,还要补齐工程系统。

1. 记录每次工具调用

每次工具调用都应该记录:

{
  "timestamp": "2026-06-07T10:30:00+08:00",
  "tool": "run_command",
  "input": {
    "command": "pnpm test src/auth/session.test.ts",
    "reason": "验证 session 查询逻辑修改"
  },
  "permission": "safe_command",
  "status": "success",
  "duration_ms": 3821,
  "output_preview": "12 passed"
}

日志能用于排查问题,也能用于评估 Agent 行为是否合理。需要注意的是,日志也要脱敏,不能把密钥、用户数据、生产配置写进去。

2. 每次修改都能回滚

最简单的回滚基础是 Git。Agent 在修改前可以检查工作区状态:

git status --short

如果工作区已经有用户未提交修改,Agent 应该避免覆盖,或者只修改明确允许的文件。修改后再展示 diff:

git diff -- src/auth/session.ts src/auth/session.test.ts

对于自动化程度更高的环境,可以在每个任务开始时创建临时分支或 patch 文件,让回滚路径更清楚。

3. 建立任务评估集

想知道 AI 编码 Agent 是否稳定,不能只看演示效果。可以准备一组固定任务作为评估集:

[
  {
    "name": "fix-null-session",
    "goal": "修复 session 为空时登录接口返回 500 的问题",
    "expected_files": [
      "src/auth/session.ts",
      "src/auth/session.test.ts"
    ],
    "validation": [
      "pnpm test src/auth/session.test.ts",
      "pnpm typecheck"
    ]
  },
  {
    "name": "add-order-cancel-api",
    "goal": "为订单模块增加取消接口,只有待支付订单可以取消",
    "expected_files": [
      "src/modules/order/controller.ts",
      "src/modules/order/service.ts",
      "src/modules/order/service.test.ts"
    ],
    "validation": [
      "pnpm test src/modules/order",
      "pnpm lint"
    ]
  }
]

评估时不要只看最终代码能否运行,也要看过程:

  • 是否读取了正确文件;
  • 是否遵守权限;
  • 是否产生无关修改;
  • 是否运行了必要测试;
  • 是否能从测试失败中恢复;
  • 是否清楚说明未验证部分。

4. 对失败要有降级策略

Agent 可能会遇到很多失败场景:

失败场景合理处理
找不到相关文件说明已搜索路径和关键词,请用户补充入口
测试命令不存在查看项目文档或 package scripts,不要乱猜
补丁应用失败重新读取文件后生成更小补丁
上下文预算不足摘要低优先级内容,保留目标、规则、相关代码
权限被拒绝解释需要该权限的原因,等待用户决定
多次修复仍失败停止自动修改,汇报当前状态和失败日志

失败不可怕,怕的是 Agent 在失败后继续盲目修改。生产环境里的 Agent 应该有停止条件,例如同一个测试连续失败三次,就暂停并交给用户判断。

一个最小可用 AI 编码 Agent 需要哪些模块

如果从零实现一个简化版 AI 编码 Agent,不需要一开始就做复杂 IDE 集成。一个最小闭环至少包含这些模块:

flowchart TD
    A[任务输入] --> B[项目规则读取]
    B --> C[代码搜索]
    C --> D[文件读取]
    D --> E[LLM 推理]
    E --> F{工具调用?}
    F -- 读取/搜索 --> C
    F -- 修改文件 --> G[补丁应用]
    F -- 执行命令 --> H[权限检查后运行]
    G --> I[git diff]
    H --> J[命令输出]
    I --> E
    J --> E
    F -- 无需工具 --> K[结果汇报]

模块优先级可以这样排:

优先级模块原因
P0文件读取、搜索、补丁应用没有这些能力就无法操作真实代码
P0权限检查防止越界读写和危险命令
P0diff 展示让用户知道改了什么
P1测试命令执行形成验证闭环
P1项目规则文件降低模型猜测
P1工具调用日志方便排查和审计
P2代码索引提高大仓库定位效率
P2历史记忆支持跨任务连续工作
P2评估集衡量长期质量

核心思路很朴素:先让 Agent 安全地读,再让它小心地改,再让它用测试验证。

Harness Engineering 的关键取舍

驾驭工程不是让模型“自由发挥”,而是设计一个系统,让模型的推理能力在工程约束里发挥作用。几个取舍尤其重要:

取舍不推荐更稳的做法
上下文全仓库塞给模型按任务渐进式加载
修改方式整文件重写生成最小补丁
权限默认允许所有命令按工具和风险分级
验证只相信模型解释运行测试、类型检查、构建
记忆保存所有历史区分项目规则、任务状态、历史摘要
失败处理继续盲改达到阈值后暂停并汇报

AI 编码 Agent 的能力边界,本质上由两部分共同决定:模型能推理到哪里,工程系统能约束和验证到哪里。模型越强,越需要清晰的工具和权限;工程系统越完善,模型输出才越容易落到真实代码里。

Harness Engineering 的价值就在这里:它把“让 AI 写代码”变成一套可运行、可审计、可回滚、可持续改进的工程流程。


评论