你不知道的 Agent:原理、架构与工程实践

1. 你不知道的 Agent:原理、架构与工程实践

AI Agent 原理、架构与工程实践概览图

1.1. 核心要点

  • Harness 优于模型:决定系统稳定性的往往是测试、验证与约束基础设施(Harness),而非模型本身。
  • 上下文分层管理:解决 Context Rot 的关键在于对信息进行分层(常驻、按需、运行时、记忆、系统层),并配合压缩策略。
  • ACI 工具设计:工具应面向 Agent 目标设计(Agent-Computer Interface),而非简单的 API 封装,需具备边界清晰和自我修正能力。
  • 状态外化与可重入:长任务的稳定性依赖于将进度和状态保存在外部(如文件系统),实现跨 session 的恢复与续跑。
  • 多 Agent 协议化:多 Agent 协作需建立在结构化通信协议和隔离边界之上,防止幻觉放大。

1.2. 太长不读

在写完「你不知道的 Claude Code:架构、治理与工程实践」之后,发现自己对 Agent 底层的理解还不够深入,加上团队在 Agent 方向已经有不少业务落地经验,一直缺少一份系统梳理,所以我又把资料、开源实现和自己写的代码一起过了一遍,最后整理成了这篇文章。

这篇文章主要讲 Agent 架构里几块最影响工程效果的内容,包括控制流、上下文工程、工具设计、记忆、多 Agent 组织、评测、追踪和安全,最后再用 OpenClaw 的实现把这些设计原则串起来看一遍。

整理下来,有几处判断和我原来想的不太一样:更贵的模型带来的提升,很多时候没有想象中那么大,反而 Harness 和验证测试质量对成功率的影响更大;调试 Agent 行为时,也应优先检查工具定义,因为多数工具选择错误都出在描述不准确;另外,评测系统本身的问题,很多时候比 Agent 出问题更难发现。
如果一直在 Agent 代码上反复调,效果未必明显,读完这篇,这几个问题应该能有些答案。

1.3. Agent Loop 的基本运转方式

Agent Loop 的核心实现逻辑抽象后其实不到 20 行代码:

const messages: MessageParam[] = [{ role: "user", content: userInput }];

while (true) {
  const response = await client.messages.create({
    model: "claude-opus-4-6",
    max_tokens: 8096,
    tools: toolDefinitions,
    messages,
  });

  if (response.stop_reason === "tool_use") {
    const toolResults = await Promise.all(
      response.content
        .filter((b) => b.type === "tool_use")
        .map(async (b) => ({
          type: "tool_result" as const,
          tool_use_id: b.id,
          content: await executeTool(b.name, b.input),
        }))
    );
    messages.push({ role: "assistant", content: response.content });
    messages.push({ role: "user", content: toolResults });
  } else {
    return response.content.find((b) => b.type === "text")?.text ?? "";
  }
}

对应的控制流如下,感知 -> 决策 -> 行动 -> 反馈四个阶段不断循环,直到模型返回纯文本为止:

Agent Loop 运行流程图:感知-决策-行动-反馈

看过不少 Agent 实现和官方 SDK,结构都差不多,循环本身相当稳定,从最小实现一路扩展到支持子 Agent、上下文压缩和 Skills 加载,主循环基本没有变化,新增能力通常都是叠加在循环外部,而不是改动循环内部。

新能力基本只通过三种方式接入:扩展工具集和 handler、调整系统提示结构、把状态外化到文件或数据库。
不应该让循环体本身变成一个巨大的状态机,模型负责推理,外部系统负责状态和边界,一旦这个分工确定下来,核心循环逻辑就很少需要频繁调整了。

1.3.1. Workflow 和 Agent 有什么区别

Anthropic 对这两类系统有一个直接区分:执行路径由代码预先写死的是 Workflow,由 LLM 动态决定下一步的是 Agent。
核心区别在于控制权掌握在谁手里。
现实中很多标着 Agent 的产品,深入看其实更接近 Workflow,不过两者本身并无高下之分,真正重要的是给任务找到更适合的解决方案。

Workflow 与 Agent 的核心区别对比图

放在一张图里看,会更直观:

五种常见 AI 控制模式全景图

1.3.2. 五种常见控制模式

