Messaging Bots
Deploy AI agents to Telegram, Discord, Slack, and WhatsApp
Messaging Bots enable your AI agents to interact with users across Telegram, Discord, Slack, WhatsApp, and Linear.
from praisonaiagents import Agent
agent = Agent(name="messaging-bot", instructions="Handle messages on Telegram, Slack, and Discord.")
agent.start("Reply to the user's greeting with a helpful welcome message.")The user messages the bot on their preferred channel; the same agent logic handles the conversation.
Quick Start
CLI (No Code)
Start a bot with a single command – no Python code required:
- Set Environment Variables
bash # Telegram export TELEGRAM_BOT_TOKEN="123456:ABC-DEF..." # Discord export DISCORD_BOT_TOKEN="MTIz..." # Slack (requires both tokens) export SLACK_BOT_TOKEN="xoxb-..." export SLACK_APP_TOKEN="xapp-..." # WhatsApp (Cloud API) export WHATSAPP_ACCESS_TOKEN="EAAx..." export WHATSAPP_PHONE_NUMBER_ID="123456789" export WHATSAPP_VERIFY_TOKEN="my-secret-verify" # Linear (OAuth token or API key) export LINEAR_OAUTH_TOKEN="your-linear-oauth-token" export LINEAR_WEBHOOK_SECRET="your-webhook-secret" - Start the Bot
bash # Telegram praisonai bot telegram --token $TELEGRAM_BOT_TOKEN # Discord praisonai bot discord --token $DISCORD_BOT_TOKEN # Slack praisonai bot slack --token $SLACK_BOT_TOKEN --app-token $SLACK_APP_TOKEN # WhatsApp Cloud API (starts a webhook server on port 8080) praisonai bot whatsapp --token $WHATSAPP_ACCESS_TOKEN --phone-id $WHATSAPP_PHONE_NUMBER_ID # WhatsApp Web Mode (no tokens needed β scan QR code) praisonai bot whatsapp --mode web # Linear (AgentSession webhooks) praisonai bot linear --token $LINEAR_OAUTH_TOKEN --signing-secret $LINEAR_WEBHOOK_SECRET # Email Bot praisonai bot email --address bot@gmail.com --password "xxxx xxxx xxxx xxxx" # AgentMail Bot (API-first, no IMAP/SMTP) praisonai bot agentmail --token $AGENTMAIL_API_KEYA default agent is created automatically with basic assistant capabilities.
- (Optional) Custom Agent
bash # Use a custom agent configuration praisonai bot slack --token $SLACK_BOT_TOKEN --app-token $SLACK_APP_TOKEN --agent agents.yamlagents.yaml:
yaml name: support-bot instructions: | You are a customer support assistant. Be helpful and concise. llm: gpt-4o-mini tools: - search_web
Python SDK
Full programmatic control with Python:
- Create Agent
python from praisonaiagents import Agent agent = Agent( name="assistant", instructions="Help users with their questions", llm="gpt-4o-mini" ) - Configure Bot
python from praisonaiagents import BotConfig config = BotConfig( token="your-bot-token", command_prefix="/", typing_indicator=True, # renews every 4s reply_in_thread=False, # Inline replies ) - Start Bot
python from praisonai.bots import SlackBot # or TelegramBot, DiscordBot bot = SlackBot( token="xoxb-...", app_token="xapp-...", agent=agent, config=config ) # Run the bot import asyncio asyncio.run(bot.start()) - Linear Bot Example
python from praisonai.bots import LinearBot bot = LinearBot( token="your-linear-oauth-token", signing_secret="your-webhook-secret", agent=agent, webhook_port=8080 ) asyncio.run(bot.start()) - Email Bot Example
python from praisonai.bots import EmailBot bot = EmailBot( address="bot@gmail.com", password="xxxx xxxx xxxx xxxx", agent=agent ) asyncio.run(bot.start())
Supported Platforms
Bot Runtimes (Bidirectional β Send + Receive)
| Bot Class | Platform | Env Variable | Status |
|---|---|---|---|
SlackBot | Slack | SLACK_BOT_TOKEN, SLACK_APP_TOKEN | β |
DiscordBot | Discord | DISCORD_BOT_TOKEN | β |
TelegramBot | Telegram | TELEGRAM_BOT_TOKEN | β |
WhatsAppBot | WhatsApp Business | WHATSAPP_ACCESS_TOKEN, WHATSAPP_PHONE_NUMBER_ID | β |
LinearBot | Linear (AgentSession webhooks) | LINEAR_OAUTH_TOKEN (or LINEAR_API_KEY), LINEAR_WEBHOOK_SECRET | β |
EmailBot | Email (IMAP/SMTP) | EMAIL_ADDRESS, EMAIL_APP_PASSWORD | β |
AgentMailBot | AgentMail (API) | AGENTMAIL_API_KEY | β |
Outbound Tools (Send-Only β Bot Runtime Coming Soon)
| Tool | Platform | Env Variable | Bot Runtime |
|---|---|---|---|
SignalTool | Signal | Requires signal-cli daemon | π Coming Soon |
LineTool | LINE | LINE_CHANNEL_ACCESS_TOKEN | π Coming Soon |
iMessageTool | iMessage (macOS only) | No token needed | π Coming Soon |
TwilioTool | SMS/Voice | TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN | π Coming Soon |
WebexTool | Webex | WEBEX_ACCESS_TOKEN | π Coming Soon |
XTool | X (Twitter) | X_API_KEY, X_API_SECRET | π Coming Soon |
Durable Outbound Delivery β All Channels
Configure outbound resilience via config.outbound_resilience β the same config block applies to every adapter:
from praisonaiagents import Agent
from praisonai.bots import Bot
agent = Agent(name="assistant", instructions="Help users")
bot = Bot(
"slack",
agent=agent,
config={
"outbound_resilience": {
"max_attempts": 5,
"dlq_path": "~/.praisonai/state/outbound-dlq.json",
}
},
)
bot.run()Without a dlq_path, the adapter retries but never silently drops β it raises after exhausting attempts. With a dlq_path, a permanent failure parks the message to disk for manual inspection or replay.
Full reference: retry config, DLQ, drain-on-restart, and per-adapter _outbound_platform labels
Inbound Media β Vision
Both WhatsApp and Telegram bots forward photos and documents directly to your agent’s vision capability. On Telegram, a media album is coalesced into a single turn β see Media Albums.
from praisonaiagents import Agent
from praisonai.bots import TelegramBot
agent = Agent(
name="vision-bot",
instructions="Describe and answer questions about images and documents.",
llm="gpt-4o",
)
bot = TelegramBot(token="your-telegram-bot-token", agent=agent)
import asyncio
asyncio.run(bot.start())Send the bot a photo with or without a caption β the agent sees the image directly.
WhatsApp Inbound MediaWhatsApp-specific details: Graph API download, security pipeline, and max_inbound_media_bytes config
Full reference: security pipeline, SSRF guard, size limits, and common patterns
Outbound Media DeliverySend agent-generated images, charts, and files via native platform uploads
How It Works
| Component | Role |
|---|---|
| Platform | Telegram, Discord, Slack, or WhatsApp |
| Bot | Message router and formatter |
| Agent | AI processing and response |
| User | End user on messaging app |
Wiring Button Clicks
Buttons and select menus rendered by your bot can be wired to your own async handlers β slash-command buttons work out of the box, and you can register custom namespaces for things like approvals, menus, or multi-step flows.
Agents can also run a group vote with a poll block and get the aggregated tally back as a typed PollResult β see Poll Blocks.
AIUI Dashboard Integration
When bots are connected through PraisonAI UI (praisonai chat), channel messages appear in the Chat dashboard with full visibility into agent processing steps β tool calls, reasoning, and intermediate responses stream in real-time.
What You See in the Dashboard
| Feature | Description |
|---|---|
| Tool call steps | Each tool the agent uses appears as a collapsible step with icon, description, and result |
| Reasoning steps | Chain-of-thought reasoning streams in real-time |
| Platform icon | Session sidebar shows the platform badge (e.g. π¬ Slack, βοΈ Telegram) |
| Message history | All channel messages and responses are persisted and replayable |
Smart Defaults
Bots ship with sensible defaults so you can start chatting immediately β no tool wiring required.
Both praisonai bot start and praisonai gateway start apply the same defaults:
| Default | Applied when | What you get |
|---|---|---|
| Safe tools | Agent has no tools configured | search_web, web_crawl, schedule_*, store_memory/search_memory, store_learning/search_learning |
| Auto-approval | auto_approve_tools=True (default) | Tool calls run without CLI prompts β chat bots can’t show them anyway |
| Session history | Agent has no memory configured | Last 20 messages remembered per user, zero-dep |
Opting out
| Goal | How |
|---|---|
| Run with zero tools | Set tools: [] explicitly in YAML, or pass tools=[] to Agent |
| Require manual approval | Set auto_approve_tools: false in the channel config |
| Override the tool list | Set default_tools: [...] under the channel β destructive tools are still filtered |
from praisonaiagents import Agent
from praisonai.bots import Bot
# Zero config β gets search_web, schedule_*, memory, learning, and auto-approval
agent = Agent(name="assistant", instructions="Help the user")
bot = Bot("telegram", agent=agent)
bot.run()# Same result β no YAML tool list needed
praisonai bot telegram --token $TELEGRAM_BOT_TOKENPlatform Awareness
Every bot automatically tells the agent which platform it’s on, what kind of chat it’s in, and which channels it can reach.
Socket Mode vs Webhook
PraisonAI bots support two connection modes:
| Mode | Use Case | Requirements |
|---|---|---|
| Socket Mode | Local development, behind firewall | App Token only |
| Webhook Mode | Production, high scale | Public URL with HTTPS |
Configuration Options
from praisonaiagents import BotConfig
config = BotConfig(
token="bot-token", # Bot authentication token
webhook_url=None, # Webhook URL (optional)
command_prefix="/", # Command prefix
mention_required=True, # Require @mention in groups
typing_indicator=True, # Show typing indicator
max_message_length=4096, # Max message length
allowed_users=[], # Empty list β unknown_user_policy decides (default deny; every drop now logs a WARNING β PR #5112)
allowed_channels=[], # Allowed channel IDs
reply_in_thread=False, # Reply in threads (default: inline)
thread_threshold=500, # Auto-thread if response > N chars (0 = disabled)
group_policy="mention_only", # Group chat policy: respond_all, mention_only (reply-to-bot counts), command_only, observe
allow_silence=True, # Agent may return NO_REPLY to stay silent
auto_approve_tools=True, # Auto-approve safe tool executions (default: True for chat bots)
unknown_user_policy="pair", # "deny" (default) | "pair" | "allow"
owner_user_id="123456789", # Platform-specific owner ID (Telegram numeric, Discord snowflake, Slack U-id)
)Running from YAML with praisonai bot start? The same admission options apply in a single-bot bot.yaml (PR #5111):
# bot.yaml
platform: telegram
token: ${TELEGRAM_BOT_TOKEN}
unknown_user_policy: pair # deny (default) | pair | allow
owner_user_id: 987654321 # required when unknown_user_policy: pair
agent:
name: Assistant
instructions: Reply to incoming messages.See Standalone Bot YAML β Admission policy for the resolved-policy startup banner and fail-closed validation.
| Option | Type | Default | Description | |
|---|---|---|---|---|
token | str | "" | Bot authentication token | |
webhook_url | str | None | Webhook URL for webhook mode | |
command_prefix | str | "/" | Prefix for bot commands | |
mention_required | bool | True | Require @mention in channels (DMs never require mention) | |
typing_indicator | bool | True | Show typing indicator. On Telegram, the indicator is renewed every 4 seconds for the entire duration of the agent run so users keep seeing “typing⦔ even during 20β30s RAG / tool-call operations. | |
max_message_length | int | 4096 | Max message length | |
allowed_users | list | [] | Allowed user IDs. Empty list now defers to unknown_user_policy (deny / pair / allow). Earlier releases treated empty as “allow everyone” on Telegram β fixed in PR #1885. | |
allowed_channels | list | [] | Allowed channel IDs | |
timeout | int | 30 | Request timeout | |
reply_in_thread | bool | False | Always reply in threads | |
thread_threshold | int | 500 | Auto-thread responses longer than N chars (0 = disabled) | |
group_policy | str | "mention_only" | Group chat behavior: respond_all, mention_only, command_only, or observe (records unmentioned messages as passive context on Telegram, Discord and Slack) | |
allow_silence | bool | false | When true, agent may return NO_REPLY to send nothing. See Intentional Silence. | |
silence_token | str | None | Custom silence marker (default: NO_REPLY) | |
allow_bots | bool | false | Opt-in for bot-authored inbound messages. Default-off drops every bot-authored inbound turn (byte-for-byte compatible with pre-#5242 behaviour). When true, the BotLoopGuard auto-breaks a runaway AβB loop using bot_loop_protection. See Bot Loop Protection. | |
bot_loop_protection | `dict \ | None` | None | Sliding-window pair-budget policy that auto-breaks a runaway AβB reply loop once allow_bots: true. Keys: enabled, max_events_per_window, window_seconds, cooldown_seconds. See Bot Loop Protection. |
default_tools | list[str] | ["search_web", "web_crawl", "schedule_add", "schedule_list", "schedule_remove", "store_memory", "search_memory", "store_learning", "search_learning"] | Safe tools auto-injected when the agent has no tools configured. Destructive tools (execute_command, delete_file, write_file, shell_command) are excluded from auto-injection even if listed. | |
auto_approve_tools | bool | True | Skip confirmation for safe tool execution. Chat bots can’t show CLI approval prompts, so this defaults to True. Set False to require approval (only useful if you wire a chat-level approval flow). | |
unknown_user_policy | Literal["deny","pair","allow"] | "deny" | How to handle messages from users not in allowed_users. deny silently drops, pair runs the owner-approval flow, allow lets everyone through. With an empty allowed_users, every user is “unknown” and this policy applies to all of them. Readable from gateway.yaml per-channel β see Bot Gateway β Channel Security. Also honoured from a single-bot bot.yaml via praisonai bot start (PR #5111) β see Standalone Bot YAML β Admission policy. | |
owner_user_id | Optional[str] | None | Platform-specific ID of the bot owner. Required for inline-button approvals β without it, "pair" policy falls back to a plain-text CLI instruction. Readable from gateway.yaml per-channel β see Bot Gateway β Channel Security. | |
retry_attempts | int | 3 | Number of retry attempts for failed operations | |
polling_interval | float | 1.0 | Interval for polling mode (seconds) |
Access-check methods
BotConfig exposes two allowlist checks with distinct purposes:
| Method | Returns | Purpose |
|---|---|---|
is_user_allowed(user_id) | bool | Runtime pass/fail β respects unknown_user_policy. Empty allowed_users defers to the policy. |
is_explicitly_allowed(user_id) | bool | Pre-policy check β True only if user_id is on a non-empty allowed_users. Never consults unknown_user_policy. Use it to decide whether to run the pairing flow. |
from praisonaiagents.bots import BotConfig
config = BotConfig(allowed_users=["telegram:123456"])
config.is_explicitly_allowed("telegram:123456") # True β on the allowlist
config.is_explicitly_allowed("telegram:99999") # False β policy decides nextCLI Capabilities
Enable powerful agent features directly from the command line:
praisonai bot slack --memoryBot remembers previous conversations
Knowledge/RAGpraisonai bot slack --knowledge \
--knowledge-sources docs.pdf manual.txtAnswer from your documents
Skillspraisonai bot slack --skills researcher writerLoad named skill modules
Extended Thinkingpraisonai bot slack --thinking highEnable reflection mode (off/minimal/low/medium/high)
Full CLI Options Reference
| Flag | Description | Example |
|---|---|---|
--memory | Enable conversation memory | --memory |
--memory-provider | Memory backend | --memory-provider chroma |
--knowledge | Enable RAG/knowledge | --knowledge |
--knowledge-sources | Source files | --knowledge-sources file.pdf |
--skills | Skill modules | --skills researcher |
--thinking | Thinking mode | --thinking high |
--web | Enable web search | --web |
--web-provider | Search provider | --web-provider duckduckgo |
--browser | Enable browser | --browser |
--tools | Named tools | --tools WikipediaTool |
--sandbox | Sandbox mode | --sandbox |
--auto-approve | Auto-approve tool executions | --auto-approve |
Platform Setup
Telegram
- Message @BotFather on Telegram
- Send
/newbotand follow prompts - Copy the bot token
export TELEGRAM_BOT_TOKEN="123456:ABC-DEF..."
praisonai bot telegram --token $TELEGRAM_BOT_TOKENTroubleshooting: Bot silently stops replying / 409 Conflict
Symptom. The bot starts, then messages stop being answered. Logs show:
[telegram] Another process is already polling this token
(only one instance per token is allowed).
Stop the other bot/gateway/UI-channel instance first.Cause. A second poller (CLI, gateway telegram channel, Claw, or an orphaned process) is using the same token. Telegram’s getUpdates API allows only one active consumer per bot token, so every extra poller receives HTTP 409 Conflict.
Fix.
- Find and stop duplicate processes:
ps aux | grep -i praisonai | grep -v grep, then `kill
`.
- Confirm no webhook is set:
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/getWebhookInfo". - Restart exactly one bot.
Prevent it: use one token per environment, prefer webhook mode in production, and never run the CLI and Claw Channels against the same token. See the Bot CLI 409 troubleshooting for a Windows recovery procedure too.
Discord
- Go to Discord Developer Portal
- Create new application β Bot β Reset Token
- Enable Message Content Intent
- Invite bot to server with proper permissions
export DISCORD_BOT_TOKEN="MTIz..."
praisonai bot discord --token $DISCORD_BOT_TOKENSlack
- Create Slack App
- Go to Slack API Console
- Click Create New App β From scratch
- Enter app name (e.g., “PraisonAI Bot”) and select workspace
- Configure OAuth & Permissions
- Go to OAuth & Permissions in the sidebar
- Scroll to Scopes β Bot Token Scopes
- Add these scopes:
Scope Purpose chat:writeSend messages app_mentions:readReceive @mentions im:historyRead DM history im:readAccess DMs channels:historyRead channel messages - Click Install to Workspace at the top
- Copy the Bot User OAuth Token (
xoxb-...)
- Enable Socket Mode
- Go to Socket Mode in the sidebar
- Toggle Enable Socket Mode ON
- When prompted, create an app-level token:
- Token Name:
socket-mode - Add scope:
connections:write - Copy the App Token (
xapp-...)
- Subscribe to Events
- Go to Event Subscriptions in the sidebar
- Toggle Enable Events ON
- Scroll to Subscribe to bot events
- Add these events:
Event Purpose app_mentionWhen someone @mentions your bot message.imDirect messages to your bot - Click Save Changes
- Reinstall the app when prompted (or go to OAuth & Permissions β Reinstall)
- Enable Messages Tab
- Go to App Home in the sidebar
- Scroll to Show Tabs β Messages Tab
- Ensure Allow users to send Slash commands and messages from the messages tab is toggled ON
- Start the Bot
bash export SLACK_BOT_TOKEN="xoxb-..." # Bot User OAuth Token export SLACK_APP_TOKEN="xapp-..." # App-Level Token praisonai bot slack --token $SLACK_BOT_TOKEN --app-token $SLACK_APP_TOKENYou should see:
β‘οΈ Bolt app is running! - Test the Bot
- Direct Message: Send a DM to your bot
- Channel Mention: In any channel, type
/invite @YourBotNamefirst, then@YourBotName hello
Troubleshooting: Bot not responding
Check these in order:
- Event Subscriptions enabled? β Must be ON
- Bot events subscribed? β
app_mentionandmessage.immust be listed - Reinstalled after changes? β Required after adding scopes/events
- App Token provided? β required β the CLI now fails fast if
--app-token/SLACK_APP_TOKENis missing:
Error: Slack app token required (Socket Mode)
Provide via --app-token or SLACK_APP_TOKEN environment variable
Create one at https://api.slack.com/apps -> Basic Information
-> App-Level Tokens (scope: connections:write)- Bot invited to channel? β Use
/invite @BotNamebefore @mentioning
Required Scopes Summary
| Scope | Required For |
|---|---|
chat:write | Sending messages |
app_mentions:read | @mention events |
im:history | DM access |
im:read | DM access |
channels:history | Channel message access |
connections:write | Socket Mode (app token) |
- Create Meta App
- Go to Meta for Developers
- Click Create App β Select Business type
- Add the WhatsApp product to your app
- Get API Credentials
- In the WhatsApp section, go to API Setup
- Copy your Phone Number ID and Access Token
- Create a Verify Token (any secret string you choose)
- Configure Webhook
- Go to Configuration β Webhook
- Click Edit and enter:
- Callback URL:
https://your-domain.com/webhook - Verify Token: The same string you set in
WHATSAPP_VERIFY_TOKEN - Subscribe to:
messages
- Start the Bot
bash export WHATSAPP_ACCESS_TOKEN="EAAx..." export WHATSAPP_PHONE_NUMBER_ID="123456789" export WHATSAPP_VERIFY_TOKEN="my-secret-verify" praisonai bot whatsapp --token $WHATSAPP_ACCESS_TOKEN --phone-id $WHATSAPP_PHONE_NUMBER_IDYou should see:
WhatsApp webhook server starting on port 8080 - Test the Bot
Send a WhatsApp message to your business phone number. The bot will reply via the Cloud API.
Troubleshooting: Webhook not verifying
- Verify token matches? β Must be identical in Meta console and env var
- Bot running? β Webhook server must be up before configuring in Meta
- HTTPS required? β Meta only accepts HTTPS webhook URLs
- ngrok running? β If using ngrok, ensure the tunnel is active
WhatsApp API Limits
| Tier | Messages/day | Requirement |
|---|---|---|
| Test | 1,000 | Default for new apps |
| Business | 10,000+ | Verified business account |
| Unlimited | No limit | Meta approval required |
WhatsApp Web Mode
WhatsApp Web mode connects directly via the WhatsApp Web protocol β no tokens, no Meta developer account, no webhooks needed. Just scan a QR code.
- Install Dependencies
bash pip install 'praisonai[bot-whatsapp-web]'This installs
neonize(WhatsApp Web client with built-in QR display). - Start the Bot
bash praisonai bot whatsapp --mode webA QR code appears in your terminal. Open WhatsApp on your phone β Settings β Linked Devices β Link a Device β scan the QR code.
- Send a Message
Send any message to the linked WhatsApp number from another phone. The bot will reply using your AI agent.
Your session is saved locally β on restart, the bot reconnects automatically without scanning again.
CLI
# Basic web mode
praisonai bot whatsapp --mode web
# With custom credentials directory
praisonai bot whatsapp --mode web --creds-dir ~/.myapp/wa-creds
# With agent capabilities
praisonai bot whatsapp --mode web --agent agents.yaml --memory --webPython
from praisonaiagents import Agent
from praisonai.bots import WhatsAppBot
agent = Agent(name="assistant", instructions="Be helpful")
# Web mode β no tokens needed
bot = WhatsAppBot(mode="web", agent=agent)
import asyncio
asyncio.run(bot.start()) # Shows QR β scan β runningYAML
# whatsapp-web-bot.yaml
platform: whatsapp
mode: web
agent:
name: "WhatsApp Assistant"
instructions: "You are a helpful AI assistant."
llm: "gpt-4o-mini"
memory: truepraisonai bot start --config whatsapp-web-bot.yamlLive Streaming Replies
Interactive UI. Telegram, Slack, and Discord channels support inline buttons, dropdown menus, and structured message blocks via MessagePresentation. Agents return a MessagePresentation and the channel adapter renders it as a native widget. WhatsApp uses plain-text fallback.
Channel bots can show live draft replies that update in real-time as your agent thinks β enable with --stream, streaming: true in YAML, or BotConfig(streaming=True). Telegram, Slack, and Discord support live edits; WhatsApp and Email send a single final message.
praisonai bot telegram --token $TELEGRAM_BOT_TOKEN --streamfrom praisonaiagents import BotConfig
from praisonai.bots import TelegramBot
bot = TelegramBot(
token="...",
agent=agent,
config=BotConfig(streaming=True, stream_edit_interval_ms=700),
)
bot.start()For progress mode, custom placeholders, or fine-grained tuning, see the advanced StreamingConfig API on the dedicated page. Public/support bots can also enable the privacy-safe activity surface so progress shows a curated phrase (Searching the webβ¦) instead of the raw tool name.
Complete guide to streaming reply configuration and best practices
Cloud API vs Web Mode
| Feature | Cloud API (default) | Web Mode (experimental) |
|---|---|---|
| Setup | Meta developer account + tokens | QR code scan only |
| Auth | WHATSAPP_ACCESS_TOKEN | Saved locally (SQLite) |
| Webhooks | Required (public HTTPS URL) | Not needed |
| Group chats | DMs only | DMs + groups |
| Reactions | Limited | Full support |
| Media | Via upload API | Direct |
| Stability | Official API, stable | Reverse-engineered, may break |
| Risk | None | Account may be banned |
| Best for | Production | Development, personal use |
Troubleshooting: QR code not showing
- Terminal supports Unicode? β Use a modern terminal (iTerm2, Windows Terminal, etc.)
- Dependencies installed? β Run
pip install 'praisonai[bot-whatsapp-web]'β this includessegnofor QR rendering - Already linked? β If a saved session exists, no QR is shown. Delete creds to re-link:
rm -rf ~/.praisonai/whatsapp/- QR times out? β WhatsApp QR codes expire after ~60 seconds. Restart the bot to get a fresh one.
Troubleshooting: Session expired
WhatsApp Web sessions expire if your phone is offline for 14+ days. Delete the saved session and scan again:
rm -rf ~/.praisonai/whatsapp/
praisonai bot whatsapp --mode webWhere are credentials stored?
By default: ~/.praisonai/whatsapp/praisonai_whatsapp.db (SQLite).
Override with --creds-dir or WHATSAPP_CREDS_DIR environment variable.
Bot Commands
Built-in commands available on all platforms:
| Command | Description |
|---|---|
/help | Show available commands and agent info |
/status | Show agent name, model, platform, and uptime |
/new | Reset conversation session β starts a fresh chat, also clearing any per-user /model override (works alongside automatic session reset policies) |
You can register custom commands programmatically:
bot.register_command("ping", my_handler, description="Check latency")Common Patterns
Restricted Access
from praisonaiagents import BotConfig
config = BotConfig(
token="your-token",
allowed_users=["user123", "user456"],
allowed_channels=["channel789"]
)Webhook Mode
from praisonaiagents import BotConfig
config = BotConfig(
token="your-token",
webhook_url="https://your-domain.com/webhook",
webhook_path="/telegram/webhook"
)Group Settings
from praisonaiagents import BotConfig
config = BotConfig(
token="your-token",
mention_required=True, # Only respond when @mentioned
command_prefix="!", # Use ! for commands
)CLI Commands
# Start Telegram bot
praisonai bot telegram --token $TOKEN
# Start Discord bot
praisonai bot discord --token $TOKEN
# Start Slack bot
praisonai bot slack --token $TOKEN --app-token $APP_TOKEN
# Start WhatsApp bot (webhook server)
praisonai bot whatsapp --token $TOKEN --phone-id $PHONE_ID --verify-token $VERIFY
# With agent configuration
praisonai bot telegram --token $TOKEN --agent agents.yamlWhatsApp Message Filtering (Web Mode)
By default, WhatsApp Web mode responds only to self-chat messages β when you message your own number. This prevents the bot from replying to every conversation on your account, including messages you send in other people’s chats.
CLI Flags
Self-Only (Default)
# Only responds when YOU message yourself
praisonai bot whatsapp --mode webAllowed Numbers
# Also respond to specific phone numbers
praisonai bot whatsapp --mode web --respond-to 1234567890,9876543210Allowed Groups
# Also respond in specific groups
praisonai bot whatsapp --mode web --respond-to-groups 120363123456@g.usCombined
# Specific numbers AND groups
praisonai bot whatsapp --mode web \
--respond-to 1234567890 \
--respond-to-groups 120363123456@g.usRespond to All
# Respond to every message (old behavior)
praisonai bot whatsapp --mode web --respond-to-allPython SDK
from praisonaiagents import Agent
from praisonai.bots import WhatsAppBot
agent = Agent(name="assistant", instructions="You are a helpful bot")
bot = WhatsAppBot(
mode="web",
agent=agent,
allowed_numbers=["1234567890", "9876543210"],
allowed_groups=["120363123456@g.us"],
respond_to_all=False, # default
)
import asyncio
asyncio.run(bot.start())YAML Config
platform: whatsapp
mode: web
respond_to:
- "1234567890"
- "9876543210"
respond_to_groups:
- "120363123456@g.us"
respond_to_all: false
agent:
name: "My Assistant"
instructions: "You are a helpful AI assistant."
llm: "gpt-4o-mini"praisonai bot start --config bot.yamlFiltering Behavior Matrix
| Scenario | Default | --respond-to 123 | --respond-to-groups g@g.us | --respond-to-all |
|---|---|---|---|---|
| Self-chat (message your own number) | β | β | β | β |
| Your message in someone else’s chat | β | β | β | β |
| DM from 123 | β | β | β | β |
| DM from 999 | β | β | β | β |
| Group g@g.us | β | β | β | β |
| Other group | β | β | β | β |
| Old/offline messages | β | β | β | β |
Docker Deployment
Deploy bots using Docker for production environments:
Slack
# Create .env file
cat > .env << EOF
OPENAI_API_KEY=$OPENAI_API_KEY
SLACK_BOT_TOKEN=$SLACK_BOT_TOKEN
SLACK_APP_TOKEN=$SLACK_APP_TOKEN
EOF
# Run with docker compose
docker compose up slack-bot -d
# View logs
docker compose logs -f slack-botDiscord
# Create .env file
cat > .env << EOF
OPENAI_API_KEY=$OPENAI_API_KEY
DISCORD_BOT_TOKEN=$DISCORD_BOT_TOKEN
EOF
# Run with docker compose
docker compose up discord-bot -dTelegram
# Create .env file
cat > .env << EOF
OPENAI_API_KEY=$OPENAI_API_KEY
TELEGRAM_BOT_TOKEN=$TELEGRAM_BOT_TOKEN
EOF
# Run with docker compose
docker compose up telegram-bot -ddocker-compose.yml:
version: '3.8'
services:
slack-bot:
image: python:3.11-slim
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY}
SLACK_BOT_TOKEN: ${SLACK_BOT_TOKEN}
SLACK_APP_TOKEN: ${SLACK_APP_TOKEN}
command: >
bash -c "pip install praisonai slack-bolt slack-sdk &&
praisonai bot slack"
restart: unless-stoppedProduction (Webhook Mode)
For production deployments with a public URL, use webhook mode instead of Socket Mode:
Slack
from praisonaiagents import BotConfig
from praisonai.bots import SlackBot
config = BotConfig(
token="xoxb-your-slack-bot-token",
webhook_url="https://your-domain.com",
webhook_path="/slack/events"
)
bot = SlackBot(config=config)
bot.start() # Listens on /slack/eventsConfigure in Slack API Console:
- Event Subscriptions β Enable Events
- Set Request URL:
https://your-domain.com/slack/events - Subscribe to bot events:
app_mention,message.im
Discord
from praisonaiagents import BotConfig
from praisonai.bots import DiscordBot
# Discord uses Gateway (WebSocket) by default
# For HTTP interactions, configure interaction endpoint:
config = BotConfig(
token="your-discord-bot-token",
webhook_url="https://your-domain.com",
webhook_path="/discord/interactions"
)
bot = DiscordBot(config=config)
bot.start()Configure in Discord Developer Portal:
- General Information β Interactions Endpoint URL
- Set:
https://your-domain.com/discord/interactions
Telegram
from praisonaiagents import BotConfig
from praisonai.bots import TelegramBot
config = BotConfig(
token="your-telegram-bot-token",
webhook_url="https://your-domain.com",
webhook_path="/telegram/webhook"
)
bot = TelegramBot(config=config)
bot.start() # Automatically registers webhook with TelegramTelegram automatically configures the webhook when you start the bot.
Multi-Channel Gateway
Run all bots simultaneously with a single gateway config:
gateway.yaml:
agents:
personal:
name: "Personal Assistant"
instructions: "You are a helpful personal assistant."
llm: "gpt-4o-mini"
support:
name: "Support Agent"
instructions: "You are a customer support agent."
llm: "gpt-4o-mini"
channels:
telegram:
token: "${TELEGRAM_BOT_TOKEN}"
session:
max_history: 100
reset:
mode: idle
idle_minutes: 60
compaction:
enabled: true
strategy: summarize
keep_recent: 10
routing:
dm: "personal"
group: "support"
default: "personal"
discord:
token: "${DISCORD_BOT_TOKEN}"
routing:
dm: "personal"
channel: "support"
default: "support"
slack:
token: "${SLACK_BOT_TOKEN}"
app_token: "${SLACK_APP_TOKEN}"
auto_approve_tools: true # NEW (default: true for chat bots)
# default_tools: # NEW β override the safe tool list per channel
# - search_web
# - store_memory
routing:
dm: "personal"
channel: "support"
default: "support"
whatsapp:
token: "${WHATSAPP_ACCESS_TOKEN}"
phone_number_id: "${WHATSAPP_PHONE_NUMBER_ID}"
verify_token: "${WHATSAPP_VERIFY_TOKEN}"
webhook_port: 8080 # opt-out: standalone server. Leave unset to share the gateway URL at /webhooks/whatsapp
routing:
dm: "personal"
default: "personal"
# Or use WhatsApp Web mode (no tokens needed):
# whatsapp:
# mode: web
# routing:
# dm: "personal"
# default: "personal"Channel key vs platform β in gateway.yaml, the YAML key under channels: (e.g. telegram, telegram_cfo) is just an identifier you choose. When the key is not a platform name, set platform: telegram (or whichever) inside the block so the gateway can pick the right protocol. This enables running multiple bots on the same platform. Note: bot.yaml requires channel keys to be platform names.
praisonai gateway --config gateway.yamlThe gateway now produces identical results to Bot() β agents get the same safe tools and auto-approval in both entry points.
Multiple bots on the same platform
For role-specific bots on the same platform (e.g., multiple Telegram bots), use this pattern:
agents:
cfo:
instructions: "You are a CFO agent specialized in financial analysis and budget planning."
model: gpt-4o-mini
ops:
instructions: "You are an ops agent specialized in system monitoring and infrastructure."
model: gpt-4o-mini
channels:
telegram_cfo:
platform: telegram
token: ${TELEGRAM_CFO_BOT_TOKEN}
routes:
default: cfo
telegram_ops:
platform: telegram
token: ${TELEGRAM_OPS_BOT_TOKEN}
routes:
default: opsZero-Code Mode (YAML Config)
Run a bot with a single YAML file β no Python code needed:
bot.yaml:
platform: telegram
token: "${TELEGRAM_BOT_TOKEN}"
agent:
name: "My Assistant"
instructions: "You are a helpful AI assistant."
llm: "gpt-4o-mini"
memory: true
web_search: true
tools: [search_web]praisonai bot start --config bot.yamlTip: You can omit
tools:entirely β the bot auto-injects safe defaults (search_web, schedule, memory, learning). Keeptools: []only if you want the bot to run with zero tools.
Token is optional
Omit token: entirely β the declared platform: resolves the platform’s own documented env var (for example TELEGRAM_BOT_TOKEN for Telegram, DISCORD_BOT_TOKEN for Discord):
platform: telegram
agent:
name: "My Assistant"
instructions: "You are a helpful AI assistant."export TELEGRAM_BOT_TOKEN="123456:ABC-DEF..."
praisonai bot start --config bot.yamlThe declared platform wins
The platform: you declare always wins. If other platform credentials happen to be exported in the environment, bot start refuses to auto-enable them behind your back and logs a warning naming each one it skipped:
WARNING Config declares 'platform: telegram'; NOT auto-enabling discord, slack
despite their credentials being present in the environment. The declared
platform wins. To run them too, list them under 'channels:' explicitly.Inbound Platform Events (opt-in)
Add an events: list under a channel to hear reactions, edits, deletions, member changes, and thread creations β not just text.
channels:
my-discord-bot:
platform: discord
token: "${DISCORD_BOT_TOKEN}"
events: [reactions, edits, members, threads] # opt-in classesAccepted class tokens:
reactionsβREACTION_RECEIVEDeditsβMESSAGE_EDITED+MESSAGE_DELETEDmembersβMEMBER_JOINED+MEMBER_LEFT(requires the privileged Discordmembersintent)threadsβTHREAD_CREATED
Omit events: and nothing new is subscribed. Currently wired on the Discord adapter.
Full walk-through β hooks, payload fields, and platform coverage.
Registered but verb-less platforms β praisonai bot run
bot run starts any registered platform by name β including signal, webhook, local, entry-point plugin channels, and adapter: drop-ins that don’t have their own verb.
from praisonaiagents import Agent
agent = Agent(name="signal-bot", instructions="Answer messages on Signal.")
agent.start("Welcome the user when they say hi.")# Same agent, run over Signal β no Python needed
praisonai bot run --platform signal --agent agents.yaml- Local channel (REPL-style)
bash praisonai bot run --platform local - Signal via signal-cli-bridge
bash praisonai bot run --platform signal \ --account +15551234567 \ --bridge-url http://bridge:8080 \ --agent agents.yaml - Generic webhook receiver
bash praisonai bot run --platform webhook --port 8080 - Plugin / drop-in channel
bash praisonai bot run --platform my-plugin-channel --token $MY_TOKEN --my-field valueAn IRC plugin that declares
serverandnickserv_passwordis driven the same way:bash praisonai bot run --platform irc \ --server irc.libera.chat \ --nickserv-password $NICK_PW
Flags
| Flag | Description | ||||
|---|---|---|---|---|---|
--platform <name> | Registered platform to start (required) | ||||
--token <t> | Falls back to the platform’s own env var | ||||
--port <n> | For webhook-style channels | ||||
--agent <path> | Agent YAML configuration file | ||||
--model <m> | LLM model to use | ||||
--browser / --browser-profile <p> / --browser-headless | Browser control | ||||
--tools <t>... | Tools to enable | ||||
--skills <s>... / --skills-dir <path> | Skills configuration | ||||
--memory / --memory-provider <p> | Memory configuration | ||||
--knowledge / --knowledge-sources <s>... | Knowledge/RAG | ||||
--web / --web-provider <p> | Web search | ||||
--sandbox / --exec / --auto-approve | Execution controls | ||||
| `–group-policy respond_all\ | mention_only\ | command_only` | Group behavior | ||
--session-id <s> / --user-id <u> | Session and memory isolation | ||||
| `–thinking off\ | minimal\ | low\ | medium\ | high` | Thinking mode |
--<channel-field> <value> | Any field declared in the channel’s ChannelDescriptor.config_fields (e.g. Signal: --account, --bridge-url; Local: --prompt). Underscores become hyphens. Unknown flags exit 2. |
An unknown platform is rejected up front with a listing of the registered ones:
Error: Unknown platform 'foo'
Registered platforms: agentmail, discord, email, linear, local, signal, slack, telegram, webhook, whatsappChannel-declared field flags
Every field a channel declares in its ChannelDescriptor.config_fields is accepted by bot run as a --field-name flag.
from praisonaiagents import Agent
agent = Agent(name="signal-bot", instructions="Answer messages on Signal.")
agent.start("Say hello.")# Signal declares `account` and `bridge_url`
praisonai bot run --platform signal --account +15551234567 --bridge-url=http://bridge:8080- Naming β a declared field
bridge_urlbecomes--bridge-url(underscore β hyphen). - Syntax β both
--flag valueand--flag=valuework. - Validation β required fields,
envfallbacks and secrets are still handled by the adapter; a missing required field errors when the adapter is built. - Values required β every field flag takes a value; a bare
--accountfollowed by another--β¦flag exits2withOption '--account' requires a value. - Discovery β these flags are channel-specific and not listed in
--help; the unknown-flag error lists the valid set.
An undeclared flag fails loudly instead of being silently ignored:
$ praisonai bot run --platform signal --server x
Error: Invalid value: Unknown option '--server' for platform 'signal'. Channel fields: --account, --bridge-url
$ echo $?
2Which command should I use?
Bot startup exit codes
praisonai bot ... now exits 1 on any startup failure β bad config path, missing token, unknown platform, or adapter import failure:
$ praisonai bot start --config /nope.yaml
Error: Config file not found: /nope.yaml
$ echo $?
1This makes systemd Restart=on-failure and shell if praisonai bot ... ; then scripting work as expected.
Token Types β When to Use What
Different platforms use different types of tokens. Here’s when to use each:
Telegram
| Token | Format | When to Use |
|---|---|---|
| Bot Token | 123456:ABC-DEF... | Always required. Get from @BotFather. Used for all bot operations. |
Discord
| Token | Format | When to Use |
|---|---|---|
| Bot Token | MTIz... | Always required. Get from Discord Developer Portal β Bot β Reset Token. Used for bot authentication. |
Slack
| Token | Format | When to Use |
|---|---|---|
| Bot Token | xoxb-... | Always required. Get from OAuth & Permissions β Install to Workspace. Used for sending messages and API calls. |
| App Token | xapp-... | Required for Socket Mode (default) β the CLI errors out if it’s missing. Get from Basic Information β App-Level Tokens (scope: connections:write). Enables the WebSocket connection without a public URL. |
| Client ID | 12345.67890 | OAuth flow only. Used when building apps that are installed by multiple workspaces (not needed for single-workspace bots). |
| Client Secret | d119ac... | OAuth flow only. Used with Client ID for the OAuth2 authorization flow. Never expose publicly. |
Cloud API (default)
| Token | Format | When to Use |
|---|---|---|
| Access Token | EAAx... | Required. Get from Meta for Developers β WhatsApp β API Setup. Used for sending messages via Cloud API. |
| Phone Number ID | 123456789 | Required. Found in API Setup page. Identifies which WhatsApp business number to send from. |
| Verify Token | Any string | Required for webhooks. A secret string you create. Must match in both Meta console and your environment. |
| App Secret | abc123... | Optional. Used to verify webhook signatures for security. Found in App Settings β Basic. |
Web Mode (experimental)
| Token | Format | When to Use |
|---|---|---|
| None | β | No tokens needed. Web mode authenticates via QR code scan (WhatsApp Linked Devices). |
Credentials are saved locally in SQLite at ~/.praisonai/whatsapp/. Override with --creds-dir or WHATSAPP_CREDS_DIR.
Best Practices
Secure your bot token
Never commit bot tokens to version control. Use environment variables or secure secret management.
Use allowlists in production
Set allowed_users and allowed_channels to prevent unauthorized access to your bot.
Enable mention requirement for groups
Set mention_required=True to prevent the bot from responding to every message in group chats.
Handle rate limits gracefully
Outbound sends now honour the platform’s Retry-After / retry_after automatically β both on live retries (deliver_with_retry) and on durable drains (OutboundQueue). To make the limiter widen the lane for the rest of your bot’s concurrent sends, pass a shared RateLimiter into deliver_with_retry(rate_limiter=...). See Bot Rate Limiting and Durable Delivery.
Safe default tools only
The default tool list is intentionally safe (search_web, schedule_*, memory/learning). Tools like execute_command require explicit opt-in and should be paired with an approval backend. See Approval Protocol.
Set approval flow for auto-approve disabled
Only set auto_approve_tools: false if you’ve wired a chat-level approval flow (e.g. SlackApproval). Otherwise tool calls will hang silently waiting for a CLI prompt the user cannot see.
New: gateway does this for you
If you set channels.<platform>.allow_shell: true with auto_approve_shell: false, the gateway now wires SlackApproval / PresentationApprovalBackend (Telegram) / DiscordApproval automatically β no Python glue required. And auto_approve_shell: true is automatically downgraded to the same wiring on externally-bound gateways or channels with a group_policy, unless auto_approve_shell_acknowledge_exposed: true opts in. See Bot Shell Execution.
Multi-Agent Configuration
You can also define multiple agents in an agents.yaml file for complex workflows:
agents.yaml:
agents:
searcher:
name: Researcher
role: Web Researcher
goal: Search the web for relevant information on the given topic
instructions: |
Search the web thoroughly for information on the user's query.
Return comprehensive, accurate results with sources.
tools:
- search_web
summarizer:
name: Summarizer
role: Content Summarizer
goal: Create clear, concise summaries of information
instructions: |
Take the research findings and create a well-structured summary.
Highlight key points and insights.
Keep it concise but informative.Inbound Message Debounce
When users send multiple rapid messages (e.g. “hey” β “can you” β “search for AI news”), debounce coalesces them into a single agent call β saving tokens and preventing duplicate responses.
Python
from praisonaiagents import Agent
from praisonaiagents import BotConfig
from praisonai.bots import Bot
agent = Agent(name="assistant", instructions="Be helpful")
config = BotConfig(debounce_ms=1500) # 1.5s window
bot = Bot("telegram", agent=agent, config=config)
bot.run()YAML
agent:
name: assistant
instructions: Be helpful
platforms:
telegram:
token: ${TELEGRAM_BOT_TOKEN}
debounce_ms: 1500Smart Message Chunking
Long agent responses are split at paragraph boundaries while preserving code fences β no more broken code blocks mid-message.
How splitting works
- Paragraph boundaries
Split at blank lines (
\n\n) first β keeps ideas together. - Sentence boundaries
If a paragraph is still too long, split at sentence endings (
.). - Hard split
Last resort: character-level split for very long single lines.
Code fence protection
Code blocks wrapped in triple backticks are never split, even if they exceed max_message_length. This ensures your users always see complete, copyable code.
Session History
Bot agents automatically remember the last 20 messages per conversation β no extra dependencies required.
Automatic (default)
from praisonaiagents import Agent
from praisonai.bots import Bot
# History is injected automatically β zero config needed
agent = Agent(name="assistant", instructions="Be helpful")
bot = Bot("telegram", agent=agent)
bot.run()
# Agent now remembers last 20 messages per sessionCustom memory
from praisonaiagents import Agent
from praisonai.bots import Bot
# Override with your own memory config
agent = Agent(
name="assistant",
instructions="Be helpful",
memory={"history": True, "history_limit": 50} # Remember more
)
bot = Bot("telegram", agent=agent)
bot.run()Ack Reactions
Acknowledge inbound messages with an emoji reaction (e.g. β³) so users know the bot is processing, then swap to a done emoji (e.g. β ) when the response is sent.
Python
from praisonaiagents import Agent
from praisonaiagents import BotConfig
from praisonai.bots import Bot
agent = Agent(name="assistant", instructions="Be helpful")
config = BotConfig(
ack_emoji="β³",
done_emoji="β
",
ack_scope="group-mentions", # default; ambient group traffic stays quiet
)
bot = Bot("telegram", agent=agent, config=config)
bot.run()YAML
agent:
name: assistant
instructions: Be helpful
platforms:
telegram:
token: ${TELEGRAM_BOT_TOKEN}
ack_emoji: "β³"
done_emoji: "β
"
ack_scope: "group-mentions" # off | direct | group-mentions | group-all | allAck Scope
Control which inbound messages get acked so busy group channels aren’t flooded with β³ on ambient chatter the bot won’t answer.
ack_scope | DMs | Group mention / reply | Ambient group chatter |
|---|---|---|---|
off | β | β | β |
direct | β | β | β |
group-mentions (default) | β | β | β |
group-all | β | β | β |
all (legacy) | β | β | β |
Which one fits?
- Small team DMs / 1:1 bots β default (
group-mentions) is fine. - Bot lives in a busy group and only answers when mentioned β keep the default; ambient traffic stays silent.
- Bot answers everything in the group β
group-all. - You want the pre-scope-gate behaviour back β
all. - You never want reactions β
off(equivalent toack_emoji="").
Long-Running Agent Feedback
RAG-enabled agents commonly take 20β30 seconds to answer (vector search + tool calls + LLM). PraisonAI Telegram bots give users continuous feedback throughout, with no extra code on your side.
from praisonaiagents import Agent
from praisonaiagents import BotConfig
from praisonai.bots import Bot
agent = Agent(name="cfo", instructions="Answer finance questions using the company knowledge base.")
# Defaults shown for clarity β you get all this without setting anything.
bot = Bot("telegram", agent=agent, config=BotConfig(
typing_indicator=True, # renews every 4s
ack_emoji="β³", # instant reaction at T+0
done_emoji="β
", # swaps in when the reply lands
))
bot.run()What the user sees
Why this matters
| Before | After |
|---|---|
One send_action("typing") at T+0 | Renewed every 4s for the full run |
| Bubble vanishes at T+5s | Bubble persists until the reply is sent |
| Users assume bot is broken, send duplicates | Users see continuous activity |
Session Reset Policy
Per-channel YAML policies automatically clear a user’s conversation history after idle time or at a scheduled hour β configured under session.reset on each channel.
channels:
telegram:
token: ${TELEGRAM_BOT_TOKEN}
session:
max_history: 100
reset:
mode: both
idle_minutes: 60
at_hour: 4| Feature | What it clears | Configuration |
|---|---|---|
| Session Reset Policy | User conversation history | channels.*.session.reset in YAML |
| Session Reaper (below) | In-memory session records | BotConfig(session_ttl=...) |
Idle, daily, and combined reset modes with full configuration reference
Session Reaper
Automatically prune stale sessions to free memory on long-running bots. Sessions idle longer than session_ttl seconds are reaped.
from praisonaiagents import Agent
from praisonaiagents import BotConfig
from praisonai.bots import Bot
agent = Agent(name="assistant", instructions="Be helpful")
config = BotConfig(session_ttl=86400) # Reap sessions older than 24h
bot = Bot("telegram", agent=agent, config=config)
bot.run()YAML Configuration
Deploy bots entirely from YAML β including agent memory, tools, roles, and multi-platform config.
Full YAML
agent:
name: Research Bot
role: AI Research Assistant
goal: Help users find and understand AI research
instructions: |
You are a research assistant that helps users
find and understand the latest AI research papers.
llm: gpt-4o-mini
memory:
history: true
history_limit: 30
tools:
- search_web
platforms:
telegram:
token: ${TELEGRAM_BOT_TOKEN}
debounce_ms: 1500
discord:
token: ${DISCORD_BOT_TOKEN}
slack:
token: ${SLACK_BOT_TOKEN}Python loader
from praisonai.bots import BotOS
botos = BotOS.from_config("bot.yaml")
botos.run() # Starts all platforms concurrentlySupported agent fields
| Field | Type | Description |
|---|---|---|
name | string | Agent display name |
role | string | Role/job title |
goal | string | Primary objective |
backstory | string | Background context |
instructions | string | Direct instructions |
llm | string | Model name (gpt-4o-mini, claude-3-sonnet) |
memory | bool/dict | Memory config (true or {history: true}) |
tools | list | Tool names from praisonaiagents.tools |
knowledge | list | Knowledge sources |
guardrail | string | Output validation |
Environment variable syntax
Use ${ENV_VAR} in YAML values β resolved at load time.
platforms:
telegram:
token: ${TELEGRAM_BOT_TOKEN}Tool Approval via Messaging
When your bot agent uses dangerous tools (e.g. execute_command), you can route approval requests to Slack:
from praisonaiagents import Agent
from praisonai.bots import Bot, SlackApproval
agent = Agent(
name="assistant",
instructions="You are a helpful assistant.",
approval=SlackApproval(channel="#approvals") # Approvals go to Slack
)
bot = Bot("telegram", agent=agent) # Users talk via Telegram
bot.run()Related
Prevent 429 errors with platform-aware rate limiting
Send PolicyAuthorise where bots may send β allow/deny guard for send_message
Ask ConversationLet agents ask another chat a question mid-turn and act on the reply
Approval ProtocolTool execution approval system
GatewayMulti-agent coordination
WebhooksEvent-driven integrations
Bot Platform CapabilitiesHow platform capabilities drive this feature
Channel DescriptorLet a channel plugin declare its config, prompt hint, and setup wizard
Bot Session CompactionSummarise old turns instead of dropping them
Outbound Media DeliveryDeliver agent-generated images and files to users on Telegram, Slack, and Discord