What is Ideal Customer Finder

Ideal Customer Finder is an agentic AI sales intelligence platform. A sales rep describes their ideal customer in natural language, and an AI agent autonomously finds matching companies from the live web, enriches them with contacts and buying signals, and generates personalized outreach - all in a minute.

It is powered by SerpApi's Google Search API for sourcing and signal detection, and Qwen AI for reasoning, scoring, and writing. Every step is traced and observable. Nothing sends without human approval.


The Problem

B2B sales reps spend 70% of their time on work that isn't selling. Researching companies, finding the right contact, writing a personalized email, updating the CRM - all of it manual, all of it slow, all of it based on stale data from static databases that were last updated months ago.

The result: reps reach out to companies that just got acquired, contact people who left six months ago, and send generic emails that reference signals that are no longer relevant. Pipeline suffers. Quota suffers.

The root cause isn't effort - it's data. Sales teams don't have access to live web intelligence at the moment they need it.


The Insight

SerpApi gives you Google's view of the live web. Every company's LinkedIn page, every funding announcement, every executive hire, every job posting - all of it accessible in real time via structured search results, plus Google's own Knowledge Graph for companies notable enough to have a Knowledge Panel.

The question is: what's the right architecture to turn that live web data into revenue?

Ideal Customer Finder is our answer - surfacing the intelligence that's already on the web so sales reps know exactly which companies to call, why, and what to say.


How It Works

A sales rep defines their Ideal Customer Profile (ICP) - the type of company they want to sell to - and the agent does the rest:

  1. Finds matching companies from the live web - SerpApi's Google Search API searches for LinkedIn company pages matching the ICP criteria in real time (see SerpApi module in the repo: backbone/app/integrations/connectors/serpapi.py)
  2. Parses firmographic data from LinkedIn search snippets - employee count, headquarters, industry, description
  3. Enriches each account - the LinkedIn snippet's own "Website:" mention first (tied to the confirmed listing), then Google's Knowledge Graph for founded year, headquarters, and employee count when a company is notable enough to have a Knowledge Panel, falling back to an inferred homepage from organic results otherwise
  4. Detects buying signals - funding rounds, executive hires, market expansions - via 4 parallel SerpApi Google Search queries per company with date-range filtering
  5. Scores each account against the ICP - Qwen assigns a fit score based on industry, size, geography, and signals
  6. Generates personalized outreach anchored to real signals - Qwen writes each email using the actual buying signal as the hook
  7. Queues everything for human approval - Qwen's drafts wait for a human decision before anything sends

The entire pipeline runs in a minute for cents.


The Architecture

Ideal Customer Finder is built as a 9-node state machine. Each node has a single responsibility, reads from the shared state, calls its tools, and writes results back. The pipeline is fully observable - every SerpApi call, every LLM call, every token logged with inputs, outputs, reasoning, and latency.

ICP definition (ambiguous, natural language input)
    ↓
[1] load_icp — reads ICP definition from DB
    ↓
[2] [Qwen] Translate ICP → structured search parameters
    ↓
[3] [SerpApi Google Search] Find LinkedIn company URLs, parse firmographics from
    snippets, enrich each account: snippet's own "Website:" mention (most reliable)
    → Knowledge Graph → inferred homepage from organic results → slug guess (last resort)
    ↓
[4] Bulk upsert sourced accounts to the database
    ↓
[5] [SerpApi Google Search] Contact enrichment — LinkedIn profile search per account
    ↓
[6] [SerpApi Google Search] 4 queries per company for buying signals (tbs date-range filtered)
    ↓
[7] [Qwen] Score each account for ICP fit (LLM reasoning + pgvector cosine similarity)
    ↓
[8] [Qwen] Generate value hypothesis per top account
    ↓
[9] [Qwen] Write personalized outreach anchored to real signals
    ↓
[10] Human-in-the-Loop checkpoint → approve or reject each draft

Why the Google Search API - And Why We Use the Knowledge Graph

Before settling on the Google Search API as the foundation, we evaluated every SerpApi engine to find the best fit for a GTM sales application. We then made a deliberate architectural decision about how deeply to use it — one that directly affects the quality of outreach a sales rep can send.

API Evaluation

Google News engine — we evaluated the standard Google Search engine against engine=google_news for signal detection. SerpApi's documented google_news response schema returns title, source, link, date, and thumbnail fields — no snippet or summary text field. Our signal classification step needs text to classify (is this a funding signal, a hiring signal, or noise?), and a schema with no snippet means an extra fetch per article just to get classifiable text. The standard Google Search engine's organic_results already pairs a direct source link (BusinessWire, FinTech Futures, company newsrooms) with full snippet text in the same response — one call gets both the source and the text needed for classification.

