On by default for gateway/bot runs — Every bot started via
praisonai bot start, onboard, or bot.yaml gets the journal automatically. No code needed. The journal lives at ~/.praisonai/state/<platform>/ingress.sqlite. Set delivery.durable: false to opt out.Default behavior (no config needed)
Every bot started throughbuild_session_manager (all shipped adapters) automatically gets an Inbound Journal at:
~/.praisonai/state/telegram/ingress.sqlite. A Discord bot uses ~/.praisonai/state/discord/ingress.sqlite. Each platform is fully isolated — no cross-platform dedup collisions.
Set PRAISONAI_HOME to override the base directory:
Opt out or override path
Add adelivery: block to any channel in your bot.yaml or gateway.yaml:
Quick Start (advanced: manual setup)
Most users get the journal automatically. For custom setups outsidebuild_session_manager:
You don’t need to call
complete() yourself when using BotSessionManager.chat() — successful chats mark the journal entry as completed automatically. You only need to call complete() manually if you’re driving InboundJournal directly without BotSessionManager.How It Works
Before PR #1980, the default
chat() path claimed entries but never called complete(). On startup, journal.replay() could re-issue messages the user had already received answers to. Upgrade to a release after 2026-06-19 — replay then only covers genuinely incomplete entries.| Stage | Purpose | What happens |
|---|---|---|
| receive | Deduplication & retry | Returns a key for new messages, retries pending or stale-claimed duplicates, returns None only for already-completed or actively-claimed entries |
| claim | Crash protection | Marks the entry as being processed (auto-released on stale timeout) |
| complete | Cleanup | Marks successful processing — BotSessionManager.chat() calls this for you automatically |
When to use which option
| Feature | InboundJournal | InboundDLQ |
|---|---|---|
| When triggered | Every inbound message | Only on agent failure |
| Solves | Webhook redeliveries, crash recovery | Failed LLM calls |
| Performance | Fast dedup check | No overhead until failure |
| Use together | ✅ Journal → agent → DLQ on exception | ✅ Complete durability stack |
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
path | str | Path | required | SQLite file path. Parent dirs auto-created. ~ is expanded. |
max_size | int | 50_000 | Max entries kept. Excess evicted: completed first, then oldest pending. |
ttl_seconds | int | 2_592_000 (30 days) | Completed entries older than this are evicted. |
claim_timeout | int | 300 (5 min) | Claimed entries older than this are considered stale and replayed. |
Per-platform examples
- Telegram
- Discord
- Slack
- WhatsApp
- Email
- AgentMail
Common Patterns
Pattern 1: Dedup-only (webhook redelivery protection)
Pattern 2: Crash recovery + replay loop on startup
Pattern 3: Combining with InboundDLQ for full durability stack
Best Practices
Use the same path across restarts
Use the same path across restarts
The journal’s SQLite file must survive restarts for crash recovery to work. Use an absolute path or a location that persists across deployments.
Tune claim_timeout to match your agent latency
Tune claim_timeout to match your agent latency
Set
claim_timeout to be longer than your p99 agent.chat() latency to avoid false stale entry detection.Call journal.replay() in your bot's startup hook
Call journal.replay() in your bot's startup hook
Always replay stale entries when your bot starts to recover from crashes.
Keep account stable per bot instance
Keep account stable per bot instance
The
account parameter is part of the deduplication key. Keep it consistent for each bot instance.Set claim_timeout below the platform's redelivery window
Set claim_timeout below the platform's redelivery window
Platforms redeliver webhooks at fixed intervals (Telegram retries within seconds, Slack waits ~3s before its first retry, etc.). Set
claim_timeout shorter than your platform’s redelivery window so that a crashed worker’s claim becomes stale before the next redelivery arrives — that’s what enables automatic recovery without a restart.Related
Delivery Config
Full reference for the
delivery: channel config block — defaults, opt-out, and path overrideInbound DLQ
Failure-side durability when agent execution fails
Durable Outbound Delivery
Outbound counterpart — persist outgoing messages with retry and idempotency
Bot Routing
Multi-channel session routing for complex bot setups

