Skip to main content
Every bot channel automatically gets crash-safe inbound delivery: a deduplicating journal and a dead-letter queue, stored in ~/.praisonai/state/<platform>/.
All channels. The outbound_resilience and dlq_path config knobs apply to all six adapters: Slack, Discord, WhatsApp, Email, Linear, AgentMail, and Telegram. Previously only Telegram was wired; the remaining adapters now inherit the same OutboundResilienceMixin.
from praisonaiagents import Agent

# Durable inbound delivery is on by default — wire an agent in bot.yaml
agent = Agent(name="support", instructions="Reply helpfully on Telegram.")
# praisonai bot start --config bot.yaml
The user starts a bot; durable inbound delivery journals messages and routes failures to a DLQ automatically.

How It Works

What’s on by default

When you start any bot via praisonai bot start, onboard, or bot.yaml, PraisonAI automatically wires:
  • Inbound Journal (ingress.sqlite) — deduplicates webhook redeliveries and replays in-flight messages on crash recovery
  • Inbound DLQ (inbound_dlq.sqlite) — persists failed-LLM messages for later replay
Both live in one canonical per-platform directory. No configuration needed.

Canonical path

~/.praisonai/state/<platform>/ingress.sqlite
~/.praisonai/state/<platform>/inbound_dlq.sqlite
<platform> is the sanitized platform name (characters outside [A-Za-z0-9_.-] replaced with _).
PlatformJournal pathDLQ path
telegram~/.praisonai/state/telegram/ingress.sqlite~/.praisonai/state/telegram/inbound_dlq.sqlite
discord~/.praisonai/state/discord/ingress.sqlite~/.praisonai/state/discord/inbound_dlq.sqlite
slack~/.praisonai/state/slack/ingress.sqlite~/.praisonai/state/slack/inbound_dlq.sqlite
whatsapp~/.praisonai/state/whatsapp/ingress.sqlite~/.praisonai/state/whatsapp/inbound_dlq.sqlite
Set PRAISONAI_HOME to change the base directory:
export PRAISONAI_HOME=/var/lib/praisonai
# → /var/lib/praisonai/state/telegram/ingress.sqlite

delivery: schema

The delivery block is part of each channel configuration in bot.yaml / gateway.yaml:
FieldTypeDefaultDescription
durablebooltrueSet to false to fully opt out and return to in-memory delivery.
storestrNonePath override. If it has a file suffix, sibling DBs are placed in its parent directory. None resolves to the canonical per-platform path.

Quick Start

1

Default (nothing to do)

Just start your bot — durable delivery is already on.
praisonai bot start --config bot.yaml
2

Opt out for a channel

# bot.yaml
channels:
  telegram:
    token: "${TELEGRAM_BOT_TOKEN}"
    delivery:
      durable: false   # returns to in-memory delivery
3

Override the store directory

channels:
  telegram:
    token: "${TELEGRAM_BOT_TOKEN}"
    delivery:
      store: /var/lib/praisonai/telegram-state
      # → ingress.sqlite and inbound_dlq.sqlite in /var/lib/praisonai/telegram-state/

Per-platform isolation

Each platform gets its own directory so DLQ replays never cross platforms: A Discord DLQ replay never consumes a Telegram failed event. Dedup keys never collide cross-platform.

Failure mode

If durability is requested but the SQLite components fail to initialise (permissions, disk full, etc.), _build_durable_components logs a warning and the manager safely falls back to in-memory delivery. Your bot continues working — no crash.

Best Practices

Durable delivery costs a tiny SQLite write per message. The benefit — zero silent message loss on crash or LLM failure — is almost always worth it.
Mount a persistent volume and point PRAISONAI_HOME at it so the SQLite files survive container restarts.
docker run -e PRAISONAI_HOME=/data -v /host/data:/data my-bot
If you run two Telegram bots on the same host for different use cases, give each bot its own store directory to keep their journals isolated.
# bot-support.yaml
channels:
  telegram:
    token: "${SUPPORT_BOT_TOKEN}"
    delivery:
      store: /var/lib/praisonai/support-telegram

# bot-sales.yaml
channels:
  telegram:
    token: "${SALES_BOT_TOKEN}"
    delivery:
      store: /var/lib/praisonai/sales-telegram
A growing DLQ (praisonai bot dlq list) signals chronic LLM failures. Wire dlq.size() into your alerting stack.

Inbound Journal

Deduplication and crash-safe replay for inbound messages

Inbound DLQ

Dead-letter queue for failed LLM calls — inspect and replay

Durable Outbound Delivery

Outbound counterpart — persist outgoing messages with retry

Dead Target Registry

Skip permanently-dead chat targets to prevent retry storms

Gateway Channel Config

Full channel configuration reference including the delivery field