Quick Start
Zero Configuration (Transient Retry)
All six adapters now retry on transient failures by default — no config needed:Slack, Discord, WhatsApp, Email, Linear, and AgentMail behave identically — transient 5xx and 429 errors are retried automatically.
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:| Channel | Retry + backoff | DLQ support | Notes |
|---|---|---|---|
| Telegram | ✅ | ✅ | Had this previously; unchanged |
| Slack | ✅ | ✅ | New in PR #2484 |
| Discord | ✅ | ✅ | New in PR #2484 |
| ✅ | ✅ | Previously swallowed errors silently — now fixed | |
| ✅ | ✅ | New in PR #2484 | |
| Linear | ✅ | ✅ | New in PR #2484 |
| AgentMail | ✅ | ✅ | New in PR #2484 |
What Gets Retried
| Error type | Retried? | Notes |
|---|---|---|
| HTTP 5xx | ✅ | Full backoff sequence |
| HTTP 429 | ✅ | Waits for Retry-After header first |
| Network blips / timeout | ✅ | Transient |
| HTTP 401 Unauthorized | ❌ → DLQ | Token/account issue, not per-message |
| HTTP 403 Forbidden | ❌ → DLQ | Permanent — bot kicked or blocked |
| HTTP 404 Not Found | ❌ → DLQ | Chat deleted or not found |
| HTTP 410 Gone | ❌ → DLQ | Permanently removed |
| Platform patterns (“bot was kicked”) | ❌ → DLQ | Platform-specific classification |
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
initial_ms | int | 1000 | First retry delay in milliseconds |
max_ms | int | 10000 | Maximum retry delay cap |
factor | float | 1.5 | Backoff multiplier per attempt |
max_attempts | int | 3 | Total attempts before parking in DLQ |
jitter | float | 0.25 | Random jitter fraction (0–1) |
dlq_path | str | None | Path to SQLite DLQ file; no DLQ when omitted |
enabled | bool | True | Set False to opt a channel out of durable delivery |
Best Practices
Always configure a DLQ path in production
Always configure a DLQ path in production
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.Respect rate limits with Retry-After
Respect rate limits with Retry-After
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.Opt channels out individually
Opt channels out individually
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.Monitor your DLQ
Monitor your DLQ
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).
Related
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

