Agent Loop五大构建块和记忆层

Addy Osmani将 Loop 的设计方法论提炼为五大构建块(Five Primitives)+ 记忆层。这六个组件构成了Loop Engineering的工程骨架——它们不是抽象概念,每一个都对应 Loop 系统中一项具体的职责。六大组件在真实Loop中的协作关系如下:

image-20260720103524589

自动化/调度

自动化是Loop的触发器,它决定了系统”什么时候开始工作”。没有自动化,Agent必须等人手动调用agent.invoke()。

自动化有三种触发模式:定时触发、事件触发、目标驱动。

  • 定时触发

按固定时间间隔唤醒系统,适合周期性巡检——每天早上生成运营日报、每 10 分钟扫描待处理队列、每小时检查服务健康状态。技术上通过 cron 表达式或 Python schedule 库实现。

# Claude Code 中的 /loop 命令
/loop 10m "检查 pending_contracts/ 文件夹,有新合同就审查"

#自定义Loop代码中的Python实现
while True:
    contracts = glob("pending_contracts/*.txt")
    for cid in contracts:
        process_contract(cid)
    time.sleep(10)
  • 事件触发

由外部事件通过 Webhook 唤醒——GitHub PR 被创建时自动运行代码审查 Loop、监控系统告警触发时自动启动诊断流程、Slack 收到特定关键词消息时自动分派任务。事件触发通过 MCP 连接器接收外部信号。

  • 目标驱动

不设时间表,设完成条件。Agent 持续运行直到验收条件被独立的Checker判定为”满足”——这恰是 Claude Code /goal 命令的运作方式。

/goal "修复 test/auth 下所有失败测试,直到 npm test exits 0 且 lint 无报错"

自己构建 Loop 系统用 Python 代码控制调度节奏——Python 代码中的 while True + time.sleep() 是最灵活的方式,也是 Loop Engineering 的核心特征:循环逻辑在代码里,不在 Prompt 里。

工作树/隔离

当多个Agent同时在同一个项目中工作时,一个朴素但致命的问题浮现:Agent A 正在读auth.ts的第50行,Agent B同时把它改成了另一段代码——A的后续操作全部基于已过期的文件状态。

git worktree解决了这个问题,它允许在同一仓库中创建多个独立的工作目录,每个目录对应不同分支,共享同一份.git 历史,但文件互不可见:

主仓库 (main)
├── worktree-1 → branch: feature/auth-fix     ← Agent A 独占
├── worktree-2 → branch: feature/api-optimize ← Agent B 独占
├── worktree-3 → branch: feature/ui-refactor  ← Agent C 独占
└── 各自有独立的文件副本,互不干扰

Addy Osmani的总结一针见血:”两个 Agent 同时写同一个文件,跟两个工程师不商量就改同一行代码一样痛苦。Worktree从物理上阻止了一个Agent的改动碰到另一个Agent的检出。”

隔离带来的价值不仅是防冲突。失败的修改被限制在自己的Worktree内,可以随时丢弃而不影响其他Agent的任务。三个Agent不再排队等上一个干完,而是真正并行工作——吞吐量线性提升。

在Claude Code中,通过–worktree标志自动创建隔离环境。在自定义 DeepAgents Loop中,通过FilesystemBackend实现同等效果:

from deepagents.backends import FilesystemBackend

maker = create_deep_agent(
    backend=FilesystemBackend(
        root_dir="./agent_workspace",
        virtual_mode=True,   # 虚拟沙盒:Agent 看不到 root_dir 之外的任何文件
    ),
    ...
)

virtual_mode=True的效果不是”不允许访问外部”,而是”看不见外部”——Agent的所有文件系统操作被限制在root_dir内,连父目录的存在都感知不到。这比操作系统的文件权限更彻底,因为不存在”提权”的可能。

Skill技能

每次启动Agent时,如果把项目规范、构建步骤、代码风格这些知识全部塞进 system prompt,会有两个后果:Token大量浪费(每次会话重复注入相同内容),以及知识漂移(Agent可能混入训练数据中的陈旧信息)。