大多数 AI 系统拆开看,其实都是这五种模式的组合。
很多场景并不需要完整的 Agent 自主权,把其中几种模式搭起来就够了,关键还是看任务本身适合哪一种设计。

  1. 提示链 Prompt Chaining:任务拆成顺序步骤,每步 LLM 处理上一步的输出,中间可加代码检查点,适合生成后翻译、先写大纲再写正文这类线性流程。
  2. 路由 Routing:对输入分类,定向到对应的专用处理流程。简单问题走轻量模型,复杂问题走强模型。
  3. 并行 Parallelization:分段法把任务拆成独立子任务并发跑,投票法把同一任务跑多次取共识,适合高风险决策或需要多视角的场景。
  4. 编排器-工作者 Orchestrator-Workers:中央 LLM 动态分解任务,委派给工作者 LLM,综合结果。
  5. 评估器-优化器 Evaluator-Optimizer:生成器产出,评估器给反馈,循环直到达标,适合质量标准难以用代码精确定义的任务。

提示链、路由、并行、编排、评估五种模式示意图

上面这些模式解决的是控制流怎么搭,下面再看另一个更工程的问题:系统为什么能跑稳。

1.4. 为什么 Harness 比模型更关键

Harness 是指围绕 Agent 构建的测试、验证与约束基础设施,这里的 Harness 至少包括四个部分:验收基线、执行边界、反馈信号和回退手段。

模型虽然重要,但决定系统能不能稳定运行的,往往是这些外围工程条件。
这个判断在代码编写这类高可验证任务上最成立,但在开放式研究、多轮协商这类弱验证任务里,模型上限本身仍然更关键。

1.4.1. OpenAI 的 Agent 优先开发实践

3 个工程师 5 个月写了百万行代码,将近 1500 个 PR,是传统开发速度的 10 倍。
这个速度背后不是模型有多强,而是几个工程决策做对了:

  1. Agent 看不到的内容等于不存在:知识必须存在于代码库本身,外部文档对运行中的 Agent 不可见。
  2. 约束编码化而非文档化:写在文档里的规范很容易被忽略,编码进 Linter、类型系统或 CI 规则里的约束才具备可执行性。
  3. Agent 端到端自主完成任务:从验证当前状态、复现 Bug、实现修复到开 PR,全链路不需要人介入。
  4. 最小化合并阻力:测试偶发失败用重跑处理而不是阻塞进度,写代码的纪律从人工 Review 变成了机器执行的约束。

OpenAI 的 Agent 开发 Harness 基础设施架构图

APP 把日志、指标、追踪三路数据经由 Vector 分发到 Victoria 存储层,对应 LogQL、PromQL、TraceQL 三个查询接口,Codex 通过这三个接口查询、关联、推理,完成改动后重启应用、重跑工作负载,结果再打回给 Codex,UI Journey 也作为输入接入。
整套可观测性栈按任务临时创建、任务完成即销毁,Agent 不需要等人告知错误,直接查询系统状态验证修改是否生效。

1.4.2. Harness 的关键结论是什么

任务清晰度与验证自动化程度象限图

图里用任务清晰度和验证自动化程度把任务分成四种状态:

  • 右上角:目标明确、结果可以自动验证,是最适合 Agent 发挥的区域。
  • 左上角:任务清楚但验收还得人盯,吞吐量天花板是人的审查速度。
  • 右下角:有自动化反馈但目标模糊,系统会高效地往错误方向跑。
  • 左下角:两者都缺,Agent 基本起不到作用。

Harness 要做的就是把任务推进右上角,让对错有机器可以执行的判断标准,而不是靠人盯。

1.5. 上下文工程:决定系统稳定性的关键

Transformer 的注意力复杂度是 $O(n^2)$,上下文越长,关键信号越容易被噪声稀释。
实践中最常见的失效模式是无关内容一旦占到上下文的大头,Agent 的决策质量就会明显下滑,这种现象通常被称为 Context Rot。
很多看起来像模型能力不足的问题,往往可以追溯到上下文组织不当。

1.5.1. 上下文分层管理架构

问题通常不是窗口不够长,而是信息密度不对。
偶尔用的东西每次都加载进来,稳定的规则和动态的状态混在一起,模型能看到的内容越来越多,但真正有用的部分越来越难被注意到。

上下文分层管理模型:常驻层、按需层、运行时层、记忆层、系统层

