Campaigns and sequences
How SignalDock turns an opportunity into a compliant, multi-touch sequence that pauses for your approval.
A campaign says who to contact, why, and how. It holds a goal, a brief for the writer agent, a country, a mode, and a versioned sequence of steps. Each enrolled contact runs through the sequence in its own durable run, which survives deploys and can wait for days.
Proposals from the strategist agent
When a signal becomes an opportunity, the strategist agent proposes a campaign for it. It picks up to three contacts at the company whose titles match your personas, chooses channels the country allows for a cold first touch, and writes two to five steps with instructions for the writer.
| Country | Cold first-touch channels, in order |
|---|---|
| NL, BE | email, LinkedIn, phone |
| DE, AT | LinkedIn, phone, letter (email needs consent) |
Sole traders only get LinkedIn and phone in the Netherlands and Belgium. The plan is checked in code after the model returns it: contacts that are not at the company and channels the country does not allow are dropped.
A proposal shows up under Campaigns with the strategist's reasoning. Nothing is sent until you Accept and enroll; accepting enrolls the suggested contacts and starts their sequences in review mode. Dismiss archives it. There is at most one live proposal per opportunity.
Steps
A step has a channel and a delay in days after the previous touch.
| Channel | What happens |
|---|---|
email | The writer agent drafts it; it is sent from a connected mailbox. |
linkedin | The writer agent drafts a connection note; a person sends it. |
phone | The writer agent writes a short call script; a person calls. |
letter | The writer agent drafts a short letter; a person posts it. |
Without your own steps a campaign uses four touches: an email, a follow-up three days later, a LinkedIn note two days after that, and a last email five days later. Editing the steps creates a new sequence version; contacts already enrolled finish on the version they started with.
What the writer agent uses
Each draft is grounded in:
- the public signal behind the opportunity (tender, permit, registry change),
- sourced facts from the research brief,
- matching passages from your knowledge base,
- the earlier touches in the same sequence, so follow-ups add something new.
The message stores this grounding as why, so the approval inbox shows the
signal, the facts the draft used with their source links, the compliance
decision, and any risks the agent flagged.
After the model returns a draft, SignalDock also checks it in code. A draft
that still contains a placeholder (such as [Voornaam] or {{name}}), cites
a source that is not in the research brief, or links to a page that is not
in the brief, the signal, or your booking link, gets those problems listed as
risks and its confidence capped at 0.5. It then always waits for review.
The inbox
Inbox → Approvals lists drafts waiting for a decision, each next to its
why. Inbox → Tasks lists LinkedIn, phone, and letter steps for a person
to do; marking one done moves the sequence on. Inbox → Replies lists
answers from prospects with the reply agent's classification; conversations
it escalated are marked Needs you until you mark them handled.
Replies
SignalDock reads new mail in each connected mailbox and keeps only answers to
its own outreach, matched by In-Reply-To, the provider thread, or (for
bounces) the original Message-ID. Other mail in the mailbox is never
stored.
Some replies are handled by rules before any model sees them:
| Reply | What happens |
|---|---|
| Bounce (mailer-daemon, "undeliverable", "onbestelbaar") | Address suppressed and marked invalid; the sequence ends. |
Out-of-office (Auto-Submitted, "automatisch antwoord") | Nothing changes; the sequence continues. |
| Short opt-out ("afmelden", "verwijder mij", "unsubscribe", "abmelden") | Address suppressed; every sequence for the contact ends. |
The reply agent classifies the rest as interested, meeting request, question, objection, not now, referral, unsubscribe, or other, with a confidence. Any real answer stops every running sequence for that contact, and drafts waiting for approval are withdrawn.
For interested, meeting-request, question, and objection replies, the agent drafts a short answer in the prospect's language from your knowledge base and booking link. It never invents prices, dates, or commitments; when the knowledge base has no answer, it drafts nothing and escalates. Drafts get the same code checks as outreach drafts and wait in Approvals unless the campaign is on autopilot and the confidence clears Reply confidence in Settings → Outreach (0.8 by default).
The conversation is escalated (marked Needs you, and emailed to the escalation address from Settings → Outreach when set) when the confidence is below that threshold, when no answer could be drafted, and for referrals and replies classified as other.
Every classified reply is recorded as a positive or negative example for the outreach email it answered, which feeds the learning loop.
Meetings
A meeting can be booked three ways:
- Booking link. With a booking URL in Settings → Outreach, the reply agent offers it. Connect Cal.com so bookings come back into SignalDock.
- The reply agent. Without a booking link, the agent reads free/busy on the calendar of the mailbox that sent the email and offers three times on different weekdays, in working hours in the prospect's time zone. When the prospect picks one, SignalDock checks the slot is still free, sends the calendar invite with a Meet or Teams link, and confirms in the thread. If the slot was taken in the meantime, it drafts nothing and escalates.
- By hand, on the Meetings page or with
POST /api/meetings.
Whichever way, a booking stops every sequence for the contact
(meeting_booked), withdraws drafts waiting for approval, records the email
that led to it as a meeting_booked example, and, with Sync to CRM
automatically on, syncs the opportunity and logs the meeting in the CRM. The
attendee gets a short reminder in the same thread a day before (or right away
when the meeting is less than a day out). Cancelled and rescheduled Cal.com
bookings update the meeting; a moved meeting gets its reminder at the new time.
After the meeting, mark it Held or No-show; outcomes feed the learning loop.
CRM sync
With Sync to CRM automatically on and a CRM connected (HubSpot, Pipedrive, or Attio), SignalDock:
- syncs the company, contacts, and deal when an opportunity becomes ready,
- logs every sent email with why it was sent (the signal, the sourced facts, and the score reasons),
- logs every reply with the agent's one-line summary,
- logs booked meetings.
Each item is written once; re-running a sync updates the same records. A CRM outage never blocks outreach.
Review and autopilot
| Mode | Behaviour |
|---|---|
review | Every email waits in the approval inbox. This is the default. |
autopilot | Emails that clear every check below are sent without waiting for a person. |
Even in autopilot, an email waits for review when:
- autopilot is switched off for the organization (Settings → Outreach, admins only),
- the writer agent's confidence is below the organization threshold (0.85 by default),
- the country rules say a person must look (for example phone outreach to a natural person),
- the address is
riskyor not yet verified.
When you approve, you can edit the subject and body first. SignalDock keeps the original text so it can learn from your edits. Rejecting a draft stops the sequence for that contact. A draft that nobody decides on within 14 days stops the sequence too.
Pausing a campaign holds every running sequence (checked hourly) until you resume it. Archiving it ends them.
Compliance on every touch
Before drafting, each touch is checked against the country rules:
- Suppressed addresses, domains, and KvK numbers are never contacted. The check runs again right before sending.
- For companies and public bodies in the Netherlands and Belgium, SignalDock records legitimate interest as the lawful basis, with the signal as the source. Sole traders and natural persons need a recorded basis first.
- Email in Germany and Austria needs recorded consent.
Every email gets the legally required footer in the recipient's language:
your legal name and address, where the data came from (on the first touch),
an AI disclosure if you enabled it, and an unsubscribe link. Gmail sends also
carry List-Unsubscribe one-click headers. Opening the link shows a
confirmation page; confirming adds the address to your suppressions and stops
every running sequence for that contact.
Sending
Emails go out from a connected mailbox inside its send window, on weekdays, within its warm-up cap. The campaign's mailbox is preferred; when it is full, SignalDock rotates to the healthy mailbox with the most room left. Follow-ups always come from the mailbox that started the thread, and are sent as replies in that thread. If no mailbox can send, the enrollment is paused.
API
POST /api/campaigns
POST /api/campaigns/{campaignId}/enrollments
GET /api/messages?organizationId=…&status=pending_approval
POST /api/messages/{messageId}/approve
GET /api/messages?organizationId=…&status=received
POST /api/threads/{threadId}/resolve
GET /api/meetings?organizationId=…&upcoming=true
POST /api/meetings
POST /api/meetings/{meetingId}/status { "status": "completed" }
POST /api/campaigns/proposals { "opportunityId": "…" }
POST /api/campaigns/{campaignId}/accept
PATCH /api/settings/outreach
POST /api/opportunities/{opportunityId}/outcome { "outcome": "won", "value": 48000 }
GET /api/analytics/outreach?organizationId=…&days=30Outcomes feed the learning loop. The analytics endpoint returns the same attribution, deliverability, and agent quality numbers as the dashboard.
See the API reference for all campaign and message operations.
Last updated on