Skip to content
3 min read · 512 words

Backend Deployment

The backend is a single uvicorn process with two file-based stores. Deploying it means: give it Python 3.14+, a persistent working directory, and the OpenAI key — then harden.

The invariants any host must satisfy

  1. Working directory = backend/app/ — imports (from database import ...) and both store paths (./agentops.db, ./chroma_db) are CWD-relative (why).
  2. Persistent disk — both stores are files; an ephemeral filesystem silently resets the platform on every restart. Serverless-without-volumes is disqualified until the Postgres migration.
  3. Outbound HTTPS to OpenAI and the OPENAI_API_KEY secret present.

Reference process setup

bash
cd backend/app
uv run uvicorn main:app --reload --port 8001

Startup is self-sufficient: tables are created and migrations applied on boot (Application Entry) — no release commands.

There is no Dockerfile (yet)

Containerization is a roadmap item, not a shipped artifact. When writing one, the three invariants above translate to: WORKDIR /app/backend/app, a volume for agentops.db + chroma_db/, and secrets via env. Until then, uv sync + the systemd pattern is the supported deployment.

Production checklist

  • Private network or authenticating reverse proxy — the API itself is unauthenticated (Security)
  • TLS termination at the proxy (Caddy/Nginx/platform)
  • OPENAI_API_KEY from a secret store, not a committed file
  • Persistent volume mounted; backup schedule for agentops.db (it's one file — sqlite3 agentops.db ".backup backup.db") and chroma_db/
  • Process supervision with restart-on-failure (systemd/supervisor/platform)
  • /health wired into uptime monitoring
  • Log capture for stdout (uvicorn access + tracebacks)
  • OpenAI spend alert configured on the OpenAI dashboard (the platform's own cost figures are estimates)

Platform notes

Host typeFit
VM (EC2, Droplet, Hetzner)✅ simplest match for the invariants
Railway / Fly / Render with volumes✅ good — attach a volume, set CWD, done
Vercel / classic Lambda❌ for the backend (no persistent FS) — fine for frontend/docs

Verifying a deployment

bash
curl https://<backend-host>/health           # {"status":"ok",...}
curl https://<backend-host>/agents/          # [] on a fresh volume
# create an agent, chat once, confirm a run row exists — the Quick Start sequence