返回

文章详情

代理应用程序的基础设施模式

Hacker News2026年7月29日 16:59

大多数团队在构建代理时,开始的方式与构建其他 web 特性相同:将模型包装在路由处理程序中,解析请求,并等待响应。这对于演示是可以的。但这是生产环境中第一个会崩溃的地方。代理是长期运行的、状态相关的和非确定性的。它们调用工具,等待外部 API,分支成子任务,遇到速率限制,并在多步骤序列的中途崩溃。如果您的代理与单个 HTTP 请求绑定在一起,您就将应用程序的可靠性与非确定性循环的时钟时间耦合在了一起。超越演示意味着打破这种耦合。本文将介绍团队使用的三种核心模式,将脆弱的代理脚本转变为可扩展且具有弹性的生产系统。代理的核心是一个循环:接收目标,决定接下来做什么,调用模型或工具,观察结果,更新状态,重复直到完成。该循环具有几个特性,使其对初学者的 web 架构不友好。代理是长期运行的。正常的 API 请求应该快速完成。然而,代理往往不会,有时需要几个小时甚至几天才能完成。代理是状态相关的。一次运行不仅仅是一个函数调用。这是一个目标,一个计划,工具调用和输出,重试,错误,决策,和最终输出。如果过程崩溃,您需要知道已经发生了什么。如果不知道,您要么丢失进度,要么盲目重新执行工作。这两者都不是很好,尤其是对于长期运行的代理。代理是非确定性的。传统工作流代码如此表示:代理代码如此表示:模型在运行时选择下一个动作,这使得恢复、重放和调试变得更加困难。一轮可能需要三步或三十步。它可能分散到几个工具中,等待人类,产生大型中间工件,或提前停止。基础设施必须通过超时、预算、检查点、批准和明确的终止条件来规定这种不可预测性的边界。结合起来,这些特性意味着代理需要的不仅仅是包裹在应用程序代码中的模型调用。他们需要一个将运行与请求解耦的架构,以及一个能够保存进度、记录决策、控制副作用和独立于模型上下文管理工件的基础设施。第一个生产模式是停止在 web 请求内运行整个代理。请求是代理运行的错误生命周期。它应该创建一个持久的运行记录,将工作放入队列中,并立即返回。这为应用程序提供了一个简单的边界:API 将作业放入队列。队列持久存储作业。工作者执行作业。数据库记录进度。客户端立即获取一个运行 ID。代理在其他地方运行。用户检查状态,订阅更新,或在运行完成时接收回调。队列是创建工作和执行工作的事物之间的持久缓冲区。当运行时间超过正常请求、任务大部分是独立的,并且您需要工作者扩展、重试或突发吸收时,这是默认的起始点。陷阱:队列知道作业的存在,但不知道该作业属于哪个逻辑过程。一个后台作业是可以的。二十个相互依赖的步骤、三次重试、两个分支和一个人类批准的暂停是队列无法为您管理的。您需要自己构建该逻辑。正如我们稍后将看到的,工作流引擎就是在这里发挥作用。可靠性:安全重试和部分失败将工作转移到队列解决了生命周期问题,但并未解决执行的持久性。大多数生产队列是至少一次的:一个作业可能会运行多次。这是为了避免失去工作的故意权衡,而您的代码必须能够承受它。一旦代理可以调用工具、记录、发送消息或分配资源,重试行为就成为应用程序正确性模型的一部分。有两个学科最为重要。幂等性回答了当单个步骤运行两次时会发生什么。补偿回答了当一个运行在一系列步骤中途停止时会发生什么。重试使得第一个成为必需。永久性故障使得第二个在生产中变得必要。与远程服务交互的代理需要这两者。错误的工作者代码假设步骤之间没有崩溃:更好的代码创建一个幂等性边界:对于代理来说,每个有副作用的工具调用需要相同的处理:在调用工具之前检查是否存在已完成的记录,更新一条“运行中”记录,调用工具,并标记为完成。重试不是恢复策略,除非重试的操作是安全的。考虑一个完成了五个步骤中的三个步骤的代理:它收取了一张卡,分配了一个资源,并发送了确认电子邮件。然后第四步永久失败。前三个步骤都不能通过数据库事务回滚,因为收取费用并不能通过删除数据库行来撤销;钱已经转移。重新从第一步开始运行将重新收取费用并重新发送电子邮件,从而重新创建幂等性所要防止的确切重复副作用问题。

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