PRISM

Modules/Intel-Techstack.md

Module: intel-techstack

WAVE 1 SPOKE. Detects the current search vendor, ecommerce platform, and supporting tech stack via BuiltWith API. Fans out to every competitor domain from intel-company output. The golden_angle_competitors field -- competitors who use Algolia -- is the most commercially critical output in this module.


Identity

Field Value
Name intel-techstack
Version 0.1.0
Layer Intelligence (Wave 1)
Wave 1 (runs alongside other spoke modules after intel-company completes)
Description Technology stack detection via BuiltWith v22 API. Identifies search vendor, ecommerce platform, CMS, CDN, analytics, personalization, and bot detection for the prospect and all competitor domains. Produces a comparative summary and flags Golden Angle competitors (competitors using Algolia).
LLM Tier None (deterministic classification, no LLM enrichment)
Timeout 120 seconds
Max Retries 2 (module level)
Gate Module NO. Failure returns partial result; does not abort audit.

Dependencies

Dependency Field Read Why
intel-company Account.competitors (via ExecutionContext.intelligence.competitor_domains) Fan-out: runs BuiltWith on each competitor domain in parallel

If intel-company has not populated competitors, the module falls back to prospect-only detection. This is non-fatal.


Hub-and-Spoke: What This Spoke Provides

intel-techstack writes to module_executions. Downstream consumers read its output as:

Consumer Field Read Why
intel-competitors search_vendor, golden_angle_competitors, competitor_tech_stacks Competitor tech intelligence for displacement analysis
audit-report search_vendor, algolia_detected, golden_angle_competitors Determines audit framing: displacement vs. greenfield vs. existing customer
synth-business-case ecommerce_platform, search_vendor Platform context for ROI model calibration
algolia-audit-skill tech_stack_summary, comparative_summary Pre-built narrative for skill output file 02-tech-stack.md

Input Schema

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

Competitor domains are NOT in the input schema. They are read from ExecutionContext.intelligence.competitor_domains at runtime, populated by intel-company.


Output Schema: TechStackOutput

Prospect Tech Stack Fields

Field Type Required Description
search_vendor SearchVendor or None no Detected search vendor. None if no search tech detected.
ecommerce_platform str or None no Detected ecommerce platform (e.g. "Salesforce Commerce Cloud")
cms str or None no Detected CMS (e.g. "Adobe Experience Manager")
cdn str or None no Detected CDN/WAF (e.g. "Akamai", "Cloudflare")
analytics list[str] no All detected analytics tools (e.g. ["Google Analytics 4", "Adobe Analytics"])
personalization list[str] no Detected personalization/A-B testing tools
bot_detection str or None no Detected bot detection / CAPTCHA solution
all_technologies list[dict] no Full raw technology list from BuiltWith (Name, Tag, Categories per entry)
removed_technologies list[dict] no Technologies BuiltWith has flagged as removed (not currently live)
tech_stack_summary str yes Human-readable summary, e.g. "dell.com: Search: Elasticsearch (ACTIVE); Ecommerce: Salesforce Commerce Cloud"
algolia_detected bool yes True if Algolia tag detected on the prospect's own domain

Competitive Intelligence Fields

Field Type Required Description
competitor_tech_stacks list[CompetitorTechStack] no Tech stack profiles for each competitor domain
comparative_summary str no Narrative comparison of search vendors across prospect + competitors
golden_angle_competitors list[str] no Company names of competitors confirmed using Algolia. The primary sales signal.

Sub-Schema: SearchVendor

Field Type Required Description
name str yes Canonical vendor name (e.g. "Algolia", "Elasticsearch", "Coveo")
status Literal["ACTIVE", "TAG_ONLY", "REMOVED", "UNDETECTED"] yes ACTIVE = name-matched vendor; TAG_ONLY = search-category match but not in known vendors list; REMOVED = BuiltWith flagged as historical
detection_source str yes How it was detected (e.g. "BuiltWith v22 API", "BuiltWith v22 API (category match)")
evidence_tier EvidenceTier yes VERIFIED for name-matched vendors; WEBFETCH for TAG_ONLY category matches

Sub-Schema: CompetitorTechStack

Field Type Required Description
company_name str yes Competitor company name
domain str yes Competitor domain (e.g. "hp.com")
search_vendor SearchVendor or None no Detected search vendor for this competitor
ecommerce_platform str or None no Detected ecommerce platform for this competitor
all_technologies list[dict] no Full raw tech list for this competitor
tech_count int yes Number of technologies detected
is_algolia_customer bool yes True if Algolia tag confirmed on this competitor domain

Collection Strategy

Source 1: BuiltWith v22 API (Prospect Domain)

