写在前面

本文整理一下 AI Agent 的 Loop 设计在工程上需要考虑的几个核心问题:范式的选择、上下文管理的策略、失败恢复与终止条件。内容以方法论梳理为主,涉及的代码与场景均为示意性示例,目的是说明设计思路,不是对某个具体框架的实现复盘。

参考文献统一列在文末。


一、Loop 范式:不止 ReAct

讨论 Agent Loop,通常会从 ReAct 说起。它由 Yao 等人于 2022 年提出[1],核心是把"推理(Reasoning)"与"行动(Acting)"在同一个循环里交错执行:

Thought → Action → Observation → Thought → Action → ...

ReAct 的优势在于结构简洁、可解释性强,在 HotpotQA、ALFWorld 等基准上表现良好[1]。但在更复杂的开放任务场景里,这种单步贪心式的循环会暴露出一些工程上的局限,因此后续出现了几种常见的扩展范式。

1.1 Plan-and-Execute

由 LangChain 团队在 2023 年提出并实现[2],思路是先让 LLM 生成一个完整的多步骤 Plan,再由 Executor 分步执行。其灵感部分来自 Plan-and-Solve Prompting 的论文研究与 BabyAGI 项目。

  • 优势:规划集中决策,执行阶段不再每步重新推理,Token 成本相对可控。
  • 代价:Plan 一旦偏离实际可行路径,后续执行会连环出错,因此通常需要配合 Replan(重规划) 机制。

1.2 Reflexion / Self-Critique

由 Shinn 等人于 2023 年提出[3]。Agent 在执行一段动作后对结果做语言化的自我反思,并将反思写入 Episodic Memory,在下一轮试错中作为新的输入,从而在不更新模型权重的前提下实现"经验积累"。

Reflexion 在有明确成败信号的任务上效果显著,论文中报告其在 HumanEval 编码任务上的 pass@1 达到 91%[3]。但在缺乏明确反馈信号的开放任务上,反思本身的可靠性会成为瓶颈。

1.3 Hierarchical / Multi-Agent

把规划与执行进一步拆开,上层 Agent 负责任务分解与调度,下层 Agent 负责具体执行。这是大部分"多 Agent 协作"框架的底层模式,在 Wang 等人的综述中有较系统的归纳[4]。

1.4 工程权衡

实际项目中,单一范式很难覆盖所有场景,常见的做法是混合使用:

  • 短链路、确定性高的任务 → ReAct
  • 多步骤、可拆分的任务 → Plan-and-Execute + Replan
  • 有明确成败判断的关键节点 → 引入 Reflexion 做自校验
  • 复杂的协同任务 → Hierarchical / Multi-Agent

范式选择没有银弹,需要结合任务的可拆分性、可验证性与 Token 成本来定。


二、上下文管理:分层结构的一种思路

Agent Loop 跑得越久,上下文越容易膨胀,直接截断会丢关键信息,不截断又会超出窗口。一种常见的处理思路是分层管理——这一思路在概念上借鉴了认知心理学中关于工作记忆与长期记忆的区分[5],近年在 LLM Agent 工程实践中被广泛参考。

2.1 三层结构(示意)

┌────────────────────────────────────┐
│ Layer 1: Working Memory (近期原文) │  ← 最近 N 轮完整保留
├────────────────────────────────────┤
│ Layer 2: Episodic Memory (中期摘要)│  ← 关键事件压缩存储
├────────────────────────────────────┤
│ Layer 3: Semantic Memory (长期事实)│  ← 结构化存储,按需检索
└────────────────────────────────────┘
  • Layer 1:最近若干轮原文保留,确保 LLM 拿到完整的局部上下文。
  • Layer 2:更早的对话以"动作-结果-状态变化"等事件级摘要的形式压缩。
  • Layer 3:从 Layer 2 析出的稳定事实(用户偏好、任务约束、关键决策),进入向量库或 KV 存储,按需检索。

需要说明的是,上述三层命名并非行业统一标准,不同框架有各自的术语与切分方式,这里只是给出一种便于讨论的抽象。

2.2 示意性伪代码

下面是一段说明设计思路用的伪代码,未经实现验证:

class ContextManager:
    """示意性实现,仅用于说明分层管理的结构"""

    def __init__(self, working_size=5):
        self.working = deque(maxlen=working_size)
        self.episodic = []                  # 中期事件摘要
        self.semantic_store = SemanticStore()  # 长期事实库

    def add(self, turn):
        if len(self.working) == self.working.maxlen:
            evicted = self.working[0]
            episode = self.summarize(evicted)   # LLM 摘要
            self.episodic.append(episode)
            self.extract_facts(episode)          # 析出到 Layer 3
        self.working.append(turn)

    def build_prompt(self, query):
        related = self.semantic_store.search(query, k=5)
        return assemble(
            facts=related,
            episodes=self.episodic[-10:],
            working=list(self.working),
            query=query,
        )

