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.

python
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.

Diagram

Task Platforms

Communication

Messaging Platforms

πŸ“± Telegram

πŸ’¬ Discord

πŸ’Ό Slack

πŸ“² WhatsApp

πŸ” Signal

🟒 LINE

🍎 iMessage

πŸ“ž Twilio SMS

πŸŽ₯ Webex

𝕏 X/Twitter

πŸ“§ Email

πŸ“‹ Linear

πŸ€– Bot Runtime

🧠 Agent

Quick Start

CLI (No Code)

Start a bot with a single command – no Python code required:

  1. 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"
  2. 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_KEY

    A default agent is created automatically with basic assistant capabilities.

  3. (Optional) Custom Agent
    bash
    # Use a custom agent configuration
    praisonai bot slack --token $SLACK_BOT_TOKEN --app-token $SLACK_APP_TOKEN --agent agents.yaml

    agents.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:

  1. Create Agent
    python
    from praisonaiagents import Agent
    
    agent = Agent(
        name="assistant",
        instructions="Help users with their questions",
        llm="gpt-4o-mini"
    )
  2. 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
    )
  3. 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())
  4. 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())
  5. 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 ClassPlatformEnv VariableStatus
SlackBotSlackSLACK_BOT_TOKEN, SLACK_APP_TOKENβœ…
DiscordBotDiscordDISCORD_BOT_TOKENβœ…
TelegramBotTelegramTELEGRAM_BOT_TOKENβœ…
WhatsAppBotWhatsApp BusinessWHATSAPP_ACCESS_TOKEN, WHATSAPP_PHONE_NUMBER_IDβœ…
LinearBotLinear (AgentSession webhooks)LINEAR_OAUTH_TOKEN (or LINEAR_API_KEY), LINEAR_WEBHOOK_SECRETβœ…
EmailBotEmail (IMAP/SMTP)EMAIL_ADDRESS, EMAIL_APP_PASSWORDβœ…
AgentMailBotAgentMail (API)AGENTMAIL_API_KEYβœ…

Outbound Tools (Send-Only β€” Bot Runtime Coming Soon)