Aspect Detail
Adapter Direct httpx (TechStackCollector._fetch_builtwith)
Endpoint GET https://api.builtwith.com/v22/api.json
Params KEY={api_key}, LOOKUP={domain}, LIVEONLY=yes
Output Nested JSON: Results -> Result -> Paths -> Technologies[{Name, Tag, Categories}]
Retry httpx raises_for_status (no built-in retry at collector level)
Evidence Tier VERIFIED (direct API, live-only filter applied)
Timeout 30 seconds

LIVEONLY=yes is critical: it filters out historical technologies. Without it, BuiltWith returns both current and removed stacks, muddying the search vendor detection.

Source 2: BuiltWith v22 API (Competitor Fan-out)

Same endpoint and params, called once per competitor domain via asyncio.gather. Each competitor is an independent BuiltWith call. Failures are isolated -- one competitor timing out does not abort others.

Execution strategy: Prospect + all competitors run in parallel via asyncio.gather. This is the module's primary performance optimization: N+1 competitor calls complete in the time of 1 sequential call chain.


Enrichment Strategy

Aspect Detail
Method deterministic_classify (NO LLM)
LLM Model None
Pipeline raw JSON -> _classify_technologies() -> category regex matching -> TechStackOutput

Technology Classification Logic

The _classify_technologies() method iterates every technology from the BuiltWith response and applies the following rules:

Search Vendor Detection (priority order): 1. Name match against KNOWN_SEARCH_VENDORS list: Algolia, Elasticsearch, Solr, Coveo, Bloomreach, Searchspring, Klevu, Constructor, Lucidworks, Swiftype, Yext, SearchStax. If matched, status = ACTIVE, evidence_tier = VERIFIED. 2. Category contains "search" (case-insensitive) and no name match: status = TAG_ONLY, evidence_tier = WEBFETCH. 3. First match wins. Multiple search vendor tags do not create multiple SearchVendor records.

Other Category Matching (case-insensitive substring on Categories list): - ecommerce_platform: category contains "ecommerce" or "shopping-cart" - cms: category contains "cms" - cdn: category contains "cdn" - analytics: category contains "analytics" (all matches, not first-only) - personalization: category contains "personalization" or "a-b-testing" - bot_detection: category contains "bot" or "captcha"

Golden Angle Detection

For each competitor in competitor_tech_stacks: - If is_algolia_customer = True on the CompetitorTechStack model, add company_name to golden_angle_competitors. - is_algolia_customer is set by checking if any raw technology name matches "Algolia" (via _match_search_vendor).

This is a direct API confirmation -- not inference. If Algolia is live-detected on a competitor's domain, that competitor is confirmed as an Algolia customer.


Validation Rules (8 Checks)

# Rule Severity Threshold
1 search_vendor is populated warning Not None
2 Minimum technology count required >= 3 technologies in all_technologies
3 At least 1 source recorded required sources list not empty
4 tech_stack_summary not empty required Non-empty string
5 comparative_summary present when competitors exist required Not empty if competitor_tech_stacks populated
6 Each competitor has at least 1 technology warning No empty competitor stacks
7 golden_angle_competitors subset of competitor names required All golden_angle entries present in competitor_tech_stacks
8 All competitor domains are valid required Each domain contains a "."

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

Note: Check 1 (search_vendor) is a warning, not a required failure. It is valid for a prospect to have no detectable search vendor (custom-built search, no search bar, etc.).


Evidence Requirements

Field Minimum Tier Rationale
search_vendor (name-matched) VERIFIED Direct BuiltWith API detection with LIVEONLY filter
search_vendor (TAG_ONLY) WEBFETCH Category-inferred, not name-confirmed
ecommerce_platform VERIFIED Direct BuiltWith API detection
all_technologies VERIFIED Direct BuiltWith API, live-only
golden_angle_competitors VERIFIED Direct API confirmation per competitor domain
comparative_summary WEBSEARCH Derived synthesis, no direct citation

Persistence

intel-techstack writes to module_executions only. It does NOT write to the accounts table directly.

module_executions Fields Written

module_name="intel-techstack",
module_version="0.1.0",
status="success" | "partial" | "failed",
output={...TechStackOutput fields...},
sources=[...Source records...],
duration_ms=...,
llm_calls=0,
llm_cost_usd=0.0

Status logic: - success: len(all_technologies) >= 3 - partial: len(all_technologies) < 3 but module did not throw - failed: unhandled exception in execute()


Cost Profile

Metric Expected Value
LLM Calls 0
Estimated Cost $0.00 (BuiltWith subscription, per-domain lookup)
Expected Duration 5-30 seconds (scales with competitor count; parallel)
External API Calls 1 (prospect) + N (competitors, parallel)

BuiltWith is typically licensed as a subscription with a per-lookup quota rather than per-call billing. Competitor fan-out consumes N additional lookups per audit.


Retry Architecture

