The heavy gateway implementation (
WebSocketGateway) lives in the praisonai_bot.gateway package. praisonaiagents.gateway holds only protocols and lightweight utilities. praisonai serve gateway and from praisonai.gateway import WebSocketGateway still work exactly as documented here via re-export shims; for a standalone install see praisonai-bot Migration.Quick Start
1
Simple Agent Gateway
Deploy an agent through the unified gateway:
2
Multi-Service Gateway
Configure agents with full gateway capabilities:
How It Works
Agents connect to services through gateway routing:Hot Reload
Editgateway.yaml while the gateway is running — file watch (with optional watchdog) and SIGHUP share the same diff-driven reload path, with drain-coordinated channel restarts. Rotating gateway.auth_token in the same reload also revokes any live sessions on the old secret — see Gateway Credential Rotation. See Gateway Config Reload.
For proactive/scheduled outbound delivery routing — including friendly alias targets like "family" or "ops" — see Friendly Aliases for Scheduled Delivery.
Voice notes
Voice messages sent to your gateway bot are transcribed automatically on Telegram, Slack, and WhatsApp — no code changes required. Configure thestt: block under each channel to force a language or opt out. See
Voice Notes (Speech-to-Text).
Authentication
Authentication posture changes automatically based on the bind interface.Bind-Aware Authentication
Complete authentication security guide
Rotating the shared secret
Changegateway.auth_token in the running gateway.yaml and hot-reload — every already-connected session that authenticated under the old secret is force-closed with WebSocket close code 4001 and reason credentials_rotated. New connections use the new secret. Defaults on; opt out with gateway.revoke_on_secret_rotation: false. See Gateway Credential Rotation for the full behaviour matrix.
The auto-generated per-install HMAC secret for pairing codes (.gateway_secret) is stored and permission-remediated separately — see Bot Pairing → Secret Management.
Pre-auth edge protections
Two guards protect internet-exposed gateway deployments by default: a per-IP connection budget (preauth_max_connections_per_ip=32) that caps unauthenticated WebSocket slots before auth runs, and a per-connection flood guard (max_unauthorized_frames=10) that closes connections sending too many unauthorized frames. Loopback clients are always exempt. Both are disabled by setting the option to 0.
Gateway Edge Protections
Per-IP connection budget, unauthorized-frame flood guard, and WebSocket close codes 4028 / 4029
Handshake and Version Negotiation
New WebSocket clients should send ahello frame to negotiate protocol version, capabilities, and policy limits in one round trip. The legacy join → joined flow remains supported for existing clients.
Gateway Handshake Protocol
Version negotiation, capabilities, and structured connection errors
Handling connect errors
A rejected handshake carries a structuredcode and next_step, so a client can tell a terminal failure (revoked token, unpaired device, unsupported protocol) from a transient one (rate limit) instead of probing-by-failure. The bundled client classifies each rejection with the shared is_recoverable(code) helper: terminal codes stop the reconnect loop and fire on_reconnect_paused(code, next_step); transient codes back off and retry, honouring any server retry_after_seconds as a lower bound.
Gateway Client — Terminal vs Transient Errors
Connect-error classification,
on_reconnect_paused, and the recoverable-code tableConfiguration Options
Gateway Configuration
Python gateway configuration options
Edge protection fields (available on
GatewayConfig and gateway.yaml):
Gateway YAML Configuration
Thegateway.yaml schema accepts three optional top-level blocks alongside channels and agents. All three are optional and ignored when not present.
gateway: block
Global gateway settings — reliability preset, drain timeout, health monitor:
api: block
Serve OpenAI-compatible and MCP HTTP endpoints from the same gateway process, sharing the live agents and sessions that chat users reach:
hooks: block
Register shell-command hooks that fire at gateway and message lifecycle events:
BotOS.from_config and tool names
BotOS.from_config("botos.yaml") now routes tool names through the standard ToolResolver chain:
- Local
tools.pyin the working directory - Wrapper
ToolRegistry praisonaiagentsbuilt-in toolspraisonai-toolspackage- Installed plugins
praisonai-tools symbol or a local tools.py function just works — no ad-hoc importlib lookup required:
Gateway Agent Defaults
Gateway agents loaded from YAML use chat-optimised defaults that differ from the Python SDK.Changed in PraisonAI v4.6.26: gateway agents now default to
reflection: false. Previous versions defaulted to true. See PR #1485.Per-Agent Approval Isolation
“Allow always” grants persist across gateway restart and default to being scoped to the approving agent, so one agent’s approval never authorises another. Grants live in a durable SQLite store at~/.praisonai/state/gateway/approvals.sqlite.
Gateway Scoped Approvals
Durable, agent-scoped allow-always grants, resolver scoping options, and the
/api/approval/allow-list endpointDefault vs Per-Agent Managers
Multi-Agent Gateway with Isolation
The
ttl parameter controls how long approval requests wait before auto-expiring (default: 5 minutes).
The get_exec_approval_manager() function is preserved as a backward-compatible alias for get_default_exec_approval_manager().Allow-list endpoint
GET/POST/DELETE /api/approval/allow-list manages allow-always grants. POST and DELETE accept an optional agent_id; GET returns a grants view alongside the legacy allow_list.
agent_id on POST/DELETE targets a legacy any-agent grant; supplying it scopes to that agent. See Gateway Scoped Approvals for full curl examples.
Gateway lifecycle predicates
Core SDK exports three pure predicates for gateway lifecycle decisions. Each is side-effect free and testable in isolation; the wrapper owns the actual teardown.Kanban Dispatcher
Kanban dispatcher (v4.6.x): Worker file descriptors are now released as soon as the subprocess starts (fixes a slow leak under sustained dispatch).release_claim failures are logged with full stack traces instead of being silently swallowed — orphaned claimed tasks now leave a clear log trail for triage. KeyboardInterrupt / SystemExit / asyncio cancellation propagate cleanly through dispatcher shutdown.
Common Patterns
Single Gateway Deployment
Multi-Agent Gateway
Development Gateway
Best Practices
Start with Unified Gateway
Start with Unified Gateway
Use
praisonai serve unified for simplicity. Agents connect automatically without configuration.Development vs Production
Development vs Production
Enable
--reload for development. Use separate services for production scaling.Service Discovery
Service Discovery
All servers expose
/__praisonai__/discovery for endpoint discovery. Agents can auto-discover capabilities.Port Planning
Port Planning
Reserve port 8765 for unified gateway. Use default ports for service-specific deployments.
Exit Codes & Supervisor Integration
praisonai serve gateway uses sysexits-based exit codes so process supervisors can distinguish a transient failure (restart) from a fatal misconfiguration (stop and fix).
What Triggers Fatal (78)
systemd Unit
Kubernetes Restart Policy
exit 0) to prevent the pod from restarting on fatal config:
In-Place Code Updates and /model
When a running gateway’s code changes on disk (via git pull, pip install -U, or an auto-update on a durable volume), the first-use lazy import triggered by a /model switch can hit a code mismatch and crash with a cryptic ImportError. The code-skew guard refuses with a clear message instead.
How It Works
At startup, the gateway captures a fingerprint of the installed code (git SHA + newest.py mtime). Before each /model switch it compares this to the current on-disk fingerprint:
User-Facing Message
When skew is detected, the user sees:<boot-short> and <disk-short> are 7-character shortened fingerprints (e.g. git SHAs or mtime: suffixes).
Fail-Open
The guard is best-effort and fail-open: if the fingerprint cannot be determined (no git, unreadable directory), the guard returnsNone and the /model switch proceeds normally. Normal operation is never blocked by the guard itself.
Opt-Out
Disable the guard for a session manager:Related
Agents
Core agent functionality
MCP Protocol
Model Context Protocol integration
Gateway CLI
CLI commands for managing the gateway
Gateway API Endpoints
OpenAI-compat and MCP HTTP endpoints on the live gateway
Relay Transport
Out-of-process platform connector relay
Bot Chat Commands
Built-in and custom slash commands for gateway bots
Slash Command Menu
Native
/ autocomplete for Telegram and Discord botsVoice Notes
Automatic transcription of inbound voice messages
Run Status Controller
Transport-agnostic run-progress state machine with a stall watchdog