Google Maps / Places engine — evaluated for headquarters enrichment. Built for physical location lookup: address, coordinates, hours, ratings. The documented response has no employee count, founded year, or company description fields — the firmographic profile ICP scoring needs isn't part of this engine's schema. Not applicable.

Google Jobs engine — evaluated as a hiring signal source. Google for Jobs listings depend on the employer (or an aggregator like Indeed or LinkedIn) publishing structured JobPosting markup that Google indexes — it's a jobs-search product, not a general company search. That means coverage for any given company in a user-defined ICP depends on whether their postings happen to carry that markup or route through an indexed job board, which isn't something we can rely on. The standard Google Search engine can surface the same hiring signal — a press release, a LinkedIn post, a news item about a hiring spree — regardless of whether the underlying job posting is structured-data-indexed.

The conclusion: engine=google with the standard organic results is the right foundation for a GTM sales application — powerful enough to source companies, enrich contacts, and detect buying signals across any industry and any signal type, all from a single unified interface.

The Knowledge Graph Decision

The standard approach to account sourcing via search is: find the LinkedIn company URL, parse the SERP snippet, guess the website from the LinkedIn slug. That last step is where data quality falls apart.

A LinkedIn slug is just a URL-safe identifier chosen by the company — it has no guaranteed relationship to their actual domain. A company with the slug acme-corp might own acme.com, acmecorp.io, or getacme.com. Guessing acme-corp.com is wrong often enough to matter — a sales rep whose outreach links to the wrong company website, or whose ICP scoring is based on a misidentified company, loses credibility immediately.

SerpApi's knowledge_graph object in the Google Search response solves this well. For companies notable enough to trigger a Google Knowledge Panel, the response includes Google's own curated attributes: website, founded, headquarters, employees, type, and description. These are not scraped — they are Google's structured entity data, maintained and verified by Google's Knowledge Graph team.

We implemented a second SerpApi call per account — a by-name search that retrieves the Knowledge Graph alongside organic results — and built a priority waterfall for each firmographic field. A bare company name is an inherently ambiguous lookup key for any system, automated or manual — two unrelated companies can share a generic name — so we layered in an even more specific signal ahead of it: the LinkedIn snippet's own "Website:" annotation, already present in the initial search and tied to the exact, already-confirmed company listing. No separate lookup needed, because it's data the pipeline had already fetched. That's the top priority, with the Knowledge Graph as the strongest available source whenever the snippet doesn't carry it:

  • Website: LinkedIn snippet's own "Website:" mention (tied to the confirmed listing) → Knowledge Graph website → first organic result not from a directory/social domain (inferred) → LinkedIn slug guess (last resort)
  • Employee count: Knowledge Graph employees attribute (e.g. "164,000 (2022)") → LinkedIn snippet regex match (present only if the snippet happened to contain "X-Y employees" text)
  • Headquarters: Knowledge Graph headquarters → LinkedIn snippet regex match
  • Founded year: Knowledge Graph founded (e.g. "April 1, 1976, Cupertino, CA") → absent (no other source)
  • Industry: LinkedIn snippet keyword match → Knowledge Graph type + description text (second pass, often better-worded)

The founded year is a concrete example of why this matters for outreach personalization. The LLM signal inference prompt includes "Founded: 2018 (7 years old)" when available — the agent uses this to infer growth-stage signals like "early enough to still be building sales infrastructure, late enough to have budget." Without the Knowledge Graph, that fact is blank and the inferred signals are generic.

We evaluated whether the extra search per account was worth the cost. The answer is yes, for two reasons. First, the accuracy improvement is not marginal — it's the difference between a verified company website and a fabricated domain, between a real employee count and a missing field. Second, the cost is one search per account, which at 5 accounts per run adds 5 searches to a run that already uses 26. The percentage increase is small; the quality improvement to the outreach is not.

enrich_with_knowledge_graph=True is the default and the right default for a sales rep tool where data accuracy directly affects whether the outreach converts — layered together with the snippet-first signal so firmographic accuracy comes from multiple SerpApi sources agreeing, not a single field.

How the Connector Was Built

The SerpApi connector was built through a structured investigation before any code was written. The first step was fetching the SerpApi documentation live to confirm the exact API surface: that site: operators work in the q parameter (required for LinkedIn company and profile searches), that tbs=qdr:m and tbs=qdr:y handle date-range filtering for signal detection, and that organic_results[].link/.title/.snippet maps directly to what the pipeline needed — no adapter layer required.

The second step was a field-by-field audit of every firmographic value the pipeline uses, classifying each one before writing a line of code:

Field Source Reliability
website LinkedIn snippet's own "Website:" mention → Knowledge Graph → inferred homepage from organic results → LinkedIn slug guess (last resort) Multi-source, most reliable signal used first
industry Keyword match against title/snippet into ~8 hardcoded buckets Best-effort, coarse
employee_count Knowledge Graph employees attribute → regex-parsed from LinkedIn snippet text Real when present, absent otherwise
headquarters Knowledge Graph headquarters → regex-parsed from LinkedIn snippet text Real when present, absent otherwise
founded_year Knowledge Graph founded Absent without KG — no other source exists