ToolPlatformEnv VariableBot Runtime
SignalToolSignalRequires signal-cli daemonπŸ”œ Coming Soon
LineToolLINELINE_CHANNEL_ACCESS_TOKENπŸ”œ Coming Soon
iMessageTooliMessage (macOS only)No token neededπŸ”œ Coming Soon
TwilioToolSMS/VoiceTWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKENπŸ”œ Coming Soon
WebexToolWebexWEBEX_ACCESS_TOKENπŸ”œ Coming Soon
XToolX (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:

python
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.

Durable Delivery

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.

Diagram
🧠 Agent VisionπŸ›‘οΈ Media ValidatorπŸ€– BotπŸ“± PlatformπŸ‘€ User🧠 Agent VisionπŸ›‘οΈ Media ValidatorπŸ€– BotπŸ“± PlatformπŸ‘€ UserSize cap Β· magic-byte check Β· SSRF guard“What’s in this photo?”Message + photoValidate & cache mediaSafe local pathchat(prompt, attachments=[path])“I see a golden retriever on a beach…”πŸ“¨ Reply
python
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 Media

WhatsApp-specific details: Graph API download, security pipeline, and max_inbound_media_bytes config

Bot Inbound Media

Full reference: security pipeline, SSRF guard, size limits, and common patterns

Outbound Media Delivery

Send agent-generated images, charts, and files via native platform uploads


How It Works

Diagram
AgentBotPlatformUserAgentBotPlatformUserSend MessageWebhook/PollProcess RequestGenerate ResponseSend ReplyDisplay Message
ComponentRole
PlatformTelegram, Discord, Slack, or WhatsApp
BotMessage router and formatter
AgentAI processing and response
UserEnd 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.

See Interactive Bot Actions.


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.

Diagram
Chat UI (WebSocket)agent.chat()Chat BridgeBot RuntimeSlack/Discord/TelegramChat UI (WebSocket)agent.chat()Chat BridgeBot RuntimeSlack/Discord/TelegramUser message_session.chat()Attach StreamEventEmitter callbackExecute agenttool_call_started (via emitter)broadcast({type: tool_call_started, platform: slack})tool_call_completed (via emitter)broadcast({type: tool_call_completed, …})Final responseRemove callbackbroadcast({type: channel_response, content: …})Send reply

What You See in the Dashboard

FeatureDescription
Tool call stepsEach tool the agent uses appears as a collapsible step with icon, description, and result
Reasoning stepsChain-of-thought reasoning streams in real-time
Platform iconSession sidebar shows the platform badge (e.g. πŸ’¬ Slack, ✈️ Telegram)
Message historyAll 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.

Diagram

πŸ€– Agent
tools=None

βš™οΈ Smart Defaults

πŸ” search_web
πŸ“… schedule_*
🧠 memory
πŸ“š learning

βœ… auto-approve
for safe tools

πŸ’¬ session history
last 20 messages

Both praisonai bot start and praisonai gateway start apply the same defaults:

DefaultApplied whenWhat you get
Safe toolsAgent has no tools configuredsearch_web, web_crawl, schedule_*, store_memory/search_memory, store_learning/search_learning
Auto-approvalauto_approve_tools=True (default)Tool calls run without CLI prompts β€” chat bots can’t show them anyway
Session historyAgent has no memory configuredLast 20 messages remembered per user, zero-dep

Opting out

GoalHow
Run with zero toolsSet tools: [] explicitly in YAML, or pass tools=[] to Agent
Require manual approvalSet auto_approve_tools: false in the channel config
Override the tool listSet default_tools: [...] under the channel β€” destructive tools are still filtered
python
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()
bash
# Same result β€” no YAML tool list needed
praisonai bot telegram --token $TELEGRAM_BOT_TOKEN
Diagram
πŸ” search_web🧠 AgentπŸ€– BotπŸ‘€ User (Telegram)πŸ” search_web🧠 AgentπŸ€– BotπŸ‘€ User (Telegram)“What’s the latest on Llama 4?”Forward message (no tool prompt)auto-approved callResultsAnswerπŸ“° Here’s the latest…

Platform 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:

Diagram

Webhook Mode (Production)

HTTPS

🌐 Public Server

☁️ Platform API

Socket Mode (Default)

WebSocket outbound

Events

πŸ–₯️ Local Bot

☁️ Slack Cloud

ModeUse CaseRequirements
Socket ModeLocal development, behind firewallApp Token only
Webhook ModeProduction, high scalePublic URL with HTTPS

Configuration Options

python
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):

yaml
# 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.

OptionTypeDefaultDescription
tokenstr""Bot authentication token
webhook_urlstrNoneWebhook URL for webhook mode
command_prefixstr"/"Prefix for bot commands
mention_requiredboolTrueRequire @mention in channels (DMs never require mention)
typing_indicatorboolTrueShow 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_lengthint4096Max message length
allowed_userslist[]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_channelslist[]Allowed channel IDs
timeoutint30Request timeout
reply_in_threadboolFalseAlways reply in threads
thread_thresholdint500Auto-thread responses longer than N chars (0 = disabled)
group_policystr"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_silenceboolfalseWhen true, agent may return NO_REPLY to send nothing. See Intentional Silence.
silence_tokenstrNoneCustom silence marker (default: NO_REPLY)
allow_botsboolfalseOpt-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`NoneSliding-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_toolslist[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_toolsboolTrueSkip 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_policyLiteral["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_idOptional[str]NonePlatform-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_attemptsint3Number of retry attempts for failed operations
polling_intervalfloat1.0Interval for polling mode (seconds)

Access-check methods

BotConfig exposes two allowlist checks with distinct purposes:

MethodReturnsPurpose
is_user_allowed(user_id)boolRuntime pass/fail β€” respects unknown_user_policy. Empty allowed_users defers to the policy.
is_explicitly_allowed(user_id)boolPre-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.
python
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 next

CLI Capabilities

Enable powerful agent features directly from the command line:

Diagram

praisonai bot slack

Capabilities

–memory

–knowledge

–skills

–thinking

–web

Full CLI Options Reference
FlagDescriptionExample
--memoryEnable conversation memory--memory
--memory-providerMemory backend--memory-provider chroma
--knowledgeEnable RAG/knowledge--knowledge
--knowledge-sourcesSource files--knowledge-sources file.pdf
--skillsSkill modules--skills researcher
--thinkingThinking mode--thinking high
--webEnable web search--web
--web-providerSearch provider--web-provider duckduckgo
--browserEnable browser--browser
--toolsNamed tools--tools WikipediaTool
--sandboxSandbox mode--sandbox
--auto-approveAuto-approve tool executions--auto-approve

Platform Setup

Telegram

  1. Message @BotFather on Telegram
  2. Send /newbot and follow prompts
  3. Copy the bot token
bash
export TELEGRAM_BOT_TOKEN="123456:ABC-DEF..."
praisonai bot telegram --token $TELEGRAM_BOT_TOKEN
Troubleshooting: 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.

  1. Find and stop duplicate processes: ps aux | grep -i praisonai | grep -v grep, then `kill

