PRISM

Modules/Intel-Hiring.md

Module: intel-hiring

Wave 1 spoke module. The primary build-vs-buy oracle. Open roles map directly to ICP tiers (economic buyer, technical evaluator, champion). Search-related hiring is the highest-confidence signal that a company is actively solving a search problem — either internally or via a vendor. The hiring_signal score feeds buying signal inference in downstream synthesis.


Identity

Field Value
Name intel-hiring
Version 0.1.0
Layer Intelligence (Wave 1)
Wave 1 (runs concurrently with other spokes after intel-company completes)
Description Hiring signals, build-vs-buy assessment, and buying committee intelligence. Collects open roles via Apify LinkedIn Jobs Scraper (with Perplexity fallback), classifies by ICP tier, detects search-related roles, computes hiring velocity, maps buying committee, and compares against competitors.
LLM Tier Claude via Instructor (enrichment, classification, buying committee mapping)
Timeout 300 seconds
Max Retries 2 (module level)
Gate Module NO. Failure degrades hiring context but does not abort audit.

Dependencies

Module Reads Why
intel-company Account.executives Exec names for buying committee mapping and champion identification
intel-company Account.competitors Competitor domains for comparative hiring sweep

Both fields are read from the accounts table via SQLAlchemy. If the account is not found, the module falls back to basic domain-level job search (no exec enrichment or competitor comparison).


Input Schema

Field Type Required Description
domain str yes Website domain to analyze, e.g. "dell.com"

Output Schema: HiringOutput

Top-Level Fields

Field Type Required Description
domain str yes Domain that was analyzed
open_roles list[OpenRole] no Open roles detected for the prospect company
role_count_by_tier dict[str, int] no Count of open roles by ICP tier, e.g.
search_related_count int no Total number of search-related open roles
hiring_velocity HiringVelocity or None no Hiring velocity metrics for the prospect
build_vs_buy BuildVsBuySignal or None no Assessment of build vs buy intent for search technology
buying_committee BuyingCommittee or None no Mapped buying committee for search technology decisions
competitor_hiring list[CompetitorHiring] no Hiring intelligence for competitor companies
comparative_summary str no Summary comparing prospect and competitor hiring patterns
hiring_summary str no Overall 2-4 sentence hiring intelligence summary

Sub-Schema: OpenRole

Field Type Required Description
title str yes Job title, e.g. "Senior Search Engineer"
department str no Department or team, e.g. "Engineering", "Product"
location str no Job location, e.g. "Austin, TX" or "Remote"
posted_date str or None no When the role was posted, YYYY-MM-DD or approximate
url str or None no URL to the job posting
icp_tier Literal no One of: tier1_economic (VP/Director budget holder), tier2_technical (architect/lead evaluator), tier3_champion (internal advocate/power user), tier4_user (end-user/individual contributor)
relevance_score float no How relevant to Algolia search/discovery, 0.0 to 1.0
search_related bool no True if role is directly related to search, discovery, or personalization
signals list[str] no Signals extracted from role, e.g. "building internal search", "Algolia experience preferred"
source str no Where role was found: "linkedin", "perplexity", "careers_page"
company_name str no Which company this role belongs to

Sub-Schema: HiringVelocity

Field Type Required Description
roles_last_30d int no Number of roles posted in the last 30 days
roles_last_90d int no Number of roles posted in the last 90 days
trend Literal no One of: accelerating, steady, decelerating, insufficient_data
interpretation str no Human-readable interpretation of velocity and what it means for sales outreach

Sub-Schema: BuildVsBuySignal

Field Type Required Description
signal Literal no One of: build (hiring search engineers to build in-house), buy (likely to purchase search solution), mixed (both signals present), insufficient_data
evidence list[str] no Evidence items supporting the assessment
confidence Literal no One of: high, medium, low

Sub-Schema: BuyingCommitteeMember