This audit is what drove the Knowledge Graph enrichment decision — founded_year is completely absent without it, and employee_count/headquarters are unreliable without it. It also drove the inline comments throughout serpapi.py that document exactly what each field's source and reliability is, so future developers always know whether a value is verified, inferred, or a last-resort guess.

An early design decision was whether the Knowledge Graph enrichment should be optional or always-on. The argument for optional was cost — it adds one extra search call per account sourced. The argument for always-on was that the whole point of the connector was better data, not just a different source for the same data. Always-on won.

The connector exposes four methods — account sourcing, contact enrichment, signal detection, and authentication — and plugs directly into the agent pipeline with no changes required to the pipeline itself.


Why SerpApi is Central - Not Peripheral

SerpApi is the foundation of Ideal Customer Finder - not an add-on. Remove it and the platform doesn't work.

Account sourcing is impossible without it. There is no static database of "Series B fintech companies with 200-500 employees that just raised a funding round." That data only exists on the live web. SerpApi's Google Search API finds LinkedIn company pages matching the ICP in real time - companies that fit the criteria today, not six months ago when some database was last refreshed.

Contact enrichment is impossible without it. SerpApi's Google Search API finds decision-maker contacts via LinkedIn profile search - names, titles, LinkedIn URLs. No separate people database needed. No stale contact lists.

Signal detection is impossible without it. The platform runs 4 parallel Search API queries per company - funding news, hiring activity, executive changes, market expansions - with SerpApi's tbs date-range filter (qdr:m for the last month, falling back to qdr:y for the last year) to ensure signals are recent. An outreach email that opens with "I saw you just raised your Series B" only works if you actually know they just raised their Series B. SerpApi makes that possible.

Firmographic accuracy depends on it. Founded year has no source at all without the Knowledge Graph, and headquarters/employee count fall back to unreliable snippet regex without it. Website resolution combines the Knowledge Graph with the LinkedIn listing's own data for the most reliable result — multiple SerpApi signals working together, not single-field reliance.

In a live run against an Enterprise SaaS (Series B+) ICP:

  • SerpApi found 5 matching companies from LinkedIn
  • SerpApi enriched 5 accounts with Knowledge Graph data (website, founded year, headquarters)
  • SerpApi returned 20 decision-maker contacts via LinkedIn profile search
  • SerpApi detected 95 buying signals from live web searches across 5 accounts
  • Qwen wrote 4 personalized outreach emails, queued for human approval

Every one of those numbers is zero without SerpApi.


The Human-in-the-Loop Design

Ideal Customer Finder never sends anything automatically. Every outreach draft requires explicit human approval before it goes anywhere. This is intentional - not a limitation.

SerpApi provides the live intelligence. Qwen does the reasoning. But a human makes the final call on every email. This is the right model for outbound sales: high automation, high quality, human accountability.


The Business Case for SerpApi

Every sales rep using Ideal Customer Finder is a SerpApi consumer. Every ICP run triggers:

  • 1 Search API call for account sourcing (finds up to 20 LinkedIn URLs, parses top 5)
  • 1 Knowledge Graph Search API call per account (firmographic enrichment)
  • 1 Search API call per account for contact enrichment
  • 4 Search API calls per account for signal detection (with tbs date-range filtering)

A sales team of 10 reps, each running 2 prospect sweeps per week at 5 accounts per run, generates ~620 Search API calls per week - just for one team. Scale that to the thousands of B2B sales teams that need this capability and the usage compounds fast.

Ideal Customer Finder is designed to make SerpApi's Google Search data the default infrastructure for B2B prospecting. The more reps use it, the more valuable the live data becomes, and the more indispensable SerpApi's infrastructure is to the sales workflow.


Key Strengths

  • Full observability. Every step traced. Every SerpApi call logged with inputs and outputs. Every token counted. A sales manager can see exactly what the agent did and why.
  • Production architecture. Multi-tenant PostgreSQL with Row-Level Security. Celery async workers. JWT authentication. Async API calls.
  • ICP-driven, not keyword-driven. The AI translates a natural language customer description into structured search parameters. A rep doesn't need to know LinkedIn's industry taxonomy. They just describe their ideal customer.

Try it out live

URL:      https://idealcustomerfinder-873195210882.us-central1.run.app/login
Email:    [email protected]
Password: IdealCustomer!2026

Two ICPs are pre-loaded: Enterprise SaaS (Series B+) and Series B Fintech Scaleup. Select one, click Run Agent, and watch the pipeline execute live against SerpApi's Google Search API. Results in a minute.

Built With

Share this project:

Updates

Submission history