Skill把这些项目知识外化为独立的SKILL.md文件——它不是给人看的文档,而是给Agent执行的工作流程清单。Addy Osmani的原则是”精确胜过聪明”(Precise beats clever):一份好的 Skill 应该像飞机驾驶舱的检查清单,每一步都清晰、可验证、不可跳过。

Skill的核心机制是渐进式披露(Progressive Disclosure)。Agent启动时只在上下文中注入Skill的名称和一行描述(约50 tokens),只有当它真正需要执行该任务时,才通过内置的文件系统工具读取完整的SKILL.md。相比传统的”全部塞进system prompt”,Token 节省可达 95%。

例如如下:

---
name: contract-review
description: 合同审查标准流程。当需要审查合同时使用此技能。
---

# 合同审查清单

## 第一步:基础信息核验
- 合同双方名称是否完整准确
- 合同金额是否明确(大小写一致)
- 签署日期是否在有效期内

## 第二步:条款审查(重点)
- 付款条款:付款方式、账期是否合理
- 交付条款:交付时间、验收标准是否明确
- 违约条款:违约金比例是否在行业标准内(通常不超过 20%)
- 保密条款:保密期限是否覆盖合同期 + 解约后 2 年

## 第三步:风险评级
- 低风险:标准模板合同,无特殊条款
- 中风险:有修改的非标准条款,但不涉及核心利益
- 高风险:涉及大额违约金、知识产权归属、独家授权

## 第四步:审批决策
- 低风险 + 金额 < 50 万 → 可自动通过
- 中风险 → 需 Checker 复核
- 高风险或金额 ≥ 50 万 → 升级人工审批

注意:Skill 的价值在于检查清单的结构化程度,而非文章的文采。每一步都应该是 Agent 可以逐条对照执行的动作项,而非供人理解的概念描述。模糊的指导(”注意合同风险”)对 Agent 毫无意义;可验证的规则(”违约金比例 ≤ 20%,否则升级人工”)才能被可靠执行。

在 DeepAgents 中加载 Skill:

agent = create_deep_agent(
    model=llm,
    tools=[...],
    skills=["./skills/"],   # Agent 启动时只加载名称列表,用到才读全文
)

SKILL.md 是纯 Markdown 文件,跨平台兼容——Claude Code、Cursor、Gemini CLI、GitHub Copilot均可直接使用。

插件/连接器

连接器是Agent与外部世界的接口层。没有它,Agent就无法与外界“交互”,如:调不了 API、查不了数据库、发不了消息。有了它,推理和执行连成一条端到端的链路:

Agent 推理:"退款在 7 天窗口内,符合政策"
  → 调数据库 MCP 查历史退款记录
  → 调支付网关 MCP 执行退款
  → 调 Slack MCP 通知客户
  → 调 Jira MCP 创建操作记录工单

技术基础是Anthropic的MCP(Model Context Protocol,模型上下文协议)。它定义了一套统一的Agent与外部系统通信标准——任何外部系统按此标准提供 MCP Server,任何 Agent 框架对接 MCP Client,两者即插即用。

在自定义 Loop 代码中,连接器以工具函数(@tool)的形式落地。任何 Python 函数用 @tool 装饰器包装后,即成为 Agent 可以调用的”手”:

from langchain.tools import tool

@tool
def read_contract(file_path: str) -> str:
    """读取合同文件内容"""
    with open(file_path, "r") as f:
        return f.read()

@tool
def approve_contract(contract_id: str, reason: str) -> str:
    """批准合同,归档到 approved/ 目录"""
    shutil.move(f"pending/{contract_id}", f"approved/{contract_id}")
    return f"合同 {contract_id} 已批准"

@tool
def escalate_contract(contract_id: str, reason: str) -> str:
    """合同存在高风险,升级给人工审批"""
    return f"合同 {contract_id} 已升级:{reason}"

子Agent/协作