Module Level (execute wrapper)

Trigger Behavior
Exception in execute() Caught, logged, returns ModuleExecutorResult(status="failed")
Max Retries 2 (via ModuleConfig.max_retries, handled by ModuleExecutor)

Collector Level

Trigger Behavior
BuiltWith API failure (prospect) Returns TechStackOutput with tech_stack_summary="BuiltWith API call failed"
BuiltWith timeout (competitor) Returns CompetitorTechStack(company_name, domain) with no tech data
BuiltWith HTTP error (competitor) Returns CompetitorTechStack(company_name, domain) with no tech data
asyncio.gather exception Logged, that competitor result skipped; others unaffected

The isolation boundary is the competitor: one competitor API failure does not contaminate other competitor results or the prospect result.


Runtime Notes

SaaS Runtime (Temporal/Python)

  • Module: prism_platform/v2/modules/intel_techstack/module.py
  • Collector: prism_platform/v2/modules/intel_techstack/collector.py
  • Validator: prism_platform/v2/modules/intel_techstack/validator.py
  • Schemas: prism_platform/v2/modules/intel_techstack/schemas.py
  • Config key: settings.builtwith_api_key (BUILTWITH_API_KEY env var)

Skill Runtime (Claude Code)

  • Skill file: ~/.claude/skills/algolia-intel-techstack/SKILL.md
  • Reads from: 01-company-context.json (competitor domains)
  • Writes to: 02-tech-stack.md, 02-tech-stack.json
  • MCP tools used: BuiltWith MCP (all 7 endpoints for prospect), BuiltWith MCP per competitor

What Makes This Production-Grade (vs a Simple Prompt)

Aspect Simple Prompt PRISM Module
Detection method "What search vendor does X use?" Direct BuiltWith API with LIVEONLY filter -- no hallucination risk
Competitor coverage Ask about each competitor manually asyncio.gather fan-out: all competitors in parallel, one timeout budget
Golden Angle Manual check Deterministic: Algolia tag on competitor domain = confirmed customer
Status classification Hope for the best ACTIVE / TAG_ONLY / REMOVED / UNDETECTED with explicit evidence tier
Failure isolation One error aborts everything Per-competitor try/catch -- 1 failure doesn't lose 5 others
Evidence "BuiltWith says..." Typed Source records with evidence tier, source URL, method
Validation Trust the output 8-point validation; partial status returned if data quality is low

Changelog

Date Change Reason
2026-04-14 Module spec written to vault Knowledge extraction for v2 planning

Evolution: v1 -> v2

What Changes in v2

Dimension v1 (current) v2 (planned)
Module structure module.py + collector.py + validator.py config.py + playbook.md + schemas.py + generic executor
Competitor input Read from ExecutionContext.intelligence (fragile, JSONB path) Read from typed Account.competitors column via FindingQuery contract
Execution strategy Hardcoded asyncio.gather fan-out Declared execution_strategy: per_company in config.py -- executor handles fan-out generically
Finding model Raw dict in module_executions.output Typed Finding with FindingCategory (TECH_STACK_DETECTION, GOLDEN_ANGLE_SIGNAL)
Claim registry Not generated ClaimRegistryEntry auto-generated per Finding for citation chain
Evidence tier Set per-field in collector Declared in playbook.md; enforced by executor
Search vendor taxonomy 12 hardcoded strings in KNOWN_SEARCH_VENDORS Loaded from config.py KNOWN_SEARCH_VENDORS list (overridable per deployment)
LLM fallback None Optional LLM classification step for ambiguous TAG_ONLY cases (configurable, off by default)

v2 FindingCategory Taxonomy

TECH_STACK_DETECTION    -- prospect tech stack confirmed
GOLDEN_ANGLE_SIGNAL     -- competitor confirmed using Algolia (sales-critical)
SEARCH_VENDOR_CONFIRMED -- prospect search vendor name + status
COMPETITIVE_TECH_MAP    -- competitor technology landscape summary

Key v2 Design Decisions

  1. execution_strategy: per_company replaces the hardcoded collect_all_with_competitors method. The generic executor reads competitor domains from the account and runs the playbook once per domain, then merges results. This makes the fan-out pattern reusable across all modules that need it (intel-traffic, intel-hiring, etc.).

  2. Golden Angle as a first-class Finding (not a field in a larger output). In v2, each confirmed Algolia competitor generates its own Finding(category=GOLDEN_ANGLE_SIGNAL) with the competitor domain, evidence URL, and detection timestamp. This makes Golden Angle signals queryable and surfaceable independently from the full tech stack dump.


  • Module-Catalog -- all 20 modules overview
  • Intel-Company -- provides competitor list this module fans out on
  • Evidence-Tier-Spec -- evidence tier system
  • Adapter-Interfaces -- BuiltWith API adapter