2026 年 AI Agent 工程师:12 步路线图——Loops、Graphs、Evals、Context、Harness(完整课程)

这是一份完整的 12 步路线图,涵盖真正决定 Agent 能否工作的七大支柱:上下文(context)、工具(tools)、记忆(memory)、循环(loops)、图谱(graphs)、运行框架(harness)、评估(evals)——每一步都配有能验证它的 Claude 工作流。

前沿模型在一年内把 SWE-bench Verified 的成绩从 30% 拉到了 80% 以上。编程 Agent 的能力肉眼可见地突飞猛进。

与此同时,只有 17% 的高管表示他们的公司在全公司范围内采用了 AI Agent。

关注我的 Substack 获取新鲜 AI 资讯:movez.substack.com

Agent 为什么会失败?因为上下文膨胀。因为循环永远不收敛。因为没人能衡量上周的改动是否让结果变得更好。Demo 在你的机器上跑得通,生产环境完全是另一回事。

这就是那 12 步路线图——穿过把两者区分开来的七大支柱,每一步都有各自的失败模式、各自的 Claude 工作流,以及跳过它时悄悄毁掉你的 Agent 的方式。

先给你一个能让其余内容连贯起来的重新框定:这七个支柱不是七种独立技能,它们是同一种技能在七个维度上的投影。

  • 坏的上下文会破坏循环。
  • 没有评估的循环永远不会收敛到你可信的结果。
  • 没有评估的图谱放大的是错误,而不是吞吐量。
  • 没有运行框架的记忆在会话结束的瞬间就蒸发了。
  • 没有上下文管理的工具会在工作开始前就把窗口淹没。

这意味着没有一种孤立的学习方式是有用的——但确实存在一个依赖顺序:先打基础,再谈执行,最后才是可靠性。12 步就是这么安排的。

01. 上下文——先看清真正加载了什么

Karpathy 的框架值得记住:模型是 CPU,上下文窗口是 RAM。上下文工程的艺术,就是用下一步恰好需要的东西填满那块 RAM——不多不少。

一个重新框定一切的数字:在 Claude Code 里,你还没敲下第一个字符,大约 7850 个 token 就已经加载了——系统提示词、自动记忆、技能描述、CLAUDE.md、环境信息、MCP 工具名。

你实际的提示词大约只有 45 个 token。所有人都在优化那 45 个,却没人打开那 7850 个。

/context 会按类别打印你的真实构成,告诉你哪些记忆文件被加载了,并标记哪个工具调用吃掉了最多的 token。要盯住两个数字:记忆文件(数值大意味着 CLAUDE.md 过于臃肿)和剩余空间。配合 /memory 可以看到实际在用的文件。

02. 上下文——先砍,再分层

Anthropic 在 Claude 5 这一代删掉了 Claude Code 系统提示词 80% 以上的内容,编码评估没有任何损失。

大多数上下文不是"错",而是写给更弱模型看的指导——现在它们只花钱,还迫使 Claude 在开工前先去调和各种矛盾。

两条让删减变得安全的规则:

  • 整块删,不要逐行删——一句话藏在评估的噪声底里,什么也说明不了。

把绝对禁令转成原则:不要写"永远不要写多行注释",而是说"写出读起来像周围代码的代码——匹配它的注释密度、命名习惯和惯用法"。

规则给出固定答案,原则给 Claude 提供一种通过阅读你的仓库来找到正确答案的方式。

  • 活下来的内容放进树状结构,而不是滚动长文。Anthropic 的指导是一个硬数字:项目级 CLAUDE.md 保持在 200 行以内,只放 Claude 无法推断出来的坑。

其他一切变成技能(描述在启动时加载、正文在调用时加载)或路径作用域规则(只在读匹配文件时加载)。

# payments-api
Web 应用的订阅计费和开票。

踩坑记录

// 非显而易见。Claude 无法通过读仓库推断出来。

  • 所有共享类型都在 src/types.ts —— 一个巨型单体文件。
  • Money 是整数分,永远不是浮点数。
  • Webhook 重试必须保持幂等——供应商会回放 72 小时。
  • db/legacy/ 已冻结。可以读,不要改。