子代理是五大构建块中最核心的设计模式。它的原则只有一条:执行者和验证者必须是两个独立的 Agent。二者身份不同、工具权限不同、上下文不同。

Maker-Checker 模式通过三项硬性设计消除了这个问题:

  • 硬性权限隔离

Checker 的工具列表中没有写入权限——不是 Prompt 让它”别乱改”,而是它的 tools 参数里根本没有修改相关的工具。这在工程上是不可绕过的。

  • 独立上下文

Checker看不到Maker的推理过程,只看到Maker的最终产出物(修改后的代码、审查结论、退款金额)。它必须基于产出物本身做独立判断,避免了被 Maker 推理带偏的”路径依赖”效应。

  • 客观评估标准

Checker不对”你觉得 Maker 做得好吗?”这种主观问题做判断。它对照 Skill 文件中的检查清单逐项核对——“合同金额是否 < 50 万?””违约金比例是否 ≤ 20%?””退款是否在 7 天窗口内?”——这些条件要么符合、要么不符合,没有灰色地带。

在DeepAgents 中,Maker-Checker通过SubAgent类型落地:

from deepagents.middleware.subagents import SubAgent

# Maker —— 有完整工具权限(读 + 写)
maker = SubAgent(
    name="contract-editor",
    description="审查合同并给出处理结论",
    system_prompt="按审查清单逐项检查。低风险且金额 < 50 万可批准。",
    tools=[read_contract, approve_contract, reject_contract, escalate_contract],
    model=llm,
)

# Checker —— 只有只读工具
checker = SubAgent(
    name="contract-reviewer",
    description="独立复核 Maker 的审查结论",
    system_prompt="独立验证 Maker 的结论是否与合同内容和审查清单一致。",
    tools=[read_contract, get_skill_checklist],  # 只有只读权限!
    model=llm,
)

agent = create_deep_agent(
    model=llm,
    tools=[read_contract],        # 主 Agent 也只有只读
    subagents=[maker, checker],
    system_prompt="""审查流程:
    1. 委派 contract-editor 审查 → 2. 委派 contract-reviewer 复核
    3. 通过则执行,不通过则退回重做(最多 3 次),仍不通过则升级人工""",
)

在Claude Code中,/goal命令内置了这个模式——用Claude Opus做Maker(写代码),用Claude Haiku做Checker(独立判断完成条件是否满足)。用户不需要手动配置权限隔离,框架层已做好。

记忆/状态

LLM有一个根本性的缺陷:每次新会话启动时,Agent 对之前发生过什么一无所知。记忆层就是把 Loop 运行过程中积累的状态信息持久化到对话之外,让下一次循环能接上上一次的上下文。

记忆在 Loop 中按时间尺度分为三层:

  • 工作记忆

当前会话的messages列表。Agent知道”刚才查了这个合同的金额是 35 万”。当上下文接近模型窗口上限时,SummarizationMiddleware自动触发压缩,将历史消息摘要为结构化记录,保留关键信息,释放Token空间。

  • 短期记忆

跨轮次的状态保存。Agent 知道”昨天处理订单 ORD-005 时进行到第三步了,今天从第四步继续”。在 DeepAgents 中通过 checkpointer(LangGraph 内置的状态快照机制)实现——每次会话结束时自动保存Agent的状态图,下次启动时从快照恢复。

  • 长期记忆

永久有效的知识和经验。Agent知道”公司退款政策是7天内可退””客户A之前退过3次,属于高频退款用户”。在DeepAgents中通过InMemoryStore(开发阶段)或持久化数据库(生产环境)实现。

from langgraph.store.memory import InMemoryStore
from langgraph.checkpoint.memory import InMemorySaver

store = InMemoryStore()         # 长期记忆
checkpointer = InMemorySaver()  # 短期记忆

agent = create_deep_agent(
    model=llm,
    store=store,
    checkpointer=checkpointer,
    ...
)

# Loop 每次执行后写入记忆
store.put(("reviews",), contract_id, {
    "status": "approved",
    "maker_conclusion": "低风险,同意通过",
    "checker_conclusion": "复核通过",
    "timestamp": "2026-06-12T15:30:00",
})

