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
| Signal | Operational response |
|---|---|
| Provider authentication expired | Repair or refresh provider credentials; API health alone does not prove provider readiness. |
| Transcript persistence warning | Investigate storage and native recovery completeness; avoid repeating successful tools just to repair transcript storage. |
| Event transport unavailable or expired | Distinguish connection failure from retention expiry. Replay retained database events where available; poll saved run state when needed. |
| Run ERROR or CANCELLED | Inspect run status and actual tool outcomes, including effects that completed before failure. |
| Disk full or missing workspace | Repair 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.