解决方式是按信息的使用频率和稳定性分层管理,每层只放自己该放的内容:

  • 常驻层:身份定义、项目约定、绝对禁止项。每次会话都必须成立的内容,保持短、硬、可执行。
  • 按需加载(On-demand):Skills 和领域知识。描述符常驻,完整内容仅在触发时再注入。
  • 运行时注入(Runtime):当前时间、渠道 ID、用户偏好等动态信息,每轮按需拼入。
  • 记忆层(Memory):跨会话经验写入 MEMORY.md,不直接进系统提示,需要时检索读取。
  • 系统层(System):Hooks 或代码规则处理确定性逻辑,完全不进上下文。

原则:别把确定性逻辑放进上下文。
凡是可以通过 Hooks、代码规则或工具约束表达的内容,都应交给外部系统处理。

1.5.2. 三种常见上下文压缩策略

  1. 滑动窗口(Sliding Window):丢弃旧消息,成本极低,但会丢失早期背景,适合简短对话。
  2. LLM 摘要(LLM Summarization):模型生成总结,保留决策核心,适合长任务。进阶做法是 Branch Summarization,明确保留架构决策和未完成任务。
  3. 工具结果替换(Tool Output Compaction):用占位符替换原始冗余输出,适合工具调用密集的场景。

1.5.3. Prompt Caching:大幅降低重复开销

LLM 推理时,如果当前请求的输入前缀与之前完全一致,KV 缓存可以直接重用。
命中的前提是精确前缀匹配。

缓存友好的设计核心是稳定性:

  • 系统提示、工具定义、长文档等不变内容放在前缀。
  • 动态信息(当前时间、用户输入)放在末尾。
  • 稳定的大系统提示,比频繁变动的小提示实际成本更低,因为后续调用的折扣可达 90%。

1.5.4. Skills 按需加载模式

核心思路:系统提示只保留索引,完整知识按需加载。

const systemPrompt = `
可用 Skills:
- deploy: 部署到生产环境的完整流程
- code-review: 代码审查检查清单
- git-workflow: 分支策略和 PR 规范
`;

async function executeLoadSkill(name: string): Promise<string> {
  return fs.readFile(`./skills/${name}.md`, "utf-8");
}

Skill 描述对路由准确率的影响对比图

关键技巧:

  • 描述要像路由条件:说明"何时该用我"比"我能做什么"更重要。
  • 包含反例(Negative Examples):加上反例后准确率可从 53% 提升至 85%。
  • 控制字数:高效描述(约 9 tokens)比冗余描述(约 45 tokens)更能节省常驻空间。

1.5.5. 压缩时最容易丢失的信息

压缩阶段最常见的问题是保留优先级设错。
建议在 CLAUDE.md 中明确保留优先级:

  1. 架构决策(不得摘要)
  2. 已修改文件和关键变更
  3. 验证状态(pass/fail)
  4. 未解决的 TODO 和回滚笔记
  5. 工具输出结果(可删,仅保留结论)

注意:不要改动标识符。
UUID、Hash、URL、文件名等必须原样保留,否则后续工具调用会失效。

1.5.6. 动态上下文发现(Dynamic Context Discovery)

文件系统天然适合做上下文接口。
与其让模型一次性读取大量 JSON,不如让 Agent 通过 grep、rg 按需读取。
这种方式下,调用工具的任务总 token 消耗可减少约 46.9%。

1.6. 工具设计:决定 Agent 的能力边界

上下文决定模型能看到什么,工具决定模型能做什么。

工具设计演进:从 API 封装到 ACI 智能接口

1.6.1. ACI(Agent-Computer Interface)设计原则

工具设计不应是简单的 API 封装,而应面向 Agent 的目标。

  • 第一代:API 封装。粒度过细,Agent 难以协调。
  • 第二代:ACI 接口。合并操作,例如直接提供 create_script 而非拆分创建、写入、改权限。
  • 第三代:高级工具调用。
    • Tool Search:动态发现工具,上下文保留率提升至 95%。
    • Programmatic Tool Calling:代码编排工具,大幅降低 token 消耗。
    • Tool Use Examples:提供 1-5 个示例,调用准确率提升至 90%。

1.6.2. 优秀工具 vs. 平庸工具

好的工具设计边界清楚、参数防错,并能提供结构化的修正建议。

