一个开源版的 Cloudflare Durable Objects 替代方案……没有供应商锁定、没有内存限制,并内置可观测性。
Durable Actors 帮助你构建实时应用例如聊天系统(如 ChatGPT、Codex)、协作工具(如 Notion)以及智能体集群(如 Devin)。
它们提供有状态的无服务器函数,这是一个基础构建块,抽象掉了分布式系统中的持久化、协调和基础设施难题。
工作原理
- 定义一个actor,一个带有持久状态(即数据在中断、错误和重启后依然存活)和串行执行(即并发调用者可以安全地更新它)的类。 例如:
- 如果你在构建 ChatGPT……一个聊天 actor 可以存储对话,使其在 LLM 不稳定和服务器崩溃时依然存活(持久状态)
- 如果你在构建 Notion……一个文档 actor 可以协调来自多人和多个智能体的并发编辑(串行执行)
- 使用 Durable Actors SDK 自动生成类型安全的客户端。目前,它支持 Python 和 TypeScript。
- 用一条命令在本地开发,之后在 GCP 上自托管 Durable Actors 运行时。
快速开始:多人 AI 聊天
1. 创建你的项目
安装 Node.js 22.19+ 和 Bun 1.3.9+。
npx durable-actors init my-actors cd my-actors npm install npx durable-actors dev #在你的机器上本地运行服务器
2. 定义一个actor
在你的 actor 项目的src/actors.ts中定义并导出 actor,这是由durable-actors dev加载的默认入口点。运行时按需加载 actor,并持久化标记为@Persisted的字段。
例如,一个聊天历史 actor:
import { openai } from "@ai-sdk/openai" import { streamText } from "ai" import { Actor, type ActorSocket, Interleave, Persisted } from "durable-actors" type Message = { role: "user" | "assistant"; content: string } export class ChatHistory extends Actor<null, string, Message[]> { @Persisted messages: Message[] = [] async onConnect(socket: ActorSocket<null, Message[]>) { socket。send(this。messages) } @Interleave // 让其他调用在 await 期间运行,例如在回复流式传输时的新连接。 async onMessage(_socket: ActorSocket<null, Message[]>, text: string) { this。messages。push({ role: "user", content: text }) const result = streamText({ model: openai("gpt-5-mini"), messages: [...this。messages] }) const reply: Message = { role: "assistant", content: "" } this。messages。push(reply) this。broadcast(this。messages) for await (const chunk of result.textStream) { reply.content += chunk this.broadcast(this.messages) } } }
3. 连接你的后端
我们让将 actor 集成到你现有的技术栈变得非常简单。只需生成客户端,你就能获得一个完全类型安全的契约来进行交互。
npx durable-actors generate
创建一个到单个共享聊天的 WebSocket 连接:
import express from "express" import { actors } from "../generated/index.js" export const app = express() app.post("/api/chat/socket", async (_req, res) => { const grant = await actors.ChatHistory.prepareWebsocket({ actorId: "lobby", metadata: null }) res.set("Cache-Control", "no-store").json(grant) })
4. 连接前端
import { useEffect, useRef, useState } from "react" import { createRoot } from "react-dom/client" import type { actors } from "../generated/index.js" function Chat() { const socket = useRef<WebSocket>(null) const [messages, setMessages] = useState<actors.ChatHistory.Outgoing>([]) useEffect(() => { let active = true async function connect() { const response = await fetch("/api/chat/socket", { method: "POST" }) const { websocketUrl } = await response.json() if (!active) return socket.current = new WebSocket(websocketUrl) socket.current.onmessage = event => setMessages(JSON.parse(event.data)) } void connect() return () => { active = false socket.current?.close() } }, []) function send(form: FormData) { const text = String(form.get("message")).trim() if (!text || socket.current?.readyState !== WebSocket.OPEN) return socket.current.send(JSON.stringify(text)) } return ( <main> <div role="log" aria-label="Messages"> {messages.map((message, index) => ( <p key={index}><strong>{message.role}:</strong> {message.content}</p> ))} </div> <form action={send}> <input name="message" aria-label="Message" required /> <button>Send</button> </form> </main> ) } createRoot(document.getElementById("root")!).render(<Chat />)
如需一个包含错误处理和重试的完整应用,请参阅AI Chat 示例。
5. 监控与调试
Durable Agents 提供内置的可观测性功能:
示例
如需完整的示例应用,请参阅AI Chat、Collaborative Documents和Chatroom。
社区
欢迎提交 bug 报告、功能请求、文档修正和代码贡献。有关仓库设置和检查,请参阅贡献指南,并遵守我们的行为准则。
使用GitHub Issues用于报告 bug、想法和问题。请通过我们的安全政策私下报告漏洞。
在GitHub Releases上关注开发和发布说明。
许可证
MIT© 2026 Terse