更深层的指南

  • 验证 → .claude/skills/verify/
  • 发布 → .claude/skills/deploy/

// 不要写在这里:目录树、框架、测试运行器、语言
// 版本。Claude 会自己从仓库里读那些。

03. 工具与 MCP——Agent 能触达什么

工具是 Agent 触碰世界的方式,而工具的描述本身就是上下文——这让它成了"Agent 能做什么"和"Agent 负担得起知道什么"之间的枢纽。

过去的建议是用示例教工具。

这个建议已经反过来:对现在的模型来说,示例会把 Claude 限制在示例所描述的探索空间里。改成设计有表现力的参数。

一个 pending | in_progress | completed 的状态枚举,不需要任何示例就能教会整个生命周期——类型本身就是文档。

Anthropic 在 SWE-bench Verified 上达到 SOTA,一部分就来自对工具描述的精准打磨,而不是模型改动。

而且"延后"胜过"倾倒"。Claude Code 只加载 MCP 工具名——大约 120 个 token——通过工具搜索按需获取 schema。

把检索应用到工具描述上(而不是全部加载),选择准确率大约提升三倍。

这使描述成了发现面:要说清工具在什么时候适用,而不只是它做什么。Claude 找不到的工具,等于你没交付的工具。

@mcp.tool()
def find_stalled_shipments(hours: int = 24) -> list[dict]:
    """N 小时内没有扫描事件的发货记录。
    当运营问什么东西卡住了,或在升级评审之前使用。"""
    return query(STALLED_SQL, hours)

@mcp.tool()
def reroute(shipment_id: str, hub: str, reason: str) -> dict:
"""重新路由一次发货。写入审计记录——合规要求
每次人工干预都要有原因。"""
return post_with_audit(shipment_id, hub, reason)

"Use when..." 是工具搜索的发现面。

reason: str 是必填的,所以审计记录无法被跳过。

类型强制的效果,是一整段指令文字求之不得的。

04. 记忆——什么能活过窗口

每个长任务最终都会超出单窗口。

在那个边界上会发生什么,是一个大多数人从未做出的设计决策——他们让自动压缩去猜,然后纳闷 Agent 为什么会忘掉一小时前说过的约束。

具体的机制值得记住。项目根目录的 CLAUDE.md 和自动记忆会从磁盘重新注入。

但用路径作用域的规则和嵌套的 CLAUDE.md 文件活在消息历史里——它们会被摘要掉,直到再次读到匹配文件才会回来。

被调用的技能正文会回来,但每个技能上限 5k、总计 25k,最旧的先丢、从尾部截断——所以任何关键内容都要放在 SKILL.md 的顶部。

最可靠的招数是计算机领域最老的那招:写进文件。

一份计划文件、一份进度日志、Agent 边干边改的笔记。它不占窗口、能活过压缩,因为它活在磁盘上。

也要刻意压缩——/compact focus on the auth bug 能保住你选择的内容;当下一个任务不依赖过去二十条消息时,/clear 被严重低估了。

05. 循环——何时停下

Agent 循环是 行动 → 观察 → 决定 → 重复。整个工程问题都在最后一步:它怎么知道自己完成了?

放任自流的话,模型会朝两个方向乱答——在半成品上宣布胜利,或者在三轮前就做完的事情上永远空转。

这两者都不是更好的提示词能修好的,因为两者都是结构性的。停止条件要放在模型判断之外的代码里。对有边界的工作,那是测试门或 schema 检查。

对规模未知的探索,收敛模式是"循环直到干涸":持续运行,直到连续 K 轮没有任何新发现。

有一个细节成败攸关,而且几乎所有人第一次都搞错:去重要针对"所有见过的",而不是"已确认的结果"。

否则被否定的发现每轮都会重新出现,循环永不干涸——你造出了一台永远付钱去重新发现同一批死胡同的机器。

const seen = new Set(); const confirmed = []; let dry = 0;

while (dry < 2) { // 连续 2 轮为空就停
const found = await runFinders();
const fresh = found.filter((b) => !seen.has(key(b)));

if (!fresh.length) { dry++; continue; }
dry = 0;
fresh.forEach((b) => seen.add(key(b)));
// ^ 对 SEEN 去重,而不是对 confirmed 去重。
// 反了的话,这个循环永远不会终止。

confirmed.push(...(await verify(fresh)));
}

