Skip to main content
Bot platform adapters now ship in the praisonai-bot package. praisonai bot serve still works exactly as documented here; for a standalone install see praisonai-bot Migration.
The user messages on Telegram, Slack, or Discord; the gateway routes each channel to the right agent. Run all your bots from one command. The Gateway Server manages multiple bot connections and routes messages to the right AI agent. Parity with Bot(): praisonai gateway start now applies the same smart defaults as praisonai bot start, resolving the previous “zero tools in daemon mode” issue. Both entry points produce identical behavior with safe tools auto-injected and auto-approval enabled by default. Each channel bot gets an isolated agent via Agent.clone_for_channel() — fresh locks, fresh interrupt controller, and no shared handoffs state — so configuring tools or memory on one channel never leaks into another.

Quick Start

1

Install PraisonAI

2

Create gateway.yaml

Create a gateway.yaml file in your project (Gateway YAML files are read as UTF-8 — non-ASCII characters work on all platforms including Windows):
3

Set Environment Variables

4

Start the Gateway

All bots start together. Messages are routed to the correct agent automatically.

Supported Channels

Telegram

Full support for DMs, groups, commands, voice, and media.

Discord

Guild channels, DMs, slash commands, and embeds.

Slack

Socket Mode, channels, DMs, slash commands, and threads.

WhatsApp

Cloud API and Web mode. DMs, groups, media support.
Windows users: Gateway Telegram error replies are automatically sanitized to ASCII-safe text — non-ASCII exception content (warning symbols, emoji, accented characters) no longer crashes the error handler with a charmap codec error. Real underlying errors (quota, rate limit, auth) surface cleanly.

Configuration Reference

Gateway Section

Agents Section

Each agent is defined by a unique ID and its configuration:

Channels Section

Each channel maps to a bot platform:
Use ${ENV_VAR_NAME} syntax in token fields. The gateway automatically reads from your environment variables.

Channel Security

