HR-Unit-CRM · how the product works

A machine that turns 30,000 cold companies into signed customers — mostly on its own.

This is a sales tool. Its job: find companies that might buy, contact them at scale, and hand the promising ones to a human only at the moment a real conversation is worth having. Below is every moving part, explained from zero.

30,000companies handled per instance
20,000emails sent per month
< 10%of the work stays manual
Start here

The business problem, in one paragraph

Imagine a company that sells a service to other businesses — and to grow, it constantly needs new customers. The old way: a room full of salespeople who Google companies, find a phone number or email, cold-call or cold-email them, and slowly work the few interested ones toward a contract. It's slow, expensive, and most of the effort is wasted on companies that were never going to buy.

What this product does: it automates the boring, high-volume 90% of that work — finding companies, researching them, emailing them, even preparing the phone calls — and saves the humans for the 10% where judgment actually pays off: the live sales conversation and the close.

Everything in the system is one long assembly line (the industry calls it a pipeline or funnel). A company enters at the top as a cold name and moves down, stage by stage. At each stage most drop out and a few advance — so the funnel is wide at the top and narrow at the bottom, where the signed deals come out.

The big picture

The five stages of the funnel

Read top to bottom. Each band is one stage. It narrows because fewer companies survive each step — and it shifts from cool to warm colours at the exact point the machine hands the work to a person.

Cool = the machine does it automatically Warm = a human takes over
RES
1 · ResearchFind companies + dig up everything about each one
30,000companies in
CAMP
2 · Campaign assignmentSort each company into the right sales campaign
autosorted by score
OUT
3 · OutreachSend AI-written email sequences, learn what works
20,000emails / month
CON
4 · ConnectA human cold-calls the ones who replied or went quiet
callslive phone work
CLO
5 · ClosingA closer runs the meetings, sends the contract, takes payment
dealssigned customers out

Only the first two numbers (30,000 companies, 20,000 emails) are real targets from the spec. The later stages narrow to progressively fewer, higher-quality prospects — exact counts depend on the campaign.

The vocabulary

Every term, in plain words

The code and the German UI use specific words for everything. Here's what each one actually means, with an everyday comparison.

Targetnot "lead"
One company the system is trying to win as a customer. The single most important object — everything else hangs off a target.
ContactAnsprechpartner
A specific person at that company you'd actually email or call — e.g. the hiring manager or a department head. One target can have several contacts.
ResearchResearch-Engine
The automated fact-gathering step. Given a region + industry, it finds companies and pulls data on each from ~10 sources (Google Maps, job boards, company registers, their website, ad libraries…).
ProvenanceProvenance
For every fact stored, the system records where it came from and when. So you can always trace why it believes a company has 200 employees.
Benchmarkbenchmark_score
A 0–100 score rating how attractive a target is, blended from five things: industry fit, size & hiring pressure, growth, marketing activity, and how reachable they are.
CampaignKampagne
A themed sales push — a product being sold, the email/call scripts for it, and rules for which targets belong in it. Every target gets routed into a campaign.
AssignmentZuweisung
The auto-sorting step: a rule decides which campaign each new target lands in — either a simple score cutoff, or an AI reading the target and matching it.
OutreachOutreach-Engine
The automated email process. It writes and sends a sequence of up to three emails to a target's contacts, personalised using the research.
Virtual company / employeeVirtuelle Firma
The sender identity the emails go out as — a set-up mailbox and persona, kept "warmed up" so it doesn't land in spam. Not a real employee.
BanditThompson Sampling
The self-optimising brain. When several email versions exist, it keeps trying them, watches which get replies, and automatically sends the winners more often.
ConnectCold-Calling
The phone stage. A human agent works through a list of targets in a live "call cockpit," dials via CloudTalk, and logs the outcome of each call.
ClosingVertragsabschluss
The finish line. A "closer" runs the real sales meetings, and when the target says yes, sends a contract for e-signature and sets up payment.
See it end to end

The life of a campaign, module by module

Let's start a brand-new campaign and watch which module takes over at each step, in order. The example throughout:

Who's selling: a staffing agency.  The product: "FlexCrew" — on-demand waiters, cooks and dishwashers a restaurant can book for busy shifts.  Who they want to sell to: restaurants & cafés in Munich — always short of staff, so an easy customer to picture.

Each step below shows the module doing the work, whether you click something or the system runs on its own, and — in the dashed box — how the algorithm actually decides.

CAMP Campaign RES Research VCO Virtual senders OUT Outreach CON Connect CLO Closing
CAMP
You do this

01You create the campaign

In the admin area you make a new campaign: "FlexCrew — Munich Restaurants." You attach the product (FlexCrew staffing), set a budget (how much it may spend on paid data/AI), and write one rule for who belongs in it.

⚙ How the rule worksYou pick one of two kinds of rule: a simple number cutoffbenchmark score > 70or a written instruction the AI reads ("restaurants that look busy and are hiring floor staff"). Whichever you choose is saved and applied automatically later.
The Campaign module now holds everything this push needs. Nothing has run yet — you've just defined the project.
RES
You start it, system runs it