06. 循环——谁来检查答案

收敛的循环也只是收敛到模型相信的东西上。解法是加一个验证者——一个独立于模型自身判断的东西,它唯一的任务就是试图推翻这个发现。

如果它活下来了,就通过。如果没活下来,它永远到不了答案。

三种值得掌握的模式:

  • 对抗式验证:对每个发现,派出 N 个被提示去反驳它的独立怀疑者;只有多数存活才保留。
  • 多视角验证:给每个验证者一个不同视角——正确性、安全性、能否复现——因为多样性捕捉的是 N 次完全相同的检查永远抓不到的失败模式。
  • 评审团:从不同角度生成 N 个尝试,用并行的评审打分,从赢家综合,同时嫁接亚军的精华。
› 对每个发现,派出三个验证者——正确性、安全性、可复现性。三选二通过才接受。

● 6 个发现 → 18 个验证 Agent,并行运行

✓ /invoices/:id 缺鉴权 3/3 —— 接受 ✓ webhook 重试竞态 2/3 —— 接受

● "验证器里不安全的正则" 0/3 —— 毙掉

● "dashboard 里的 N+1 查询" 1/3 —— 毙掉 6 个发现里有 2 个自信但错了。抓住它们的是循环,不是你的评审,也不是你的用户。

注意这里的指向。验证者就是在线的评估——和第 11 步是同一套纪律,只不过从"每次发布"下沉到"每个结果"。能建出好验证者的团队会发现第 11 步容易得多,因为他们早就写下了"好"意味着什么。

07. 图谱——什么并行跑

大多数人把 Agent 写成一条直线——第一步、第二步、第三步,每一步礼貌地等上一步。然后他们发现,一半的步骤根本不需要等。

节点是一份工作单元,边表示这个输出喂养那个输入。如果没有数据跨越,就没有边——那么等待就是纯粹的浪费。

主力形态是菱形:扇出收集广度,用普通代码归约,用一个 Agent 综合。

归约这步值得强调,因为钱是从这里漏掉的——展平去重是 flatMap 加一个 Set,不是 Agent。

边是免费的。把 Agent 花在判断上,不要花在管道上。

天花板真的很高。Claude Code 的动态工作流在一次运行里能协调多达 1000 个并行子 Agent,而编排花费的模型 token 是零——因为它是脚本,不是对话。

› 运行一个工作流,审计 src/routes/ 下每个路由是否缺
鉴权。每个路由文件一个 Agent,每个发现验证后再报告。●
Claude 写了一个编排脚本 · 启动中… ✓ 范围 1/1 ✓ 扇出
18/18 每个文件一个 Agent ◯ 验证 11/18 每个发现 3 票怀疑者
○ 综合 0/1 你的会话保持响应——整个舰队在后台运行

正是这套架构,让一个团队在六天内把 Bun 运行时约 96 万行代码从 Zig 移植到 Rust,测试套件仍然有 99.8% 通过。

08. 图谱——形状的代价

拓扑不是装饰——它是对延迟和花费影响最大的杠杆,两个选择占了大部分影响。

首先是 parallel() 对 pipeline()。parallel() 屏障让一切等到最慢的节点完成,才开始下一阶段。

pipeline() 让每个条目独立流经所有阶段——条目 A 可以在阶段 3,而 B 还在阶段 1。

默认用 pipeline。只有当某个阶段真的需要一次性拿到所有前序结果时才用屏障,比如跨集合去重。"感觉更干净"不是理由;屏障延迟是真实、可测量、被浪费掉的时间。

第二,按节点分层模型。每个子 Agent 默认继承你会话的模型,除非脚本覆盖——所以一次大运行默认按你的最高档位计费。

有边界、重复性的节点——提取这个字段、给这张工单分类——应该放在更便宜的模型上,而真正发生判断的合并节点保持高档。

一百个便宜的扇出节点喂养一个顶级综合,相比同样任务平铺跑完,花费只有零头,最终质量相同。

09. 运行框架——在会话死亡中存活

