durable-actors README

The project's README from github.com/TerseAI/durable-actors. As one markdown file: README.md.

Durable Actors

an open-source alternative to Cloudflare Durable Objects... with no vendor lock-in, memory limits, and observability built in.

Durable Actors help you build real-time applications like chat systems (e.g. ChatGPT, Codex), collaboration tools (e.g. Notion), and agent swarms (e.g. Devin).

They provide stateful serverless functions, a foundational building block that abstracts away persistence, coordination, and infrastructure challenges in distributed systems.

Live demo · TypeScript documentation · Python documentation

How it works

  1. Define an actor, a class with durable state (i.e. data survives interruptions, errors, and restarts) and serialized execution (i.e. concurrent callers can update it safely). For example:
  1. Generate type-safe clients automatically with the Durable Actors SDK. For now, it supports Python and TypeScript.
  2. Develop locally with one command and later self-host the Durable Actors runtime on GCP.

Quickstart: Multiplayer AI Chat

Teammates share one TeamAgent chat across regions; prompts queue, replies stream to everyone, and conversation state is durably persisted.

1. Create your project

Install Bun 1.4.2+.

bunx durable-actors init my-actors
cd my-actors
bun install
bunx durable-actors dev # Run the server locally on your machine

2. Define an actor

Define and export actors in your actor project’s src/actors.ts, the default entrypoint loaded by durable-actors dev. The runtime loads actors on demand and persists fields marked @Persisted.

For example, a chat history 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 // Let other calls run during await, e.g. new connections while a reply streams.
    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. Connect your backend

We make it super easy to integrate the actors into your existing tech stack. Just generate the client and you get a fully type safe contract to interact with.

bunx durable-actors generate

Create a WebSocket connection to one shared chat:

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. Connect the frontend

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 />)

For a complete app with error handling and retries, see the AI Chat example.

5. Monitor and debug

Durable Agents provides built-in observability features:

o11y-screenshot

Examples

For complete sample applications, see AI Chat, Collaborative Documents, and Chatroom.

Community

Bug reports, feature requests, documentation fixes, and code contributions are welcome. See the contributing guide for repository setup and checks, and follow our code of conduct.

Use GitHub Issues for bugs, ideas, and questions. Report vulnerabilities privately using our security policy.

Follow development and release notes on GitHub Releases.

License

MIT © 2026 Terse

durable-actors (TerseAI/durable-actors)

Searching Database…

这是什么?Durable Actors 是一个开源项目,相当于 Cloudflare Durable Objects 的替代方案,用来构建实时、多智能体协作的系统,比如聊天应用、协作工具和智能体集群,自带持久化状态和 WebSocket 支持。
这是托管服务,还是需要我自己部署?这是一个可以自行部署的 actor 运行时,会为你的后端自动生成类型安全的 SDK 客户端;本地一条命令就能开发,之后再自行部署运行时,目前文档只介绍了在 GCP 上部署的方法。
怎么开始写一个 actor?先安装 Bun 1.4.2+,在项目的 'src/actors.ts'(也就是 'durable-actors dev' 加载的入口文件)里定义 actor,然后生成类型安全的客户端,通过 WebSocket 把后端和前端连接起来。
开始之前需要先装好 Bun 吗?需要,创建和运行 Durable Actors 项目必须使用 Bun 1.4.2 或更高版本。
我能部署到任意云平台吗,还是只能在 GCP 上?README 只写了在 GCP 上自行部署运行时的方法,没有提到其他云服务商。
客户端可以用哪些语言来写?SDK 目前支持 Python 和 TypeScript,两者都能自动生成类型安全的客户端。
这里的“actor”到底指什么?actor 是一个带有持久化状态的类,状态在崩溃和重启后依然保留;它的执行是串行化的,并发调用也能安全地更新状态,比如聊天记录 actor 或类似 Notion 的文档 actor。
它适合做哪类应用?适合需要多智能体协同状态的实时应用,比如 ChatGPT 式的聊天、类似 Notion 的协作文档,以及 Devin 式的智能体集群。
它能帮我调试生产环境里的 actor 吗?可以,它内置了可观测性功能,方便在 actor 运行时进行监控和调试。
有现成的示例可以学习吗?有,仓库里附带完整的示例应用:AI Chat、协作文档和聊天室。
Creator
TerseAI
Size
12.5 MB
Stars
230
Age
1mo
Commits · 90 Days