Skip to main content
Submit a run with background=true and AgentOS answers immediately with a run_id. The run executes on the server while your client polls, streams, or disconnects. Add QueueConfig(durable=True) and that acceptance becomes a committed database row that survives crashes and deploys. Your database is where truth lives, queue.redis is how replicas talk to each other, and durable=True turns acceptance into a promise.

Quickstart

Run Postgres:
durable_queue.py
Submit a run:
The 202 is returned after the queue row commits. Poll for the result:
The response carries status (PENDING, RUNNING, PAUSED, COMPLETED, CANCELLED, or ERROR) and, once finished, content.

The 202 contract

Every background submission, durable or not, returns the same shape: The background and stream form fields select the execution mode: Teams and workflows use the same fields under /teams/{team_id}/runs and /workflows/{workflow_id}/runs. See Background Execution for the SDK-level arun(background=True) API and the SSE resume protocol.
Background execution requires a db on the agent, team, or workflow. Submissions without one are refused with 400.
The AgentOS Control Plane submits every chat run with background=true. Runs started from the UI go through the same path as any other background submission: the concurrency cap applies, and the queue applies if your AgentOS is configured with QueueConfig(durable=True).

Without durability

The run lives in the memory of the replica that accepted it. If that process dies, every waiting and in-flight run on it is lost, and nothing marks them as failed. In a multi-replica deployment, /resume and /cancel only work on the replica that holds the run.

With durability

QueueConfig(durable=True) writes each accepted run as a row in the queue table before the 202 is sent. A worker on every replica claims rows and executes them. If a replica dies, its runs are either reclaimed by another replica or marked failed, depending on max_attempts. See Durable queue for the exact guarantee, retry policy, idempotency keys, and configuration.

With more than one replica

Set QueueConfig(redis=...) as soon as you run two or more replicas behind a load balancer. One setting installs both the event stream and the cancellation manager on each replica, backed by a shared Redis, so a run started on one replica can be watched, resumed, and cancelled from any other. No set_cancellation_manager() or set_event_stream() call is needed. See Multi-replica deployments for what Redis does here, and why queue.redis is a different job from db=RedisDb.

Upgrading from v2

Background runs are capped at 32 per replica in v3. In v2 each submission spawned an unbounded asyncio.create_task; now runs beyond the cap wait as PENDING. Raise or disable the cap with QueueConfig(max_concurrency=...) or AGNO_BACKGROUND_MAX_CONCURRENCY. Durability, Redis coordination, idempotency keys, session ordering, and the /queue endpoints are opt-in through QueueConfig.

Guides

Durable queue

Acceptance as a committed row. Crash semantics, retries, idempotency, session ordering.

Multi-replica deployments

Wire events out and cancels in through Redis. Coordination versus job storage.

Human-in-the-loop continuations

Continue a paused durable run through the queue under the same run_id.

Operations and monitoring

Dead-letter listing, requeue, queue stats, retention, admin gating.

Limitations

Developer Resources