`.

  1. Confirm no webhook is set: curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/getWebhookInfo".
  2. 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

  1. Go to Discord Developer Portal
  2. Create new application β†’ Bot β†’ Reset Token
  3. Enable Message Content Intent
  4. Invite bot to server with proper permissions
bash
export DISCORD_BOT_TOKEN="MTIz..."
praisonai bot discord --token $DISCORD_BOT_TOKEN

Slack

  1. Create Slack App
    1. Go to Slack API Console
    2. Click Create New App β†’ From scratch
    3. Enter app name (e.g., “PraisonAI Bot”) and select workspace
  2. Configure OAuth & Permissions
    1. Go to OAuth & Permissions in the sidebar
    2. Scroll to Scopes β†’ Bot Token Scopes
    3. Add these scopes:
    ScopePurpose
    chat:writeSend messages
    app_mentions:readReceive @mentions
    im:historyRead DM history
    im:readAccess DMs
    channels:historyRead channel messages
    1. Click Install to Workspace at the top
    2. Copy the Bot User OAuth Token (xoxb-...)
  3. Enable Socket Mode
    1. Go to Socket Mode in the sidebar
    2. Toggle Enable Socket Mode ON
    3. When prompted, create an app-level token:
    4. Token Name: socket-mode
    5. Add scope: connections:write
    6. Copy the App Token (xapp-...)
  4. Subscribe to Events
    1. Go to Event Subscriptions in the sidebar
    2. Toggle Enable Events ON
    3. Scroll to Subscribe to bot events
    4. Add these events:
    EventPurpose
    app_mentionWhen someone @mentions your bot
    message.imDirect messages to your bot
    1. Click Save Changes
    2. Reinstall the app when prompted (or go to OAuth & Permissions β†’ Reinstall)
  5. Enable Messages Tab
    1. Go to App Home in the sidebar
    2. Scroll to Show Tabs β†’ Messages Tab
    3. Ensure Allow users to send Slash commands and messages from the messages tab is toggled ON
  6. 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_TOKEN

    You should see:

    ⚑️ Bolt app is running!
  7. Test the Bot
    1. Direct Message: Send a DM to your bot
    2. Channel Mention: In any channel, type /invite @YourBotName first, then @YourBotName hello
Troubleshooting: Bot not responding

Check these in order:

  1. Event Subscriptions enabled? β†’ Must be ON
  2. Bot events subscribed? β†’ app_mention and message.im must be listed
  3. Reinstalled after changes? β†’ Required after adding scopes/events
  4. App Token provided? β†’ required β€” the CLI now fails fast if --app-token / SLACK_APP_TOKEN is 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)
  1. Bot invited to channel? β†’ Use /invite @BotName before @mentioning
Required Scopes Summary
ScopeRequired For
chat:writeSending messages
app_mentions:read@mention events
im:historyDM access
im:readDM access
channels:historyChannel message access
connections:writeSocket Mode (app token)

WhatsApp

  1. Create Meta App
    1. Go to Meta for Developers
    2. Click Create App β†’ Select Business type
    3. Add the WhatsApp product to your app
  2. Get API Credentials
    1. In the WhatsApp section, go to API Setup
    2. Copy your Phone Number ID and Access Token
    3. Create a Verify Token (any secret string you choose)
  3. Configure Webhook
    1. Go to Configuration β†’ Webhook
    2. Click Edit and enter:
    3. Callback URL: https://your-domain.com/webhook
    4. Verify Token: The same string you set in WHATSAPP_VERIFY_TOKEN
    5. Subscribe to: messages
  4. 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_ID

    You should see:

    WhatsApp webhook server starting on port 8080
  5. Test the Bot

    Send a WhatsApp message to your business phone number. The bot will reply via the Cloud API.

Troubleshooting: Webhook not verifying
  1. Verify token matches? β†’ Must be identical in Meta console and env var
  2. Bot running? β†’ Webhook server must be up before configuring in Meta
  3. HTTPS required? β†’ Meta only accepts HTTPS webhook URLs
  4. ngrok running? β†’ If using ngrok, ensure the tunnel is active
WhatsApp API Limits
TierMessages/dayRequirement
Test1,000Default for new apps
Business10,000+Verified business account
UnlimitedNo limitMeta 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.

Diagram

WebSocket

πŸ“± Scan QR Code

WhatsApp Servers

πŸ€– PraisonAI Bot

🧠 AI Agent

  1. Install Dependencies
    bash
    pip install 'praisonai[bot-whatsapp-web]'

    This installs neonize (WhatsApp Web client with built-in QR display).

  2. Start the Bot
    bash
    praisonai bot whatsapp --mode web

    A QR code appears in your terminal. Open WhatsApp on your phone β†’ Settings β†’ Linked Devices β†’ Link a Device β†’ scan the QR code.

  3. 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

bash
# 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 --web

Python

python
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 β†’ running

YAML

yaml
# whatsapp-web-bot.yaml
platform: whatsapp
mode: web

agent:
  name: "WhatsApp Assistant"
  instructions: "You are a helpful AI assistant."
  llm: "gpt-4o-mini"
  memory: true
bash
praisonai bot start --config whatsapp-web-bot.yaml

Live 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.

bash
praisonai bot telegram --token $TELEGRAM_BOT_TOKEN --stream
python
from 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.

Bot Streaming Replies

Complete guide to streaming reply configuration and best practices


Cloud API vs Web Mode

FeatureCloud API (default)Web Mode (experimental)
SetupMeta developer account + tokensQR code scan only
AuthWHATSAPP_ACCESS_TOKENSaved locally (SQLite)
WebhooksRequired (public HTTPS URL)Not needed
Group chatsDMs onlyDMs + groups
ReactionsLimitedFull support
MediaVia upload APIDirect
StabilityOfficial API, stableReverse-engineered, may break
RiskNoneAccount may be banned
Best forProductionDevelopment, personal use
Troubleshooting: QR code not showing
  1. Terminal supports Unicode? β†’ Use a modern terminal (iTerm2, Windows Terminal, etc.)
  2. Dependencies installed? β†’ Run pip install 'praisonai[bot-whatsapp-web]' β€” this includes segno for QR rendering
  3. Already linked? β†’ If a saved session exists, no QR is shown. Delete creds to re-link:
bash
rm -rf ~/.praisonai/whatsapp/
  1. 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:

bash
rm -rf ~/.praisonai/whatsapp/
praisonai bot whatsapp --mode web
Where 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:

CommandDescription
/helpShow available commands and agent info
/statusShow agent name, model, platform, and uptime
/newReset 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:

python
bot.register_command("ping", my_handler, description="Check latency")

Common Patterns

Restricted Access

python
from praisonaiagents import BotConfig

config = BotConfig(
    token="your-token",
    allowed_users=["user123", "user456"],
    allowed_channels=["channel789"]
)

Webhook Mode

python
from praisonaiagents import BotConfig

config = BotConfig(
    token="your-token",
    webhook_url="https://your-domain.com/webhook",
    webhook_path="/telegram/webhook"
)

Group Settings

python
from praisonaiagents import BotConfig

config = BotConfig(
    token="your-token",
    mention_required=True,   # Only respond when @mentioned
    command_prefix="!",      # Use ! for commands
)

CLI Commands

bash
# 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.yaml

WhatsApp 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.

Diagram

Yes

No

Yes

No

Yes

No

πŸ“© Incoming Message

Older than\nconnect time?

πŸ—‘οΈ Drop (stale)

Self-chat?\n(sender = chat JID)

βœ… Process

In allowlist?

❌ Ignore

CLI Flags

Self-Only (Default)

bash
# Only responds when YOU message yourself
praisonai bot whatsapp --mode web

Allowed Numbers

bash
# Also respond to specific phone numbers
praisonai bot whatsapp --mode web --respond-to 1234567890,9876543210

Allowed Groups

bash
# Also respond in specific groups
praisonai bot whatsapp --mode web --respond-to-groups 120363123456@g.us

Combined

bash
# Specific numbers AND groups
praisonai bot whatsapp --mode web \
  --respond-to 1234567890 \
  --respond-to-groups 120363123456@g.us

Respond to All

bash
# Respond to every message (old behavior)
praisonai bot whatsapp --mode web --respond-to-all

Python SDK

python
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

yaml
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"
bash
praisonai bot start --config bot.yaml

Filtering Behavior Matrix

ScenarioDefault--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

bash
# 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-bot

Discord

bash
# 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 -d

Telegram

bash
# 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 -d

docker-compose.yml:

yaml
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-stopped

Production (Webhook Mode)

For production deployments with a public URL, use webhook mode instead of Socket Mode:

Slack

python
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/events

Configure in Slack API Console:

  1. Event Subscriptions β†’ Enable Events
  2. Set Request URL: https://your-domain.com/slack/events
  3. Subscribe to bot events: app_mention, message.im

Discord

python
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:

  1. General Information β†’ Interactions Endpoint URL
  2. Set: https://your-domain.com/discord/interactions

Telegram

python
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 Telegram

Telegram automatically configures the webhook when you start the bot.


Multi-Channel Gateway

Run all bots simultaneously with a single gateway config:

gateway.yaml:

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.

bash
praisonai gateway --config gateway.yaml

The gateway now produces identical results to Bot() β€” agents get the same safe tools and auto-approval in both entry points.

Diagram

Telegram

Gateway

Discord

Slack

WhatsApp

Personal Agent

Support Agent

Multiple bots on the same platform

For role-specific bots on the same platform (e.g., multiple Telegram bots), use this pattern:

yaml
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: ops

Zero-Code Mode (YAML Config)

Run a bot with a single YAML file β€” no Python code needed:

bot.yaml:

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]
bash
praisonai bot start --config bot.yaml

Tip: You can omit tools: entirely β€” the bot auto-injects safe defaults (search_web, schedule, memory, learning). Keep tools: [] 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):

yaml
platform: telegram

agent:
  name: "My Assistant"
  instructions: "You are a helpful AI assistant."
bash
export TELEGRAM_BOT_TOKEN="123456:ABC-DEF..."
praisonai bot start --config bot.yaml

The 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.

yaml
channels:
  my-discord-bot:
    platform: discord
    token: "${DISCORD_BOT_TOKEN}"
    events: [reactions, edits, members, threads]   # opt-in classes

Accepted class tokens:

  • reactions β†’ REACTION_RECEIVED
  • edits β†’ MESSAGE_EDITED + MESSAGE_DELETED
  • members β†’ MEMBER_JOINED + MEMBER_LEFT (requires the privileged Discord members intent)
  • threads β†’ THREAD_CREATED

Omit events: and nothing new is subscribed. Currently wired on the Discord adapter.

Inbound Platform Events

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.

python
from praisonaiagents import Agent

agent = Agent(name="signal-bot", instructions="Answer messages on Signal.")
agent.start("Welcome the user when they say hi.")
bash
# Same agent, run over Signal β€” no Python needed
praisonai bot run --platform signal --agent agents.yaml
Diagram

praisonai bot run

found

unknown

declared

undeclared

πŸ“ –platform name

πŸ” Registry

πŸ“‡ config_fields

β›” Exit 1

🏳️ –field flags

πŸ”Œ Adapter

β›” Exit 2

πŸ€– Bot facade

🧠 Agent

  1. Local channel (REPL-style)
    bash
    praisonai bot run --platform local
  2. Signal via signal-cli-bridge
    bash
    praisonai bot run --platform signal \
        --account +15551234567 \
        --bridge-url http://bridge:8080 \
        --agent agents.yaml
  3. Generic webhook receiver
    bash
    praisonai bot run --platform webhook --port 8080
  4. Plugin / drop-in channel
    bash
    praisonai bot run --platform my-plugin-channel --token $MY_TOKEN --my-field value

    An IRC plugin that declares server and nickserv_password is driven the same way:

    bash
    praisonai bot run --platform irc \
        --server irc.libera.chat \
        --nickserv-password $NICK_PW

Flags

FlagDescription
--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-headlessBrowser 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-approveExecution 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, whatsapp

Channel-declared field flags

Every field a channel declares in its ChannelDescriptor.config_fields is accepted by bot run as a --field-name flag.

python
from praisonaiagents import Agent

agent = Agent(name="signal-bot", instructions="Answer messages on Signal.")
agent.start("Say hello.")
bash
# Signal declares `account` and `bridge_url`
praisonai bot run --platform signal --account +15551234567 --bridge-url=http://bridge:8080
  • Naming β€” a declared field bridge_url becomes --bridge-url (underscore β†’ hyphen).
  • Syntax β€” both --flag value and --flag=value work.
  • Validation β€” required fields, env fallbacks 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 --account followed by another --… flag exits 2 with Option '--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 $?
2
Diagram

yes

no

yes

no

Built-in bot run flag?
–token / –port / –agent / –model …

Fixed –flag

Declared in the channel’s config_fields?

Generated –field-name flag

β›” Exit 2 with valid field list

Which command should I use?

Diagram

Just a token + one platform

A registered platform without its own verb

A bot.yaml describing platforms + agent

Multiple channels / production gateway

What do you have?

praisonai bot <platform>

praisonai bot run –platform <name>

praisonai bot start –config bot.yaml

praisonai gateway start –config gateway.yaml

Bot startup exit codes

praisonai bot ... now exits 1 on any startup failure β€” bad config path, missing token, unknown platform, or adapter import failure:

bash
$ praisonai bot start --config /nope.yaml
Error: Config file not found: /nope.yaml
$ echo $?
1

This 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

TokenFormatWhen to Use
Bot Token123456:ABC-DEF...Always required. Get from @BotFather. Used for all bot operations.

Discord

TokenFormatWhen to Use
Bot TokenMTIz...Always required. Get from Discord Developer Portal β†’ Bot β†’ Reset Token. Used for bot authentication.

Slack

TokenFormatWhen to Use
Bot Tokenxoxb-...Always required. Get from OAuth & Permissions β†’ Install to Workspace. Used for sending messages and API calls.
App Tokenxapp-...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 ID12345.67890OAuth flow only. Used when building apps that are installed by multiple workspaces (not needed for single-workspace bots).
Client Secretd119ac...OAuth flow only. Used with Client ID for the OAuth2 authorization flow. Never expose publicly.

WhatsApp

Cloud API (default)

TokenFormatWhen to Use
Access TokenEAAx...Required. Get from Meta for Developers β†’ WhatsApp β†’ API Setup. Used for sending messages via Cloud API.
Phone Number ID123456789Required. Found in API Setup page. Identifies which WhatsApp business number to send from.
Verify TokenAny stringRequired for webhooks. A secret string you create. Must match in both Meta console and your environment.
App Secretabc123...Optional. Used to verify webhook signatures for security. Found in App Settings β†’ Basic.

Web Mode (experimental)

TokenFormatWhen 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:

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.

Diagram
🧠 Agent⏱️ DebouncerπŸ‘€ User🧠 Agent⏱️ DebouncerπŸ‘€ UserStart 1500ms timerReset timerReset timerTimer expires βœ““hey”“can you”“search for AI news”“hey\ncan you\nsearch for AI news”πŸ“° Here are the latest AI news…

Python

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

yaml
agent:
  name: assistant
  instructions: Be helpful

platforms:
  telegram:
    token: ${TELEGRAM_BOT_TOKEN}
    debounce_ms: 1500

Smart Message Chunking

Long agent responses are split at paragraph boundaries while preserving code fences β€” no more broken code blocks mid-message.

Diagram

Paragraph 1

Code Block

Paragraph 3

🧠 Agent Response
(8000 chars)

Chunker

πŸ“¨ Message 1
Introduction

πŸ“¨ Message 2
“`python…“`

πŸ“¨ Message 3
Conclusion

How splitting works
  1. Paragraph boundaries

    Split at blank lines (\n\n) first β€” keeps ideas together.

  2. Sentence boundaries

    If a paragraph is still too long, split at sentence endings (. ).

  3. 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.

Diagram

πŸ‘€ User: What is Python?

🧠 Agent: Python is…

πŸ‘€ User: Show me an example

🧠 Agent: Sure! Based on
our Python discussion…

Automatic (default)

python
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 session

Custom memory

python
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.

Diagram
🧠 AgentπŸ€– BotπŸ‘€ User🧠 AgentπŸ€– BotπŸ‘€ User“Summarize this article”React ⏳Process messageResponse readySend responseRemove ⏳, React βœ…

Python

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

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 | all

Ack Scope

Control which inbound messages get acked so busy group channels aren’t flooded with ⏳ on ambient chatter the bot won’t answer.

Diagram

Yes

No

Yes

No

πŸ“¨ Inbound message

Direct / DM?

⏳ Acked under any scope except off

Mention or reply to bot?

⏳ Acked under group-mentions, group-all, all

⏳ Acked only under group-all or all

ack_scopeDMsGroup mention / replyAmbient 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 to ack_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.

python
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

Diagram
🧠 AgentπŸ€– BotπŸ‘€ User🧠 AgentπŸ€– BotπŸ‘€ Useragent.chat() β€” 20–30sloop[every 4s]“What is our Q1 burn rate?”React ⏳ (instant)“typing…” bubbleRenew “typing…”ResponseSend replySwap ⏳ β†’ βœ…

Why this matters

BeforeAfter
One send_action("typing") at T+0Renewed every 4s for the full run
Bubble vanishes at T+5sBubble persists until the reply is sent
Users assume bot is broken, send duplicatesUsers 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.

yaml
channels:
  telegram:
    token: ${TELEGRAM_BOT_TOKEN}
    session:
      max_history: 100
      reset:
        mode: both
        idle_minutes: 60
        at_hour: 4
FeatureWhat it clearsConfiguration
Session Reset PolicyUser conversation historychannels.*.session.reset in YAML
Session Reaper (below)In-memory session recordsBotConfig(session_ttl=...)
Bot Session Reset

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.

python
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

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

python
from praisonai.bots import BotOS

botos = BotOS.from_config("bot.yaml")
botos.run()  # Starts all platforms concurrently
Supported agent fields
FieldTypeDescription
namestringAgent display name
rolestringRole/job title
goalstringPrimary objective
backstorystringBackground context
instructionsstringDirect instructions
llmstringModel name (gpt-4o-mini, claude-3-sonnet)
memorybool/dictMemory config (true or {history: true})
toolslistTool names from praisonaiagents.tools
knowledgelistKnowledge sources
guardrailstringOutput validation
Environment variable syntax

Use ${ENV_VAR} in YAML values β€” resolved at load time.

yaml
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:

python
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