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
| 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
- Cold-start latency on the first chat (~10–30 s while Agno loads and makes the first provider call). Subsequent chats are fast.
- Postgres connection refused at first boot if the DB isn’t ready yet. Set
WAIT_FOR_DB=trueif your platform’s DB takes a moment to provision. - Render free Postgres has a connection cap (~5) and pauses after 30 days idle — fine for a smoke test, not for prod.
- Koyeb secret resolution fails the whole deploy if one referenced secret is missing — create even the ones you don’t use, with an empty string.
- GHCR rate limits for unauthenticated pulls are generous, but if you’re rebuilding in CI, log into GHCR with a PAT.