Install
$ agentstack add skill-zevenue-headless-gtm-01-icp-qualify ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
ICP Qualify - the gate
Discovery filters match labels (industry codes, size bands, locations as a database recorded them). This skill judges fit: would this specific company plausibly buy from this specific client? The two questions diverge constantly - acquisitions, competitors, stale headcounts, and shell listings all pass label filters and then waste enrichment spend downstream. The gate exists so every credit spent after discovery goes to a company that could actually buy.
The skill is general-purpose by construction: nothing client-specific is hardcoded. It first understands the client, then compiles a client-specific qualification brief, gets it approved, and only then judges prospects.
Phase 1 - understand the client
Detect the operating mode; never ask for what is already available.
- Package mode - running inside the chain: inherit the client profile
(what they sell, ICP bounds, exclusions) from the chain's client-profile artifact or the router's plan. Ask nothing.
- Standalone mode - invoked directly: the user names the client company
and provides whatever they have - ICP description, firmographic bounds, competitor names, exclusion list. Proceed with whatever exists. Missing information never blocks a run.
Research fallback (bounded). If the client's business or ICP is still unclear, read the client's own website - homepage, about, product pages, at most ~5 pages - and draft the missing understanding. Cache everything learned into the client profile so research runs once per client, not once per run.
Phase 2 - compile the qualification brief
From the client understanding, write the criteria that will judge every prospect. The brief has two mandatory checks, one universal check, and client-specific dynamic checks:
- Business nature (primary). What does the prospect actually do, judged
from its description - and does that match who the client sells to? This is also where competitors are caught: a prospect in the client's own product category is never a lead.
- Firmographics. Headcount band, geography, industry bounds from the ICP.
Cheap, rule-based - and applied with the wide-tolerance rule below, because discovery data is often stale.
- Independence and liveness (universal). Is this still an operating,
independent business? Acquired, merged, dormant, or shell companies are not buyers regardless of fit. This check is client-independent and always on.
- Dynamic checks (client-specific). Derive 1–3 checks from this client's
reality that the generic checks can't know - e.g. for a QA-automation client: "does the prospect ship software?"; for a payroll client: "does the prospect have employees in the covered countries?". These are generated fresh per client, from the profile and research.
The brief is an artifact, not a thought. Write it out (see references/brief-template.md), show it for approval before judging anything, then save it to the client config. Later runs reuse the saved brief - regenerate only when the user asks for a refresh, when calibration amends it, or when a run's disqualification rate departs sharply from the client's history (suggest a refresh; never regenerate silently). The brief records which model it was calibrated with; a model change re-triggers the acceptance check below.
Phase 3 - judge every prospect
Read references/dq-catalog.md before judging - it defines every disqualification category and the evidence each requires.
Apply the checks in cost order: exclusion list first (free), firmographic screen next (rules on existing fields), then business-nature and the remaining judgment checks.
Three verdicts, asymmetric on purpose:
qualified- fits the brief; no DQ category applies.disqualified- a DQ category applies with quotable evidence (a
sentence, a redirect, a number, a list entry). Name the category and the evidence, always.
uncertain- fit can't be confirmed, but no DQ can be proven.
Uncertainty is never a disqualification. The two mistakes cost differently: wrongly qualifying wastes a few credits; wrongly disqualifying throws away a real buyer. When in doubt, uncertain.
The wide-tolerance rule for firmographics. Discovery data lies about size and location often enough that near-misses must not hard-fail: outside the band but within roughly 2× of the ceiling or half of the floor → uncertain, resolved later by fresher evidence. Beyond that → disqualified (no data error is that large). Missing data → proceed; absence is never evidence.
Description sourcing. Business-nature judgment needs a description. When a record has none (common for Maps-sourced rows), fetch the prospect homepage's title and meta-description with a plain HTTP request - free, no scraping service - and judge from that. If the fetch fails, the verdict is uncertain with the gap noted.
Two passes. Pass 1 runs pre-spend on discovery fields. Pass 2 re-runs after scrape/signal skills have added evidence: re-judge every uncertain, confirm every qualified (evidence can also demote - an acquisition surfaced by a scrape moves a qualified row to disqualified). Verdicts update in place with pass: 2; rows move between output files to match their new verdict.
Execution engines
- Default: judgment runs in-session. No API key, no per-company cost.
- Scale option: for large lists, an external model may do the judging via
an OpenAI-compatible endpoint - any vendor. Configuration: QUALIFY_LLM_BASE_URL, QUALIFY_LLM_API_KEY, QUALIFY_LLM_MODEL. Missing configuration → in-session, silently.
- Acceptance check: a newly configured model must first pass the chain's
held-out evaluation set before judging a real list, and its false-disqualification rate is the number to watch - that's the expensive mistake. A model that fails falls back to in-session judgment.
- External judgments return structured JSON matching the record contract;
invalid responses are retried once, then that record becomes uncertain.
Calibration (first run per client, and per model)
- Judge the first 10 records; show a compact table: company · verdict ·
category · one-line reason.
- Take corrections. Every correction becomes a rule written into the brief
(e.g. "hybrid manufacturers with named product lines qualify").
- Repeat in batches of 10. After two consecutive clean rounds, run the
remainder without check-ins.
- Same client + same model later → skip calibration. Model changed → run the
acceptance check, then one abbreviated calibration round.
Output contract
Three files per run, under runs// per _shared/CONVENTIONS.md:
records.jsonl- what flows downstream: allqualifiedrows, plus
uncertain rows only if the user opts them in (see the gate below). Every row keeps all upstream fields and carries its qualification object, so a later pass can re-find and re-judge the uncertain ones.
uncertain.jsonl- the review queue, when uncertain rows are withheld:
each with its open question. Nothing here is lost; it waits for pass 2 or a human decision.
disqualified.jsonl- the audit trail: every rejection with category,
reason, and quoted evidence. Downstream skills never read this file; the client conversation about "why did the list shrink" starts here.
Because disqualified rows are physically absent from records.jsonl, downstream skills need no changes - they read the forwarded file exactly as they always have.
The qualification object on every row:
{"qualification": {
"verdict": "disqualified",
"dq_category": "acquired",
"reason": "Operates as a division of a larger vendor",
"evidence": "https://example.com - 'Example is now part of BigCo'",
"flags": [],
"pass": 1,
"confidence": 90}}
The uncertain gate. After judging, report the counts and ask one question: "Qualification complete - N qualified, M uncertain, K disqualified. Forward the uncertain ones too? (yes/no)" - with the uncertain list summarized so the choice is informed. Never forward them silently; never drop them silently.
Run summary. Close every run with: total in · qualified / uncertain / disqualified · DQ breakdown by category · flags raised · and downstream spend avoided (disqualified count × the per-company cost of the chain's paid steps) - the gate's ROI, stated every time. In standalone mode with no cost sheet available, say so and ask for a per-company figure rather than invent one.
What never to do
- Never delete a record - every row lands in exactly one of the three files.
- Never disqualify on uncertainty, missing data, or a label alone.
- Never qualify a company in the client's own product category.
- Never judge prospects before the brief exists and has been approved.
- Never let a calibration correction go unrecorded in the brief.
- Never end a run without the summary and its spend-avoided line.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Zevenue
- Source: Zevenue/headless-gtm
- License: MIT
- Homepage: https://zevenue.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.