Thiago Garofalogarofalodeveloper.com

Genesis: B2B prospecting agents in production

Period: July 2026 to date · Role: concept, architecture, code, operations and daily use · Status: in production on a self-operated VPS, three instances

One-sentence summary: an engine of agents that reads public data sources (mining concessions, the federal company registry, public procurement contracts, import statistics), discovers who buys what I sell, finds the entry channel and hands me, every day, a short list of commercial missions with a ready-made script.

1. Context and problem

I sell industrial supplies (quick couplings, clamps, hoses, valves) to mining companies, contractors and distributors. The bottleneck was never product or price. It was knowing whom to approach, through which channel (supplier portal, procurement e-mail, phone) and when, with a small sales team.

Manual prospecting had three costs:

Off-the-shelf CRM and prospecting tools did not solve it because they do not know the Brazilian sources that matter in this niche (the mining agency ANM/SIGMINE, the federal company registry dump, the public procurement portal PNCP, the ComexStat import statistics), nor the concept of an “entry channel” in a large industrial company, where the path is the supplier qualification portal, not a salesperson.

Self-imposed constraint: 100% open source and self-hosted. No paid managed platform. The system had to run locally at first (a machine without Docker) and later on the VPS, without a rewrite.

2. Results so far

Indicator Value
Companies loaded (mining instance, 7 states) 35.8 thousand
Mining processes matched to companies 156 thousand
Mining companies with a verified entry channel (curated seed) 25
Missions generated per day (configurable) 5
Instances in production 3 (mining, valves, São Paulo Metro works)
Paid dependencies 0

What changed in practice: the commercial routine starts by opening the Command Center, which already shows the five companies of the day, why them (mining process phase, active contract, importing state), the entry channel with a link and the contact script. The funnel (new, contacted, registered, approved, quoting, customer) is recorded per company, with dated notes.

Conversion metrics per channel and prioritization accuracy have not been consolidated yet. That is what section 7 proposes to measure, and it is the part that matters for the academic work.

3. Architecture

flowchart LR
  subgraph Sources[Public sources]
    ANM[ANM / SIGMINE<br/>mining processes]
    CNPJ[Federal Revenue<br/>company registry dump]
    PNCP[PNCP<br/>public contracts]
    COMEX[ComexStat<br/>imports by tariff code]
  end

  subgraph M2[Module 2 · Search Robot]
    COL[Collectors<br/>normalization + dedupe]
    ENR[Enrichment<br/>website, e-mail, supplier portal]
  end

  subgraph DB[Base · PostgreSQL + Drizzle]
    EMP[(companies)]
    PROC[(processes / works / imports)]
    CONT[(contacts<br/>channel + confidence)]
    ACOES[(actions / missions)]
    LOG[(cron_runs)]
  end

  subgraph M3[Module 3 · Daily cron]
    GER[generate-actions<br/>ranking + selection]
  end

  subgraph M1[Module 1 · Command Center]
    UI[Missions of the day<br/>playbook per channel]
    LEADS[Funnel and lead record]
    DASH[Dashboard]
  end

  HUM((Human<br/>decides and acts))

  ANM --> COL
  CNPJ --> COL
  PNCP --> COL
  COMEX --> COL
  COL --> EMP
  COL --> PROC
  EMP --> ENR --> CONT
  EMP --> GER
  PROC --> GER
  CONT --> GER
  GER --> ACOES
  GER --> LOG
  ACOES --> UI --> HUM
  HUM --> LEADS --> EMP
  EMP --> DASH

Modules and boundaries

The instance pattern

Each niche is a fork of the engine with its own database, port and collectors. The mining instance uses ANM + the federal registry; the valves instance uses the federal registry (industry code 2813-3 and company name) + ComexStat (tariff code 8481.80.95 by state and municipality, because there is no longer public data per importer); the Metro instance uses the PNCP API filtered by the agency’s tax ID, where every contract already names the winning supplier. The interface, funnel, cron and playbook code is the same. Changing niche means writing one collector and adjusting the ranking function.

4. The agent loop

I use the classic definition of an agent: it perceives the environment, keeps state, decides and acts, and is evaluated by a performance measure. In Genesis each part lives in a module:

Cognitive function Where it lives How it works today
Perception Module 2 collectors Periodic reading of public sources; name normalization (SIGMINE has no tax ID, so matching against the federal registry is by normalized company name)
Memory Database (companies, contacts with confidence, funnel, notes, cron log) Idempotency through a unique key in contacts; stage history per company; audit of every run
Reasoning / decision generate-actions Deterministic ranking by signals: known channel first, then hot process phase (mining concession), then active contract, then company size. Excludes companies with an open action. Selects N per day
Action Command Center + playbook Generates the mission with an objective (register on the portal or open a relationship), estimated time and a script per channel type, including a ready message. The external action is human
Learning Not yet closed-loop The funnel records the outcome, but the ranking is not adjusted by it yet. That is the next step

Two design choices are deliberate:

  1. Human in the loop. The agent does not send e-mails or fill in portals by itself. In industrial B2B sales a bad first contact closes the door for years. The agent lowers the cost of deciding; it does not decide.
  2. No scraped personal data. Contacts of people are entered manually by the user. Automatic enrichment looks only for institutional channels (website, procurement e-mail, supplier portal).

5. Engineering decisions

6. Lessons

7. Next steps and evaluation plan

The planned cognitive layer (Phase 4 of the backlog) is where the project meets the graduate program. The proposal is to treat every addition as an experiment with a metric defined before coding.

Layers to add

  1. Message personalization with a local LLM (Ollama, Llama 3.1 or Qwen 2.5). Today the playbook is a template per channel. The LLM receives company, substance or work, state and channel, and generates the message. Evaluation: reply rate for generated messages against templates, in weekly A/B tests.
  2. RAG over niche documents (pgvector, nomic-embed-text, 768 dimensions). Tender notices, supplier qualification rules, portal pages. Goal: the agent answers “what does this company require to qualify a supplier” from a cited source.
  3. Lead qualification by LLM alongside the deterministic ranking. Same candidates, two lists. Evaluation: agreement between the lists and, at the funnel outcome, which list got more of the companies that reached quotation.
  4. Closed learning loop. The funnel outcome (registered, approved, quoting, discarded) feeds back into the ranking weights. It starts with a monthly manual adjustment and evolves into automatic adjustment.

Metrics to start collecting

Metric How to measure Why it matters
Prioritization precision % of the day’s missions that advance in the funnel within 30 days Measures whether the reasoning chooses well
Reply rate per channel replies / contacts, by channel type Defines where the agent should concentrate effort
Conversion per stage new, contacted, registered, quoting, customer Full funnel, per instance
Cost per actionable lead human hours + infrastructure / leads with a verified channel Compares against manual prospecting
Human time per mission estimated vs. actual, recorded at completion Measures the real operational gain
Rules vs. LLM agreement overlap of the lists and accuracy at the outcome Decides whether the LLM joins the ranking or only the message

Possible angles for academic work

8. Stack

Next.js 16 · React 19 · TypeScript · Tailwind 4 · Drizzle ORM · PostgreSQL 16 + pgvector · PGlite · Playwright · cheerio · node-cron · Ollama · Docker Compose · Caddy · Ubuntu on a self-operated VPS.

9. Code

The code of the three instances is private: it contains the prioritization logic and the curated channel seed, which are the commercial advantage of the business. It can be presented in interviews or academic evaluation with synthetic data. Architecture, database, deployment and restore-runbook documents exist in the repository and follow this case.