Deploy

All deploy paths are driven from liberzon/agents-gateway-deploy and pull the prebuilt multi-arch image ghcr.io/liberzon/agents-gateway:latest (linux/amd64 + linux/arm64).

One-click platform deploys

Deploy on Railway Deploy to Render Deploy to Koyeb
Platform Config Mechanism Recommended for
Render render.yaml runtime: image, pulls GHCR image directly First try — easiest
Railway railway.toml + wrapper Dockerfile Image-only deploys via wrapper Best Postgres UX
Koyeb koyeb.yaml docker.image: pulls GHCR image Free nano tier

All three default to PROMPT_STORAGE_BACKEND=postgres and prompt you for DB credentials and at least one LLM API key at deploy time.

Full step-by-step (provisioning Postgres, env vars, smoke test, teardown): DEPLOY_TEST_PLAN.md.

Kubernetes

Kustomize-based, with base manifests under k8s/base/ and per-project overlays. Deploy from the action workflow:

gh workflow run deploy-k8s.yml \
  -f project=agents-gateway \
  -f environment=production \
  -f image_tag=latest

Requires a KUBECONFIG_AGENTS_GATEWAY secret (base64-encoded kubeconfig). For GKE workload-identity auth, see config/projects.yaml.

Cloud-specific manifests

Maintained alongside the app in liberzon/agents-gateway/deploy/:

Target Path
AWS (ECS + CloudFormation) deploy/aws/
Azure (Container Apps + Bicep) deploy/azure/
Google Cloud Run deploy/gcp/
Generic (docker-compose, plain K8s) deploy/generic/

Smoke test

After deploy, run this against your service URL to confirm DB + LLM end-to-end:

URL=https://your-deployed-service.example.com

# 1. health
curl -fsS "$URL/health"

# 2. proves DB connectivity + ORM table auto-create
curl -fsS "$URL/v2/agents"

# 3. create a test agent (assumes AUTH_DISABLED=true, or pass -H "X-API-Key: <key>")
curl -fsS -X POST "$URL/v2/agents" \
  -H 'Content-Type: application/json' \
  -d '{"id":"smoke","name":"Smoke","template":"Reply with the single word: pong."}'

# 4. real LLM call through the deployed gateway
curl -fsS -X POST "$URL/v2/agents/smoke/chat" \
  -H 'Content-Type: application/json' \
  -d '{"message":"Reply with pong","user_id":"u","session_id":"s","timezone":"UTC","locale":"en","model":"gemini-2.5-flash-lite","stream":false}'

# 5. cleanup
curl -fsS -X DELETE "$URL/v2/agents/smoke"

Expected: each step returns 2xx, step 4 echoes the Gemini reply ("pong"). Anything else → save logs and open an issue.

Operational notes