Field Type Required Description
name str yes Full name of the person
title str yes Job title
role Literal no One of: economic_buyer, technical_evaluator, champion_candidate, influencer, blocker, unknown
linkedin_url str or None no LinkedIn profile URL if available
tenure_description str or None no How long they have been in this role
previous_company str or None no Previous employer if known
champion_signals list[str] no Signals this person could be an Algolia champion, e.g. "previously used Algolia at prior company"

Sub-Schema: BuyingCommittee

Field Type Required Description
members list[BuyingCommitteeMember] no Identified buying committee members
confidence Literal no One of: high, medium, low
methodology str no How the buying committee was identified, e.g. "executive list + open roles + Perplexity enrichment"

Sub-Schema: CompetitorHiring

Field Type Required Description
company_name str yes Competitor company name
domain str yes Competitor domain
open_roles list[OpenRole] no Open roles detected for this competitor
search_related_count int no Number of search-related roles at this competitor
hiring_velocity HiringVelocity or None no Hiring velocity for this competitor

Collection Strategy

The module runs a two-phase pipeline: job data collection (Apify primary, Perplexity fallback), then Claude enrichment.

Phase 1: Apify LinkedIn Jobs Scraper (Primary) — Direct Job Data

Aspect Detail
Adapter HiringCollector via Apify API
Evidence Tier VERIFIED (direct LinkedIn data, not search-derived)
Source Label "Apify LinkedIn Jobs Scraper"
Method direct_api
Confidence high
Fallback Perplexity sonar-pro if APIFY_API_KEY not set

When Apify is available, the collector fetches live LinkedIn job postings directly. This is the highest-confidence source for open role data — it reflects actual postings, not search-engine-indexed summaries.

Phase 1 Fallback: Perplexity API (sonar-pro) — When Apify Unavailable

Aspect Detail
Adapter PerplexityAdapter via HiringCollector
Evidence Tier WEBSEARCH (Perplexity searches LinkedIn, Glassdoor, Indeed, company careers pages)
Source Label "Perplexity sonar-pro"
Method llm_extraction
Confidence medium

Perplexity fallback queries:

Query Purpose
Prospect open roles (search/engineering/product) Job titles, departments, seniority for ICP mapping
Competitor hiring for each domain Parallel job data for each intel-company competitor
Search-specific roles Targeted: site search, discovery, search engineer, Elasticsearch, Algolia
Exec-level roles at prospect VP/Director/Head-of-level postings for economic buyer identification

Phase 2: Claude via Instructor — Enrichment and Classification

Aspect Detail
Adapter Claude claude-3-5-sonnet / claude-opus via Instructor
Evidence Tier ESTIMATE (inference on collected role data)
Purpose ICP tier classification, search_related detection, build_vs_buy assessment, buying committee mapping, hiring velocity computation

Enrichment pipeline: 1. Raw role data -> per-role classification: icp_tier, relevance_score, search_related, signals 2. role_count_by_tier computed from tier classifications 3. HiringVelocity derived from posted_date distribution 4. BuildVsBuySignal determined: build if search engineers hired for internal platform, buy if search vendor evaluation roles or minimal engineering search roles 5. BuyingCommittee mapped from exec list (intel-company) cross-referenced with open roles 6. CompetitorHiring built per competitor domain 7. comparative_summary and hiring_summary generated


ICP Tier Classification

The ICP tier system maps open roles to MEDDPICC buying committee roles:

Tier Label Example Roles MEDDPICC Role
tier1_economic Economic Buyer VP Digital, VP Engineering, Director of Search, CTO Economic Buyer (E)
tier2_technical Technical Evaluator Search Architect, Principal Engineer, Platform Lead Decision Criteria (D)
tier3_champion Champion Candidate Product Manager (Search), UX Engineer (Discovery) Champion (C)
tier4_user End User Frontend Developer, Search Analyst Users

Roles with relevance_score >= 0.7 AND search_related=True are the primary buying signal.


Build vs Buy Signal Logic

