Skip to main content
The gateway now ships in the praisonai-bot package. praisonai serve gateway still works exactly as documented here; for a standalone install see praisonai-bot Migration.
Operator scopes grant teammates least-privilege access to a shared Gateway — read-only dashboards, send-but-not-approve operators, or full admins — without handing over the whole keys.
The user assigns scoped roles; each operator reaches only the gateway actions their role allows.

Quick Start

1

Single-operator (no scopes — unchanged)

Today’s setup keeps working. Authenticated clients receive all scopes when no policy is configured.
2

Multi-operator (scoped tokens)

Map each operator token to the scopes they need in gateway.yaml, then run your agent as usual.
When no auth_scopes policy is configured, every successfully authenticated client is granted all scopes — identical to today’s binary auth behaviour. Single-operator setups need no changes.

How It Works

  1. Client connects with a bearer token.
  2. Gateway resolves scopes via GatewayConfig.resolve_scopes(token).
  3. Each HTTP route and WebSocket action checks the required scope.
  4. Outbound events are filtered — approval events only reach clients with the approvals scope.
WebSocket frames go through the central authorize_method gate before any handler runs.

Scope Reference

admin implies every scope, but approvals and pairing do not imply each other — they are sibling capabilities. Only admin grants both. A method requiring both (via field escalation) therefore resolves to admin. See Incomparable scopes escalate to ADMIN.

Which scope should this operator have?

The APPROVALS scope is coarse — any holder may attempt to resolve any pending request. To bind a specific request to a specific operator inside that scope, use per-request reviewer custody.

Per-user attribution under a shared token

Operators sharing one gateway token collapse to a single audit identity by default. A proxy or SSO layer can stamp the X-Operator-Id header per user so each decision is still attributed to an individual on the audit trail.
The gateway stamps this as operator:alice on the audit trail. See Approval Attribution for the full identity derivation order.

Configuration

YAML — flat mapping

Python


Scope-Gated Routes

For programmatic (WebSocket / RPC) methods, see Method → Scope Registry below. The WebSocket message requirement comes from the Method Scope Registry below — the dispatcher calls resolve_required_scope("message") (and resolve_required_scope("agent.message")) rather than hard-coding the check per route.

Method Scope Registry

New gateway methods are closed until classified — you cannot accidentally ship an unauthenticated control-plane call. Every method maps to a GatewayMethodDescriptor in the module-level GATEWAY_METHODS registry. resolve_required_scope looks up that descriptor and returns the effective scope for a call.
Default-deny. Unknown or unregistered methods require admin. Adding a new gateway method without calling register_gateway_method means any caller holding less than admin is denied — this is intentional (fail closed), so new control surface is never reachable by omission.
As of PraisonAI PR #5217, the WebSocket dispatcher calls the registry directly — every inbound method goes through a central authorize_method(method, client_scopes, params) gate before any handler runs. resolve_required_scope() is the single source of truth. A plugin-registered or newly-added method is gated automatically; a method nobody classified requires admin by omission rather than being reachable ungated. See Central authorization gate below.

Quick lookup

Registering a plugin method

Plugin authors adding a new dispatcher method register its required scope once, at import time.
register_gateway_method refuses duplicates — pass replace=True to override an existing entry.

Per-field escalation

Escalation raises the required scope when a sensitive field is present; a plain call stays at the baseline.
Escalation only ever raises the requirement — a field mapped to a weaker scope than the baseline is ignored.

Strict fields (fail-closed on unknown payload)

strict_fields=True escalates any structural field not explicitly listed as safe, so unexpected payload keys fail closed.
APPROVALS and PAIRING are sibling scopes — neither implies the other. A method whose baseline is one but whose payload escalates to the other resolves to admin, its common upper bound, so a single-scope check can never be satisfied by holding only one of the two capabilities.

Core method classification

Core methods are classified at import; anything unlisted defaults to admin. Connection-lifecycle frames (hello, join, leave) run before a client has negotiated any scope, so they classify as read — the lowest meaningful level. abort (and its wire alias message_abort) mutates the turn just like sending one, so both carry the same write requirement as message. server_reply is unique — the handler escalates to approvals for approval-kind replies (parity with approvals.resolve), so a WRITE-only role can answer choice/input but not approval prompts. See Gateway Server→Client Request Channel.
GatewayMethodDescriptor is a frozen dataclass; its escalate_fields and safe_fields collections are defensively copied at construction, so mutating the originals after registration cannot change resolution.