Anthropic 把问题框得很妙:一个长任务是"由轮班工程师组成的软件项目,每个新工程师到来时都不记得上一班发生了什么"。

单靠压缩修不好它。即使让前沿模型在"建一个 claude.ai 的克隆"上跨上下文窗口循环,也会失败——而且失败在两种具体、可复现的方式上。

第一,Agent 试图一次性搞定整个应用,实现到一半上下文耗尽,留给下一个会话的是一个半成品、无文档、需要逆向工程的功能。

第二,在项目后期,Agent 环顾四周,看到真实的进展,宣布任务完成。

两者都在任何编码开始前就能修好:用一个只运行一次的初始化 Agent 来搭建环境——一个启动开发服务器的 init.sh、一份进度日志、一个初始 git 提交、一份 JSON 格式的功能清单——claude.ai 克隆那份有 200 多个条目,每个都标记为失败。

{
  "category": "functional",
  "description": "新建聊天按钮能创建全新会话",
  "steps": [
    "导航到主界面",
    "点击'New Chat'按钮",
    "验证创建了新会话",
    "检查聊天区显示欢迎状态"
  ],
  "passes": false
}

// 200+ 个这样的条目,全部以 false 开头。Agent 只能翻转 passes。
// "不允许删除或修改测试" —— 故意用强硬的措辞,
// 因为一个能改规范的模型就一定会改规范。

有一个细节值得直接偷走:他们为这份清单选了 JSON 而不是 Markdown,因为模型乱改 JSON 的可能性在实测上明显更低。

10. 运行框架——每个会话一个增量

环境搭建好之后,每个编码会话获得一份契约:先定位,只挑一个功能,像用户那样验证,让仓库保持干净。

"干净"的意思是真实团队里那个意思——没有大 bug、代码有序、下一个工程师不用先收拾别人的烂摊子就能开工。

定位仪式是机械性的,每次都省 token:pwd、读进度文件、读 git 日志、读功能清单、运行 init.sh,在碰任何东西之前先测试基础功能仍然正常。

最后那一项检查比听起来重要得多——没有它,在一个已经坏掉的应用之上开始新功能的 Agent,只会把破坏弄得更深。

关于标记完成:Claude 的倾向是完成一个改动、跑几个单元测试、宣布完成,却从不端到端检查功能。

[助手] 让我先了解当前状态。 [工具] bash — pwd [工具] read — claude-progress.txt [工具] read — feature_list.json [工具] bash — git log --oneline -20 [工具] bash — ./init.sh 启动开发服务器 [助手] 在碰任何东西之前先验证基础功能… ✓ 核心聊天、主题切换、会话加载全部通过 [助手] 选择优先级最高的失败功能。不猜。不做考古。上一班留下了笔记。

给它真实的测试工具,要求它像真人用户那样验证——浏览器自动化、真实点击。

这一条要求显著提升了 Anthropic 实验中的表现,抓到了从代码里根本看不见的 bug。

11. 评估——一个数字,而不是一种感觉

转折点永远是同一句话:用户反馈改动后 Agent 感觉变差了,而团队除了猜和试之外没有别的验证方式。

没有评估,调试就是被动的——等投诉、手动复现、修复、祈祷没有别的回归。你分不清真实回归和噪声。

从比你想象更小的规模开始。团队拖延是因为他们以为需要几百个任务;从真实失败里抽 20–50 个就是绝佳的起点,因为早期改动有巨大的效应量。

从你已经手动测试过的东西、你的 bug 跟踪器、你的支持队列里抽。把它们写到两个领域专家会独立得出同样结论的程度——任务里的歧义会变成指标里的噪声。

还要构建平衡的集合:既测"行为应该触发"的场景,也测"不应该触发"的场景,否则你会优化出一个什么都搜的 Agent。

刻意组合三种评分器。

  • 基于代码——快、便宜、客观;能用的地方都用。
  • 基于模型——为细微之处设评分标准,与人类校准,理想情况下每个维度一个独立评审,而不是一个评审给所有东西打分。
  • 人类——黄金标准,克制使用,用来校准其他两者。

而且评分要评 Agent 产出的东西,而不是它走的路径:检查精确的工具调用序列是脆弱的,因为 Agent 经常找到你没想到的合法做法。

