Case study
KonvoLead
A B2B SaaS product: a WhatsApp and phone-based AI sales agent that real-estate developers subscribe to, so their own leads get an instant, grounded first response instead of waiting on a human.
In active development — not yet live with real buyer traffic. The WhatsApp Business Account is completing Meta's verification process; every flow below has been built and exercised end to end through an internal test harness.
The problem
Why this exists
A developer's WhatsApp leads — from ads, referrals, or organic enquiry — sit until a human rep has time to respond, and that response is inconsistent in speed, language, and factual accuracy. For a buyer who may be spending their life savings, that inconsistency is the real risk. KonvoLead is built against one metric: more attended site visits than the developer's existing manual follow-up produces — not more messages sent, not more "engagement."
Architecture
How it works
- 1A lead messages in on WhatsApp or calls in; the number they reached maps to one developer's private agent.
- 2The agent reasons in an 11-tool loop — it can look up verified project facts, check visit availability, log a requested time, update what it knows about the buyer, or hand off to a human, never just generating a reply from memory.
- 3Every factual claim — price, spec, availability — is read from a structured, verified data table populated once when the developer onboards. Softer questions go through retrieval and reranking over the project's real documents. If neither has an answer, the agent says so: "I don't know" is a valid, safe answer, not a failure.
- 4Buyer facts — budget, timeline, which project they're interested in — persist on the lead's own record, so a conversation picks back up correctly even after a multi-day gap.
- 5When the agent hits the edge of what it can honestly help with — a negotiation, a complaint, a missing fact — it escalates to a human rep with the full context already summarized, not a cold handoff.
Judgment calls
Key decisions
Structured facts, not vector search, for anything that has to be exactly right
Prices, specs, and availability are never generated or interpolated by the model — they're read verbatim from a table populated once at onboarding. Retrieval and reranking are reserved for the soft, narrative edges of a conversation. It's the single rule that keeps the agent from ever bluffing on a fact a buyer could hold it to.
Redesigning the pricing model after learning what developers would actually share
The original plan assumed direct access to unit-level price lists. In practice, developers wouldn't hand that over, so the first version became a public-rate estimator — then, months later, was replaced entirely with real per-configuration pricing extracted verbatim from each developer's own documents at onboarding. Two different answers to "how do we talk about price," each responding to what was actually possible to get from a customer.
One rep gets paged, not five
When the agent escalates, exactly one available rep is notified, round-robin, with the full lead context packed into the notification itself — WhatsApp's own messaging rules only allow that much outside a live conversation. A deliberate trade against a broadcast-to-everyone pattern that would have needed a lot more machinery to build well.
The model swaps by config, not by code change
Which Claude model runs the conversation is an environment variable, not a hardcoded choice — specifically so a cheaper, faster, or more capable model can be A/B tested without touching the agent's logic.
Honest lessons
What didn't work
A single missing table took down every question, not just the one it was for
Wiring in a new pricing data source made it a hard dependency of the two tools the agent used to answer almost anything, so one missing database table left it unable to answer basic questions about size or location — not just price. The fix became a standing rule: a new data source can never be a hard dependency of an existing read path.
The same timezone bug, found twice
“5pm” silently became “10:30pm” because a buyer's requested visit time was parsed against the server's clock instead of India's, and got rejected as outside working hours. It was fixed once in the scheduling logic — then resurfaced independently in a different piece of code validating the same booking. The lesson written down afterward: a time that looks right isn't the same as a time that's been checked against the right clock.
Two data models that never got reconciled
An early, MVP-era set of tables sat unused alongside the real pipeline for most of the project's life — nothing populated them for a real developer, so any tool reading from them silently returned nothing instead of erroring. It surfaced only when the agent flatly denied having a unit type a project actually had — the quietest and most expensive failure mode in the system, because it never looked broken. It looked like an empty database.
By the numbers
What's real, not aspirational
$0.26
Cost of a real, traced 3-turn conversation on Claude Sonnet
11 tools
The agent's full action space, from lookup to escalation
100+ / 44 days
Commits since the first one, with no gap longer than a few days