02Research goes and finds the companies

On the campaign you set the search: postcodes (Munich) + industry (restaurants & cafés) + how many to find. You press "run" (or let it run automatically every hour). The Research module then does the digging: it searches Google Maps, reads their websites, checks job ads (e.g. "hiring waiters") and public registers.

⚙ How the search worksIt walks through every postcode × industry combination one at a time (so it covers the whole city without repeating itself), doing one focused Google search each. The free data sources are called all at once (fast, no cost); the paid ones are called only when needed — and only if the campaign still has budget left.
For each restaurant it finds, it creates a Target and fills it with facts — every fact tagged with where it came from.
CAMP
System does this

03Each company gets a score and joins your campaign

The system gives every new target a benchmark score from 0–100 (how good a prospect it is). Then it checks your rule from step 1. Companies that match drop into your campaign; the rest wait in a shared pool.

⚙ How the score is builtThe 0–100 comes from blending five things, each rated then weighted: (1) industry fit, (2) size & how hard they're hiring, (3) growth signals, (4) marketing activity, (5) how reachable they are. If the data is thin or old, it lowers its confidence and docks points. Then your rule runs: a busy Munich café hiring waiters might score 78 → above your cutoff of 70 → it joins the campaign. Leftovers in the shared pool are handed out fairly, one-by-one (round-robin) so no campaign hogs them.
Your campaign now has a list of scored, sorted target companies — ready to be contacted.
VCO
You set this up once

04You set up the "senders"

Emails can't come from nowhere — they need a From-address. The Virtual Companies module holds these sender identities (a fake company name + real mailboxes). They're kept "warmed up" in the background so they look trustworthy and don't land in spam.

⚙ How senders are chosenWhen it's time to email, the system rotates through your mailboxes evenly (round-robin) and skips any that already hit their daily send limit. That spreads the volume out so no single mailbox suddenly blasts 500 emails and gets flagged as spam.
Think of it as printing the letterhead and stamps before the mailout. Usually done once, reused across campaigns.
OUT
You write it, system sends it

05Outreach writes and sends the emails

You write the email scripts pitching FlexCrew (a first email, plus follow-ups). From then on the Outreach module runs itself: for each restaurant it asks the AI to write a personalised version of your script, then sends it from one of your virtual senders. No reply? It sends the next follow-up a few days later.

⚙ How the "bandit" chooses (and the AI writes)If you've written more than one version of an email, the bandit decides which to send: mostly the version winning so far, but every so often a challenger — so it keeps learning instead of betting everything on an early guess (this explore-vs-exploit balance is the Thompson Sampling algorithm). The AI then writes that version for this specific restaurant, and the system double-checks it didn't invent fake prices before anything is sent.
Result: each restaurant gets a genuinely personalised FlexCrew pitch, and the winning email style automatically gets used more.
OUT
System does this

06Replies get sorted automatically

The system checks the mailboxes every few minutes. When a company replies, it figures out which target it belongs to and routes it:

⚙ How replies are matched & countedEvery outgoing email carries a hidden ID; when a reply comes in, the system reads that ID to know exactly which restaurant and which email it answers. It counts "no reply" in working days only (weekends and public holidays don't count), so a restaurant isn't given up on over a long weekend.
Interested reply → sent straight to Closing.  ·  No reply after 3 emails → handed over to Connect for a phone call.
CON
A person does this

07An agent calls the promising ones

A supervisor builds a calling shift. A Connect agent starts it and works through the list in a live "cockpit" screen — the system dials each number for them (via CloudTalk). After each call the agent picks the outcome from a list: not reached, gatekeeper, interested, appointment booked, not interested…

⚙ What the outcome triggersThe outcome the agent picks sets the target's stage automatically. "Appointment booked" counts as a win that also teaches the bandit which call script works best (same learning as the emails). "Not reached" auto-schedules a call-back for later.
If the agent books a meeting, the target moves forward. "Not reached" schedules an automatic call-back later.
CLO
A person does this

08A closer wins the deal

Every booked appointment is shared out evenly among Closing agents. A closer runs the actual sales meetings. When the company says yes, they send the contract for e-signature, and once it's signed the system sets up payment collection automatically.

⚙ How deals are shared & closedBooked meetings are dealt out to closers evenly, one each in turn (round-robin), so no one is overloaded. The moment the contract is signed, a signature notification from the e-sign service triggers the payment link automatically — no one has to remember to send it.
Final status: Sold. The restaurant now books FlexCrew staff — and a person only got involved at the phone call and the close.

The one-line summary: you set up a campaign for a product — FlexCrew staffing (CAMP) — and after that the system does the heavy lifting: it finds restaurants (RES), scores and sorts them (CAMP), emails them from your senders (VCO + OUT), and learns which emails and call scripts win (Bandit). People only step in for the phone call (CON) and the close (CLO). A spending limit (budget) and a full history (audit) run under all of it the whole time.

How the app actually runs it

Under the hood: the machine room

The funnel above is the what. Here's the how — what actually happens inside the app at each stage. Almost nothing runs on a button press; the work is done by background jobs pulled off queues and by scheduled tasks that wake up on a timer. Names in mono are the real classes/jobs in the codebase.

RESResearch engine
Kicked off byA supervisor's "test run" button, or the hourly cron research:process-cron-triggers
Runs as
queue: researchProcessResearchJob
Talks to
SerperWaybackMeta Adsbund.devFirecrawlSerpAPITheirStackHandelsregister
The actual steps
  1. OrchestratedResearchPipeline: one focused Serper query per postcode×industry combo
  2. Free sources fired together, then paid ones one-by-one — each gated by GuardCampaignBudget
  3. PersistResearchCandidate writes the Target + every fact (with its source)
  4. RecalculateTargetBenchmark scores it across the 5 dimensions
  5. EvaluateAndAssignTarget hands it to campaign assignment
Watch it liveReverb · research-job.{id}
CAMPCampaign assignment
Kicked off byEvery new target (inline), plus hourly targets:rotate-unassigned for leftovers
How it decidesA deterministic rule (a small DSL) — no per-target AI call. Threshold on the benchmark score, or a prompt rule.
The actual steps
  1. Stage 1: if research already knows the origin campaign, use it
  2. Stage 2: otherwise a fair RotateUnassignedTargets round-robin over the catch-all pool
  3. AssignTargetToCampaign writes the link + an audit record (score, tiebreaker, reasoning)
  4. If the target's data is > 60 days old → fire ReResearchTarget to refresh first
Re-runs whenA campaign is created/activated or its rules change (Eloquent events → re-rotate)
OUTOutreach engine
Kicked off byHourly CheckOutreachWaitWindows — finds targets due for their next email
Runs as
queue: outreach-mailDispatchOutreachMail
Talks to
Anthropic ClaudeMicrosoft GraphTrulyinbox
The actual steps
  1. The bandit picks which email version to send (learns from past replies)
  2. GenerateOutreachMail builds an XML-sanitised prompt, calls Claude, validates the JSON, rejects hallucinated prices
  3. SendOutreachMail sends it from a round-robin virtual-employee mailbox via Graph
  4. Row written to outreach_messages (unique per target+step, so no double-sends)
Replies come back viaEvery 5 min PollVirtualEmployeeMailboxesRouteInboundMessage matches on In-Reply-To. A positive reply moves the target straight to Closing. Three failed emails → TransferToConnect.
CONConnect (calling)
Kicked off byA supervisor building a shift (only inside allowed time windows) and an agent starting it
Runs as
queue: connect-syncqueue: webhooks
Talks to
CloudTalk (power-dialer)
The actual steps
  1. A "package" of targets is pushed to CloudTalk (PushPackageToCloudTalk)
  2. The agent works a live cockpit; call events stream back in real time
  3. A finished call fires CallCompletedUpdatePipelineFromCall + a bandit event
  4. Outcome sets the pipeline stage (reached / gatekeeper / appointment / rejected…)
Watch it liveReverb · shift.{id}
CLOClosing
Kicked off byA positive reply (PositiveReplyReceived) or a scheduled appointment
Talks to
SignRequestGoCardless
The actual steps
  1. The target is round-robin'd to a closing agent
  2. Agent works the meetings through the closing pipeline stages
  3. On "yes": contract sent for e-signature via SignRequest
  4. ContractSigned webhook → SendGoCardlessLink sets up payment
Ends atSold, Not sold, or Unqualified

The plumbing that makes it all tick

Five cross-cutting systems run underneath every stage:

Queues Horizon

Six named queues (research, outreach-mail, connect-sync, webhooks…) run the slow work in the background so the UI stays instant.

Scheduler cron

Timed jobs wake up (hourly / daily) to trigger research, check email wait-windows, refresh stale data, enforce budgets.

Live updates Reverb

WebSockets push real-time progress to the browser — research runs and the call cockpit update without refreshing.

Budget guard

Every paid API call is checked against the campaign's budget first; hit the limit and the campaign auto-pauses.

Audit trail

Every business change is logged immutably — who, old value, new value, when. Nothing can be edited or deleted away.

Who operates it

The four kinds of user

full access

Admin

Runs the system itself: settings, API keys, the virtual sender companies. The technical owner.

manages the work

Supervisor

Sets up campaigns, hires connect agents, builds calling shifts, decides who can see what.

phone

Connect agent

Does the cold-calling. Sees only the campaigns they've been released to — nothing else.

deals

Closing agent

Runs meetings and signs deals. Sees only the specific targets assigned to them.

Where this comes from: the client's German spec — docs/product-requirements.md and docs/technical-requirements.md. This page is a plain-language orientation, not the authoritative spec.

Terms map 1:1 to the code: Target, Campaign, Contact, OutreachStep, ConnectStep, VirtualEmployee, BanditEvent. English in the code, German in the UI.