task:
  id: "fix-auth-bypass_1"
  desc: "修复密码字段为空时的鉴权绕过"
  graders:
    - type: deterministic_tests     # 快、客观、可复现
      required: [test_empty_pw_rejected.py]
    - type: llm_rubric               # 测试抓不到的细微之处
      rubric: prompts/code_quality.md
    - type: static_analysis
      commands: [ruff, mypy, bandit]
    - type: state_check              # 看结果,不看声明
      expect: { security_logs: { event_type: "auth_blocked" } }
  tracked_metrics:
    - type: transcript
      metrics: [n_turns, n_toolcalls, n_total_tokens]

Agent 嘴上说"修好了"。state_check 决定它到底修没修好。

评结果,不要评公告。

12. 评估——让数字保持诚实

没人读的测试套件,是没人该信的数字。你得读过很多次试验的转录,才会知道你的评分器好不好用——任务失败时,转录会告诉你 Agent 是真的错了,还是你的评分器拒绝了一个有效的解法。

失败应该让人觉得公平:错在哪、为什么,一目了然。

两个陷阱会让好 Agent 看起来很差。

  • 多次试验 0% 通过率通常意味着任务本身坏了,而不是 Agent 不行。Opus 4.5 在 CORE-Bench 上最初只有 42%——然后一个研究员发现评分过于死板:期望 "96.124991…" 却拒绝 "96.12";还有含糊的规格和不可复现的任务。修复之后:95%。
  • 反方向的陷阱是饱和——100% 的评估能追踪回归,但给你没有可爬的坡,真实的能力提升开始表现为噪声。

然后要把两个指标分开。pass@k 是 k 次尝试中至少成功一次的概率——它随 k 上升。pass^k 是全部 k 次都成功的概率——它快速下降。单次 75% 时,三次全过只有约 42%。

一次成功就够的场景用 pass@k;面向用户的东西用 pass^k,因为用户期望它每次都工作。

› 用新模型跑套件并与基线对比。● 47 个任务 × 3 次尝试 · 141 次运行 · 并行能力套件
pass@1 61% → 74% +13 回归套件 pass@1 99% → 99% 一致性保持 pass^3
52% → 68% +16 ● 2 个回归:refund_partial、escalation_tone → 转录写入
./eval-results/failures/ 升级决策花了一个下午,而不是三周

最后,让它成为例行公事。把套件接进 CI,每次改动、每次模型升级都跑。

这就是把一次新模型发布从数周手动测试变成一天跑套件加读差异的东西——也是没有评估的团队永远追不上的复利优势。

给 Claude 的 7 项作业——每个支柱一项

打开你从没看过的那个窗口。先测量,再删减。记忆文件数值大意味着 CLAUDE.md 过重——一条命令诊断出来,一个下午修完。

› /context 然后 /doctor

审计你的工具描述。每个描述都应该说清工具什么时候适用,而不只是它做什么。那句话就是发现面——没有它,连上的工具就是 Claude 永远不会选的工具。

› 审查这个 MCP 服务器里的每个工具描述。给每个加上"何时使用"的句子,并收紧参数类型。

把状态移到文件系统上。让 Claude 维护一份它边干边改的计划文件。它因为活在磁盘上所以能活过压缩——长任务不再做到一半丢线。

› 开工前,把计划写进 plan.md,每完成一步就更新。每次恢复时重读。

给循环加一个验证者。挑一个让 Claude 自己判断"做完了"的任务。加一个外部检查,看看第一次的答案有多频繁过不了三个怀疑者。

› 每次修复后,派出三个验证者——正确性、安全性、可复现性。三选二通过才接受。

把一个线性任务变成扇出。找一个你顺序遍历文件或来源的任务。每个条目一个 Agent,同时运行,然后一次合并。墙上时钟的差异就是全部课程。

› 运行一个工作流审计 src/routes/ 下每个路由。每个文件一个 Agent,验证每个发现,然后综合。

搭建一个多会话项目。在长构建开始前,让 Claude 写 init.sh、一份进度日志、一份把所有内容标记为失败的 JSON 功能清单。