在Claude Code的语境下,记忆层以更轻量的文件形式落地:AGENTS.md充当始终加载的长期知识,PROGRESS.md充当Agent自维护的进度文件(记录”上次做到哪了”),Linear/Jira 看板充当团队级的可视化记忆。

注意:InMemoryStore在进程重启后会丢失。生产环境需替换为持久化存储后端(如 PostgreSQL),确保Loop重启后记忆不丢失。

其他方面

设计Loop的要素

设计一个Loop需要考虑确定如下方面问题,这些问题覆盖了从”系统为什么存在”到”系统怎么安全退出”的完整生命周期。在动手写代码之前,先逐一填好这份”设计契约”——它决定了你的Loop是一个可靠的自动系统,还是一个烧完Token后空转停下的实验品。

1) 目标(Objective)

Loop 要优化什么?目标不能模糊——“提升代码质量”没法验证,”保持 CI 绿色”可以。一个好的 Loop 目标应该是可度量的状态,而非主观的期望。

2) 触发(Trigger)

什么时候运行?定时(每10分钟)、事件驱动(CI失败Webhook)、或目标驱动(一直跑到验收条件满足)。触发方式决定了Loop的响应速度和运行成本之间的平衡。

3) 发现(Discover)

怎么找到要干的活?Loop 需要一个明确的”扫描机制”——读CI日志、遍历 pending_contracts/文件夹、查询未分配的工单。没有发现的Loop就像没有眼睛的工人——不知道活儿在哪。

4) 工作空间(Workspace)

Agent在哪里安全操作?每个Agent实例需要独立的工作区,防止互相踩脚。git worktree或FilesystemBackend(virtual_mode=True)提供物理级别的隔离,失败的修改不会扩散到其他 Agent 的任务中。

5) 上下文(Context)

Agent 携带什么知识?不能每次启动都从零灌输。通过 SKILL.md 存放项目规范和处理流程,通过AGENTS.md存放始终加载的核心约定,通过渐进式加载让 Agent 在需要时才读取完整知识。

6) 委托(Delegation)

哪个Agent做什么?Maker负责执行(有写入权限),Checker负责验证(只有只读权限),编排者负责调度和异常决策。各自身份不同、工具权限不同——这不是让 Agent “扮演不同角色”,而是从工具列表层面就做了硬性隔离。

7) 验证(Verification)

怎么判断做对了?不能靠Agent自己说”好了”。Checker 对照客观条件逐项核查:退款金额是否在政策范围内?违约金比例是否 ≤ 20%?所有测试是否通过?验证条件必须是二值的——通过或不通过,不存在”差不多”。

8) 状态(State)

什么信息需要跨会话存活?Loop下一次启动时需要知道”上次处理到哪了”、”哪些合同已经审过了”、”哪个工单连续失败 3 次需要特殊处理”。状态信息存放在对话之外——InMemoryStore、checkpointer、或持久化数据库。

9) 预算(Budget)

何时强制停止?一个没设上限的Loop可以烧掉成百上千美元的Token而毫无产出。设置硬性的max_steps(最大迭代步数)、max_tokens(Token 预算)、timeout_seconds(超时保护)——这些不是建议,是安全带。

10) 升级(Escalation)

什么时候通知人类?Loop不是万能的。有些情况必须升级:重试3次仍然不通过、金额超过自动审批阈值、涉及不可逆操作(执行退款、合并 PR、部署生产环境)。升级路径要明确到”通过什么渠道通知谁”——Slack@负责人、创建工单、发送邮件。

11) 退出(Exit)

怎么知道真完成了?必须由独立的Checker模型(而非做事的 Maker)来判定完成条件是否满足。Maker说自己”干完了”不算,Checker对照验收条件逐项确认才算。没有独立退出判断的 Loop,就像没有刹车的自动驾驶汽车——迟早出事。

