← Building a solo company with AI agents

Part 6 of 40 · 7 min read

Market to lead: turn an enquiry into a decision worth making

Experimental · Work in progress · Internal R&D

Capture an enquiry, resolve identity, qualify fit and route an opportunity using the prototype’s concrete thresholds and handoffs.

Arunank Sharan · Kuzushi Labs ·

In this article

A solo founder should not have to copy every inbound email into a spreadsheet, look up the sender, decide whether the enquiry fits and remember to follow up. That is the work this loop is designed to absorb. Its output is a qualified opportunity with supporting context, or a clear reason to defer or reject it.

The local prototype already implements capture, identity resolution, enrichment, consent-state handling, fit scoring, lead scoring and sales handoff. It uses deterministic agents so each transition can be inspected. Live mailbox transport and stronger qualification models remain separate work.

Walk one enquiry through the system

Take this sample form:

form = {
    "submission_id": "pilot-enquiry-017",
    "name": "Mira",
    "email": "[email protected]",
    "company": "Example Analytics",
    "consent": True,
    "message": "Can we book a demo of a document-search pilot?",
}

The form connector creates a submission record and a trigger. The capture agent creates a lead. Enrichment resolves identity and adds the available company context. Consent handling records the supplied permission state. The qualification stages then evaluate fit and intent before routing a sales handoff.

The existing pipeline interface is straightforward:

from mtl.pipeline import build_capture_pipeline

pipeline, dispatcher = build_capture_pipeline()
lead = pipeline.handle_form(form, tenant_id="studio-demo")
print(lead.state if lead else "No lead created")

The fixture data determines the outcome. This is a local pipeline call, not a subscription to a real form provider. In the current sequential driver, the downstream steps happen in one process; a durable event consumer will eventually replace that orchestration path.

The score is inspectable arithmetic

The prototype combines fit, intent and engagement:

composite = 0.40 * fit + 0.35 * intent + 0.25 * engagement
qualified = composite >= 60 and intent >= 30

With fit 75, intent 70 and engagement 30, the result is 62. That passes both local qualification thresholds. With the same fit but weak intent 20, the composite is 44.5 and the intent floor also fails. A promising company is not automatically an active buyer.

The matcher also contains an uncertainty route: a fit in the 35–50 region with confidence below 0.5 can trigger review. These are experimental constants. The current use of company-domain patterns and keywords makes the fixture predictable; it is not a validated model of customer quality. A serious next evaluation would include students, competitors, consultants, existing customers, ambiguous domains and enquiries without a company email.

Preserve identity without flattening the history

If Mira fills in the form and emails the next day, I want two interactions linked to the same person. I do not want two sales opportunities by default, nor do I want the second message discarded as a duplicate just because the sender matches.

The deduplication keys therefore answer different questions. A submission ID identifies a repeated transport event. A resolved person identifies a contact. An opportunity represents a buying process. They should not share one simplistic key.

The lead record should carry the source interaction, score version, evidence supporting fit, outstanding questions and handoff state. It should also show whether enrichment was unavailable or exceeded the prototype's US$0.20 per-lead cap. Missing data should remain missing, rather than become a confident negative score.

Where the founder enters

A routine qualified lead can be assigned and prepared for sales. An unusual strategic account or uncertain fit belongs in the review inbox. The review should say why it stopped: “Company type is ambiguous; product need is clear; budget and deployment requirements are missing.” That is more actionable than “AI confidence low.”

For this studio, I would ask the founder only for the unresolved commercial choice. The agent can prepare a concise brief with the requested deliverable, relevant source excerpts and a suggested next question. Sending that question is a separately authorised action.

Close the loop with sales outcomes

Lead scoring that never sees won, lost and unprofitable work will optimise for its own labels. The cross-loop prototype links opportunities back to leads and campaigns. That allows a later outcome to inform which demand was actually useful.

My initial measurements would be duplicate-opportunity rate, time to a reviewable brief, missing-context rate, and conversion of accepted leads into suitable work. I would also sample rejected leads. A very tidy inbox is not a success if the system quietly filtered out the best customer.

Turn a qualification rule into a replayable decision

The value of a deterministic first version is that a lead can be replayed after the scoring policy changes. Keep raw evidence separate from the derived score. If a new policy weights engagement differently, I should be able to recompute the score without pretending the customer said something new.

from company_lab.business import qualify

cases = [
    {"fit": 75, "intent": 70, "engagement": 30},
    {"fit": 75, "intent": 20, "engagement": 30},
]
results = [qualify(**case) for case in cases]
assert str(results[0][0]) == "62.00"
assert results[0][1] is True
assert results[1][1] is False

For each result, the production record should retain score-policy version, evidence IDs, derived values and the action taken. A reviewer changing the disposition should record why. “Not a fit because the requirement is a one-off spreadsheet export” is useful training evidence; “score wrong” is not.

A real enquiry contains missing and conflicting facts

Suppose the contact writes from a personal address but says she represents a 200-person company. The enrichment adapter cannot confirm the organisation. I would retain company_size=unknown with the claimed value in the source interaction. Missing verification is not evidence that the company is tiny. The agent can ask for the relevant deployment requirement or business use before spending more on enrichment.

The source pipeline's small enrichment cap is a useful boundary. I would enforce it before calling the provider, using the provider's charge model and a task-level reservation. A failed enrichment call may still be billable. The result should preserve whether the lookup returned no match, failed transiently or was skipped because the budget was exhausted.

A CRM connector then projects only the fields it owns: source, contact reference, qualification state and concise evidence-backed summary. It should not overwrite account ownership or an existing negotiated relationship merely because a new form arrived.

The lead loop retains source facts, distinguishes unknown evidence and routes borderline cases for review.

Compose the agent's job as a small set of actions

For capture, expose find_contact, record_interaction and propose_lead. For qualification, expose read_offering, read_evidence, request_missing_information and propose_disposition. Sending a message still goes through the communication action and its permission checks.

This separation gives the model a useful task: identify the need and the missing facts. Arithmetic and state transitions remain deterministic. If the model extracts “demo next Thursday,” retain the original phrase and resolved timezone rather than turning it immediately into an appointment. The calendar loop can confirm the intended date and availability.

A high-value output for the founder might read:

The prospect needs source-linked search over maintenance documents. The requested document volume fits the pilot. Deployment location and acceptance owner are missing. Prepare a clarification email; do not promise a delivery date yet.

Every claim in that brief should point to the interaction or offering record. The agent does not need to invent a company profile to make the brief sound complete.

Measure the rejected queue as carefully as the accepted queue

Create a review sample stratified by source and disposition. If every rejected lead is excluded from evaluation, the system can look accurate by approving only easy cases. Inspect personal-email leads, existing customers, referrals, unsupported languages and incomplete forms separately.

The practical evaluation distinguishes identity accuracy, evidence extraction, suitability decision and communication choice. A correctly scored lead sent from the wrong mailbox is still an operational failure. A borderline lead held for one specific question can be a successful outcome even though it did not convert automatically.

For the first implementation exercise, replay a duplicate form, a follow-up email and a contradictory enrichment result. The expected output is one buying process with three evidence records and an explicit unresolved fact. The connector, ontology and qualification agent each have a part in that result.