› 扮演初始化 Agent:写 init.sh、claude-progress.txt 和 feature_list.json,覆盖每个需求,全部 passes:false。

把上周的 bug 变成套件。打开你的 bug 跟踪器,把真实失败转成 20 个有明确通过标准、不二义的任务。这套件比你这季度能采用的任何框架都值钱。

› 这里有 20 个真实失败。把每个写成评估任务,能用确定性评分器就用,不能就用评分标准。

结论

任何人都能把 demo 跑通。工作在于之后的一切。

模型会按自己的节奏持续变强,而那种进步是免费的——无论你做没做任何事,它都会到来。

不会免费到来的是模型周围的系统。

  • 保持精简的上下文。Agent 真正能在之间选择的工具。
  • 能活过窗口的记忆。会收敛并被检查的循环。
  • 扇出而不是排队的图谱。让下一个会话能接着上一个继续的运行框架。还有一个能告诉你这一切有没有变好的数字。

大多数人会继续等待一个足够好、不需要这一切的模型。

而建起这 12 步的人,会在模型状态糟糕的日子里交付能工作的 Agent——在生产环境里,这才是唯一真正重要的可靠性。


个人点评

这篇是 Codez 的《AI Agent Engineer in 2026: 12 steps roadmap》——一份写给 2026 年 Agent 工程师的完整路线图。它最大的价值不是给你 12 个步骤,而是把 Agent 拆成 七个真正决定"能不能跑起来"的支柱,再给每个支柱配一条 Claude 工作流:context(上下文)、tools(工具)、memory(记忆)、loops(循环)、graphs(图谱)、harness(运行框架)、evals(评估)。

几个让我特别有共鸣的地方:

1. "七个支柱其实是一件事的七个投影"这个归纳很准。 很多人学 Agent 是一块一块学的:先学 context 管理,再学工具调用,然后补 evals。这篇把它收敛成一句话——坏 context 会破坏 loop,没 evals 的 loop 永远不会收敛。这个"失败模式联动"的视角,比单独学每个部分更能解释为什么 Agent 上线就崩。

2. "Production is a different animal"——demo 和生产的落差。 几乎所有 Agent 项目都在演示时完美、部署后崩溃。这篇把原因拆出来了:context 膨胀、loop 不收敛、session 死亡。这跟我自己做 Hermes、做多 Agent 编排时的体感完全一致——本地跑通只是起点,能稳定跑一周才是真考验。

3. 每个支柱都对应一个 Claude 工作流,这是全文最实操的部分。 比如 "Loops - who checks the answer" 讲的不是让 Agent 循环,而是谁在检查结果质量;"Harness - one increment per session" 讲每次会话只前进一个增量,避免 session 死亡时全丢。这些是真正能落地进工作流的判断。

4. "The agent says fixed, the state_check decides whether it was. Grade outcomes, not announcements." 这句话值得所有做 Agent 的人抄下来——评估看的是结果状态,不是 Agent 嘴上说了什么。这直接对应我记忆中"评估要能落地到当前实践"的原则。

两点补充:

  • 这篇偏纯 Engineering 视角,把 Agent 当系统在讲。如果你更关心"Agent 如何服务内容生产/内容运营"这个场景,需要额外补充一层:评估指标(evals)不该只衡量代码正确率,还要衡量内容质量维度(信息密度、结构完整性、是否符合账号调性)。
  • 12 步覆盖了七个支柱,但没有单独展开"多 Agent 协作"(multi-agent orchestration)的成本收益。实际工作中,引入第二个 Agent 是增加系统复杂度的决策,需要权衡。这是路线图之外值得你自己实验的部分。

总的来说,这是一份写给正在认真做 Agent 的人的路线图,不是概念科普。适合:正在搭 Agent 系统但遇到"本地能跑、线上就崩"的人,做多 Agent 编排的人,以及想给自己的 Agent 加一层可靠评估的工程师。建议把 12 步当检查清单,对照自己的 Hermes / Agent 项目逐条过一遍。


转载声明:本文原载于 X(Twitter),作者 Codez(@0xCodez)。原文链接:https://x.com/0xCodez/status/2089393338977829278

觉得这篇文章有帮助?分享给更多朋友