Central authorization gate

Every gateway method now flows through one default-deny gate before any handler runs. Nothing changes for end users — the gateway gates dispatch for you.
Plugin authors extending the dispatcher can call the gate directly.
  • Called once, centrally, at the top of _handle_client_message — no per-handler wiring needed.
  • Default-deny: an unclassified method requires admin.
  • admin implies every scope.
  • read is the baseline lifecycle scope — any operator holding at least one actionable scope (write / approvals / pairing / admin) satisfies read, so a write-only operator can still complete hello / join / leave / session.status. An empty scope set cannot satisfy even read.
  • A malformed method (non-string / unhashable) fails closed to admin rather than raising TypeError.
  • Transport PING / PONG frames bypass the gate (handled earlier in the wire loop).
GatewayUnauthorized is a PermissionError subclass carrying .method: str and .required: OperatorScope. str(exc) renders as method 'X' requires scope 'Y', and the dispatcher maps it to the insufficient_scope wire envelope with required_scope set.

Method → Scope Registry

Every gateway method declares its required scope in one place — a declarative registry — instead of scattered checks per endpoint. New methods are closed until explicitly classified; an unregistered method requires admin.

Core method classification

Core methods are classified at import in praisonaiagents.gateway.protocols: Connection-lifecycle frames (hello, join, leave) run before a client has negotiated any scope, so they classify as read — the lowest meaningful level. abort (and its wire alias message_abort) mutates the turn just like sending one, so both carry the same write requirement as message.

Registering a plugin method

A plugin that adds a new gateway surface registers its scope at import time:

Per-payload-field escalation (raise, never lower)

A descriptor can raise the required scope when a specific field appears in the params — an otherwise write method that mutates configuration should require admin when the config field is present:

Strict-fields mode (fail closed on unknown fields)

For high-risk methods, enable strict_fields=True with an allowlist of known-safe fields. Any field not in safe_fields or escalate_fields escalates to admin:

Incomparable scopes escalate to ADMIN

approvals and pairing are sibling capabilities — neither implies the other. When a method’s baseline is one and a field escalates to the other, the combined requirement escalates to admin rather than silently picking one (a single-scope check cannot satisfy both):

API reference

register_gateway_method is safe to call at plugin import time. The core-method classification runs at praisonaiagents.gateway.protocols import, so any plugin registration you do afterwards adds to the same registry.
Do not lower a scope by re-registering with replace=True unless you own the method. Downgrading the required scope of a core method is a security regression.
For the approval-flow context these scopes gate, see Scoped Approvals.

Common Patterns

Read-only dashboard viewer — [read] for status and transcripts without send or approve rights. Send but not approve — [read, write] for operators who reply to users but cannot resolve tool approvals. Approvals-only on-call — [read, approvals] for security-sensitive approval resolution without channel admin rights. Full admin — [admin] for SREs who need pause/resume/reconnect plus all other capabilities.

Error Handling

HTTP 403 when scope check fails:
WebSocket message without write scope:

Granting approvals is effectively remote command execution — never assign it casually. On a loopback-bound gateway, local non-proxied requests bypass auth by default and are granted all operator scopes — intended for local development only. External binds (0.0.0.0, LAN IPs) are unaffected and still require a token with the correct scopes. Set ALLOW_LOOPBACK_BYPASS=false to opt back into strict auth on loopback, or true to force-enable the bypass even on an external bind (unsafe — never do this in production). See Bind-Aware Auth.

Best Practices

Start every operator with [read] and expand only when their role requires it.
Issue separate tokens per operator so you can revoke one role without rotating everyone.
Combine approvals scope with /api/approval/allowlist for defence-in-depth on tool execution.
Prefer explicit scope lists over [admin] unless the operator truly needs channel control.
An unregistered gateway method defaults to admin (fail closed). When a plugin adds new surface, always call register_gateway_method(name, scope=...) at import time so the requirement matches the intent — not just whatever the current default happens to be.

Bind-Aware Auth

Token requirements when binding to external interfaces

Gateway Overview

Multi-channel gateway architecture and setup

Scoped Approvals

Resolve tool-execution approvals with the approvals scope