// ✅ 优秀实践:使用 Zod 绑定定义与实现,提供修正建议
const updateTool = betaZodTool({
  name: "update_yuque_post",
  description: "更新语雀文章内容,不适合创建新文章",
  inputSchema: z.object({
    post_id: z.string().describe("语雀文章 ID,纯数字字符串,如 '12345678'"),
    content_markdown: z.string().describe("Markdown 格式正文"),
  }),
  run: async (input) => {
    const post = await getPost(input.post_id);
    if (!post) throw new ToolError("文章 ID 不存在", {
      error_code: "POST_NOT_FOUND",
      suggestion: "请先调用 list_yuque_posts 获取有效的 post_id",
    });
    return await updatePost(input.post_id, input.content_markdown);
  },
});

好工具与差工具的对比:边界、反馈与成功率

建议:调试 Agent 时优先检查工具定义。
大多数错误源于描述不准而非模型能力不足。

1.7. 记忆系统设计:跨会话的一致性

Agent 本身不具备原生的时间连续性。
要实现跨会话一致性,记忆层必须单独设计。

1.7.1. 四层记忆模型

Agent 记忆系统架构:工作记忆、程序性记忆、情景记忆、语义记忆

  1. 工作记忆(Working Memory):当前上下文窗口中的消息。
  2. 程序性记忆(Procedural Memory):Skills 流程和规范。
  3. 情景记忆(Episodic Memory):持久化的 JSONL 会话历史。
  4. 语义记忆(Semantic Memory):MEMORY.md 中沉淀的稳定事实。

1.7.2. 记忆整合与回退机制

当 token 使用率超过阈值(如 50%)时,触发记忆整合:

  • 成功路径:生成摘要并追加到 MEMORY.md。
  • 失败路径:将原始消息归档,保留完整历史以备回溯。

记忆整合触发流程与回退策略示意图

核心:流程必须可回退。
系统只移动指针,不真正删除原始数据。

1.8. 自主度与长任务管理:从"单轮"到"持续"

提高自主度不仅是减少确认次数,更是让 Agent 能在长跨度内稳定推进任务。

1.8.1. 跨 Session 续跑:状态外化

长任务失败的主因通常是 Session 结束导致上下文耗尽或现场丢失。
更稳定的做法是角色协作与状态外化:

  • Initializer Agent:仅运行一次,生成任务清单(feature-list.json)、进度记录(claude-progress.txt)。
  • Coding Agent:循环执行,每次从外部文件恢复现场,实现单一功能并跑通测试,更新状态后提交代码。

长任务跨 Session 恢复流程:Initializer 与 Coding 协作模式

1.8.2. 显式任务状态:外部锚点

任务状态必须显式记录为外部对象,而非仅留在模型的工作记忆中。

  • 同一时间仅限一个 in_progress。
  • 每完成一步均先更新外部状态文件。
  • 长任务偏航时,自动注入进度提醒。

1.8.3. 后台 I/O 异步接入

将慢速 subprocess(如文件操作、网络请求)放入后台,通过通知队列在下一轮注入结果,避免阻塞主循环。

1.9. 多 Agent 组织:隔离、协作与协议

多 Agent 的核心价值在于将人的持续参与,转化为对 Agent 产出工件(如 PR)的最终审核。

1.9.1. 统筹者模式(Orchestrator-Workers)

主 Agent 负责全局统筹,子 Agent 独立并行工作。

  • 信息隔离:子 Agent 的搜索和调试细节不污染主 Agent 上下文。
  • 摘要回传:主 Agent 仅接收子 Agent 的结论摘要。

多 Agent 协作架构:Orchestrator、Worker 与隔离边界

1.9.2. 结构化协作协议

多 Agent 协作必须建立在清晰的通信协议之上,而非仅靠自然语言。

// 推荐的消息结构示例
{
  "request_id": "req_001",
  "from_agent": "orchestrator",
  "to_agent": "coder",
  "content": "实现登录接口",
  "status": "pending",
  "timestamp": 1747312345
}

多 Agent 任务流管理与隔离边界示意图

关键设施:

  1. 协议:统一的消息结构。
  2. 任务图:记录依赖关系的 .tasks/。
  3. 隔离边界:使用 .worktrees/ 隔离每个 Agent 的文件修改。

多 Agent 协作中的隔离与消息传递机制

1.9.3. 交叉验证:打断幻觉放大链

在多 Agent 互动中,错误会被层层放大。
交叉验证(如独立的第二个 Agent、单测、编译器)能有效打断这种错误链。

交叉验证机制:通过独立反馈打断错误传递

1.10. Agent 自动化评测:构建质量基石

