Skip to main content
Bot platform adapters now ship in the praisonai-bot package. praisonai bot serve still works exactly as documented here; for a standalone install see praisonai-bot Migration.
Platform capabilities tell PraisonAI what your bot’s platform can do, so streaming, chunking, and rate limiting work the same way everywhere.
from praisonaiagents import Agent

agent = Agent(name="assistant", instructions="Reply on Telegram with streaming when supported.")
agent.start("Send a long answer with progressive updates.")
Capabilities describe what a channel can render; Display Policy controls what you want shown.
The user receives a reply; platform capabilities tell PraisonAI how to chunk, stream, and rate-limit on that channel.

Quick Start

1

Look up built-in capabilities

from praisonai import Bot
from praisonaiagents import Agent
from praisonai.bots._registry import get_platform_capabilities

agent = Agent(name="assistant", instructions="Be helpful")
caps = get_platform_capabilities("telegram")
print(caps.max_message_length)  # 4096
print(caps.length_unit)         # utf16

bot = Bot("telegram", agent=agent)
2

Register a custom platform

from praisonaiagents.bots import PlatformCapabilities
from praisonai.bots._registry import register_platform

class MyBot:
    async def start(self): ...
    async def stop(self): ...

register_platform(
    "mybot",
    MyBot,
    capabilities=PlatformCapabilities(
        max_message_length=2000,
        supports_edit=True,
        markdown_dialect="markdown",
    ),
)

How it works

UnifiedDelivery (via create_delivery(bot)) reads platform_capabilities to chunk long replies, stream edits, and apply rate limits.

Configuration options

FieldTypeDefaultDescription
max_message_lengthint4096Maximum message length in the platform’s unit
length_unitstr"codepoints""codepoints" or "utf16"
supports_editboolFalseIn-place message edits (streaming)
supports_typingboolTrueTyping indicators
markdown_dialectstr"markdown"e.g. "telegram_markdown_v2", "discord_markdown"
needs_rate_limitboolTrueApply Praison rate limiting
edit_interval_msint1000Minimum ms between edits
max_files_per_messageint1Attachments per message
max_file_size_mbint10Max file size in MB
supported_file_typesList[str]["*"]Allowed mime types or extensions
accepts_webhooksboolFalseChannel receives inbound HTTP webhooks
verifies_webhook_signatureboolFalseAdapter exposes a webhook verifier
reconciles_unknown_sendboolFalseAdapter can confirm whether a prior send actually landed (via was_delivered(idempotency_key)). Enables effectively-once delivery via the durable outbox.
supports_idempotency_tokenboolFalseInformational — transport accepts a provider-level idempotency token. Set reconciles_unknown_send as well if you need effectively-once.
Methods: to_dict() and from_dict(data).

Webhook-based platforms

Platforms that set accepts_webhooks=True must also expose a webhook_verifier so enforce_webhook_verification can enforce signatures fail-closed. See Webhook Verification.

Built-in platform defaults

PlatformNotes
Telegrammax_message_length=4096, length_unit="utf16", supports_edit=True, markdown_dialect="telegram_markdown_v2", needs_rate_limit=True, edit_interval_ms=1000, max_file_size_mb=50
Discordmax_message_length=2000, length_unit="codepoints", supports_edit=True, needs_rate_limit=False, edit_interval_ms=500, max_files_per_message=10, max_file_size_mb=8
slack, whatsapp, linear, email, agentmailUses PlatformCapabilities() defaults until the adapter declares its own

Native / command menu

Some platforms publish the bot’s commands to their native / menu so typing / shows autocomplete. Adapters override publish_command_menu to project the shared CommandRegistry; the base implementation is a no-op.
PlatformNative / menuAPI used
Telegramset_my_commands
DiscordCommandTree.sync()
Slack, WhatsApp, others❌ (base no-op)future — override publish_command_menu
See Native / Autocomplete for user-facing behaviour and the Discord shim caveat.

Common patterns

Subclass with default_capabilities() (Telegram and Discord use this):
@classmethod
def default_capabilities(cls) -> PlatformCapabilities:
    return PlatformCapabilities(max_message_length=2000, supports_edit=True)
Entry-point registrations (via praisonai.channels) get default capabilities unless the adapter class exposes a default_capabilities() classmethod. This keeps zero-config connectors functional while letting polished adapters declare exact limits:
# pyproject.toml
[project.entry-points."praisonai.channels"]
myplatform = "mypackage.bot:MyPlatformBot"
class MyPlatformBot:
    @classmethod
    def default_capabilities(cls):
        from praisonaiagents.bots import PlatformCapabilities
        return PlatformCapabilities(max_message_length=1000, supports_edit=False)
    
    async def start(self): ...
    async def stop(self): ...
Serialise for config files:
caps = get_platform_capabilities("telegram")
data = caps.to_dict()
restored = PlatformCapabilities.from_dict(data)

Best Practices

Telegram counts UTF-16 code units. Wrong length_unit can silently truncate messages.
Discord.py handles limits internally; raw Telegram HTTP does not.
UnifiedDelivery streams via edits when this flag is true.
Keeps registry caching consistent when platforms override defaults.

Durable Outbound Delivery

Effectively-once delivery via crash reconciliation

Display Policy

Operator policy for streaming and footers

Bot Platform Plugins

Register custom adapters

Bot Streaming Replies

Uses supports_edit and edit_interval_ms

Bot Rate Limiting

Uses needs_rate_limit

Chunking Strategies

Uses max_message_length and length_unit