← ZoomInfoCONTENT HISTORY

Update to ZoomInfo

Snapshot Sep 30, 2026 · 23:18 UTC · version 6.1.0

Collection source: not recorded for this historical snapshot. These snapshots do not have a confirmed matching collection source. Differences in file lists alone do not establish changes to the package.

WHAT CHANGED · RULE-BASED ANALYSIS

Supporting file metadata differs

Newly listed paths: .DS_Store. This compares saved file lists, not package contents; a different collection source can change the list.

Observed in package metadata. These changes alone do not establish a new customer-facing feature.

Supporting files

Before

[]

After

[{"relative_path":".DS_Store","size_in_bytes":6148}]

Compare saved observations

Download comparison JSON
Full technical diff · 1 changed fields

changed /included_files

BEFORE
[]
AFTER
[
  {
    "relative_path": ".DS_Store",
    "size_in_bytes": 6148
  }
]
Full snapshot data
{
  "name": "score-leads",
  "description": "Score and prioritize leads or cold contacts (mixed ZoomInfo person IDs, emails, or name+company rows). Returns Hot / Warm / Cold tier per lead with a response-time SLA tuned to the use case (live inbound routing, MQL triage, event follow-up, PQL triage, content follow-up, SDR queue ordering), per-axis breakdown (person fit · account fit · source signal · trigger), a \"why now\" reasoning snippet per lead, and recommended next action with verified contact data. Resolution by email is deterministic; name+company surfaces verification when needed; typo'd emails fail explicitly rather than fall back. Iteratively refinable. Triggers on phrases like \"score these leads\", \"which lead/contact should I call first\", \"prioritize my MQLs\", \"rank inbound\", \"who should I prioritize?\", \"tier this list\".",
  "included_files": [
    {
      "relative_path": ".DS_Store",
      "size_in_bytes": 6148
    }
  ],
  "skill_md_contents": "---\nname: score-leads\ndescription: Score and prioritize leads or cold contacts (mixed ZoomInfo person IDs, emails, or name+company rows). Returns Hot / Warm / Cold tier per lead with a response-time SLA tuned to the use case (live inbound routing, MQL triage, event follow-up, PQL triage, content follow-up, SDR queue ordering), per-axis breakdown (person fit · account fit · source signal · trigger), a \"why now\" reasoning snippet per lead, and recommended next action with verified contact data. Resolution by email is deterministic; name+company surfaces verification when needed; typo'd emails fail explicitly rather than fall back. Iteratively refinable. Triggers on phrases like \"score these leads\", \"which lead/contact should I call first\", \"prioritize my MQLs\", \"rank inbound\", \"who should I prioritize?\", \"tier this list\".\n---\n\n# Score Leads\n\nTier leads as Hot / Warm / Cold with a response-time SLA tuned to the use case. Calls `get_gtm_context(detailed: true)` unconditionally, resolves leads by email (deterministic) or name+company (surface ambiguity), scores on four axes, and presents a **scannable** per-lead output with a specific \"why now\" reasoning snippet so the rep can trust the tier.\n\n## The bar\n\n1. **Tier and SLA are the first thing the rep sees** — not buried under TL;DR or component breakdown.\n2. **Resolution accuracy 100%** — every input bucketed; email typos fail loudly, never silent fallback to name search.\n3. **Every Hot lead carries verified contact data** — phone + accuracy score visible. Bad data on a Hot lead = dial-the-wrong-number failure.\n4. **Every tier comes with a concrete next action** — \"Direct dial 555-1234. Lead with [signal].\" Not \"engage promptly.\"\n5. **Every lead carries a \"why now\" reasoning snippet** — citing the specific axis driver (person seat × source × fresh trigger / intent / prior engagement). Never the composite restated; never generic (\"strong fit\"). Same trust discipline as `score-accounts`.\n6. **Output scannable in <30 seconds per row.** Component breakdown below the fold.\n\n## Scope\n\nScores **individual leads**, not accounts. Use `score-accounts` for company-level prioritization. For Hot leads, chain to `personalize-email`.\n\n## Input\n\n- **Leads (required)** — list of ZI person IDs / emails / name+company rows / mixed CSV.\n- **Source (recommended)** — `demo_request`, `pricing_inquiry`, `free_trial`, `product_signup`, `content_download_high_intent`, `content_download_low_intent`, `webinar_attended`, `webinar_registered`, `newsletter_subscribe`, `cold_inbound`, `unknown`. If missing, ask once then default to `unknown` (source = 50, flagged).\n- **Use case (default `inbound_routing`)** — `inbound_routing`, `event_followup`, `pql_triage`, `content_follow_up`. Drives SLA tuning.\n- **Weight overrides (optional)** — `{person, account, source, trigger}` summing to 100.\n- **Tier thresholds (optional)** — `{Hot, Warm}`. Cold is the remainder.\n\n## Four-axis framework\n\n| Axis | Question | Source | Default weight |\n|---|---|---|---|\n| **Person fit** | Is this individual a buyer persona? | `enrich_contacts` | **35%** |\n| **Account fit** | Does their employer match ICP? | `enrich_companies` vs `get_gtm_context.icp` | **25%** |\n| **Source signal** | What action got us this lead? | User-supplied | **25%** |\n| **Trigger / intent** | Fresh event or intent at the employer? | `enrich_company_signals` (news + scoops + intent) | **15%** |\n\nWeights overridable. Each axis 0–100; composite is the weighted sum.\n\n## Tier + SLA (varies by use case)\n\nSLA defaults below. `inbound_routing` is the live-triage motion where speed-to-lead dominates; other motions relax accordingly. Pick what fits — don't manufacture urgency the motion doesn't need.\n\n| Tier | Composite | `inbound_routing` | `event_followup` / `pql_triage` | `content_follow_up` | Recommended action |\n|---|---|---|---|---|---|\n| **Hot 🔥** | ≥ 75 | < 5 min | < 1 hr | < 4 hr | Direct dial / personal outreach. Chain to `personalize-email`. |\n| **Warm 🌤** | 50–74 | < 1 hr | same day | < 24 hr | SDR sequence with personalized opener. Multi-touch cadence. |\n| **Cold ❄️** | < 50 | < 24 hr | < 48 hr | weekly nurture | Nurture cadence; tag for content drip; do not call. |\n\nFor high-intent sources (`demo_request`, `pricing_inquiry`, `free_trial`) in live-triage mode, fast response materially lifts qualification rate. Outside live-triage, the right SLA is longer.\n\n## Resolution (four-bucket, lead-specific)\n\n- **Auto-resolved** — high confidence; score immediately.\n- **Verified** — match found with caveats (common name at large co); surface verification note.\n- **Ambiguous** — multiple plausible matches, no clear winner; pause scoring.\n- **Failed** — no match. **Never silently fall back to alternate identifier paths.**\n\nRouting by type:\n- **Numeric person ID** → auto-resolved.\n- **Email** → `enrich_contacts(email)`. Email is a unique identifier. Match → auto-resolved. No match → failed. **Do NOT auto-route to name search** — a typo'd email (e.g., `firstname@compny.com`) must not silently resolve to a different real person.\n- **Name + company** → `enrich_contacts(firstName/lastName/companyName)`. Single high-accuracy match → auto-resolved. Multiple plausible → verified with note. No match → failed.\n- **Free-text \"John Smith at Acme\"** → parse and route to name+company path.\n\n100% resolution accuracy is the gate.\n\n## Workflow\n\n### 1. Pull GTM context (always)\n`get_gtm_context(detailed: true)`. Capture personas, ICP, strategic priorities (for intent-topic curation).\n\n### 2. Honor input data first\nUse user-supplied source / weights / thresholds / use case. If `source` is missing on a multi-row list, ask once then default to `unknown` (50, flagged).\n\n### 3. Resolve identifiers\nPer the four-bucket rules. Batch in groups of ≤10 concurrent.\n\n### 3.5. Relationship-context pre-flight (mandatory)\n\nTag each lead's **company** against GTM context:\n- **`competitor`** ⚔️ — in `get_gtm_context.competitors`. Hard-warn — most inbound from competitors is talent or competitive intel.\n- **`customer`** 🤝 — in `get_gtm_context.customers` / `proof_bank`. Reroute to `expansion` / `discovery_follow_up`.\n- **`partner`** 🔗 — in `get_gtm_context.partners`. Co-sell framing.\n- **`prospect`** — default.\n\nThe relationship tag appears in the headline before the tier emoji.\n\nFor Hot leads at `customer` or `competitor` companies: pause before pushing to cold-outbound AE; surface the routing question first.\n\n### 4. Define the intent relevance set (only if trigger weight > 0)\nFrom `get_gtm_context.strategicPriorities` and offerings, derive 5–10 themes you sell into. `enrich_company_signals` returns each employer's active intent topics directly — no topic lookup or pre-query — so these themes are the **match set** for the intent portion of the trigger axis in step 6: a returned topic counts only if it maps to one.\n\n### 5. Fetch data per lead (parallel, batched ≤10; chunked for large lists)\n- `enrich_contacts(personId, fields: jobTitle, managementLevel, department, contactAccuracyScore, hasDirectPhone, hasMobilePhone, hasEmail, directPhone, mobilePhone, email)`.\n- `enrich_companies(zoominfoCompanyId, fit-scoring fields)`.\n- `enrich_company_signals(zoominfoCompanyIds: [unique employer IDs], signalTypes: [\"NEWS\", \"SCOOP\", \"INTENT\"])` for the employers — only if trigger weight > 0. One batched call (≤10 company IDs) covers news, scoops, and intent; dedupe employers across leads so a shared company is fetched once. No pre-filtering on score, category, topic, or date — applied in step 6.\n\n**Batch + context-window discipline.** Process in **chunks of ~25 leads** 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 leads in working context — once per-axis scores + the winning signal/topic strings are captured per lead, drop the rest. For >50-lead lists, summarize completed chunks into running totals (tier distribution, top-Hot list, missing-axes counts) and discard their per-lead breakdowns from context.\n\n### 6. Score each axis\n\n**Person fit (0–100)** — compare `enrich_contacts` to `get_gtm_context.buyerPersonas`:\n\n| Dimension | Max | Banded |\n|---|---|---|\n| Management level | 30 | C = 30 · VP = 25 · Director = 18 · Manager = 10 · Non-Manager = 3 |\n| Department | 25 | Primary persona dept = 25 · adjacent = 15 · unrelated = 0 |\n| Job-title keyword | 20 | Exact = 20 · partial = 10 · none = 0 |\n| Contact accuracy | 15 | ≥95 = 15 · 85–94 = 10 · 75–84 = 5 · <75 = 0 |\n| Contact data completeness | 10 | email + direct + mobile = 10 · email + one phone = 7 · email only = 4 · none = 0 |\n\n**Account fit (0–100)** — industry 30 · employee band 25 · revenue band 20 · geo 15 · business model 10.\n\n**Source signal (0–100):**\n\n| Source | Score |\n|---|---|\n| `demo_request` / `pricing_inquiry` | 100 |\n| `free_trial` / `product_signup` | 90 |\n| `content_download_high_intent` (comparison, RFP, pricing guide) | 75 |\n| `webinar_attended` | 60 |\n| `webinar_registered` | 50 |\n| `content_download_low_intent` / `cold_inbound` | 35 |\n| `newsletter_subscribe` | 25 |\n| `unknown` | 50 (default; flag) |\n\n**Trigger / intent (0–100)** — same logic as `score-accounts` (news, scoops, and intent come from `enrich_company_signals`, filtered to the last 90 days by each signal's `date`), with **seat-fit modifier**:\n- `event_score = signal_type_weight × recency_factor × seat_fit`, where `signal_type_weight` maps from each signal's news `category` or scoop `scoopType`.\n- Signal weights: 95 (M&A, funding, C-suite hire) · 75 (product launch, hiring surge, earnings) · 55 (partnership, new facility) · 45 (pain-point scoop, other PERSON moves) · 25 (generic press).\n- Recency: 0-14d = 1.0 · 14-30d = 0.7 · 30-60d = 0.4 · 60-90d = 0.2 · >90d = 0.\n- **Seat fit:** if event maps to the lead's seat (new CFO → CFO seat; product launch → CRO/CMO seat; hiring surge in dept X → leader of dept X) → 1.0. Otherwise 0.5. Prevents company-level triggers from inflating irrelevant leads.\n- Intent: from the `enrich_company_signals` intent topics that map to the relevance set (step 4) with `signalScore` ≥ 60 in roughly the last 30 days (use each signal's `date`) — matching `score-accounts` — `max(signalScore × audienceStrengthFactor)`. A=1.0 · B=0.85 · C=0.7 · D=0.55 · E=0.4 (from `audienceStrength`).\n- Take max(trigger event, intent). Cap 100.\n\n### 7. Compute composite + assign tier\n```\ncomposite = round((person × w_p + account × w_a + source × w_s + trigger × w_t) / 100)\n```\nPer Hot/Warm/Cold thresholds.\n\n### 8. Compose the per-lead row\n\nFirst 30 seconds of read must contain, in order:\n\n1. **Relationship tag** (if non-default): ⚔️ / 🤝 / 🔗.\n2. **Tier emoji + label.**\n3. **SLA** — tuned to the use case (see Tier + SLA table).\n4. **Quality flags inline with SLA:**\n   - `⚠️ verify title (record Xmo old)` — when `lastUpdatedDate` >6mo.\n   - `📱 mobile only` vs `☎️ direct line`.\n   - `⚠️ acc <85` — low contact-accuracy.\n5. **\"Why now\" reasoning snippet** — one line, anchored on the strongest specific signal:\n   - **Strong person + source + trigger** → \"VP-Sales seat × demo request 3h ago × Series B closed 8d ago.\"\n   - **High-source-only** → \"Pricing inquiry from VP at perfect-ICP company; no fresh trigger.\"\n   - **Trigger-anchored** → \"Fresh CFO appointment 5d ago × CFO-seat lead — trigger × seat = direct match.\"\n   - **Intent-driven** → \"Spiked on '[topic]' (score 92, audience A) over 14d.\"\n   - **Engagement-driven** (from `account_research`) → \"Open opp at this account; named champion engaged 6d ago.\"\n   - **Low signal across axes** → \"Low signal — monitor only.\"\n   Never restate the composite. Never use generic phrasing (\"strong fit and engagement\") — that applies to every Hot lead and tells the rep nothing.\n6. **Recommended next action** — concrete, with phone number / channel.\n7. **Contact data line** — email · phone · accuracy.\n\nExample (stale-but-high-accuracy Hot lead, mobile only, `inbound_routing`):\n\n```\n🤝 🔥 Hot · Call within 5 min ⚠️ verify title (record 11mo old) · 📱 mobile only · acc 95\n[First Last] · [Title] · [Company]\nWhy now: [Trigger event] X days ago × [seat] = direct match. (Source: [demo_request].)\nRecommended: Direct dial 555-XXXX (mobile, verify title before dialing). Lead with [angle].\n```\n\nComponent breakdown shown BELOW THE FOLD.\n\n### 9. Self-check before output\n\n- ☑ Tier + SLA (use-case-appropriate) visible in the first row of every output.\n- ☑ Hot leads have verified phone + accuracy ≥85, or flag fires.\n- ☑ **\"Why now\" snippet** on every lead — specific axis driver, never composite restated, never generic.\n- ☑ Recommended next action is concrete with channel + signal.\n- ☑ Component breakdown below the fold.\n- ☑ Every input bucketed (auto-resolved / verified / ambiguous / failed) — none silently dropped.\n- ☑ Failed emails NOT silently routed to name search.\n- ☑ Source missing → flagged in caveats, not silently defaulted.\n- ☑ Each row readable in <30s.\n- ☑ Batch chunked when N > 25; intermediate payloads dropped from context.\n- ☑ Iteration options offered.\n\n### 10. Present + offer iteration\n\n1. **Accept** — chain to `personalize-email` per Hot.\n2. **Adjust weights.**\n3. **Tighten / loosen thresholds.**\n4. **Refilter** — show only Hot, exclude seats.\n5. **Drill into a lead.**\n6. **Add leads.**\n7. **Backfill source** for unknowns.\n\nRe-execute step 5 only when lead list changes; otherwise recompute from cached axis scores.\n\n## Anti-patterns — fail-fast checklist\n\n1. **Long preamble before the tier label.**\n2. **Silent email→name fallback** on typo'd email.\n3. **Source defaulted without flagging.**\n4. **Generic \"why now\"** — \"strong fit and engagement\" applies to every Hot lead. Each row must cite the specific driver.\n5. **Composite-as-rationale.** Re-stating the score number instead of the axis driver.\n6. **Tier without SLA.**\n7. **Hot lead with low-accuracy unflagged.**\n8. **Component breakdown above the fold.**\n9. **No drill-down to `personalize-email`** for Hot.\n10. **Auto-accepting ambiguous matches** (e.g., 8 same-named contacts at a large enterprise).\n11. **Forcing the live-triage SLA onto a non-live-triage use case.** Event follow-up, PQL triage, and content nurture motions have their own SLA bands; using the inbound-routing 5-min framing on them burns rep capacity on the wrong leads.\n\n## Fallback rules\n\n- **`get_gtm_context` empty** → use user-supplied personas/ICP if any; flag.\n- **Source missing** → ask once; else 50 with flag.\n- **Email no match** → failed; do NOT fall back to name search. If domain edit-distance ≤2 from a known-company domain (from GTM context or batch's resolved set), suggest the closest (e.g., `firstname@compny.com` → \"did you mean `firstname@company.com`?\").\n- **Name + company multi-match** → verified with note OR ambiguous.\n- **`enrich_company_signals` returns no relevant intent and no news/scoops for the employer** → trigger = 0; don't pad (absence of trigger is a real score, not a weight-redistribution case).\n- **Contact accuracy <75** → flag on the row; recommend verification before dialing.\n\nNever block tiering on a single missing axis. Never invent contact data or source.\n\n## Output Format\n\n### TL;DR — Lead Scoring · N leads · Pass [M]\n\n*Use case: [restate]. SLA band: [restate]. Weights · Thresholds Hot≥[X] · Warm[Y–Z].*\n\n**Tier distribution:** 🔥 Hot: X · 🌤 Warm: Y · ❄️ Cold: Z · ❌ Unresolved: W.\n\n**🔥 Hot leads** (SLA per use case):\n\n🔥 **Jordan Smith** · VP Sales at Acme Corp · **[SLA]** · *Why now: demo request × VP-Sales seat × fresh CEO hire 8d ago* · 📞 555-123-4567 · ✉ jordan@acme.com · acc 98\n🔥 [next Hot lead...]\n\nHot listed first.\n\n---\n\n### Resolution Summary\n\n| Input | Resolved To | ZI ID | Status |\n|---|---|---|---|\n\n`Status` legend: ✅ Auto-resolved · 🔍 Verified · ⚠️ Ambiguous · ❌ Failed.\n\n### Ranked Lead List\n\n*Hot first → Warm → Cold. Each row <30s read.*\n\n| Tier | Name | Title | Company | SLA | Why now | Contact | Acc | Composite |\n|---|---|---|---|---|---|---|---|---|\n\n### Component Breakdown (below the fold)\n\n| Lead | Person | Account | Source | Trigger | Composite | Tier |\n|---|---|---|---|---|---|---|\n\n### Weights & Axes Used\n\n```\nperson:  [%]\naccount: [%]\nsource:  [%]\ntrigger: [%]\n```\n\n### Recommended Actions per Tier\n\nSLAs adapt to the use case (see Tier + SLA table).\n\n- **🔥 Hot — SLA per use case.** Direct dial / personal outreach. Chain to `personalize-email`. Verify phone if acc <85.\n- **🌤 Warm.** SDR sequence; multi-touch cadence sized to use case.\n- **❄️ Cold.** Nurture; content drip; do not call.\n\n### Iteration Options\n\n1. Accept → chain to `personalize-email`.\n2. Adjust weights.\n3. Tighten thresholds.\n4. Backfill source for unknowns.\n5. Drill into a lead.\n6. Add leads.\n\n### Caveats (when relevant)\n\n- **Source missing on N leads** — defaulted to 50; backfill for precision.\n- **Failed resolutions** — N unresolved; review.\n- **Low contact accuracy on Hot leads** — N have acc <85; verify phone before dialing.\n- **Signal depth** — `enrich_company_signals` returns the most recent signals per type, so the trigger axis reflects the most recent window for very active employers.\n- **GTM-context gap** — personas sparse; person-fit reduced.\n- **Stale records** — N leads' records >12mo old; current title may have changed.\n\n### Final Filter + Weight Set (on accept)\n\n```json\n{\n  \"weights\": {\"person\": 35, \"account\": 25, \"source\": 25, \"trigger\": 15},\n  \"tier_thresholds\": {\"Hot\": 75, \"Warm\": 50},\n  \"buyer_personas\": [...],\n  \"intent_topics\": [\"...\"],\n  \"use_case\": \"inbound_routing\",\n  \"_meta\": {\"lead_count\": ..., \"tier_distribution\": {...}, \"axes_missing\": [...], \"pass_count\": ...}\n}\n```\n\n### Chain Targets\n\n- `personalize-email` per Hot lead → drafts grounded in the same axis driver that tiered the lead.\n- `score-accounts` on the leads' companies → company-level prioritization alignment.\n- `find-similar` on a Hot lead → lookalike prospects at same / similar companies.\n"
}

SHA-256: 232fd65787aaf4f2ae035d6c264d52c8a4b489bdd9b2c557b34a922e1cdbcf6d