← ZoomInfoCONTENT HISTORY

Update to ZoomInfo

Snapshot Sep 30, 2026 · 22:44 UTC · version 6.1.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "score-accounts",
  "description": "Score and rank a list of accounts (mixed ZoomInfo company IDs, names, or domains) by ICP fit + buying intent + recent triggers. Returns per-account composite score (0–100), tier (A/B/C), explainable component breakdown (fit / intent / trigger / engagement), a specific \"why now\" sentence per account, and the working weight set as a saveable search filter set. Resolves name/domain inputs via search_companies with explicit confirmation for ambiguous matches. Iteratively refinable — adjust weights, swap axes, retier, or drill into a specific account. Use for account-based selling, ABM list prioritization, territory planning, sales prospecting prioritization, signal-based selling, buyer intent ranking, B2B prospecting. Triggers on phrases like \"score these accounts\", \"prioritize this list\", \"rank by ICP fit and intent\", \"which accounts should I work first\", \"build a tiered account list\".",
  "included_files": [],
  "skill_md_contents": "---\nname: score-accounts\ndescription: Score and rank a list of accounts (mixed ZoomInfo company IDs, names, or domains) by ICP fit + buying intent + recent triggers. Returns per-account composite score (0–100), tier (A/B/C), explainable component breakdown (fit / intent / trigger / engagement), a specific \"why now\" sentence per account, and the working weight set as a saveable search filter set. Resolves name/domain inputs via search_companies with explicit confirmation for ambiguous matches. Iteratively refinable — adjust weights, swap axes, retier, or drill into a specific account. Use for account-based selling, ABM list prioritization, territory planning, sales prospecting prioritization, signal-based selling, buyer intent ranking, B2B prospecting. Triggers on phrases like \"score these accounts\", \"prioritize this list\", \"rank by ICP fit and intent\", \"which accounts should I work first\", \"build a tiered account list\".\n---\n\n# Score Accounts\n\nRank a list of accounts by ICP fit + intent + trigger signals. Calls `get_gtm_context(detailed: true)` unconditionally, resolves mixed-identifier inputs explicitly surfacing ambiguity, scores each account on four axes, and presents both the ranking and the weight set as iteratively-refinable artifacts.\n\n## The bar\n\n1. **Resolution accuracy 100%** — every input auto-resolved / verified / ambiguous / failed. Nothing silently picked.\n2. **Every score explainable** — composite is a transparent weighted sum, never an opaque number.\n3. **\"Why now\" cites a specific signal** — not the composite restated.\n4. **Every tier comes with a recommended action.**\n5. **Weights and axes are exposed and overridable.**\n\nSellers reject black-box scores. Transparency + per-account \"why now\" are what make this skill trusted.\n\n## Scope\n\nScores **company-level accounts**, not contacts. Persona-aware ranking is a chain target via `personalize-email` after tier-A is produced.\n\n## Input\n\n- **Accounts (required)** — list of ZI IDs / company names / domains / mixed CSV.\n- **Use case (default `prospecting`)** — `prospecting`, `abm`, `territory_planning`, `pipeline_acceleration`. Affects tier thresholds + recommended actions.\n- **Weight overrides (optional)** — `{fit, intent, trigger, engagement}` summing to 100.\n- **Tier thresholds (optional)** — `{A, B}`. C is the remainder.\n- **ICP override (optional)** — natural-language refinement on top of `get_gtm_context.icp`.\n- **Intent topics (optional)** — explicit list overriding GTM-derived defaults.\n\n## Four-axis framework\n\n| Axis | Question | Source |\n|---|---|---|\n| **Fit** | Does this match our ICP? | `enrich_companies` vs `get_gtm_context.icp` |\n| **Intent** | Are they actively researching topics we sell into? | `enrich_company_signals` (intent), matched to GTM priorities |\n| **Trigger** | Fresh event creating a window? | `enrich_company_signals` (news + scoops), last 90d by signal date |\n| **Engagement** | Already interacting with us? | `account_research` narrative for known accounts. If absent, weight redistributed. |\n\nEach axis 0–100 independently. Composite is the weighted sum — never collapsed to an opaque number.\n\n## Default weights\n\n```\nfit:        45%\nintent:     25%\ntrigger:    25%\nengagement:  5%   (redistributed if unavailable)\n```\n\nUser overrides accepted. Weights are exposed in every output. Cache per-axis scores; recompute only the composite when weights change.\n\n## Tier thresholds\n\n| Tier | Composite | Recommended action |\n|---|---|---|\n| **A** | ≥ 75 | Route to AE for 1:1 outreach within 24h. Chain to `personalize-email`. |\n| **B** | 50–74 | SDR sequence; ABM retargeting; nurture-to-meeting. |\n| **C** | < 50 | Watchlist; monitor for tier-promotion signals. |\n\nUse-case adjustments: `abm` → A=80/B=55 · `territory_planning` keeps defaults · `pipeline_acceleration` → A=65/B=40.\n\n## Workflow\n\n### 1. Pull GTM context (always)\n`get_gtm_context(detailed: true)`. Capture ICP, personas, competitors, offerings, strategic priorities. ICP = fit-axis target; strategic priorities → intent-topic curation.\n\n### 2. Honor input data first\nUse user-supplied weights / thresholds / ICP refinements / intent topics. Fall back to GTM defaults only for missing fields.\n\n### 3. Resolve identifiers (four-bucket routing)\n\n- **Auto-resolved** — top match dwarfs alternatives. Score without confirmation.\n- **Verified** — clear top match BUT plausible alternatives exist. Score; surface verification note.\n- **Ambiguous** — no dominant match. Pause scoring; surface candidates.\n- **Failed** — no match. List separately.\n\nRouting by input type:\n- **Numeric ZI ID** → auto-resolved.\n- **Domain** (`.com` / `.io` / `.co` / `.ai`) → `search_companies(companyWebsite)`. Single match → auto-resolved. Multiple → ambiguous.\n- **Name** → `search_companies(companyName)`.\n  - Top match's size/revenue dwarfs alternatives → auto-resolved.\n  - Clear top but 3+ plausible alternatives → verified with note.\n  - No dominant match → ambiguous.\n- **No match** → failed.\n\n**Surface rule.** Never silently pick a winner. Present top 5 with attributes; ask user to confirm. Use GTM context as soft tiebreaker for `verified` (e.g., a B2B SaaS context defaults an ambiguous name to the SaaS-industry candidate over an unrelated-industry candidate, with a flag).\n\n**Domain-confirmation gate (mandatory for high-collision names).** When `search_companies(companyName=X)` returns >100 matches AND no strong GTM tiebreaker exists, require domain confirmation. Surface top match's domain and ask. Never silently auto-pick — cost of getting it wrong is scoring the wrong company entirely.\n\n**Duplicate-record detection (mandatory).** If top candidates share the same domain root (e.g., `acmeco.com` and `acmecoinc.com`) AND ≤20% revenue diff AND same metro/country → flag suspected duplicate. Surface both records and offer to union. For signal-heavy workflows, scoring both and unioning is the right default — signals may be split across records.\n\nResolution path must hit 100% accuracy. Score auto-resolved + verified immediately; pause ambiguous; list failed separately.\n\n### 3.5. Relationship-context pre-flight (mandatory)\n\nTag each resolved account against GTM context. Tag visible on the row before the tier letter — sellers see relationship status BEFORE running the play.\n\n- **`competitor`** ⚔️ — in `get_gtm_context.competitors`. Don't exclude from ranking (competitive intel matters) but make it impossible to miss visually.\n- **`customer`** 🤝 — in `get_gtm_context.customers` / `proof_bank`. Shift recommended action to expansion / renewal.\n- **`partner`** 🔗 — in `get_gtm_context.partners` / `integration_partners`. Shift to co-sell / integration angle.\n- **`prospect`** — default; no tag.\n\nIn the row label: `⚔️ [Account] (B 62)`. Skill never silently produces \"pursue this competitor\" rankings.\n\n### 4. Define the intent relevance set\nFrom `get_gtm_context.strategicPriorities`, offerings, and competitor categories (or a user-supplied list), derive 5–10 themes you sell into. `enrich_company_signals` returns each company's active intent topics directly — there is no topic lookup or pre-query step — so these themes are the **match set** used in scoring (step 6): a returned topic counts toward intent only if it maps to one of them. Keep the themes; the matching happens per account during scoring.\n\n### 5. Fetch data per account (parallel, batched ≤10; chunked for large lists)\n\nBoth calls below batch multiple accounts per request, so fetch a chunk of accounts together rather than one-by-one:\n- `enrich_companies(zoominfoCompanyIds: [chunk], fields: industries, employeeCount, revenue, country, metroArea, businessModel, employeeCountByDepartment, foundedYear)` — up to 25 per call.\n- `enrich_company_signals(zoominfoCompanyIds: [chunk], signalTypes: [\"INTENT\", \"NEWS\", \"SCOOP\"])` — up to 10 per call. Returns each account's recent intent topics (each with `signalScore` and `audienceStrength`), news (with `category`), and scoops (with `scoopType`), plus a `date` on every signal. Do **not** pre-filter on score, topic, category, or date — that is applied during scoring (step 6).\n\n**Hard batch limit: ≤10 accounts per `enrich_company_signals` call (≤25 per `enrich_companies` call).**\n\n**Batch + context-window discipline.** For lists >25 accounts, process in **chunks of ~25 accounts** end-to-end (resolve → fetch → score → compose row → write chunk → discard raw payloads) before moving to the next chunk. Don't accumulate full raw enrichment payloads for hundreds of accounts in working context — once per-axis scores + the winning trigger event + the winning intent topic are captured per account, drop the rest. For >100-account lists, summarize completed chunks into running totals (tier distribution, top-A list, multi-product anomalies, duplicate-suspected flags, missing-axes counts) and discard the per-account breakdowns from context. Output is built incrementally chunk-by-chunk so a long list doesn't blow context.\n\nSkip `account_research` here; fire selectively in §7.5 for tier-A.\n\n### 6. Score each axis\n\n**Fit (0–100)** — compare `enrich_companies` to `get_gtm_context.icp`:\n\n| Dimension | Max | Banded scoring |\n|---|---|---|\n| Industry / sub-industry | 25 | Primary = 25 · secondary = 15 · adjacent = 8 · none = 0 |\n| Employee count band | 20 | In band = 20 · one off = 12 · two off = 4 · outside = 0 |\n| Revenue band | 20 | Same banding |\n| Geography | 15 | ICP country = 15 · in continent = 8 · outside = 0 |\n| Business model | 10 | B2B/B2C match = 10 · mixed = 5 · mismatch = 0 |\n| Technographic (optional) | 10 | Uses named tech-stack vendor = 10 · else 0. Verify via `search_contacts` + `techAttributeTagList` if needed. |\n\nCache per account; reuse across weight changes.\n\n**Intent (0–100)** — from the `enrich_company_signals` intent topics, keep those that map to the relevance set (step 4) with `signalScore` ≥ 60 in roughly the last 30 days (use each signal's `date`). Score `max(signalScore × audienceStrengthFactor)` over the survivors. A=1.0 · B=0.85 · C=0.7 · D=0.55 · E=0.4 (from `audienceStrength`). Cap 100. Record the winning topic for \"why now.\" If no relevant intent survives → 0 with \"no relevant intent activity\" flag.\n\n**Trigger (0–100)** — from the `enrich_company_signals` news and scoop signals, kept to the last 90 days by each signal's `date` (drop older). Map each signal's news `category` or scoop `scoopType` to the weight below:\n\n```\nevent_score = signal_type_weight × recency_factor\n```\n\n| Signal type | Weight |\n|---|---|\n| M&A, Funding, New CEO/C-suite hire | 95 |\n| Product launch, Hiring surge, Earnings beat/miss | 75 |\n| Partnership, New facility | 55 |\n| Pain-point scoop, Other PERSON moves | 45 |\n| Generic press release | 25 |\n\nRecency: 0-14d=1.0 · 14-30d=0.7 · 30-60d=0.4 · 60-90d=0.2 · >90d=0.\n\nAccount trigger = `max(event_score)` capped at 100. Record winning event for \"why now.\"\n\n**Engagement (0–100)** — if `account_research` returns rich CRM context: active deal/renewal/champion = 80–100 · past meeting/known stakeholder = 40–70 · no history = null. If null, redistribute weight and surface gap.\n\n### 7. Compute composite + assign tier\n\n```\ncomposite = round((fit × w_fit + intent × w_intent + trigger × w_trigger + engagement × w_engagement) / 100)\n```\n\nAssign per thresholds. Default A≥75 / B 50–74 / C<50 (use-case overrides apply).\n\n### 7.5. Auto-pull `account_research` on tier-A rows (mandatory)\n\nTier A = \"route to AE in 24h.\" Engagement-axis gap on tier-A is the highest-cost gap to close.\n\nFor each tier-A account (and ONLY tier-A — cost control): `account_research(zoominfoCompanyId, query=\"Open opportunities, active deal stages, named champion or blocker, last activity date, renewal timing\")`. Parse for:\n- **Open deal status** — stage, value, next step.\n- **Renewal date** — surface prominently if within 90 days.\n- **Named champion / blocker** — source-tag `[from account_research]`.\n- **Last activity** — flag if >60 days old.\n\nAppend inline beneath the why-now:\n\n```\n| 1 | [Account] | 🤝 A | 84 | ... | [Trigger event] X days ago — [pain-bridge]\n                                     ↳ Engagement: open deal $XXXk, champion [Name], last activity Xd ago [from account_research]\n```\n\nIf no CRM history → annotate \"no engagement signal — cold open.\"\n\nFor tier-B/C: skip — cost-to-value doesn't justify.\n\n### 8. Compose \"why now\" per account\n\nOne sentence anchored on the strongest signal:\n\n- **Trigger + in-tier fit** → cite event + date. \"Closed [counterparty] acquisition 20 days ago.\"\n- **High intent** → cite topic + score + recency. \"Spiked on '[topic]' (score 92, audience A) over 14 days.\"\n- **Strong fit, no fresh signal** → \"Perfect-fit ICP — no fresh trigger; pursue on fit alone.\"\n- **Engagement-driven** → \"Active deal in flight; renewal due in 47 days.\"\n- **Strong trigger BUT C-tier (fit mismatch)** → be explicit about routing: \"Do not pursue — strong trigger (new CEO 10 days ago) but ICP mismatch ([reason]) keeps this low priority.\" Don't bury the trigger; surface BOTH signal and recommendation.\n- **Low signal across all axes** → \"Low signal — monitor only.\"\n\nNever restate the composite as the why-now. Always cite the underlying axis driver.\n\n### 9. Self-check before output\n\n- ☑ Composite shown with component breakdown (fit / intent / trigger / engagement).\n- ☑ \"Why now\" cites a specific signal, not the composite.\n- ☑ Tier has a recommended next action.\n- ☑ Weights + axes used exposed.\n- ☑ Every input bucketed (resolved / ambiguous / failed) — none silently dropped.\n- ☑ Ambiguous surfaced, not silently picked.\n- ☑ Stale signals (>90d) contribute 0; not padded.\n- ☑ Missing axes flagged + weights redistributed transparently.\n- ☑ Iteration options offered.\n\n### 10. Present + offer iteration\n\n1. Accept ranking; save filter+weight set.\n2. **Adjust weights** — re-rank without recomputing axes.\n3. **Tighten / loosen tier thresholds.**\n4. **Refilter** — remove tier C / specific industries.\n5. **Swap ICP** — different ICP definition.\n6. **Drill into one account** — chain to `personalize-email`.\n7. **Add accounts** — extend list and re-score.\n\nRe-execute step 5 only when account list changes. For weight / threshold / ICP changes → recompute from cached axis scores.\n\nTerminate when user accepts, saves, or hands off.\n\n## Anti-patterns — fail-fast checklist\n\n1. **Black-box composite** — single number without component breakdown.\n2. **\"Why now\" = composite restated.**\n3. **Silent identifier resolution** on ambiguous names.\n4. **Fixed weights not exposed.**\n5. **Tier without action.**\n6. **Stale signal padding** — events >90d contributing.\n7. **Generic \"why now\"** — \"good fit\" applies to every account.\n8. **Ignoring missing axes** — pretending engagement exists when null.\n9. **Auto-accepting ambiguous matches.**\n10. **No iteration affordance.**\n\n## Fallback rules\n\n- **`get_gtm_context` empty** → use user-supplied ICP override; surface gap.\n- **No intent returned, or none matching the relevance set** → intent score = 0 (real signal, not a gap).\n- **No news or scoops returned** → trigger = 0; flag.\n- **Engagement unavailable** → weight = 0; redistribute proportionally.\n- **All axes thin** → tier C \"monitor only\"; honest.\n- **Resolution failure** → list separately; never silently drop.\n\nNever block ranking on a single missing axis. Never invent data.\n\n## Output Format\n\n### TL;DR — Account Scoring · N accounts · Pass [M]\n\n*Use case: [restate]. Weights · Thresholds A≥[X] · B[Y–Z].*\n\n**Resolution:** [R resolved · A ambiguous · F failed]. [If A>0: \"User confirmation required.\"]\n**Tier distribution:** A: x · B: y · C: z.\n\n**Top 3:**\n1. [Account] (tier · composite) — [why now]\n2. ...\n\n---\n\n### Resolution Summary\n\n| Input | Resolved To | ZI ID | Confidence | Status |\n|---|---|---|---|---|\n\n`Status` legend: ✅ Auto-resolved · 🔍 Verified · ⚠️ Ambiguous · ❌ Failed.\n\n**Ambiguous matches — please confirm:** [list top 5 candidates per ambiguous input with attributes].\n\n### Ranked Accounts\n\n*Sorted by composite descending. Engagement column `–` when redistributed.*\n\n| # | Account | Tag | Tier | Composite | Fit | Intent | Trigger | Eng | Why now | ZI ID |\n\n(Tier-A rows also carry an \"↳ Engagement: ...\" sub-line from §7.5.)\n\n### Weights & Axes Used\n\n```\nfit:        [%]\nintent:     [%]\ntrigger:    [%]\nengagement: [%]   (redistributed if axis unavailable)\n```\n\n**Axes missing this run:** [list, or \"none\"].\n\n### Recommended Actions per Tier\n\n- **Tier A** — Route to AE for 1:1 outreach within 24h. Chain to `personalize-email`.\n- **Tier B** — SDR sequence; ABM retargeting; cadence with the why-now as opener.\n- **Tier C** — Monitor; re-score weekly.\n\n### Iteration Options\n\n1. Accept ranking; save filter+weight set.\n2. Adjust weights.\n3. Tighten thresholds.\n4. Refilter.\n5. Swap ICP.\n6. Drill into one account.\n7. Add accounts.\n\n### Caveats (when relevant)\n\n- **Ambiguous pending** — N accounts not yet scored.\n- **Failed resolutions** — N inputs had no match.\n- **Engagement axis unavailable** — surface per-account (`no CRM signal — consider cross-check`) for each tier-A row.\n- **Signal depth** — `enrich_company_signals` returns the most recent signals per type (server-capped), so for very active accounts the intent/trigger axes reflect the most recent window rather than an exhaustive history.\n- **Intent thin** — <3 topics resolved; intent directional.\n- **Stale-signal cliff** — N accounts' best trigger >60d old.\n- **Edge-of-recency** — N trigger events 80–90d.\n- **GTM-context gap** — `icp` sparse; fit-axis precision reduced.\n\n### Final Filter + Weight Set (on accept)\n\n```json\n{\n  \"icp\": { /* GTM ICP or user override */ },\n  \"weights\": {\"fit\": 45, \"intent\": 25, \"trigger\": 25, \"engagement\": 5},\n  \"tier_thresholds\": {\"A\": 75, \"B\": 50},\n  \"intent_topics\": [\"...\"],\n  \"use_case\": \"prospecting\",\n  \"_meta\": {\"account_count\": ..., \"tier_distribution\": {...}, \"axes_missing\": [...], \"pass_count\": ...}\n}\n```\n\n### Chain Targets\n\n- `personalize-email` per tier-A contact → grounded in the same \"why now\" signal.\n- `build-list` to extend the universe.\n- `find-similar` on a tier-A seed.\n- `tam-sizer` with this filter set to confirm universe size.\n"
}

SHA-256: ecde64453530547d2ed4596fb87c51222ed12052e307e6fc92cc6091609ee2f4