← Back to tools

Open source · MIT

View on GitHub ↗

Account research agent with code-enforced disqualifier policy

LangGraph agent that takes a company domain and produces a decision-ready ICP-fit brief — with a self-correcting critic loop and a hybrid disqualifier policy enforced in code, not in the prompt.

$0.30

per account brief

MIT

open source license

LangGraph Anthropic SDK Pydantic Firecrawl Claude Sonnet Claude Haiku Python

The problem

ICP-fit research is the bottleneck behind every meaningful outbound conversation — but it’s also the easiest task to fake with surface signals. Clay tables score companies by populating columns; what they can’t do is reason about why a “strong fit by signals” might still be wrong (a sales-tech vendor matches every ICP keyword but is actually a competitor, not a buyer). The naive answer is “use Claude in a Clay column” — but that gives you scoring without self-correction, evidence without auditable reasoning, and binary disqualifiers that miss the cases where the rule is right AND the exception is right too.

What it does

Input: one company domain (e.g. vercel.com). Output: a decision-ready markdown brief with an ICP fit score, evidence quotes, a recommendation (pursue / nurture / pass / research-more), a pitch angle grounded in the evidence, and — when applicable — a transparent Disqualifier Override section explaining why the agent ignored a rule and chose to recommend pursue anyway.

The architecture is a LangGraph state machine: research nodes (scraper with inline jobs extraction, web_enricher with Anthropic’s native web_search) feed extractor nodes (icp_extractor, gtm_maturity), which feed a critic that scores the brief and — when gaps exist — emits structured Gap objects naming which specific node should re-fire to close them. The orchestrator selectively re-dispatches via LangGraph’s Send API. Self-correcting research, not one-shot enrichment.

Architecture

Architecture diagram of the Account Research Agent: a domain enters the orchestrator, which dispatches in parallel to the scraper (with inline jobs extraction) and the web_enricher. Both feed two parallel extractors (icp_extractor with fit and override, and gtm_maturity). Both extractors feed the critic, which either loops back to the orchestrator on gaps or proceeds to the compiler, which emits the final brief. Orange nodes are Haiku 4.5 calls; blue nodes are Sonnet 4.6 calls.

Blue nodes call Claude Sonnet 4.6 for reasoning and tool use. Orange nodes call Claude Haiku 4.5 for structured extraction. The two subgraphs (Research and Extractors) run their nodes in parallel within a single super-step — that’s the design choice that lets the critic loop fire exactly once per iteration rather than chasing race conditions.

Architectural decisions worth defending

1. Code-enforced disqualifier policy, not prompt-enforced. A naive ICP-fit agent treats disqualifiers as binary (agency → score 1, Series F → score 1). Real GTM judgment is more nuanced. This agent has two paths when a disqualifier hits: honor it (default — code clamps fit_score ≤ 1) or override it (the agent must populate override_reasoning with a specific, dated, source-attributable signal — and the brief surfaces the override in a dedicated section). The clamp lives in code, so the LLM cannot accidentally skip the rule. Override is opt-in via an explicit field, not opt-out via convincing prose.

2. LangGraph for the loop, Anthropic SDK direct for the leaf nodes. LangChain wrappers add abstraction debt without earning their weight at the leaf-node level. The framework only carries the state machine and the critic loop; node bodies call the SDK directly with forced tool use for structured output, native web_search for the research node. No LangChain wrappers, no provider lock-in.

3. The critic emits structured Gap.target_node, not just “this is incomplete.” When the critic finds gaps, it names which specific node should re-fire to close them — funding-stage gap → re-fire web_enricher with a hint; pricing page missing → re-fire scraper with /pricing. The orchestrator dispatches selectively. That’s the difference between self-correcting research and one-shot enrichment.

See it work

Run the agent on vercel.com (Series F, $9.3B valuation — well past a typical Series A-C target):

ICP fit: 4.0/5 (Series F · B2B SaaS — developer platform / AI cloud infrastructure) Recommendation: Pursue — confirmed GTM Engineer JD + new COO signals live buying window.

Disqualifier override: Series F stage hit the series-d-plus-legacy rule, but COO Grosser published a Nov-2025 thesis on the GTM Engineer role she’s hiring. Internal Vercel Agent deployment confirms agentic GTM posture. These are concrete, dated signals that Vercel is actively building — not maintaining — GTM infrastructure.

A Clay table can score 4.0. It cannot tell you why it overrode the rule. That gap is what this tool demonstrates.

Four full sample briefs in outputs/samples/ on GitHub — a clean buyer-fit (Retool, with Head of RevOps Jonathan Krangel cited by name), two peer-vendor edge cases (Clay, Apollo), and one disqualifier (Deloitte).

Part of the pre-outbound stack

This is the first repo in a three-stage agentic pre-outbound system. Each repo runs standalone; together they compose end-to-end.

RepoAnswersOutput contract
Account Research Agent (this tool)Who fitsJSON via python run.py <domain> --json
Signal MonitorWhen to actJSON via python run.py --only <domain> --json
Meeting Prep AgentWhat to sayMarkdown + JSON sidecar via python run.py <input.yaml>

Downstream, Outbound Campaign Crew (CrewAI) consumes this tool’s summary.json to write claim-traceable sequences — and refuses, in code, to write outbound to any account this agent disqualified.

And the discipline layer above all of them:

RepoRole
eval-watchHow do you know your agents — all of them — are right? Monthly GH Actions cron, regression gate vs anchored baseline, STATUS.md auto-committed to the repo.

Three MIT repos. Three architecturally-coherent state machines. One thesis: code-enforced rules over prompt-asked-nicely rules, critic-driven self-correction, modular composition through stable CLI contracts. Same pattern shows up seven times across the portfolio: disqualifier clamp (here) → length compliance (sister project, the blog autopilot) → three clamps in Signal Monitor → concurrency clamp in SM runtime → four clamps + sequential composition in MPA → eval discipline enforced in CI (eval-watch) → Flow gates + task guardrails in CrewAI (Outbound Campaign Crew).

Use it

The agent is MIT licensed. Bring your own Anthropic and Firecrawl API keys. Configure the ICP for your own buyer profile in config.yaml (the policy and rule structures are domain-agnostic — they map cleanly to any consultative B2B context).

git clone https://github.com/aehirota/account-research-agent
cd account-research-agent
pip install -r requirements.txt
python run.py acme.com

Architecture deep-dive in docs/architecture.md. Operational docs in CLAUDE.md. Known limitations in KNOWN_ISSUES.md.

Let's talk

Let's build your revenue system

I'm available for GTM engineering and RevOps projects. Tell me where revenue is leaking and I'll tell you what I'd build.