A small Python adaptation of the actor-hosted chat in the durable-actors README, using the OpenAI Agents SDK.
Requires Python 3.11+, uv, and your own OpenAI API key.
uv sync --locked
cp .env.example .envSet OPENAI_API_KEY in .env before starting the actors. The actor uses OPENAI_MODEL, defaulting to gpt-5-mini. Every reply calls OpenAI.
Start the actors:
uv run durable-actors devThen, in another terminal:
uv run uvicorn src.backend:app --host 127.0.0.1 --port 8000Open localhost:8000.
An illustrative FastAPI design coordinates chat through a socket layer, a per-conversation queue, agent workers, and object storage.
+-------------------+ +----------------------------+
| Browser | HTTP | FastAPI Servers |
| |<------------------->| - Serves UI |
+-------------------+ +----------------------------+
^ |
| direct WebSocket |
v v
+----------------------------------------------------------------------+
| Socket layer |
| - Dedicated socket servers (optional) |
| - Connects and disconnects clients |
| - Tracks connections by conversation |
| - Redis Pub/Sub for broadcasts across servers |
+----------------------------------------------------------------------+
^ |
| | enqueue by conversation
| v
| +----------------------------------+
| | Conversation queue |
| | - Keyed by conversation ID |
| | - One active turn per chat |
| +----------------------------------+
| |
| v
| +----------------------------------+
| broadcasts | Agent workers | +--------------+
+-------------| - Loads conversation history | | OpenAI API |
| - Runs OpenAI Agents SDK |<----->| |
| - Saves updated history | +--------------+
+----------------------------------+
^
|
v
+----------------------------------+
| Object storage |
| - Conversation history |
+----------------------------------+
A worker loads history, streams the reply through Redis Pub/Sub, saves the conversation, and acknowledges the queued turn.
Browser Socket layer Queue Worker Object storage OpenAI
| | (chat ID) | | |
|-- message --->| | | | |
| |-- enqueue ->| | | |
| | |-- next turn -->| | |
| | | |-- load history>| |
| | | |<-- history ----| |
| | | |-- Agents SDK ---------------->|
| | | |<-- streamed text -------------|
| |<-- Redis Pub/Sub ------------| | |
|<-- chunks ----| | | | |
| | | |-- save history>| |
| | | |<-- saved ------| |
| |<-- done via Redis -----------| | |
|<-- done ------| | | | |
| | |<-- acknowledge-| | |
| | | | | |
FastAPI serves the UI and grants connections while durable-actors handles WebSockets, ordered agent turns, and persistence.
+-------------------+ +----------------------------+
| Browser | HTTP | FastAPI Server |
| |<------------------->| - Serves UI |
| | | - Grants socket access |
+-------------------+ +----------------------------+
^ |
| direct WebSocket |
v v
+----------------------------------------------------------------------+
| durable-actors runtime |
| |
| - websockets |
| - ordered turns |
| - persistence |
| - OpenAI Agents SDK runs |
+----------------------------------------------------------------------+
^
|
v
+--------------+
| OpenAI API |
+--------------+
The browser connects directly to its chat actor, which streams the agent reply and persists the conversation when the handler returns.
Browser FastAPI ChatHistory actor OpenAI
| | (one per chat ID) |
|-- request socket ->| | |
| |-- prepare socket --->| |
| |<-- grant connection -| |
|<-- WebSocket URL --| | |
| | |
|========== direct WebSocket ==============>| |
|<------------- saved history --------------| |
| | |
|--------------- user message ------------->| |
|<-------------- start event ---------------| |
| |-- Agents SDK ------>|
| | history + prompt |
| |<-- streamed text ---|
|<-------------- text chunks ---------------| |
|<-------------- done event ----------------| |
| | |
| Persist conversation |
| when handler returns |