深度解析塑造未来的技术文章。

Talorys 如何在 Serverless 上运行有状态 AI 智能体

有状态 AI 智能体怎么跑在无状态的 Serverless 上?Talorys 基于 Cloudflare Workers、Durable Objects 和 SQLite,全部免费层即可运行。

插图:一座小房子系在一个发光方块上,周围是无尽的服务器状方块网格。
一个智能体、一个对象、一个账号:整个应用都住在别人机房网格里的同一个 Durable Object 中。

这是我的一个反直觉观点,我打算把它讲清楚:个人 AI 智能体比起放在你桌子底下的树莓派,其实更适合跑在 Serverless 基础设施上。Talorys 是一个开源的个人助手项目,只需一条 npx create-talorys@latest 命令就能部署到你自己的 Cloudflare 账号里,它目前是最有力的证据,说明“在无状态 Serverless 上跑有状态 AI 智能体”这个问题不仅能解决,而且天然契合。至于 Hacker News 上那群人争论它算不算“自托管”,我觉得他们从一开始就吵错了方向。

我这些年一直在跑基础设施,也一直在给它善后。真正干掉自托管个人软件的,不是部署,而是第三个月:磁盘被日志塞满,TLS 证书过期,然后你再也想不起来到底是哪个 systemd 单元在负责调度。Talorys 直接绕开了整类故障,因为它根本没有服务器。它需要的一切(聊天、记忆、任务、定时提醒)都跑在 Cloudflare 的免费层上:Pages 负责前端,一个私有 Worker 负责 API,一个基于 SQLite 的 Durable Object 存放所有状态,Workers AI 提供模型。单个用户每月的总成本:零。

真正的问题:智能体是有状态的,而 Serverless 不是

AI 智能体本质上是一堆长期存活的状态,只是伪装成了请求-响应式应用。它需要对话历史、持久化的记忆、任务列表、不管有没有人登录都要在早上 7 点触发的定时任务,还需要在多步链路运行时存放工具输出的地方。这些东西每一样都和经典的 Serverless 模型格格不入:在那个模型里,你的函数就像一条金鱼,醒来处理一个请求,然后什么都忘掉。

业界的标准做法是在边缘重新拼凑状态:会话数据用 Redis,持久化记录用 Postgres,定时任务用队列加调度器,语义召回用向量数据库。这套方案能跑,但你其实是用托管服务重新搭了一个服务器农场,账单和运维面积也随之而来。我见过一些团队,在给智能体接线这五个有状态服务上花的工程时间,比写智能体逻辑本身还多。正如我之前所说,LLM 智能体本质上就是分布式系统,而分布式系统正是好心办坏事的地方。

Talorys 押的是相反的注:把所有状态放在唯一一个地方。一个名为 personal-agent 的 Durable Object 承载了整个世界,包括对话、记忆、任务、笔记、项目、自动化、会话、设置和用量统计,全部存在它内嵌的 SQLite 数据库里。没有 KV,没有 D1,没有 R2,也没有 Vectorize。README 里写得很明确,这些都不需要配置。这不是偶然,而是架构本身。

Durable Objects 是作弊码

Durable Objects 大概是当前云计算里最低调也最激进的原语,我觉得这不是夸张。Durable Object 是一个单实例的代码单元,配有强一致、支持事务的存储,并且与它物理上部署在一起。当一个请求寻址到 personal-agent 对象时,Cloudflare 会把它唤醒,从冷启动到就绪只需毫秒级,然后在本地 SQLite 上运行你的代码,空闲后再把它冻结。你既能享受长期运行的服务器进程的开发体验,又拥有 Lambda 式的计费模型。

对于单用户的个人智能体,这个模型那些出了名的限制反而变成了优点:

  • 单写者是特性。一个用户就是一个写者。多租户状态那些并发上的麻烦全都消失了,你免费获得对所有数据的串行化、事务性访问。
  • 同置部署消除延迟。智能体的记忆查询、任务查找和对话历史都是对本地磁盘上 SQLite 的读取,而不是跨可用区访问数据库的网络往返。
  • Alarm 取代 cron。Durable Object 的 alarm 让对象自己安排唤醒。提醒、周期性例程和每日摘要都能在没有任何机器在线的情况下触发:对象休眠,alarm 将其唤醒,它完成工作,再回去睡觉。
  • 休眠不花钱。空闲时间零成本。一个每天闲置 23 小时的个人助手,正是 Serverless 定价模式最初要服务的工作负载。

