Skip to main content
Fly app names are global, so up.sh generates a unique name (agentos-<suffix>), records it in fly.toml, and pairs it with a Postgres app named <app>-db. Later fly commands read the app name from fly.toml, so no --app flag is needed.

Manage

The platform runs one machine by design. Both deploy scripts pass fly deploy --ha=false because the Fly default creates two machines, which doubles cost and runs two in-process schedulers double-firing every cron. fly.toml keeps the machine warm with auto_stop_machines = "off" and min_machines_running = 1; with scale-to-zero, scheduled jobs silently stop firing.

Production auth

Token-Based Authorization is on by default. Production startup requires JWT_VERIFICATION_KEY or a readable JWKS file at the container path in JWT_JWKS_FILE; otherwise the process exits. Token-Based Auth gives you three things:
  1. No public access. The server rejects requests without a valid token.
  2. Per-request identity. Middleware validates the token and exposes its user_id, optional session_id, scopes, and claims to the request.
  3. Scope-based permissions. Token scopes control access to AgentOS routes and resources.
The templates do not enable per-user data isolation. To scope non-admin session, memory, trace, and run access to the JWT subject, pass authorization_config=AuthorizationConfig(user_isolation=True) to AgentOS. See User Isolation. To opt out (not recommended), set authorization=False in app/main.py and redeploy. Use this only inside a private network behind another auth layer. Without it, anyone who guesses your Fly URL can access your platform.

Customize

Ask your coding agent to run /create-new-agent, or do it by hand. Create agents/my_agent.py:
Register it in app/main.py:
Local containers hot-reload on save. For production, run ./scripts/fly/redeploy.sh.
app/settings.py defines default_model(), used by every agent. Change it in one place:
Add anthropic to pyproject.toml, set the provider key in your env, and regenerate pins:
Rebuild locally with docker compose up -d --build. For production:
Agno ships 100+ toolkits. See Toolkits.
  1. Edit pyproject.toml.
  2. Regenerate pins: ./scripts/generate_requirements.sh (add upgrade to refresh every pin).
  3. Rebuild locally with docker compose up -d --build, or redeploy with ./scripts/fly/redeploy.sh.
Set both variables in your env file:
Sync with ./scripts/fly/env-sync.sh. The interface activates automatically and routes messages to Agent Builder; change the agent= argument in app/main.py to point at another agent. See Slack setup.
The deployment check runs daily by default (ENABLE_DEPLOY_CHECK=True); it is deterministic and free. Scheduled evals are off by default (ENABLE_SCHEDULED_EVALS=False) because they use model calls. Both workflows stay runnable on demand regardless.
Fly’s stock postgres-flex image does not ship pgvector, so sessions and memory work but knowledge bases (RAG) fail at CREATE EXTENSION time. The fix is a two-line Dockerfile:
Set FLY_PG_IMAGE to that image before running ./scripts/fly/up.sh. The image applies when the Postgres cluster is created; up.sh reuses an existing cluster, so switching later means tearing down with ./scripts/fly/down.sh and provisioning fresh.

Format, validate, and run evals

The format, validate, and eval scripts run on the host and need a venv. Set it up once:
./scripts/mcp_check.sh runs inside the container, so it needs no venv.

Environment variables

up.sh also reads three variables from your shell when provisioning:

Troubleshooting

Install flyctl, then run fly auth login. The scripts accept either binary name, flyctl or fly.
Expected. Mint the key at os.agno.com: connect your OS (Connect OSLive, enter your Fly URL), then turn on Token-Based Authorization (JWT) under SettingsOS & Security and paste the full PEM. To add a PEM later, set JWT_VERIFICATION_KEY and run ./scripts/fly/env-sync.sh. To use JWKS, bake or mount the file in the Fly Machine, set JWT_JWKS_FILE to its container path, then sync the variable.
The script only manages names it generated. A different name means continuing would overwrite fly.toml and abandon that app. Restore the agentos placeholder (or an agentos-* name from a previous run), or tear down first with ./scripts/fly/down.sh.
JWT auth is on whenever RUNTIME_ENV is not dev. Set JWT_VERIFICATION_KEY and sync. To use JWT_JWKS_FILE, first bake or mount a readable JWKS file at that container path, then sync the variable. env-sync.sh does not upload the file. To opt out inside a private network behind another auth layer, set authorization=False in app/main.py.
The stock postgres-flex image has no pgvector; sessions and memory are unaffected. Set FLY_PG_IMAGE to a pgvector-enabled image and recreate the cluster. up.sh reuses an existing cluster, so tear down first with ./scripts/fly/down.sh. See Enable pgvector for knowledge bases.
AGENTOS_URL may still be the localhost default. up.sh sets it to https://<app>.fly.dev automatically; for a custom domain or tunnel, set it by hand and run ./scripts/fly/env-sync.sh. Re-running up.sh resets a hand-set value to the generated fly.dev URL, so re-pin it afterwards. The other cause is the machine scaling to zero: keep auto_stop_machines = "off" and min_machines_running = 1 in fly.toml.
A plain fly deploy created a second machine, and each runs its own scheduler. Deploy with the scripts; they pass --ha=false.