Deploy and Operate

Configure storage, coordination and recovery for harness services in your infrastructure.

Start with a working service and verified tool results. Before running multiple replicas, configure shared persistence, event/cancellation coordination, authentication and per-session request serialization.

Use shared Postgres and Redis

Install the clients in the environment used by harness_service.py:

uv pip install "psycopg[binary]" redis
export DATABASE_URL="postgresql+psycopg://user:password@postgres:5432/agents"
export REDIS_URL="redis://redis:6379/0"

These hostnames are placeholders for provisioned services reachable by every replica. Use your deployment's secrets mechanism for credentials. In harness_service.py, replace the SQLite database construction, add the imports below, and replace the AgentOS construction:

import os

from agno.db.postgres import PostgresDb
from agno.os import AgentOS, QueueConfig

# Create db before agent, and pass this db to the agent constructor.
db = PostgresDb(db_url=os.environ["DATABASE_URL"])

# After constructing the agent with db=db:
agent_os = AgentOS(
    agents=[agent],
    db=db,
    queue=QueueConfig(
        durable=True,
        redis=os.environ["REDIS_URL"],
        max_attempts=1,
    ),
)
app = agent_os.get_app()

The same database configuration must be used by the agent and runtime. Every replica must register the same agent ID and use compatible harness configuration. Native credentials and extension files must be provisioned separately. Give each execution environment deliberate native-home and working-directory locations; do not assume sharing a database shares a filesystem.

QueueConfig(redis=...) coordinates events and cancellation. Redis is not a replacement for Postgres run/session and queue storage. The tested Redis transport uses standalone Redis/Valkey, not Redis Cluster. Review Multi-replica Deployments.

Protect the service

The tutorial binds to loopback without caller authentication. Before making it reachable by product clients, configure AgentOS Security and Auth, enforce caller/session ownership and provision scoped tool credentials. Bind the service to the deployment interface only behind the selected access controls.

For tenant isolation, configure verified JWT authorization and user_isolation=True. A client-supplied user_id alone is not an access boundary. Verify that a second authenticated user cannot read, resume or cancel the first user's run, and that missing or invalid credentials are rejected.

Native tool permissions and a cwd are not session-container provisioning. Remote MCP tools must enforce their own authentication and authorization. Do not expose unrestricted shell/file tools over an unprotected endpoint.

Set a retry and recovery contract

Keep max_attempts=1 until side effects are safe to repeat. A larger queue allowance permits whole-run re-execution after interruption. Native SDKs can also retry transport requests internally. Treat model invocation counts, run attempts and business-operation executions as different measurements.

Claude and Codex agent retries compose with queue retries: up to max_attempts × (retries + 1) adapter invocations for retryable failures, before native transport retries. Permanent-error classification is persisted for the queue. Clients must handle retry warnings because failed attempts may already have streamed output. See Retries and Tool Effects for configuration and client behavior. A resumed session does not guarantee exactly-once effects.

Preserve tool operation IDs across attempts. Store tool outcomes independently when they represent business transactions. Serialize turns within a session while allowing independent sessions to run concurrently.

Monitor what can fail

SignalOperational response
Provider authentication expiredRepair or refresh provider credentials; API health alone does not prove provider readiness.
Transcript persistence warningInvestigate storage and native recovery completeness; avoid repeating successful tools just to repair transcript storage.
Event transport unavailable or expiredDistinguish connection failure from retention expiry. Replay retained database events where available; poll saved run state when needed.
Run ERROR or CANCELLEDInspect run status and actual tool outcomes, including effects that completed before failure.
Disk full or missing workspaceRepair execution storage; database-backed conversation history does not restore arbitrary files.

Validate before increasing scope

Exercise your chosen deployment with two replicas: streamed and nonstreamed runs, real tools, client disconnect, cancellation, duplicate requests, worker death and same-session contention. Test credentials across expiry and restart. Native Claude restoration and Codex history fallback are different acceptance outcomes.

Queue eligibility varies by request path. Plain registered-agent text submissions are the baseline here; do not infer identical durable handling for factory-backed, remote, version-pinned or media-bearing requests without checking their supported path.

Session-owned execution sandboxes are a separate architecture step. The setup on this page does not allocate isolated session containers or restore a coding workspace on replacement.