2.3 实践中需要注意的几个点

  • 摘要会偏向叙事性内容,容易丢失数字、ID、时间戳等"骨架信息" 。可在摘要前先用规则或抽取模型把关键实体单独存出来,再让 LLM 处理叙事。
  • 检索召回率受 Query 形式影响。直接拿原始 Query 做向量检索经常召回不到位,常见的改进是先做 Query 改写、生成多意图再并行检索。
  • 工具调用的中间结果占用 Token 多。一种做法是只在上下文里保留"结果摘要 + 引用 ID",原文按需回查。

三、终止条件与失败恢复

很多教程把终止条件简化为 max_steps=10,这在 Demo 阶段够用,但生产环境会带来很多隐性问题。

3.1 终止判断的多个维度

一个相对完整的终止判断,至少要覆盖以下几个维度:

维度 触发条件 推荐后续动作
任务完成 LLM 显式输出"完成"标记 进入结果汇总
步数上限 step ≥ max_steps 强制中止 + 摘要返回
时间上限 duration ≥ max_time 强制中止 + 摘要返回
死循环检测 相同 Action 连续多次 触发 Replan 或上报
Token 预算 total_tokens ≥ budget 触发上下文压缩或终止
显式失败 关键 Action 返回不可恢复错误 触发降级或人工介入

统一用 max_steps 兜底,会丢失很多本可以更优雅处理的信号。

3.2 失败分类与恢复策略(示意)

class FailureHandler:
    """示意性分类,具体策略需结合业务调整"""

    def handle(self, action, error):
        if error.is_transient():
            # 网络抖动、限流、超时
            return RetryStrategy(backoff="exponential", max=3)
        elif error.is_recoverable():
            # 可降级:切换备用模型、备用工具
            return FallbackStrategy(alternative=self.find_alternative(action))
        else:
            # 不可恢复:权限不足、参数非法、依赖缺失
            return EscalateStrategy(target="human")

三类失败对应三种典型场景:

  • Transient(临时性) :网络抖动、限流、超时 → 指数退避重试
  • Recoverable(可降级) :某接口不可用、模型超载 → 切换备用方案
  • Fatal(致命) :权限拒绝、参数非法、依赖缺失 → 早停并上报

最后一种最容易被错误处理。如果 Agent 在权限被拒后反复尝试绕路,日志会迅速变得难以排查,正确做法是早停并把决策权交给人。

3.3 状态持久化

长任务 Agent 需要支持从中断点恢复,否则一次进程异常就会导致整个会话作废。

一种最小可行方案是:每完成一个 Action,把 (step_id, state_snapshot, decision_log) 追加写入持久化存储;重启时按 step_id 倒序找最近一个有效快照恢复执行。代价是写入开销与状态序列化的复杂度——尤其当状态中包含 LLM 返回的非结构化内容时,序列化策略需要单独设计。


四、小结

把以上几点收束一下:

  1. Loop 范式按任务特征选择,混合范式在工程上更常见。
  2. 上下文管理决定 Agent 的"耐久度" ,分层是一种成熟的思路,但具体切分要看业务。
  3. 失败处理是从 Demo 到生产的分水岭,失败分类与终止条件设计的投入回报率很高。
  4. 状态持久化是长任务 Agent 的基础设施,值得在早期就规划好。

以上内容偏方法论,具体到某一框架的实现细节可能会有差异,欢迎评论区交流不同的处理思路。


最近翻到的一本工程向参考书《OpenClaw觉醒:基于AI智能体的超级生产力构建指南》(人民邮电出版社),目录里第 3 章"核心架构深度解析"覆盖了生命周期、上下文管理、多智能体路由等本文讨论的几个主题,第 4 章涉及沙箱与安全模型,感兴趣的可以翻翻。抽一位读者送出去。

送书福利

抽 1 本《OpenClaw觉醒:基于AI智能体的超级生产力构建指南》。

参与方式:

  1. 关注我的 CSDN 账号
  2. 评论区聊聊你做 Agent 时遇到过的 Loop / 上下文 / 失败恢复问题,或者你的解法

我会从评论里挑 1 位送出。

【活动截止日期】5月27日

中奖结果在截止后一周内公布,通过 CSDN 站内私信通知,书由出版社直接寄出。


参考

[1] Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K., & Cao, Y. (2022). ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629. https://arxiv.org/abs/2210.03629

[2] LangChain Blog. Plan-and-Execute Agents (2023). https://www.langchain.com/blog/plan-and-execute-agents

[3] Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K., & Yao, S. (2023). Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366. https://arxiv.org/abs/2303.11366

[4] Wang, L., Ma, C., Feng, X., et al. (2024). A Survey on Large Language Model based Autonomous Agents. Frontiers of Computer Science. arXiv:2308.11432. https://arxiv.org/abs/2308.11432

[5] Atkinson, R. C., & Shiffrin, R. M. (1968). Human memory: A proposed system and its control processes. Psychology of Learning and Motivation, 2, 89-195.

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