这是我希望更多人从这个项目中领悟到的道理。如果你的应用天生是单租户的(个人工具、每个客户一个的工作区、每台设备一个的协调器),那么“每个租户一个 Durable Object”的模式会给你一样过去只有 VPS 才能提供的东西:一台概念上始终在运行的小电脑,空闲时零成本,也永远不需要系统管理员。光是调度这一项就值回票价。跑过个人 cron 盒子的人都知道那种失败模式:机器重启,cron 守护进程没有回来,你两周后才发现提醒已经悄悄停了。Alarm 是由基础设施自己托管的调度,少了一件需要你盯着的事。

网络模型比大多数生产环境的设计还要好

作为有安全背景的人,我看到这里坐直了身子。Talorys 里的智能体 Worker 部署时设置了 workers_dev: false 和 preview_urls: false,它根本没有公网 URL。浏览器只和一个 *.pages.dev 站点通信;位于 /api/* 的 Pages Function 通过 service binding 把请求转发给 Worker,这是 Cloudflare 同一账号内计算资源之间的内部私有连接。认证和鉴权都在 Worker 里完成,而不是在前端。

想想这消除了什么。没有可以被扫描的公开 API 端点,没有可能配错的防火墙规则,也没有忘了打补丁的反向代理。智能体后端的攻击面实际上就是“你必须通过前端的认证流程才能进来”。我审计过一些真实公司的生产部署,它们有预算,也有安全团队,但网络策略还不如这个个人项目严格。我在云环境中见过的最常见事故模式,是某个内部服务一直“只允许内网访问”,直到某天不再如此,因为有人在负载均衡器配置上手滑了。你没法手滑把一个 service binding 变成公网可访问的东西,那个 URL 根本不存在。

安装程序也值得一提。它在本地用 PBKDF2-SHA256 对所有者密码做哈希,只把哈希值作为 Cloudflare secret 存储,生成 256 位的会话密钥,为资源分配唯一名称,然后验证线上部署,包括确认未认证的请求确实会被拒绝,而且不消耗任何 AI 推理配额。部署后检查认证是否真的拒绝未认证请求,这类事情我以前都写进过事故复盘报告里。在一个一条命令的安装器里看到它,是一种令人愉快的惊喜。

堡垒:一扇有守卫的大门,内部密室只能通过内部桥梁进入。
一个公开入口,零公开后端:通过 service binding,智能体 Worker 根本没有可供攻击的 URL。

在免费层里生存,同时不自欺欺人

免费层是真实存在的,但它是一份预算,不是自助餐。Cloudflare 给免费账号提供按日计的 Workers AI 额度,以“Neurons”计量,每天 10,000 个,另外还有请求和 Durable Object 的用量配额。这些数字由 Cloudflare 设定,可能会变。Talorys 处理这件事的诚实程度,比我见过的大多数“免费层”项目都高:AI 额度用完时,聊天界面会直说,并在每日重置后恢复;而任务、笔记、记忆和提醒照常工作,因为它们都不需要模型。

这些护栏值得你在自己的项目里借鉴。Talorys 提供了可配置的上限:单次输出 token 数、上下文 token 数(较早的历史会被总结,而不是被悄悄截断)、每次请求的工具调用和推理步数、每天的 AI 请求数,以及每天的定时 AI 运行次数。这是一种成熟的态度。无上限的智能体循环,正是让你醒来发现账单暴涨或配额耗尽的原因,而“智能体决定调用了 40 次工具”这种失败模式,我见过在生产环境里烧掉真金白银。相关的一点:该项目选择让简单的提醒和摘要从不使用 AI,这一点完全正确。如果一段代码路径是确定性的,就不要把它绕到概率模型上去。这与将模型输出约束为结构化决策背后的纪律是一致的,即只在真正需要判断的地方使用模型。

社区里有一个“踩坑”提醒:有几个人反映,把 Workers AI 和付费 Workers 套餐混用时出现了不透明的计费意外,Neuron 的计算和文档中的限额对不上,提交给支持的工单也石沉大海。具体情况我无法核实,但这符合我很熟悉的一种模式:计量式 AI 计费到处都让人困惑,“对免费层友好”并不等于“不可能被收费”。如果你在付费套餐上部署,第一天就在 Cloudflare 控制台里设置花费提醒。要把服务商的用量界面当作事实来源,而不是应用本地的估算。

“自托管”之争没有抓住重点

那么,我开头的论断也要求我做出一点让步。这个项目下的热门评论几乎都在为“自托管”这个词打口水仗,而抬杠的人确实有道理:它完全依赖 Cloudflare。你的数据存放在他们的数据中心,推理跑在他们的 GPU 上,如果他们明天改了免费层,你的助手也会跟着变。把这称为自托管,已经把这个词拉伸到了断裂的边缘。更善意的理解是:除了你已经掌控的 Cloudflare 账号之外没有任何第三方,没有回传给开发者的遥测,中间也没有运营方,这更适合被描述为“自有”或“自主保管”。措辞很重要,用词更准确,这个项目就能少挨些骂。

但抬杠的人在这里我就不认同了。个人软件真正的威胁模型并不是“某家公司可能修改服务条款”,而是数据外泄、遥测,以及开发者破产、关停托管版本。在这三点上,Talorys 确实很强:没有分析或追踪代码,不会向作者回传任何信息,也没有需要关闭的托管版本。同时,代码采用 MIT 许可证,正如一位评论者指出的,把 AI 调用指向本地模型服务器只是一个小补丁,整个技术栈甚至可以在 wrangler dev 下用模拟的 AI 提供方在本地运行。如果有一天 Cloudflare 变得无法接受,退出的路径也很短。相比之下,许多“自托管”应用其实就是一个从别人镜像仓库拉取镜像的 Docker Compose 文件,还时不时回传做许可证校验。

评论串里还埋着一个更公允的批评:没有证据表明这个助手真的好用。聊天界面、记忆的增删改查、向量嵌入和定时任务,每一项单独做都很简单;真正决定个人助手成败的,是 harness、提示词、记忆检索策略和工具的 schema,而一张干净的架构图根本无法证明这些。这个品类里几乎每个项目都是如此,对此保持怀疑是正确的。请把 Talorys 当作基础设施来评判,把它看成一个设计良好的底盘,而不是一个经过验证的副驾驶。如果你正在为这类应用权衡模型,我们那篇在自己的硬件上运行 LLM覆盖了主权光谱的另一端。

黄铜天平一端是挂锁,另一端是一朵小云。
控制与便利分坐天平两端,诚实的权衡在于厂商锁定与运维负担之间。

这套设计值得你借鉴什么

即使你从来不部署 Talorys,这套架构也值得你内化为参考。可以迁移的思路包括:

  1. 每个租户一个对象。如果你的应用是单用户的,或者能被干净地分区,就把代码和状态放在同一个 Durable Object 里,然后删掉你的缓存层、消息队列和连接池。
  2. 没有公开的后端 URL。设置 workers_dev: false 并使用 service binding,是 Serverless 中成本最低的安全收益。无法访问的服务就无法被攻击。
  3. 用 alarm 替代 cron 盒子。与基础设施绑定的调度能扛过重启、重新部署,也能扛过你自己的健忘。
  4. 感知配额的降级。设计应用时,让昂贵的依赖(模型)可以失败或耗尽,而核心产品仍然可用。降级应当是一项功能,而不是一次故障。
  5. 只追加的迁移。Durable Object 命名空间在更新时从不重建,schema 迁移在第一次请求时以事务方式执行。这就是在不冒数据丢失风险的前提下,更新有状态 Serverless 的方法。

更大的教训关乎个人软件的走向。二十年来,选择一直是二元的:把数据交给 SaaS 公司托管,或者自己变成半职业的系统管理员。Durable Objects 以及其他云厂商必然会推出的同类原语,打开了第三条路:你独自掌控的软件,由你租用的基础设施运行,在个人规模下几乎零成本。这不是自托管,它也许更好。