要素 设计问题 示例
目标(Objective) Loop 要优化什么? “保持 CI 绿色”
触发(Trigger) 什么时候运行? 每10分钟/ CI失败事件
发现(Discover) 怎么找到要干的活? 读取CI 日志、GitHub Issues
工作空间(Workspace) Agent 在哪里安全操作? Git Worktree 隔离
上下文(Context) 有哪些持久化知识? SKILL.md、CLAUDE.md
委托(Delegation) 哪个Agent 做什么? maker-agent vs checker-agent
验证(Verification) 怎么判断”做对了”? 测试通过
状态(State) 什么信息跨会话存活? 进度文件、看板
预算(Budget) 何时停止? 最大轮数、Token 上限、时间限制
升级(Escalation) 什么时候通知人类? 三次重试失败→ 创建 Issue 并 @ 负责人
退出(Exit) 怎么知道完成了? 独立评估器模型判断

以上11 个要素并非同等重要。最核心的是三个:验证(谁来判断对不对)、升级(搞不定时怎么办)、退出(怎么才算完)。这三个要素决定了 Loop 是从”自动”到”自主”的关键跨越。

运行Loop的关键风险

Loop 跑起来之后,风险不再来自”Agent不干活”,而来自”Agent在错误的方向上干了很多活”。以下是生产环境中反复验证过的七类关键风险及对应的硬性防控。

1) 无限循环

Agent 在一个子任务上反复”优化”,永远不满足退出条件。比如Agent不断 Google 搜索”如何写好一篇博客”,搜了50轮还在搜。

防控方式:设置 max_steps 硬上限(DeepAgents 默认1000步),达到上限后强制终止并升级人工,不允许 Agent自己打破这个限制。

2) 目标漂移

模糊的目标导致Agent在推理过程中逐渐偏离原始意图。典型症状是:让它”修复认证模块的 Bug”,经过20轮迭代后它开始重构整个用户系统。

防控方式:将目标转化为可验证的、不可被 Agent 自行”重新解读”的验收条件——“test/auth/ 下 14 个测试全部通过”是不可漂移的,而”让认证更健壮”是可以被漂移的。

3) 上下文溢出

长会话积累的messages超过模型窗口上限后,早期的关键指令会被截断。当 Agent在窗口之外看不到原始任务描述时,它就开始”自由发挥”。

防控方式:SummarizationMiddleware 在上下文达到 85% 窗口上限时自动触发压缩,将历史消息摘要为结构化记录;同时将关键状态(进度、未完成任务列表)持久化到文件系统,而非依赖对话上下文。

4) 静默失败

Agent 的产出”看起来不错”——格式漂亮、措辞专业——但实际没有任何有用的进展。典型例子是 Agent 写了一份结构完美的合同审查报告,但结论是错的——它没发现违约条款越过了法定上限。

防控方式:独立的Checker验证。Checker不读Maker的报告,而是重新读原始合同,对照 Skill 检查清单逐项核对,然后对比自己的判断和Maker的结论是否一致。

5) Token 成本爆炸

多Agent多轮运行下,API费用可能失控。一个Maker-Checker-重试循环,每轮涉及多次LLM调用(Maker 执行、Checker 验证、编排者决策),3次重试就是9次调用。如果每个子代理的上下文都满配,成本会快速飙升。

防控方式:设置 max_tokens 和 max_cost_usd 预算上限;Checker 用更便宜的模型(如 Haiku 替代 Opus);Skill 通过渐进式加载减少上下文注入量。

6) 理解负债

自动化程度越高,人对系统的理解越落后。Loop替你写了更多代码、做了更多决策,但你对这些代码和决策的理解并没有同步增长。当系统出问题时,你面对的是一个你不认识的代码库。

防控方式:强制人工Code Review 流程——Loop可以自动生成 PR,但合并必须人工批准。

7) 认知投降

比理解负债更危险的是认知投降——开发者放弃形成独立判断,对 Loop 的产出照单全收。”Agent 都验证通过了,应该没问题吧。”