Signal Indicators Sales Implication
build Multiple search engineer roles, Elasticsearch/OpenSearch/Solr mentioned, "build internal search" in JD signals Prospect building in-house. Positioning: "Why build when you can buy Algolia?"
buy 0-1 search engineers, vendor evaluation role posted, Algolia/Typesense/Solr in JD as tools Prospect likely evaluating. Positioning: "We win vendor evaluations. Here's why."
mixed Both search engineers AND vendor-evaluation signals Complex picture. Positioning: hybrid/extensibility angle.
insufficient_data Too few roles, no search-specific roles found Cannot determine. Fall back to techstack signals.

Hiring Velocity Interpretation

Trend Definition Sales Signal
accelerating roles_last_30d > (roles_last_90d / 3) * 1.5 Ramp event likely. Outreach now.
steady roles_last_30d approximately equals roles_last_90d / 3 Stable investment. Standard qualification.
decelerating roles_last_30d < (roles_last_90d / 3) * 0.5 Potential freeze or strategic shift. Probe budget.
insufficient_data Fewer than 3 roles with dates Cannot determine.

Validation Rules

# Rule Severity Threshold
1 At least 1 open role found required open_roles not empty
2 All roles have a title required Every OpenRole.title is non-empty
3 build_vs_buy is populated warning build_vs_buy not None
4 hiring_summary is populated warning hiring_summary not empty string
5 Competitor hiring populated if competitors were provided warning competitor_hiring not empty if competitor list non-empty
6 Buying committee populated warning buying_committee.members not empty

Required failures -> status "partial". Warning failures -> logged but passed.


Evidence Requirements

Field Minimum Tier Rationale
open_roles (Apify path) VERIFIED Direct LinkedIn data
open_roles (Perplexity path) WEBSEARCH Perplexity searches job boards
icp_tier classification ESTIMATE Claude inference on role text
build_vs_buy ESTIMATE Claude inference on role signals
hiring_velocity ESTIMATE Computed from posted_date distribution
buying_committee WEBSEARCH Perplexity enrichment + exec list cross-reference
competitor_hiring VERIFIED or WEBSEARCH Depends on whether Apify or Perplexity used

Cost Profile

Metric Expected Value
LLM Calls 2-4 (Perplexity fallback) + 3-6 (Claude Instructor enrichment)
Apify Cost ~$0.01-0.05 per run (LinkedIn Jobs actor)
Claude Cost ~$0.05-0.15 (sonnet tier for enrichment)
Expected Duration 60-180 seconds
External API Calls 1 (Apify) or 3-5 (Perplexity fallback)

Retry Architecture (Two Layers)

Layer 1: Collector Retries (network errors)

Trigger Retry Backoff
Apify timeout 3 attempts Exponential (2^attempt seconds)
Apify rate limit 3 attempts Exponential
Perplexity timeout 3 attempts Exponential
Perplexity rate limit (429) 3 attempts Exponential
Other HTTP error No retry Fail immediately

Layer 2: Module Retries (data quality)

Trigger Retry Backoff
Empty role response 2 attempts 5 seconds fixed
Instructor parse failure 2 attempts 5 seconds fixed

If all retries exhausted: return ModuleExecutorResult with status="partial" (not "failed" — partial hiring data is non-blocking).


Persistence

intel-hiring writes to module_executions table only (not the accounts table). Downstream synthesis modules read module_executions.output JSONB directly.

Key fields consumed by downstream synthesis: - open_roles with icp_tier and search_related flags - search_related_count — primary buying signal input - build_vs_buy.signal — used in positioning logic - buying_committee.members — directly feeds power map in AE playbook - hiring_velocity.trend — feeds outreach timing recommendations


Runtime Notes

SaaS Runtime (Temporal/Python)

  • Module: prism_platform/v2/modules/intel_hiring/module.py
  • Collector: prism_platform/v2/modules/intel_hiring/collector.py
  • Enricher: prism_platform/v2/modules/intel_hiring/enricher.py (Claude via Instructor)
  • Validator: prism_platform/v2/modules/intel_hiring/validator.py
  • Schemas: prism_platform/v2/modules/intel_hiring/schemas.py
  • Persistence: module_executions table only

