作者指出单纯依赖提示词设计 Agent 存在瓶颈,需要通过上下文工程和循环工程让 LLM 自我评估和校验输出质量。
你们在智能体设计上过度依赖提示词工程。不管叫上下文工程还是该死的循环工程,你仍然在让 LLM 确保自己只生成事实信息,并让它自我审查。
你越让 LLM 自我评估或执行分析,就越引入更多的幻觉点和漂移风险。
当你使用文本生成器来自动化那些你不想做的事情时,你仍然需要把它当作其他软件一样对待,并设计它的运行逻辑。
在讨论长时间运行的智能体之前,先提醒自己以下几点:
使用短时运行的智能体没有问题。选择最简单的工具来完成工作。
区分模型和智能体。模型接收文本输入并生成文本输出,但它不会执行其他操作。智能体是执行部分。智能体依赖模型,例如模型在生成 JSON 对象中途达到 token 上限,这是一个模型级别的事件(输出被截断),但会导致智能体级别的后果(畸形的工具调用、状态写入损坏、账本条目损坏)。
本系列讲的是安全约束框架。LLM 调用可以作为工具使用(例如,将 40 个工具结果总结为 200 字),但它应该作为确定性函数调用的一部分,由约束框架在其自己的调度计划中决定何时调用,并自行验证输出。不是智能体在任务执行中途自己决定"哎呀,我现在真的应该压缩上下文了"。
第一部分:上下文与记忆
每次向 LLM 发送提示词,都会重新发送完整的对话历史。聊天式的体验只是一个 UI,是用户的幻觉™。这意味着在较长的对话中,你可能会耗尽上下文窗口,模型开始截断内容,或者遇到上下文腐烂和漂移——模型偏离了要点。
始终发送完整对话这一事实使上下文管理更容易。这意味着你可以在窗口内处理上下文,消除肩胛骨后面的结,使其尽可能保持语义紧凑。即使你有一个 100 万美元——抱歉,token 的窗口,你仍然会遇到腐烂和漂移。
这也意味着你可以把一个智能体的上下文提取出来,然后转存到另一个智能体中,继续对话。因此你可以去掉思维 token 和工具调用开销,只保留语义相关的内容。
上下文有自己的生命周期。你从系统提示词、工具定义、用户提示词、对话、推理、工具调用等开始。所以在考虑为这些长时间运行的会话管理上下文时,我们应该思考在整个生命周期中要做什么。
创建(并理解)上下文
上下文在使用 LLM 时自然构建。你需要刻意关注的是什么进入了窗口。Gumloop 有一个很酷的上下文使用量表,可以实时显示对话过程中 LLM 模型上下文窗口的使用情况。它按类别显示 token 分解,例如:
在长时间运行的智能体中,你会看到对话部分增加,而系统提示词和工具定义保持稳定。
随着上下文积累,你可以裁剪语义上不相关的 token,并将较大的块总结成语义等价但更小的块。
Google 的 ADK 上下文压缩通过总结智能体工作流事件历史的较旧部分来减小上下文大小。它使用滑动窗口方法来收集和总结会话内的智能体工作流事件数据。一旦达到特定数量工作流事件或调用的阈值,就会总结较旧事件的数据。
你无法始终依赖总结之前的上下文。在某些时候,约束框架应该执行完整的上下文重置。这意味着它将拆除会话,并从持久化构件重建下一个请求(在下一节探讨)。
LLM 是无状态的,所以如果你的上下文是临时的,你将丢失整个智能体会话。然而,你可以将上下文写入持久化存储。如果将这些存储架构设计为不可变账本,那就更好了——智能体可以写入和读取,但不能修改或删除。
这些存储服务必须由你(开发者)提供,你可以确定性定义权限。让 LLM "求你了永远不要更新账本"不是软件工程。
存储什么内容取决于你。可以转存整个窗口、总结它、只写 H1 标题等。
在 Google 的 EAP 中,记忆生成将其中许多决策捆绑在一起。
提取从源数据中仅提取最有意义的信息作为记忆持久化,而不是转存所有内容。
整合将新提取的信息与现有信息合并,让记忆随着新信息的摄入而演进。
生成异步在后台运行,因此智能体不必等待其完成。
事件摄入持续流式处理和管理对话事件,根据你配置的批处理规则自动触发生成。
而且提取是可定制的。你通过提供特定主题和少量示例来告诉记忆库什么算有意义。
利用存储的上下文,你可以使用账本作为重建机制。在新的会话中,智能体可以读取持久化计划、进度笔记和只可追加的已完成事件记录,从而重建"我在哪里",而不必重放完整对话历史。
正如 Cloudflare 所说,你可以裁掉 20% 的员工用 AI 替代,并用智能体的计划作为上下文。如果智能体有一个结构化计划,该计划本身就提供了足够的上下文:"我在第 3 步(共 7 步),这一步是'等待制裁检查结果',结果刚刚到达。"
在 Google 的 EAP 中,管理存储和检索也带来了一系列特性。
整合和检索按身份隔离,因此一个实体的记忆不会渗透到另一个实体。
存储是持久的,可从多种环境访问:智能体运行时、本地环境或其他部署选项。检索可以使用限定于特定身份的相似性搜索,只拉取相关内容而不是所有内容。
可以设置生存时间,让过期信息自动失效,TTL 应用于插入或生成的记忆。
修订版本自动维护,让你能够检查记忆随着新信息摄入而如何演变。
IAM 条件限制哪些主体可以读取或写入给定范围的记忆。
身份作为上下文管理问题
你可以检索所有限定于特定用户身份的记亿。记忆的范围在记忆生成或创建时定义,且是不可变的。
这使得按身份划分的记忆对于给定用户或实体的独立作业和会话是持久的。在 Google 的 Agent Memory Bank 中,记忆通过 LLM 从会话事件中提取和整合,限定于用户或智能体身份,通过相似性搜索检索,并通过基于 TTL 的过期和修订历史进行管理。
在 Cloudflare 中,身份是智能体的一个持久化、可寻址的属性。 Durable Object 身份在休眠/重启后持久存在,无需重新建立;这是让任务状态和身份记忆在崩溃后可以再次找到的锚点。
这种持久化特性需要额外的机制来确保跨实例和通过故障点的连续性,我们将在下一部分中讨论。
第二部分:持久化执行
作为上下文管理的一部分,你现在有了一些持久化存储。很好,如果会话丢失,你可以用它把上下文拉回智能体。
"嘿 Claude,检索这个然后继续——"
我们来看看智能体在故障时确定性恢复的方法。
长时间运行的智能体并不会长时间运行。它在需要时运行,持续跟踪任务、上下文和之前的状态。预期智能体会有很多等待时间。但正如我们在第一部分讨论的,LLM 每次提示词都会收到完整对话请求,因此持久化的全部概念就是"如何有效地组织这些数据,使得任务到任务之间 LLM 的行为保持一致"。
什么需要持久化,什么不需要
回顾 Cloudflare 的文章,他们的长时运行智能体模式确保以下内容跨调用持久化:
智能体状态——智能体继续会话所需的持久化数据
所有创建的 SQLite 表,包括在 SQLite 上构建的抽象
计划任务,存储在 SQLite 中,触发警报以唤醒智能体
每个 WebSocket 客户端的连接状态
以下内容不需要存活:
回调和 Promise 链
智能体有一个身份和持久化状态。它不需要活动的计算实例。它可以配置为在事件发生时唤醒,完成后重新进入休眠。唤醒源是智能体与外部世界交互的全部接口;你不需要一个始终运行的循环来让智能体"持续运行"数周。
要唤醒一个 AI 智能体,可以使用 webhook 回调——AI 智能体触发外部工作、注册自己的回调 URL,然后进入休眠状态,只在回调到达时才苏醒。对于不支持回调的服务,也可以定义带退避策略的轮询机制:AI 智能体调度一次轮询,然后用递增的延迟重新调度,并设置最大间隔。
最后,还可以定义广泛的自动化工作流,其中包含可独立重试的多步骤管道,然后将其交给专门的工作流引擎处理,而不是在 AI 智能体内部管理步骤顺序。
子 AI 智能体同样具备各自独立的持久性。每个子 AI 智能体拥有自己的状态、调度计划、持久纤维和生命周期,并将自己的数据存储在父级附近。
对持久性而言,关键属性是:父级在子级工作期间无需保持活跃。它可以启动工作、进入休眠状态,然后在子级的调度计划或恢复检查触发时被唤醒。一次崩溃不会同时击垮整个家族;每个身份都可以独立恢复。
作为预测信号的 Token 与速率限制监控
通过对每个会话和每个租户的 Token 消耗进行监控,可以在遇到速率限制或错误时定义续期和重试策略。如果累积使用量轨迹预测在下一次检查点之前会触发速率限制,容器可以主动设置检查点、进行限流或切换模型/提供商。
在最粗粒度层面的恢复可以是一个在启动时读取账本的会话。一个简单的"我在哪里"检查就可以恢复任务,即使没有更精细的策略。然后可以为一项工作持续持久化一行数据,在定义的点暂存中间状态,并在重启时从最后一次暂存点恢复。
幂等性在这里对持久性接受至关重要,特别是对于 webhook 驱动的 AI 智能体——调用方会重试投递,必须避免重复的副作用。所有这些背后的通用模式是事件溯源或日志式恢复:
我们描述了一个由 AI 智能体的计划组成的不可变任务账本:应该发生什么,按什么顺序等。你还需要一个单独的仅追加执行日志,记录实际发生的事情,包含每次工具调用、每次模型响应、每次状态转换。它可以被确定性回放以重建状态,无论哪个进程或容器恢复这项工作。
这正是 Restate 的日志功能和 DBOS 的工作流/步骤注解背后的理念。
Restate 在继续下一步之前持久化每一步,并确定性回放以重建崩溃前的状态,而 DBOS 则将检查点写入 Postgres。
这些工具还为需要在失败时撤销部分工作的 AI 智能体提供补偿和回滚机制。当 AI 智能体执行多个操作后出现问题,需要系统性地撤销变更以保持一致性。
持久执行供应商格局
你可以通过评估 DBOS、Restate、Inngest 等供应商来了解不同的实现思路。一些通用示例包括:
外部事件挂起与恢复——用于暂停工作流直到某个信号到达(一级原始特性)(webhook、审批、人工决策)并在稍后恢复,可能跨重新部署,在等待期间不占用计算资源。
流量控制和并发限制——具有每个租户或每个工作流并发上限和速率限制的持久队列,这样重试和扇出不会压垮下游系统。
在应用代码中表达持久性与独立的编排层:有些将持久性对普通控制流透明(你的语言中的库或注解),有些将其作为托管平台原始特性提供,有自己的执行模型。
你也可以在 n8n 中通过实现其基于工作流的确定性特性来设计自己的持久执行逻辑,定义重试、在持久存储中写入数据、确定性触发器如定时器和 webhook。
身份作为持久性属性
在 Cloudflare 的模型中,AI 智能体的名称是路由键,这个身份跨休眠、重启和重新部署保持不变。凭证按每个 AI 智能体或子 AI 智能体身份作用域划分。持久性的回报是归因:因为身份是持久的,执行日志中的每条记录都可以追溯到一个持久的 AI 智能体身份。
在平台层面,Google 的 AI 智能体身份与注册表是这一理念的产品化版本,跟踪哪个身份、在哪个版本上、正在运行哪个任务。
第三部分:任务进展与评估
你会注意到你的 AI 智能体逐渐开始犯错误和产生幻觉。要在不直接询问 AI 智能体的情况下判断它是否仍在任务正轨上,大多数 AI 工程师找到了一个完美的解决方案:问另一个 LLM。
LLM 即裁判是最简单的修复方法,也是最不可靠的。它是同一个模型类别在产生同一种错误,只是隔了一层。本文讨论的是如何最小化进展验证对任何 LLM 判断的依赖,以及在 LLM 仍然有用的地方,将其限制在狭窄、可检查的角色中。
检查清单作为进展的基本单位
在任务账本或检查清单中,每个条目都需要在 AI 智能体执行之前定义完成标准。在 AI 智能体开始之前写下完成条件是单次最高杠杆的动作,正是因为它阻止了 AI 智能体在运行中途重新定义"完成"。
配套规则是每次只处理一个条目。每次只处理一个条目可以防止 AI 智能体试图同时做所有事情而导致半途而废,也使得验证变得可处理,因为每次执行恰好有一个声称的状态转换需要检查。
确定性验证门
"ask the model if it's done"(问模型是否完成)的替代方案是针对执行日志或实时系统状态运行检查,返回布尔值,不依赖任何模型调用。
门类型分类,从最便宜/最可靠到更复杂的:
状态/响应码:API 调用返回的是 200,而不是 4xx/5xx。
Schema 验证:响应是否解析为有效的 JSON/XML 并匹配预期形状(必填字段存在、类型正确)。
跨字段一致性检查:响应载荷中的用户名是否与请求用户的身份一致;返回的 ID 是否与请求的 ID 匹配。
状态差异检查:这一步声称创建/更新/删除的内容是否实际出现在/改变/消失在目标系统中(在操作后重新查询)。
测试执行:针对代码变更运行的单元/集成测试。
验证活动的其他机制包括:
有效进展的状态机——用于语义解析的有限状态机方法将状态定义为工具调用/步骤类型,将转换定义为它们之间的允许序列;观察到的动作序列在运行时通过 FSM 解析。状态机之外的状态是违规;意外的转换是异常。通过一个小的固定合法状态集,每个转换可以在提交到账本之前针对执行日志进行验证。
沙箱和行为基线——你也可以先在受控环境(沙箱)中运行 AI 智能体,观察它实际做了什么:它调用了哪些工具、移动了多少数据量、到达了哪些目的地、进行了哪些系统调用。然后你可以:
一旦观察到安全就将特定操作晋升到生产环境,理想情况下作为确定性允许列表条目,而不是再次调用 AI 智能体的判断;
使用该配置文件作为最小特权权限和偏差告警的参考基线。
AI 智能体行为的非生成式检查——一些有用的检查根本不生成文本。仅编码器分类器(BERT 系列模型,如 DeBERTa、RoBERTa 或 ModernBERT)可以在标记好的对齐/不对齐或良性/恶意示例上微调,并输出一个标量对抗阈值,在循环中不放入生成式模型的情况下给出判定。
工具调用模式的异常检测——监控递归循环(同一工具以微小参数变化反复调用)、Token 计数峰值、乱序执行,并在它们累积之前终止运行。
可接受的 LLM 即裁判用法
意图评估只有在执行前明确定义了意图才可能
"明确"意味着:枚举的工具允许列表、定义的任务必须经过的步骤或状态序列、定义的数据源、定义 Spawn 子 AI 智能体的基于规则的机制,以及定义的 API 端点和方法。
一旦这些存在,评估就归结为针对执行日志的一系列是/否问题:这一步执行了吗,字段填写正确吗,调用返回了预期的代码吗,检索到的数据是否经过 schema 验证,等等。
凡使用 LLM 做评估的地方,都应将其约束在狭窄、可核查的判断范围内。例如:"这条轨迹是否匹配分类法中的 X 类别。"这种用法之所以可接受,正是因为模型充当的是模糊编译器——将观察到的行为映射到确定性类别上,而非凭空杜撰"好与坏"。
本文所述的一切将横跨多个产品,并需要持续的工程投入。不要把它当作构建可靠长时运行智能体的分步蓝图或框架,而应将其视为对所有自封的循环工程专家所忽视的确定性组件的一次探索。
我将继续探索这些话题,以及它们在 n8n 和更广泛市场中的应用。欢迎大家提出改进意见、反馈和纠错,请通过 LinkedIn 与我联系。
n8n 用户背景多元、经验水平和兴趣各异。我们一直希望在博客文章中重点介绍不同的用户及其项目。如果你正在使用 n8n并希望为社区带来启发,欢迎联系我们 💌