I built a sales agent that prospects, follows up, and learns on its own
The starting problem: sales prospecting takes time, follow-ups don't happen, and the same mistakes repeat from one conversation to the next.
My question: can a system do this for me — and get better over time?
What the system does
It finds prospects. Playwright scrapes Google Maps for a given niche and city. Every business gets qualified: is there a phone number, what's the Google rating, does it have a website or not. Duplicates get filtered out by phone number.
It reaches out. A WhatsApp message is generated by Ollama (qwen2.5:7b, local) for each prospect — personalized with the business name, its rating, its audit score. The message goes through a human approval step in Discord before it's sent.
It follows up. An automatic D+3 / D+7 / D+14 sequence. Each follow-up takes a different angle: added value, social proof, a clean close. After three follow-ups with no reply — silence.
It remembers. For each prospect, a Markdown file is maintained automatically: facts extracted from the conversation, objections raised, the agreed next step, budget mentioned. That file gets indexed into the RAG.
It learns. After every positive conversation, the agent extracts the objections and the responses that worked. Those patterns feed a graph of connections between similar conversations. Scripts get updated automatically.
A 7-component architecture
1. Prospecting engine → Playwright + Google Maps + qualification
2. Multi-channel contact → WhatsApp (Baileys) + Email (SMTP) + Discord approval
3. Follow-up sequence → 4h scheduler + D+3/D+7/D+14 + contextual generation
4. Per-prospect memory → one .md file per number + nomic-embed-text RAG, 768 dim
5. Knowledge base → .md files per niche + DuckDuckGo web verification
6. Learning system → .patterns.jsonl + conversation graph + auto-update
7. Declarative workflows → self-describing JSON, executable by any AI agent
Everything runs locally. Zero cloud API for AI inference. The only external services are Convex (database) and Discord (interface).
The 3 bugs that taught me the most
The 4,180-token prompt. Ollama has a 4,096-token context window. My prompt was injecting 11,621 characters of knowledge base into every message. Ollama silently truncated it, then churned for 5 minutes before crashing. The answer had been sitting in the logs the whole time: truncating input prompt limit=4096 prompt=4180. Fix: a compact version of the context — 300 tokens for WhatsApp, 700 for email.
The 5-minute timeout. Even after shrinking the prompt, the error kept happening. Cause: non-streamed requests leave Ollama waiting silently through the entire generation. After 5 minutes, the server drops the connection — on the Ollama side, not the client's. Fix: switch every inference call to streaming. Tokens arrive progressively, the connection stays alive.
Benin's phone numbers. Benin changed its phone number format: 8 digits → 10 digits with the 01 prefix. Google Maps returns the new format. The agent was silently trying to send WhatsApp messages to invalid JIDs. Fix: phoneToJid() handles both formats and forces conversion to the new one.
What the local LLM changes economically
Ollama on CPU, no cloud API.
100 messages generated per day × 30 days with GPT-4 Turbo: roughly €60/month for generation alone. In a market where clients pay 150,000 XOF (~€230) for an entire project, that cost structure becomes a meaningful variable.
With a local LLM: zero marginal cost after setup. Latency is higher (10-30 seconds per message instead of 2 seconds). But for messages that aren't urgent and go through human validation — that's acceptable.
Zero marginal cost enables patterns you wouldn't dare try with a metered API: generating 50 messages in bulk, running pattern analysis in the background, following up with every dormant lead without computing ROI first.
The control interface
Everything is driven from Discord — 12 slash commands:
/prospecter niche:restaurants ville:Cotonou nombre:50— launches scraping/campagne canal:whatsapp— generates messages for every uncontacted lead/dashboard— pipeline + AI intelligence + follow-ups in 3 embeds/prospect 22967xxxxxx— a prospect's full profile, with history and patterns/analyse jours:7— AI feedback on what worked / didn't work/learning stats|graph|update— state of the learning system
What it isn't yet
The agent replies to prospects in 10-30 seconds (Ollama CPU latency). On some fast-moving conversations, that's noticeable.
Google Maps scraping is limited by CAPTCHAs — no bulk scraping without pauses.
The learning system improves the scripts, but not yet the follow-up intervals or the qualification criteria.
These limits are known. They don't undermine the system's usefulness. They define the next phase.
→ The agent, not the employee — the philosophy behind the architecture
→ I built an AI assistant that knows everything I know