Skill Runtime (Claude Code)

  • Skill file: ~/.claude/skills/algolia-intel-hiring/SKILL.md
  • Reads from: 01-company-context.json (for exec names and competitor domains)
  • Writes to: 09d-hiring-signals.md, 09d-hiring-signals.json
  • MCP tools used: WebSearch (Perplexity-equivalent job search), WebFetch (careers page)

Evolution: v1 → v2

v1 Architecture (Current)

Aspect v1 Design
Job collection Apify LinkedIn Jobs Scraper (primary) + Perplexity sonar-pro (fallback)
Enrichment Claude via Instructor — ICP tier, build_vs_buy, buying committee classification
Context source Account.executives and Account.competitors JSONB columns (from intel-company)
ICP tier Claude inference on role title and description
Build vs buy Claude inference on aggregated role signals
Buying committee Exec list cross-referenced with open roles via Perplexity enrichment
Competitor hiring Per-domain query (Apify or Perplexity)

v2 Architecture (Planned — Playbook-Based Agent)

In v2, intel-hiring becomes a playbook-driven agent. The config object holds a hiring_playbook that instructs data collection with precise source, role classification, and signal extraction rules:

Aspect v2 Design
Job collection Perplexity with explicit source constraints in system prompt
Primary sources LinkedIn Jobs, Glassdoor, Indeed, company careers page (direct WebFetch)
Citation requirements Every role must include job title + URL. No URL = role flagged as unverified.
ICP tier Playbook defines exact title-to-tier mapping rules (not left to Claude inference)
Build vs buy Playbook defines keyword triggers per signal type — "Elasticsearch" = build, "evaluate search vendors" = buy
Buying committee Playbook specifies MEDDPICC role mapping from title patterns; champion_signals expanded to include prior employer detection
Hiring velocity Computed deterministically from date-stamped roles, not inferred
Competitive context Automatic diff: prospect search_related_count vs each competitor search_related_count
hiring_signal score Numeric score (0-100) computed from: search_related_count, icp_tier distribution, velocity trend, build_vs_buy confidence
Schema Extended HiringOutput adds hiring_signal: float (0.0-1.0) for synthesis modules
Agent memory Can carry prior-run role lists for trend tracking over time

The hiring_signal score is the key v2 addition. It normalizes all hiring intelligence into a single float that synthesis modules can use in buying signal inference without re-parsing raw role data.


Aspect Simple LinkedIn Search PRISM intel-hiring
Collection Manual search, one query Apify LinkedIn Jobs actor (direct data) + Perplexity multi-query fallback
ICP mapping None Every role classified: tier1_economic through tier4_user
Search signal None search_related flag + relevance_score (0-1) per role
Build vs buy Guesswork Evidence-backed classification with confidence level and supporting signals
Buying committee None Members mapped from exec list + role patterns, with MEDDPICC roles assigned
Velocity None roles_last_30d vs roles_last_90d trend with sales interpretation
Competitor comparison None Parallel collection per competitor domain, comparative_summary generated
Champion detection None previous_company cross-check, champion_signals per committee member
Downstream use Text blob Typed fields: search_related_count feeds scoring, build_vs_buy feeds positioning, buying_committee feeds AE power map
Source provenance None Evidence tier per field: VERIFIED (Apify) vs WEBSEARCH (Perplexity) vs ESTIMATE (Claude)

Changelog

Date Change Reason
2026-03-30 Initial implementation Session 1: backend phase 1
2026-04-14 Module spec written to vault Knowledge extraction — module catalog completion

  • Module-Catalog — all 20 modules overview
  • Intel-Company — foundation module this depends on
  • Intel-News — sibling spoke module
  • Module-Spec-Template — the template this spec follows
  • Evidence-Tier-Spec — evidence tier system
  • Adapter-Interfaces — Apify and PerplexityAdapter