The system
AgentSDR is one web application and one PostgreSQL database. There is no queue server and no separate worker deployment. The background work runs inside the same process as the web app, and a small scheduler calls a few web addresses on a timer. What runs inside the app, and how often:
Because the email and WhatsApp loops have no lock between copies, run one
copy of the app. The schedule and its secrets are in
Configuration; the tuning knobs are in
Workers and tuning.
Anything that reaches AgentSDR from outside (a Gmail notification, a Unipile
webhook) needs your public address to be reachable from the internet. That is
the
BETTER_AUTH_URL setting.
A lead’s journey
This is the path from a spreadsheet row to a booked meeting.- Import. You upload a CSV or XLSX. Email, names and company map to the core fields, and every other column becomes a custom field you can use as a merge field. See Import leads and Custom fields. Each row becomes a Person, the one identity shared by every channel. See Leads overview.
- Enrich. In Tables, columns call your enrichment providers or AI to find emails, companies and facts. See Tables, Enrichment and AI columns. Provider keys are connected in Enrichment providers.
- Campaign. You add people to an email, LinkedIn or WhatsApp campaign. Email campaigns, LinkedIn campaigns and WhatsApp campaigns explain the sequences.
- Send. Each channel paces itself by your
Sending rules: daily limits, gaps and sending
hours.
- Email. Once a day the app builds each mailbox’s queue for the day. The minute loop then sends what is due, from your connected Google Workspace mailboxes.
- LinkedIn. The scheduler runs invitations and follow-ups through Unipile, within each account’s daily limit.
- WhatsApp. The 30-second loop sends one step per number per tick.
- Reply arrives. Gmail pushes a notification when mail comes in (Gmail reply sync), and Unipile posts a webhook for LinkedIn and WhatsApp messages. Webhooks are verified, and events for accounts that do not belong to the organization are dropped.
- One conversation. A reply on any channel lands in the same CRM conversation for that Person. See CRM overview and the Master Inbox.
- AI classification. A background job reads the reply and proposes a category, a sub-category and a pipeline stage, with a confidence. Low confidence changes are held for a person. See AI provider for the model and key, and Knowledge for the documents the AI may use.
- Draft in Action required. The AI writes a reply draft from your instructions and knowledge. It waits in Action required until a person approves, edits or dismisses it. Nothing is sent by the draft step alone.
- Follow-up sequence. A sequence is a series of timed follow-ups for a sub-category of reply. Each step becomes a new draft for review when it is due.
- Pipeline and analytics. The person moves through the pipeline, and Analytics counts what happened per channel.
What stops outreach to a person
Outreach stops for four reasons. Each is enforced in code, usually in more than one place, because the last check runs again just before the provider call.- A reply on any channel. When a reply is stored in the CRM, the Person’s
pending email enrollments are set to
reply_receivedand their queued emails are removed, their LinkedIn leads are set toREPLIED, and their WhatsApp campaign leads are set torepliedwith no next send. A reply wins over every cold-outreach timer. It does not mark the Person Do Not Contact. - Do Not Contact. A flag on the Person, not on one channel. A person can set it from the CRM. It is also set automatically when a reply says something like “unsubscribe me” or “do not contact me”, or when the AI classifies the reply as Do Not Contact. Setting it moves the record to Action required, interrupts the Person’s running sequence, cancels its pending steps and marks open drafts stale. Email sends, LinkedIn invitations, follow-ups and messages, and WhatsApp sends all check it before sending, and refuse. See Responsible use.
- Unsubscribe. Every outreach email carries a signed one-click unsubscribe
link. A click adds that address to the organization’s suppression list
(reason
unsubscribed), removes its queued emails and stops its sequence. Before every send the scheduler checks the list again. This is email only: it does not set Do Not Contact for LinkedIn or WhatsApp. The link depends onUNSUBSCRIBE_SECRET, which you must never change after sending (Configuration). - A bounce. When Gmail delivers a bounce report, AgentSDR reads the failed
address, adds it to the suppression list (reason
bounced) and marks the enrollment bounced, so no campaign emails it again. A report that only says delivery is delayed does not suppress yet, and a report that cannot be read is kept for a person to look at.
Where your data lives, and what leaves your server
Everything AgentSDR stores is in your PostgreSQL: people, companies, campaigns, messages, the CRM and the settings. Saved integration credentials are in the same database, encrypted withINTEGRATION_CREDENTIALS_KEY.
Recordings are the one thing stored elsewhere, in your own Cloudflare R2 bucket.
AgentSDR sends data out only to services you connect, only when a feature needs
them, and never from environment variables you did not set.
If a service is not connected, the feature that needs it is off and
nothing is sent: see Integrations.
Organizations and isolation
Every piece of business data belongs to exactly one organization, and people work inside one. Roles are owner, admin and member: members use the product, while owners and admins also manage integrations, AI settings, members and teams. Integrations, AI settings, sending rules, pipelines and sequences are per organization, so two organizations on one server share nothing and cannot see, change or count each other’s data. Background jobs and webhooks work out which organization an item belongs to from the data itself (the mailbox, the Unipile account) before they touch it. See Organizations; the rulebook is in Multi-tenancy conventions.Next
Quickstart
Connect a mailbox and send a first campaign.
Concepts
The words the product uses, in one place.
Self-hosting
Run AgentSDR on your own server.
Architecture
The developer view of the same system.