评测的核心在于:测试用例、评分标准和自动验证。

1.10.1. 评测结构的复杂性

Agent 评测不仅是看输出了什么,更要验证环境里发生了什么。

传统单轮评测 vs. Agent 循环评测结构对比

  • Single-turn:判断 Response 是否正确。
  • Agent Loop:运行环境 + 工具调用,验证 Outcome(环境最终状态)。

Agent 评测体系全景图:任务、评分器、执行记录与基础设施

1.10.2. 核心指标与评分器

  • 指标选择:
    • Pass@k:验证理论上的能力上限。
    • Pass^k:验证回归质量,保证上线稳健性。
  • 评分器类型:
    1. 代码评分器:单测、结构比对,确定性最高。
    2. 模型评分器(LLM Judge):按标准评分或对比选优。
    3. 人工评分器:专家标注,用于建立基准和校准。

评测指标与方式的行业现状分布图

1.10.3. 先修评测,再改 Agent

当通过率下降时,先查评测基础设施(如资源不足、评分器 Bug),再动 Agent。

环境资源上限对评测错误率的影响曲线图

1.11. 执行过程追踪(Tracing)

没有 Trace,失败案例就无法稳定复现。

1.11.1. Trace 记录要素

  • 完整 Prompt 与系统提示。
  • 多轮消息历史。
  • 工具调用详情(参数与返回值)。
  • 最终输出与消耗统计。

1.11.2. 观察者模式:事件流底座

Agent 在关键节点(如 tool_start)发出事件,多路下游(日志、UI、评测)按需订阅,实现架构解耦。

基于事件流的可观测性架构图

1.12. OpenClaw:工程化落地实践

OpenClaw 是一个遵循上述原则构建的工业级 Agent 系统。

1.12.1. 五层解耦架构

  1. Gateway:WebSocket 消息分发。
  2. Channel 适配器:多渠道(23+)统一接口。
  3. Pi Agent:核心逻辑循环,与渠道解耦。
  4. 工具集:遵循 ACI 原则的 Shell/FS/Web 等工具。
  5. 上下文与记忆:Skills 延迟加载与 MEMORY.md。

OpenClaw 系统架构图:五层解耦模型

1.12.2. 主动触发:Cron 与 Heartbeat

系统不再仅依赖用户消息,通过定时计划和轮询主动推进任务。

1.12.3. 安全边界:先于功能

  1. 白名单授权:限定用户范围。
  2. 工作空间隔离:强制路径检查,防止越界。
  3. 审计日志:操作全记录。

1.12.4. 防注入与故障切换

  • 内容边界标注:使用 <untrusted_content> 隔离外部输入。
  • Provider Fallback:多模型供应服务自动切换。

OpenClaw 的安全防护与内容边界标注示例

1.13. Agent 落地中的常见反模式(Anti-patterns)

  1. 系统提示充当知识库:导致提示过长,关键规则被忽略。应将知识移入 Skills,提示仅保留索引。
  2. 工具数量失控:Agent 频繁选错工具。应合并重叠工具,建立明确的命名空间。
  3. 验证闭环缺失:Agent 仅给出执行陈述而无法验证。应为每类任务绑定客观验收标准。
  4. 多 Agent 无边界:导致状态漂移和故障归因困难。应明确角色权限,使用 Worktree 隔离。
  5. 记忆不整合:长对话后决策质量显著下降。应监控 token 并实现超阈值自动整合。
  6. 缺乏自动化评测:修改后无法感知回归风险。应将失败案例立即转为持久化的测试用例。
  7. 约束靠"期望"而非"机制":规则仅停留在文档中。应改用工具验证、Linter 或 Hook 强制执行。

1.14. 结语:迈向工业级 Agent 时代

实现工业级 Agent 的稳定运行,靠的不是更复杂的模型循环,而是消息解耦、状态外化、分层提示、记忆整合与安全边界等工程细节的严丝合缝。


1.15. 参考资料

  1. OpenAI, Harness engineering: leveraging Codex in an agent-first world
  2. Anthropic, Managing context on the Claude Developer Platform
  3. LangChain, State of Agent Engineering
  4. Anthropic, Demystifying evals for AI agents
  5. OpenAI, Designing AI agents to resist prompt injection
  6. Cloudflare, How we rebuilt Next.js with AI in one week
  7. Anthropic, Introducing Agent Skills