Skip to main content
from praisonaiagents import Agent

agent = Agent(name="support", instructions="Reply helpfully on Slack or Telegram.")
agent.start("Tell the user their ticket was updated.")
Every bot reply now survives transient channel errors — 5xx responses, 429 rate limits, and network blips are automatically retried with bounded exponential backoff before parking in a Dead Letter Queue on permanent failure. The user sends a bot reply; transient channel errors retry with backoff before a permanent failure lands in the dead-letter queue.

Quick Start

1

Zero Configuration (Transient Retry)

All six adapters now retry on transient failures by default — no config needed:
from praisonaiagents import Agent
from praisonai.bots import TelegramBot

agent = Agent(
    name="Support Agent",
    instructions="Answer user questions helpfully.",
)

bot = TelegramBot(token="YOUR_TOKEN", agent=agent)
await bot.start()
Slack, Discord, WhatsApp, Email, Linear, and AgentMail behave identically — transient 5xx and 429 errors are retried automatically.
2

Enable Dead Letter Queue

Add a dlq_path so permanently-failed replies are parked for later replay:
from praisonaiagents import Agent
from praisonai.bots import SlackBot, BotConfig, OutboundResilienceConfig

config = BotConfig(
    outbound_resilience=OutboundResilienceConfig(
        dlq_path="~/.praisonai/state/outbound_dlq.db",
        max_attempts=5,
        initial_ms=1000,
        max_ms=30000,
    )
)

agent = Agent(name="Slack Agent", instructions="Help the team.")
bot = SlackBot(token="YOUR_TOKEN", agent=agent, config=config)
await bot.start()
3

Tune Backoff Parameters

Fine-tune retry behaviour per channel:
from praisonai.bots import BotConfig, OutboundResilienceConfig

config = BotConfig(
    outbound_resilience=OutboundResilienceConfig(
        initial_ms=500,       # first retry after 500ms
        max_ms=15000,         # cap at 15s
        factor=2.0,           # double each attempt
        max_attempts=4,       # give up after 4 tries
        jitter=0.3,           # add 30% random jitter
        dlq_path="~/.praisonai/state/dlq.db",
    )
)

How It Works

The mixin (OutboundResilienceMixin) wraps each adapter’s raw send with deliver_outbound(). State is initialised lazily from self.config.outbound_resilience — existing adapter constructors need no changes.

Channel Support

All six channels now share the same durable delivery path:
ChannelRetry + backoffDLQ supportNotes
TelegramHad this previously; unchanged
SlackNew in PR #2484
DiscordNew in PR #2484
WhatsAppPreviously swallowed errors silently — now fixed
EmailNew in PR #2484
LinearNew in PR #2484
AgentMailNew in PR #2484
WhatsApp previously swallowed permanent send errors silently. This was fixed: permanent failures now propagate, matching every other channel.

What Gets Retried

Error typeRetried?Notes
HTTP 5xxFull backoff sequence
HTTP 429Waits for Retry-After header first
Network blips / timeoutTransient
HTTP 401 Unauthorized❌ → DLQToken/account issue, not per-message
HTTP 403 Forbidden❌ → DLQPermanent — bot kicked or blocked
HTTP 404 Not Found❌ → DLQChat deleted or not found
HTTP 410 Gone❌ → DLQPermanently removed
Platform patterns (“bot was kicked”)❌ → DLQPlatform-specific classification

Configuration Options

OptionTypeDefaultDescription
initial_msint1000First retry delay in milliseconds
max_msint10000Maximum retry delay cap
factorfloat1.5Backoff multiplier per attempt
max_attemptsint3Total attempts before parking in DLQ
jitterfloat0.25Random jitter fraction (0–1)
dlq_pathstrNonePath to SQLite DLQ file; no DLQ when omitted
enabledboolTrueSet False to opt a channel out of durable delivery

Best Practices

Without dlq_path, failed replies after max attempts are re-raised and logged but not recoverable. A DLQ lets you replay them after fixing an outage.
The mixin reads the Retry-After response header and waits exactly that long before the next attempt, so your bot stays within platform rate limits without sleeping longer than necessary.
Set outbound_resilience.enabled = False in a channel’s config to disable durable delivery for that channel only — useful for fire-and-forget channels where retries would send duplicates.
Parked entries are permanent failures. Set up alerts on DLQ growth to detect channels that are consistently unreachable (e.g. bots kicked from a workspace).

Dead-Target Registry

Short-circuit known-dead channels before sending

Bot Channels

Overview of all supported messaging channels

Delivery Config

Full delivery configuration reference

Inbound DLQ

Dead-letter queue for inbound messages