Skip to main content
Set redis exactly when you run more than one replica. With one replica, in-process defaults do the same job.

One setting, two managers

queue.redis sets both the event stream and the cancellation manager on every replica that constructs AgentOS(...). No other wiring is needed. A background run started on replica A may execute on replica B while the client’s next request lands on replica C. Both directions have to cross replica boundaries. Configuring only one is a common misconfiguration: cancels reach every replica while resumed streams idle on the wrong one, or the reverse. One setting covers both so that cannot happen by accident. In v2, cross-replica cancellation meant constructing RedisRunCancellationManager yourself and calling set_cancellation_manager() in every process, and the event buffer had no shared backend at all.
An explicit setter still wins for either manager. queue.redis only replaces defaults, never a backend you installed yourself, so a custom cancellation manager or an AgentOS(event_stream=...) override keeps working. If exactly one of the two is explicit, AgentOS logs a warning that cancellation and events may ride different Redis instances. Keys are namespaced under {key_prefix}:run:cancellation: and {key_prefix}:os:events: when key_prefix is set. Start a streaming run against one replica, then call /resume on another. Events replay and tail from Redis regardless of which replica executes the run.

Two Redis roles

queue.redis and db=RedisDb(...) are different settings with different requirements. A common production layout is Postgres for db (truth and jobs) and a plain Redis or Valkey for redis (coordination). Pointing both at one Redis works, as in the Redis event stream cookbook, but the persistence requirement then applies to it.

Connection options

Pass a URL for the common case, or RedisCoordination to inject clients:
Valkey works anywhere Redis does. A RedisCluster client is rejected for the queue store.

Stream retention

Per-run stream keys expire 30 minutes after the last activity, refreshed while the run is live. Each stream keeps roughly the most recent 10,000 events. A client that reconnects after expiry gets the persisted events from the database through /resume with session_id, not the live tail.

Without Redis on multiple replicas

Durable execution still works: jobs live in the database and any replica can claim them. The live view does not. A streaming submission accepted on replica A whose job is claimed by replica B produces a tail that idles until the client times out, even though the run completes. AgentOS logs this at startup:
Polling is unaffected, because the run row is in the database.

Next Steps