防控方式:定期人工抽查 Loop 的产出——不是读摘要,是随机抽几个实际处理结果,从头到尾检查一遍。这项操作没有自动化替代方案。

风险 描述 防控措施
无限循环 Agent不断”优化”但永远无法完成 设置硬性 max_steps 上限
目标漂移 模糊的需求导致Agent追求错误的目标 明确的、可验证的终止条件
上下文溢出 长会话降低推理质量 定期压缩、使用摘要
静默失败 Agent产出看起来不错但实际无进展 独立评估器验证
Token 成本爆炸 多Agent多轮运行成本飙升 Token预算上限、成本监控
理解负债 工程师长期不读生成代码 强制Code Review流程
认知投降 开发者停止形成独立判断 定期人工审查Loop产出

未来发展趋势与工程师角色

范式已定:从写 Prompt 到写 Loop

2026 年上半年的变化速度超出了大多数人的预期。2025 年底 Ralph Loop 还是一个社区实验,到 2026 年 6 月,Loop Engineering 已经来到行业中心。范式转变的核心信号不是”有人提出了新概念”,而是”有人展示了一种更高效的工作方式。

可以确定的是:Loop Engineering不是替代Prompt Engineering,而是把它内化为Loop系统中的一个组件。Prompt仍然存在——但它们现在是由循环代码自动生成和调试的,而不是由人手写。工程师的核心技能从”怎么问AI一个好问题”变成了”怎么设计一个系统,让系统去问AI正确的问题”。

几个清晰的方向:

  • Maker-Checker 分离将成为默认架构

不是所有场景都需要,但只要涉及” Agent 的产出会被直接应用”——代码合并、退款执行、合同审批——独立验证机制就是必需的。这不是成本,是保险。Claude Code 的 /goal 已经证明了其工程可行性:用 Opus 干活、用 Haiku 独立判断完成条件,成本可控,效果可验证。

  • 记忆系统决定 Agent 的上限

模型的推理能力正在趋同——Claude Opus 4.5、GPT-5、Gemini 3 之间的差距在缩小。但企业的私有知识库不会趋同——你的公司的退款政策、合同模板、审批流程、历史处理经验,是你独有的。能把多少企业知识编码为 Agent 可直接加载的 Skill 和记忆,决定了你的 Loop 能处理多复杂的任务。

  • 可观测性从”加分项”变成”必须项”

一个 24×7 运行的 Loop 如果没有运行日志、成本追踪、成功率监控和异常告警,它就不是生产系统——它是一个定时炸弹。未来半年,Loop 的可观测性工具(类似LangSmith对LangChain的作用)将成为一个独立的工具品类。

开发者的新角色

Loop Engineering不取代工程师,它改变了工程师的工作内容,未来开发者工作内容包括如下:

第一,设计循环(Design the Loop)。定义目标、触发条件、验证标准、升级路径——这是 Loop Engineering 最核心的创造性工作。一个好的Loop设计师的价值在于”判断什么值得自动化,什么必须人工介入”。这不是技术判断,是工程判断。

第二,训练系统(Train the System)。Skill文件不会自己写。每次Loop出错、每次Checker发现漏判、每次人类介入解决了问题,都需要有人把这次经验转化为持久化的知识——更新SKILL.md、补充检查清单、修正验证条件。这个工作让系统越来越好用,但它永远不会自动化——它需要工程判断。

第三,验证产出(Verify Output)。不管Loop多成熟,人类保留最终决断权。定期审查Loop的产出——不是读摘要,是随机抽查实际处理结果,从头到尾验证一遍。Osmani说”做一个打算继续当工程师的人”,意思就是:你的判断力不能被自动化替代,因为当系统出错时,只有你的判断力能把系统拉回来。

用一句话总结开发者角色变化:你不再亲手做每一个任务,但你比以往更需要理解每一个任务。 这不是轻松了,是责任更重了——因为现在你不仅要对”自己做的工作”负责,还要对”你设计的系统做的工作”负责。

--- 本文结束 The End ---