跳到正文
Elaine Blog
返回

生产中的 Runtime 怎样设计:状态、执行、存储与版本升级

更新于:
Agent Runtime

如果一个 Agent 只在开发者终端里运行十秒,函数调用和内存状态也许足够。用户提交任务后可以离线,审批隔天到达,程序期间升级,任务还必须接着执行时,就需要明确 Runtime 的生产边界。

设计的起点是任务会跨越哪些失败和等待,而不是先选消息队列或画十几个微服务。

沿一次退款画出责任

任务 API 校验身份与输入,生成稳定 task ID,并在事务中保存申请和待执行意图。队列负责把“有任务可领取”传给 Worker。Worker 领取租约后执行当前步骤,把状态、事件和下一步意图提交。支付系统保存真正的支付账本。

浏览器读取任务 API 和事件流,不直接把 Worker 的内存当成事实来源。审批服务写入经过认证的决定,再唤醒等待任务。

持久任务的状态与外部副作用边界

这些是逻辑职责,可以最初在一个应用和一个数据库里实现。只有部署、伸缩或隔离需要时再拆开。拆服务不会自动提高一致性,反而会新增网络和双写边界。

每一类事实由谁说了算

任务数据库回答流程进行到哪里;订单系统回答订单版本和剩余可退金额;支付账本回答钱是否已退;对象存储保存报告文件。它们可以互相引用,但不能随意替对方宣布事实。

Checkpoint 中保存的订单版本 13 是执行时读到的快照。两天后恢复时,应按业务需要重新读取当前版本,再判断旧审批是否仍适用。不能因为状态恢复成功,就默认外部世界没变。

日志便于排查,不适合作为唯一交易账本。一个日志平台漏采样或延迟到达,不应改变是否执行退款的决定。

数据表怎样围绕问题设计

最小设计可以有任务、步骤尝试、事件、审批和 Outbox。每张表都对应一个明确问题:任务当前状态是什么,某次尝试为什么失败,外部操作身份是什么,谁批准了什么,哪些消息尚需发送。

大文件与长工具结果放对象存储,状态保存内容摘要、位置和校验信息。否则每个 Checkpoint 都复制完整 PDF,恢复成本和存储量会随轮次迅速增长。

schema_version 标识状态结构,workflow_version 标识执行逻辑,prompt_version 标识模型指令。三者不是同一个版本。修改一段提示词与删除一个恢复节点,风险和迁移方式不同。

老任务遇到新代码怎样办

假设旧版本等待 approval 节点,新版本把它拆成 risk_review 和 finance_review。如果直接用新图恢复旧 Checkpoint,节点名称和状态含义可能不再匹配。

可以让旧任务继续由旧版本 Worker 完成;也可以编写显式状态迁移,将旧状态映射到新流程并保留审计记录;或者在安全业务边界创建新执行,引用旧任务事实。选择取决于等待时长和兼容成本。

不要只改 JSON 字段名就声称完成迁移。需要同时检查剩余步骤、已发生副作用、审批绑定和重放行为。历史退款不能因节点改名再次执行。

隔离要到查询与执行层

tenant ID 不仅出现在 Prompt,还要进入任务读取、事件订阅、对象下载和工具授权。用户知道一个 task ID,不应因此读取别人的任务。

Worker 使用的服务身份与用户委托范围也要区分。系统管理员权限不能无条件被每个 Agent 继承。高风险动作在执行时验证当前授权,并保存必要依据。

执行不可信代码还需要独立进程、容器或其他实际隔离措施。Python 函数只读几个文件,不等于建立沙箱;路径校验也不能替代操作系统隔离。

怎么知道系统正在变差

只看模型平均耗时,会遗漏等待队列和人工审批。应分别观察排队时间、活动执行时间、外部等待时间和端到端完成时间。

再观察租约过期率、重试次数、未知支付结果、死信数量和恢复积压。一个任务耗时一天可能是正常等待审批;一分钟内重试五十次才可能意味着放大故障。

Trace 关联 task、run、step 与外部 request ID,但应避免把敏感原文无限传播到日志。保存摘要、受控附件和适当保留期限,使排查与数据边界同时成立。

容量和恢复速度同样重要

平时每秒十个任务,停机一小时就积累三万六千个。恢复时若全部立即启动,模型限额和支付系统可能再次被压垮。

按租户、任务类型和下游能力分配并发,恢复流量与新流量共享明确预算。等待人工的任务不占 Worker;需要大型模型的步骤与轻量数据库步骤可以分队列,但不必为每个函数创建一种队列。

备份任务数据库也不等于可恢复:还要保留相容代码、对象存储、凭据配置和外部操作关联。恢复演练应验证业务结果与权限,而非只看到进程启动。

从教学示例走向部署

配套示例用 SQLite、显式命令和虚构审批者展示事务与恢复边界。它没有认证服务、分布式租约或真实支付,不能直接作为生产系统部署。

在真实项目里,先列出最长等待、允许重复的动作、不能重复的副作用、权威数据源和升级策略,再决定哪些交给框架,哪些仍由业务代码承担。后面四篇沿这些问题阅读开源实现,避免把框架宣传语当作业务保证。


分享这篇文章:

上一篇
A2A 怎样连接独立 Agent:从发现能力到任务交付
下一篇
用 LangGraph 实现可恢复任务:完整 Python 实战与源码解读