Serve Agents Authentication

How praisonai serve agents protects public binds with an API key

praisonai serve agents starts freely on localhost but requires an API key on any public bind, because POST /agents can execute YAML-defined tools.

Diagram

praisonai serve agents

Yes

No

Yes

No

🌐 –host

🔍 localhost?

✅ Starts

🔑 API key set?

🛑 SystemExit

Quick Start

  1. Private mode (default)

    Localhost binds need no key:

    bash
    praisonai serve agents --port 8000

    Any of 127.0.0.1, localhost, or ::1 starts without an API key.

  2. Public mode (with key)

    Non-localhost binds require a key. Generate one and start:

    bash
    export PRAISONAI_SERVE_API_KEY="$(openssl rand -hex 32)"
    praisonai serve agents --port 8000 --host 0.0.0.0

    Or pass it as a flag:

    bash
    praisonai serve agents --port 8000 --host 0.0.0.0 --api-key "$PRAISONAI_SERVE_API_KEY"
  3. Call a protected route

    Send the key with either header:

    bash
    curl -H "Authorization: Bearer $PRAISONAI_SERVE_API_KEY" http://SERVER_IP:8000/agents/list
    curl -H "X-API-Key: $PRAISONAI_SERVE_API_KEY" http://SERVER_IP:8000/agents/list

The Localhost Allowlist

The server treats these hosts as private and skips the key requirement:

HostPrivate?
127.0.0.1✅ Yes
localhost✅ Yes
::1✅ Yes
0.0.0.0❌ No — key required
Any LAN / public IP❌ No — key required

“Non-localhost” means any --host value outside the allowlist above.


Configuration

Provide the key through either path — the flag wins if both are set.

SourceExample
CLI flag--api-key "$KEY"
Environment variableexport PRAISONAI_SERVE_API_KEY="$KEY"

Generate a strong key with:

bash
openssl rand -hex 32

The SystemExit Error

Binding to a non-localhost host without a key exits immediately with:

praisonai serve agents: --api-key (or PRAISONAI_SERVE_API_KEY) is required when binding to a non-localhost host; POST /agents can execute YAML-defined tools.

Fix it by setting PRAISONAI_SERVE_API_KEY (or --api-key), or bind to 127.0.0.1 for a private-only server.


Protected vs Public Routes

When a key is set, most routes require the header. A few stay public for health checks and discovery.

RouteAuth
/healthPublic
/Public
/.well-known/agent.jsonPublic
/__praisonai__/*Public
/agentsProtected
/agents/{agent_name}Protected
Everything elseProtected

Both headers are equivalent and use constant-time comparison. Missing or wrong keys return 401 {"error": "Unauthorized"}.


Consistent YAML Lowering

Both POST /agents and POST /agents/{agent_name} flow through a single cached generator, so identical YAML gets identical treatment — guardrails, approval, tool_timeout, and retry settings now apply uniformly across both endpoints.

The generator is cached for the app’s lifetime (built once at startup) instead of rebuilt per request, so requests share the same adapter, config list, and resolver.


Best Practices

Generate keys with openssl

Use openssl rand -hex 32 for a 256-bit key. Avoid short or guessable values.

Never commit the key

Keep PRAISONAI_SERVE_API_KEY out of source control. Load it from your shell, a .env file that is git-ignored, or a secrets manager.

Use a secrets manager in production

Inject the key from AWS Secrets Manager, Vault, or your platform’s secret store rather than hard-coding it in deploy scripts.

Rotate the key

Rotate periodically and after any suspected exposure. Update both the server env and every client header at the same time.


Related