Each channel enforces the same access-control pipeline as standalone bots. Every key below is read per-channel from gateway.yaml — including unknown_user_policy and owner_user_id, which the gateway now wires through at start and on hot-reload (PR #2856).
The same configuration comes straight from gateway.yaml:

observe: passive group context

observe records unmentioned group messages as passive context so the bot can answer with full conversational awareness when it’s finally mentioned. With mention_only (the default), messages that don’t @mention the bot are dropped and leave no session record. With observe, those messages are appended to the session transcript as ordinary user turns — the bot still does not answer them, but the next time it is addressed (e.g. @bot summarise what we just decided) the preceding conversation is in its history. Pair observe with session_scope: per_chat so passive messages route to the shared per-chat key that a later addressed turn reads from. Under the default per_user scope, passive turns are retained only in that sender’s own history — they do not leak into any single user’s per_user history when per_chat is used.
observe is Telegram-only today. Other adapters ignore it and fall back to their default group handling.
When to use it: a busy group where users want to @bot and have it see prior discussion; the bot stays quiet until addressed. When not to use it: noise-sensitive or high-PII channels — every unmentioned message is stored, increasing the volume of retained conversation text. See Session Scopes and Intentional Silence.

Shell execution

Set allow_shell: true on any channel to turn its bot into a shell-capable agent, with approval routed per platform. Policy is per-channel — one channel can auto-approve while another requires owner sign-off. On channels with routing rules, routed agents inherit execute_command too — the shell setup is re-applied to each routed agent, cloned and cached per (channel, agent). See Bot Shell Execution.
Routing rules apply to Slack @mentions. Slack handle_mention dispatches through registered on_message handlers, so per-route agent selection and allow_shell opt-in reach @mentions the same way they reach DMs and channel messages. On older builds, @mentions bypassed routing and ran the raw default agent. See Messaging Bots → Slack.
See Bot Shell Execution for the full routing ladder, per-platform ID resolution, env-var reference, and copy-paste recipes.
allowed_users interacts with unknown_user_policy. With an empty allowed_users list, every Telegram user is treated as “unknown” and the unknown_user_policy decides their fate:
  • "deny" (default) — all messages silently dropped (recommended for production).
  • "pair" — unknown users go through the owner-approval pairing flow.
  • "allow" — every user is let through (only set this in trusted networks).
Earlier releases incorrectly treated empty allowed_users as “allow everyone” on Telegram, bypassing the policy entirely. Fixed in PR #1885. Discord and Slack were already correct.

Startup warnings

An empty allowed_users triggers a policy-aware warning at gateway start and on hot-reload. Grep these exact strings in your logs:
If you see the deny warning and expected messages to flow through, your config is secure-by-default and DMs are intentionally dropped. Add IDs to allowed_users, or set unknown_user_policy: pair (with owner_user_id) or allow.
As of PR #1791, gateway-mode bots enforce the same security pipeline as standalone bots (praisonai bot start). Previous versions silently bypassed allowed_users, pairing, and group_policy in gateway mode.
Pair with unknown_user_policy: "deny" for the most secure default. To intentionally allow everyone (e.g. internal staging), leave allowed_users empty and set unknown_user_policy: "allow" — both are required.

Interactive presentations (optional)

GatewayMessage carries an optional presentation: MessagePresentation field. When set, channel adapters that implement SupportsPresentation render it as a native widget (Telegram inline keyboard, Slack Block Kit, Discord components). Channels that do not implement the protocol fall back to the message’s plain-text content. See Interactive Bot Messages for the full presentation model.

Hot-Reload

Editing gateway.yaml while the gateway runs triggers a diff-driven reload — only affected agents or channels restart. The WebSocket server stays up. See Gateway Hot-Reload for the full restart-scope table.

CLI Commands

Python Usage

from_config_file() automatically resolves ${ENV_VAR} syntax in your YAML, creates agents with tools, and configures channel bots.
The gateway exposes a health endpoint at http://host:port/health:
Returns:
The push section is only included when push notifications are enabled.
The gateway calls _create_bot() to build independent clones for each channel:Each clone has fresh locks and interrupt controllers, preventing cross-channel interference. Learn more about Agent Cloning.
You can still run a single bot without the gateway:
This starts just one bot connected to a single agent — no gateway needed.
Never commit bot tokens to version control. Always use environment variables or a .env file.

BotOS Options

When creating a BotOS instance in Python, the following options control gateway-level behaviour:

Observability

Gateway Metrics

Scrape GET /metrics for Prometheus-format counters and gauges on every hop of the message flow — no extra dependencies.

Correlation IDs

One stable id joins ingress, session, and agent-run logs for every turn. Read it inside any tool with current_correlation_id().

Gateway Tracing Hook

Open a distributed-tracing span around each pipeline stage — inbound, admit, agent.run, llm.call, tool.call, outbox.enqueue, delivery.

Code-Skew Guard

After running git pull or pip install -U, the gateway’s /model command detects that the installed code version has changed and blocks the model switch with a “restart required” message. This prevents the model from changing when the running code is out of sync with the installed libraries. To opt out (useful in development):
Helpers for custom tooling:

Best Practices

Leave allowed_users empty only with unknown_user_policy: "deny" for production. Pairing mode is fine for personal bots; public gateways need explicit allowlists.
Map dm, group, and default to different agents when support and personal assistants should not share memory or tools. Isolated clones prevent cross-channel leakage.
Reference tokens as ${TELEGRAM_BOT_TOKEN} in YAML — never commit secrets. Gateway resolves env vars at load time on all platforms including Windows.
Poll the health endpoint during deploys and wire Gateway Metrics into Prometheus for message-flow visibility.
/undo in a bot chat reverts files in that chat’s workspace, not the gateway process cwd. This happens automatically — apply_bot_smart_defaults() calls Agent.set_snapshot_root(workspace.root) after attaching the Workspace. See File Snapshot → Bot / Gateway Workspaces.

Bind-Aware Auth

Token auth plus the bind-aware loopback bypass (permissive on loopback by default) for gateway operational endpoints.

Gateway Error Handling

Supervision, restarts, and error recovery in the gateway.

Gateway Metrics

Prometheus-format message-flow metrics from GET /metrics.

Correlation IDs

Join ingress, session, and agent-run logs on one stable id per message.

Restart Continuation

Re-drive interrupted turns and notify the originating channel after a restart.