Start the conversation

Messages delivered. Failures handled. Proof recorded.

Twilio primary, Guni secondary — switchable per campaign with no pipeline changes. Every send attempt logged with the provider's message SID. Failures retry automatically, then flag for review.

2 providersTwilio primary, Guni secondary — switchable per campaign config
60s / 300sretry delays — 3 attempts before flagging for review
0 double sendsMessageSid idempotency prevents duplicate delivery on retry
100%of send attempts logged with outcome and provider SID
How delivery works

Send. Retry. Flag. Never silently fail.

Every outbound send fires after the turn has been persisted to the database. If the send fails, the delivery_status is set to FAILED and a retry job is enqueued. The platform retries twice before flagging the turn for operator review — no silent failures, no lost messages.

  • Turn persisted to database before outbound send — data is never lost on send failure
  • Provider's message SID recorded on successful send — permanent linkage to provider record
  • First retry after 60 seconds — second retry after 300 seconds
  • After three failed attempts, turn flagged for operator review
  • Recovered workers check existing message row before retrying — no double sends
  • Campaign-level provider setting — switch from Twilio to Guni with a config change
Delivery and retry flow
  1. 1
    Turn persisted
    Written to DB before send fires — data safe
  2. 2
    Send attempt
    Twilio or Guni per campaign sms_provider field
  3. 3
    Success
    SENT status + provider message SID recorded
  4. 4
    Failure → retry 1
    FAILED status set, retry job enqueued at 60s
  5. 5
    Failure → retry 2
    Retry job enqueued at 300s
  6. 6
    Failure × 3
    Turn flagged for operator review — no further retry
Provider management

Two providers. Zero pipeline changes to switch.

The SMS provider is abstracted behind the Channel interface. Twilio and Guni both implement it. Switching a campaign to a different provider requires only a field change — the pipeline never needs to know which provider is in use.

Provider abstraction

Twilio and Guni are interchangeable at the campaign level. The pipeline calls channel.send() — it doesn't care which provider executes it. Adding a third provider in future requires only a new Channel implementation.

How it works: sms_provider field on the campaign record determines which provider is used — no code change required to switch.

Idempotent sends

If a send job is retried after a worker failure, the pipeline checks the existing message row before attempting to send again. A completed send is never repeated — the contact never receives the same message twice from a retry.

How it works: MessageSid is the idempotency key — checked at both the webhook and pipeline entry point before any processing begins.

Message SID audit trail

Every successful outbound send records the provider's message SID alongside the delivery status and timestamp. This creates a permanent linkage between the platform's internal record and the provider's delivery record.

How it works: Message SID is the audit key — available in the operator platform's conversation view and CSV export.

Rate limit handling

When the AI provider returns an HTTP 429 rate limit error, the platform retries automatically with exponential backoff via tenacity. If all retries are exhausted, the pipeline falls back to a safe response without raising an exception.

How it works: Rate limit retry is a code guarantee — the pipeline never propagates a 429 to the contact or the operator.

Want to see how delivery
is tracked end to end?

We'll walk through a live campaign send — provider selection, retry logic, and audit trail included.