Quick Start
How It Works
The pairing system intercepts messages from users not inallowed_users and routes them through an approval workflow controlled by the unknown_user_policy.
Policy Options
| Policy | Behaviour | When to use |
|---|---|---|
"deny" (default) | Silently drops messages from users not in allowed_users. | Closed / internal bots. |
"pair" | Generates a code and DMs the owner an Approve/Deny button. Falls back to CLI if owner_user_id is unset. | Semi-public bots where you want owner control. |
"allow" | Lets every unknown user through (no persistent pair). | Fully public bots (combine with rate limits / approval protocol). |
Which Policy Should I Choose?
CLI Fallback
Whenowner_user_id is not set, the bot replies to the requester:
<channel_type> is one of: telegram, discord, slack.
Security: HMAC-signed Callbacks
All inline-button callbacks are cryptographically signed to prevent tampering:- Callback format:
pair:{action}:{channel}:{user_id}:{code}:{sig} - Signature: First 8 hex chars of
HMAC-SHA256(PRAISONAI_CALLBACK_SECRET, payload) - Verification: Tampered
callback_datafails verification and is silently ignored + logged
Platform-specific UI
Telegram
Telegram
Uses Implementation: Telegram’s
InlineKeyboardMarkup with ✅ Approve / ❌ Deny buttons. Callbacks are handled via CallbackQueryHandler that parses the signed callback_data and verifies the HMAC signature.What the owner sees:InlineKeyboardButton with callback_data containing the signed pairing payload.Discord
Discord
Uses Implementation: Discord’s Button components in an Action Row with HMAC-signed
discord.ui.View with success (green) and danger (red) button styles. Handled via button.callback method that verifies the HMAC signature in the custom_id.What the owner sees:custom_id values.Slack
Slack
Uses Block Kit Implementation: Slack Block Kit buttons with HMAC-signed values and dedicated action handlers.
actions block with primary (blue) and danger (red) button styles. Handled via @app.action("pair_approve") and @app.action("pair_deny") decorators that verify the signature in the button’s value.What the owner sees:Configuration Options
For the completeBotConfig options including unknown_user_policy and owner_user_id, see the canonical reference at Messaging Bots Configuration.
Common Patterns
- Semi-public Bot
- Internal Bot
- Public Bot
Best Practices
Always set PRAISONAI_CALLBACK_SECRET in production
Always set PRAISONAI_CALLBACK_SECRET in production
Generate a strong secret and set it as an environment variable:Without this, inline buttons stop working when your bot restarts.
Use platform-native user IDs for owner_user_id
Use platform-native user IDs for owner_user_id
Each platform has its own user ID format:
- Telegram: Numeric ID (e.g.,
123456789) - Discord: Snowflake ID (e.g.,
123456789012345678) - Slack: User ID format (e.g.,
U1234ABCD)
Combine 'allow' policy with rate limiting and tool approval
Combine 'allow' policy with rate limiting and tool approval
If using Consider also implementing rate limiting at the platform level.
unknown_user_policy="allow" for a public bot, protect yourself with:Treat denied pairings as final
Treat denied pairings as final
When you deny a pairing request, the code is consumed and cannot be retried. The user must send a new message to generate a fresh code. This prevents spam and ensures each approval decision is deliberate.
Related
Messaging Bots
Complete bot configuration and setup
Bot Security
Security best practices for bots

