Documentation

SpearHead Reference

Complete documentation for the multi-agent spear phishing research platform. From installation to API endpoints, OSINT tools, and the knowledge graph.

5 Agents
Scout → Report
10+ Sources
OSINT tools
4 Providers
LLM backends
Open Source
MIT license
Getting Started

Overview

SpearHead is a multi-agent spear phishing research platform that automates the full OSINT-to-phishing-email lifecycle. It is designed exclusively for authorized security testing, academic research, and defensive cybersecurity training.

Authorized use only. SpearHead is intended for Red Team engagements under a signed statement of work, Blue Team defense training, or academic research. Unauthorized use against real targets is illegal and unethical.

Architecture

The system is composed of five specialized agents that run in sequence, each feeding results into the next phase:

ScoutAgent
OSINT collection across 10+ sources (web, GitHub, WHOIS, DNS, HIBP, Apify)
ProfilerAgent
Entity extraction and Neo4j knowledge graph construction
AttackAgent
Graph RAG to generate personalized phishing email simulations
ReviewerAgent
Quality scoring and detector analysis for each simulation

Services

ServiceStackPortPurpose
BackendPython / FastAPI8000Pipeline engine, REST API, WebSocket
DashboardNext.js 163000Operational UI — graph, console, results
Neo4jneo4j:5 (Docker)7474 / 7687Knowledge graph database

Quick Start

Two ways to get SpearHead running quickly, depending on your setup:

Option A — Docker Compose (recommended)

No Python, Node.js, or Neo4j installation required. Just Docker Desktop.

bash
$ git clone https://github.com/ismaellaya/SpearAI.git
$ cd SpearAI
$ cp .env.example .env
# Edit .env — set GEMINI_API_KEY or adjust OLLAMA_BASE_URL
$ docker compose up --build

Open http://localhost:3000 once the three services are running. See the Docker Compose section below for full details, Ollama tips, and runtime key management.

Option B — Shell scripts (dev mode)

Requires Python 3.10+, Node.js 20+, and Docker Desktop already installed. The scripts start Neo4j via Docker Compose, activate the virtualenv, run the FastAPI backend, and launch the Next.js dev server.

bash
$ git clone https://github.com/ismaellaya/SpearAI.git
$ cd SpearAI
$ cp .env.example .env
# Install Python dependencies (first time only)
$ python -m venv .venv
$ source .venv/bin/activate # Linux / macOS
$ .venv\Scripts\activate # Windows PowerShell
$ pip install -r requirements.txt
# Install dashboard dependencies (first time only)
$ cd dashboard && npm install && cd ..
# Run everything
$ chmod +x run_dashboard.sh && ./run_dashboard.sh # Linux / macOS
$ .\run_dashboard.ps1 # Windows PowerShell
Use this option when actively developing SpearHead — hot reload is enabled for both the backend (--reload) and the dashboard (next dev).

Docker Compose

The easiest way to share SpearHead with a tester or run it on a fresh machine — no Python venv, no manual service juggling. A single command builds and starts Neo4j, the FastAPI backend, and the Next.js dashboard together.

Prerequisites

Only Docker Desktop (Mac/Windows) or Docker Engine + Compose v2 (Linux) is required. No Python, Node.js, or Neo4j installation needed on the host.

1 — Clone & configure

bash
$ git clone https://github.com/ismaellaya/SpearAI.git
$ cd SpearAI
$ cp .env.example .env

Open .env and set at least one LLM provider. For Gemini (recommended for first run):

env
LLM_PROVIDER=gemini
GEMINI_API_KEY=your_key_here
If you use Ollama running locally, the container cannot reach localhost. Set the host address instead:
Mac / Windows (Docker Desktop): OLLAMA_BASE_URL=http://host.docker.internal:11434
Linux: OLLAMA_BASE_URL=http://172.17.0.1:11434

2 — Build & start

bash
# First run builds images (~5 min). Subsequent starts are instant.
$ docker compose up --build
# Run in the background
$ docker compose up --build -d

All three services start together. The backend connects to Neo4j automatically once it is ready (typically within ~60 seconds of first startup). You will see logs from all three services interleaved in the terminal.

3 — Open SpearHead

URLService
http://localhost:3000Dashboard — main UI
http://localhost:8000/healthBackend health check
http://localhost:7474Neo4j browser (neo4j / changeme)

On first visit, the Setup Screen will appear asking you to select a use case (Academic, Red Team, etc.). This choice is stored in .env automatically.

Stopping & restarting

bash
# Stop all services (data is preserved in ./data/neo4j and ./results)
$ docker compose down
# Rebuild after a code change
$ docker compose up --build
# Wipe everything including graph data
$ docker compose down -v

Configuring OSINT keys at runtime

You do not need to edit .env before every key change. Open the dashboard → Settings panel → OSINT Tools, enter the key and click Save. The backend writes it to .env immediately and picks it up on the next pipeline run — no container restart needed.

The .env file is mounted as a bind-mount inside the backend container. Never commit it to a public repository — it may contain LLM API keys.

Installation (Manual)

Manual installation gives you full control over each service and is recommended for production or customized deployments.

1 — Python backend

bash
$ python -m venv .venv
# Activate (Linux/macOS)
$ source .venv/bin/activate
# Activate (Windows)
$ .venv\Scripts\activate
$ pip install -r requirements.txt

2 — Neo4j (Docker)

bash
# Starts Neo4j at bolt://localhost:7687
# Web UI at http://localhost:7474
$ docker-compose up -d

Default credentials: neo4j / changeme (set in .env).

3 — FastAPI server

bash
$ python -m uvicorn src.api:app --reload --host 0.0.0.0 --port 8000

4 — Dashboard

bash
$ cd dashboard
$ npm install
$ npm run dev # Dev server at http://localhost:3000

Configuration

Copy .env.example to .env in the project root. Only one LLM provider is required — all OSINT keys are optional and can also be set at runtime from the dashboard Settings panel.

env
# ── Neo4j ────────────────────────────────────────────────────────────────────
# Docker Compose overrides NEO4J_URI to bolt://neo4j:7687 automatically.
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=changeme
# ── LLM Provider — pick one: local | gemini | claude | openai ────────────────
LLM_PROVIDER=gemini
# Ollama (LLM_PROVIDER=local)
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llama3
# Gemini (LLM_PROVIDER=gemini)
GEMINI_API_KEY=
GEMINI_MODEL=gemini-2.0-flash
# Claude / Anthropic (LLM_PROVIDER=claude)
ANTHROPIC_API_KEY=
ANTHROPIC_MODEL=claude-sonnet-4-6
# OpenAI (LLM_PROVIDER=openai)
OPENAI_API_KEY=
OPENAI_MODEL=gpt-4o
# ── Use case (set automatically via Setup Screen on first run) ────────────────
# Values: academic | red_team | blue_team | awareness | threat_intel
# USE_CASE=
# ── Optional OSINT tools ──────────────────────────────────────────────────────
GITHUB_TOKEN= # Raises GitHub rate limit from 60 to 5 000 req/h
HUNTER_API_KEY= # Hunter.io email finder — 25 searches/month (free tier)
APIFY_API_TOKEN= # Apify social scraping — Instagram & TikTok profiles
APIFY_ENABLED=true # Set to false to disable Apify without removing the key
HIBP_API_KEY= # HaveIBeenPwned individual email lookup (paid key)

USE_CASE values

ValueContext injected into LLM prompts
academicAcademic research and security education context
red_teamAuthorized penetration test under signed statement of work
blue_teamDefensive SOC analyst training material
awarenessAuthorized employee security awareness campaign
threat_intelThreat intelligence and attribution research
Getting Started

Environment Variables Reference

All configuration is done via environment variables in .env. Optional keys can also be set at runtime from the dashboard Settings panel without restarting the backend.

VariableTypeDefaultDescription
NEO4J_URIurlbolt://localhost:7687Neo4j Bolt URI (overridden to bolt://neo4j:7687 in Docker Compose)
NEO4J_USERstringneo4jNeo4j username
NEO4J_PASSWORDsecretchangemeNeo4j password
LLM_PROVIDERstringgeminiLLM backend: local (Ollama) | gemini | claude | openai
OLLAMA_BASE_URLurlhttp://localhost:11434Ollama server URL — use host.docker.internal:11434 in Docker
OLLAMA_MODELstringllama3Ollama model name
GEMINI_API_KEYsecretGoogle Gemini API key
GEMINI_MODELstringgemini-2.0-flashGemini model name
ANTHROPIC_API_KEYsecretAnthropic Claude API key
ANTHROPIC_MODELstringclaude-sonnet-4-6Anthropic model name
OPENAI_API_KEYsecretOpenAI API key
OPENAI_MODELstringgpt-4oOpenAI model name
USE_CASEstring(setup screen)Authorization framing: academic | red_team | blue_team | awareness | threat_intel
GITHUB_TOKENsecretGitHub PAT — raises rate limit from 60 to 5 000 req/h
HUNTER_API_KEYsecretHunter.io API key for email discovery
APIFY_API_TOKENsecretApify token for Instagram & TikTok OSINT
APIFY_ENABLEDbooltrueSet to false to disable Apify per-run without removing the key
HIBP_API_KEYsecretHaveIBeenPwned key for individual email breach lookup (paid)
CORS_ORIGINSstringlocalhost:3000Comma-separated allowed origins for the dashboard
Pipeline

Pipeline Modes

ModeAgentsOutput
fullScout → Profiler → Attack → Reviewer → ReportEmails + graph + JSON report
searchScout → ProfilerKnowledge graph only (no emails)
deep_searchScout (extended depth) → ProfilerMore OSINT + knowledge graph
Deep Search runs additional DuckDuckGo passes, increases the OSINT result cap, and enables extended Wayback Machine lookups. It takes 2-3x longer than a standard search.

Running a Scan

Follow these steps to run a full pipeline from the dashboard:

  1. 1Enter target(s) in the sidebar textarea — names, email addresses, or domains (up to 10 per run).
  2. 2Fill the Engagement Context panel: org name, type (Corporation / University / Government), known domains, and scope notes.
  3. 3Select the pipeline mode (Full / Search / Deep Search) and the number of attack variation angles (1–3).
  4. 4Choose the SpearDetector mode: Entropy (fast, no API needed) or AI (requires a configured LLM).
  5. 5Click Run Pipeline. Watch the Phase Timeline and Agent Console update in real time.
  6. 6When complete, click View Results to see generated emails grouped by target and variation. Use the Compare mode for side-by-side analysis.

Batch Targets

Enter multiple targets one per line in the sidebar textarea (maximum 10 per run). The pipeline processes them sequentially and tracks progress via the batch_info WebSocket field.

bash
# Example target list (one per line)
john.doe@example.com
jane.smith@corp.com
targetdomain.com
Alice Johnson
Use Clean DB (in Settings) before a new engagement to avoid graph data from previous runs mixing with the current batch. The Clean DB option also runs automatically for the first target when checked in the UI.
Best Practices

First Run Workflow

The single most effective technique for improving result quality is running the pipeline on a new target with Deep Search enabled and a disambiguation hint in parentheses:

bash
# Use natural language — commas separate targets, so avoid them inside hints
John Smith (CTO working at Acme Corp based in Madrid)
alice.johnson@corp.com (IT Security engineer at Corp Ltd in London)
targetdomain.com

The hint inside parentheses acts as a semantic anchor: the ScoutAgent's LLM summarizer uses it to discard search results that belong to a different person with the same name, and the ProfilerAgent uses it to reject entities that don't fit the described profile.

Step 1 — First run (new target)

  1. 1Enable Deep Search (the "Deep" button in the sidebar turns amber when active).
  2. 2Add context in parentheses after the target name using natural language — avoid commas as they are used to separate targets. Example: "John Smith (CTO at Acme Corp based in Madrid)".
  3. 3Fill the Engagement Context panel with the target organisation's known domains.
  4. 4Run in Full mode. The pipeline creates a Person node in Neo4j with high-confidence properties.

Step 2 — Enrichment from the graph

Once the node exists in Neo4j, right-click it in the graph and launch a new pipeline directly from the context menu. On this second pass:

  • The ProfilerAgent sees existing node properties and discards entities that contradict the established profile.
  • Re-running with Deep Search adds more OSINT depth without duplicating existing confident nodes.

Step 3 — Annotate and validate

Right-click any node → Annotate to mark it with one of three statuses:

StatusColorMeaning
confirmed🟢 green #00ff88Manually verified as correct
false_positive🔴 red #ff4444Belongs to a different person — keep visible but flagged
needs_review🟡 amber #ffaa00Uncertain — pending verification

Annotations are stored as Neo4j node properties and persist across runs. They help the LLM on future executions by providing a curated, validated context.

Reducing False Positives

False positives — nodes that belong to a different person with the same name — are the main quality issue when profiling common names. These techniques reduce them significantly.

Disambiguation hints (most effective)

Add context in parentheses directly in the target field. The more specific, the better:

Target inputEffect
John SmithHigh false-positive risk — common name
John Smith (software engineer)Better — filters unrelated professions
John Smith (senior engineer at Acme)Good — company narrows scope significantly
John Smith (CTO at Acme Corp based in Madrid)Best — role + company + city is unambiguous

Engagement Context scope notes

The scope_notes field in the Engagement Context panel is injected into the ProfilerAgent prompt. Use it to explicitly rule out categories:

bash
# Example scope notes
Target is the CTO of Acme Corp Madrid — discard any results
related to sports, music, or other industries. Focus only
on software engineering and corporate leadership.

Confidence filter

Use the confidence filter in the graph toolbar (ALL / MED+ / HIGH) to hide low-confidence nodes during review. Person nodes are always shown regardless of the filter. Switch to HIGH first to inspect the reliable core, then expand to ALL to review edge cases.

False-positive nodes you annotate as false_positive remain in the graph with a red ring. They act as negative examples, signalling to future pipeline runs that these entities have already been evaluated and rejected.

Engagement Context Tips

The Engagement Context panel (collapsible, between the target input and the phase timeline) enriches both the OSINT collection and the LLM analysis phases.

FieldWhat it does
org_nameInjected into the dork generator LLM prompt to produce more targeted Google queries
org_typeSets the organisational frame (Corporation / University / Government / NGO / Startup) — influences ProfilerAgent entity weighting
known_domainsActivates passes 5–7 (WHOIS, DNS, crt.sh) and 7b (HIBP) on those domains; results go to org_domain_sources, kept separate from person data
scope_notesFree-text injected into ProfilerAgent prompt to constrain entity extraction and reduce off-topic false positives

known_domains: what gets activated

  • +WHOIS lookup — registrant org, registrar, creation/expiry dates
  • +DNS enumeration — MX records reveal email provider (Google Workspace / M365 / custom), TXT records expose SPF + DMARC policy
  • +crt.sh Certificate Transparency — subdomain discovery, cert issuer
  • +HIBP domain breach check — free lookup of corporate email domain against known breaches
  • +Org-scoped DuckDuckGo search — "target name" site:domain.com for confirmed association evidence
  • +Email pattern inference — ProfilerAgent derives first.last@domain, flast@domain patterns from DNS + confirmed Email nodes
When the context panel has active data, a cyan active badge appears on the panel header. Infrastructure nodes created from known_domains (HOSTED_BY, REGISTERED_BY, USES_SERVICE, ISSUED_BY) are linked to the Website node, never directly to the Person node.

Working with the Graph

Toolbar quick reference

ButtonAction
Query
Open / close the Cypher Query panel — run custom Neo4j queries
Analytics
Open / close the Graph Analytics panel — centrality, density, components
Minimap
Toggle minimap overlay in the bottom-left corner
Zoom In
Zoom in on the graph canvas
Zoom Out
Zoom out on the graph canvas
Fit View
Zoom to fit — centers and scales all visible nodes
Export PNG
Export the current graph view as a PNG image
Export Data
Export graph data as CSV zip (nodes + edges) or GEXF (Gephi-compatible)
Refresh
Reload graph data from Neo4j
Labels
Toggle node labels on/off — useful on dense graphs
Fullscreen
Enter or exit fullscreen mode
Cluster
Cluster nodes by type — sectors arranged radially around center
Select
Multi-select mode — drag a box to select nodes, then delete them (Esc to exit)
Legend panel (bottom-left)
ALL / MED+ / HIGHConfidence filter — hides low-confidence nodes; Person nodes always visible
Node type chipsToggle visibility by node type (Person, Email, Company, Location, …)
Annotation filterFilter by annotation: All / Confirmed / Needs Review / False Positive

Right-click context menu

  • Edit Node — update properties directly from the dashboard
  • Annotate Node — set confirmed / false_positive / needs_review status with optional notes and tags
  • Generate Email — runs AttackAgent + ReviewerAgent using this node's Neo4j neighbourhood as RAG context
  • Delete Node — removes the node and all its relationships
  • Right-click on canvas background — opens Add Node picker to manually insert a new entity

Before starting a new engagement

Export the current graph (FileDown → GEXF) before clearing the database. GEXF files can be opened directly in Gephi for offline analysis. Then use Clean DB in Settings → Danger Zone (requires confirmation) to start fresh.

The radial layout fixes node positions (fx/fy) on the d3 simulation. It resets automatically when you refresh the graph or start a new run.
Agents

ScoutAgent

ScoutAgent
Faithful OSINT summarization. Lower temperature reduces hallucination while still producing readable narrative summaries from raw search snippets.
temperature
0.3

Collection passes (sequential)

PassSourceCondition
1Google/DuckDuckGo dork (LLM-generated)Always
1bOrg-scoped search: "name" site:domain.comOnly if org_context.known_domains set
2GitHub — public repos, languages, topics, bioAlways
3Wayback Machine CDX APIDomain targets only
4WHOIS — registrant, registrar, datesDomain targets only
5DNS — MX, TXT (SPF/DMARC), A recordsDomain targets only
6crt.sh Certificate Transparency (subdomains)Domain targets only
7HIBP domain breach check (no API key)Domain targets only
7bHIBP email/paste lookupEmail targets (requires HIBP_API_KEY for paid endpoint; otherwise uses domain fallback)
8Hunter.io email finderRequires HUNTER_API_KEY
9Apify social media (Instagram, TikTok)Requires APIFY_API_TOKEN

Output keys

bash
{
"target": "john.doe@example.com",
"sources": [...], # Person/target OSINT results
"org_domain_sources": [...], # Infrastructure data (WHOIS/DNS/crt.sh) — kept separate
"summary": "...", # LLM narrative summary
"memory_context": "..." # Condensed context for AttackAgent
}

Source deduplication

Before passing to the LLM summarizer, _deduplicate_sources() applies:

  • +Max 3 results per domain (prevents link-farm flooding)
  • +Snippet prefix dedup (first 80 chars) removes near-duplicates
  • +Hard cap: 50 sources total
  • +Apify sources (image_url) and HIBP breach entries (DATA_BREACH) are always preserved, exempt from caps

ProfilerAgent

ProfilerAgent
Lowest temperature for precise structured JSON extraction. Small deviations from the schema are recovered by json-repair before Neo4j insertion.
temperature
0.1

Node types

PersonWebsiteEmailCompanyEducationLocationTopicUsername

Relationship types

RelationshipUsage
WORKS_ATPerson → Company (current or past employer)
EDUCATED_ATPerson → Education (university, school)
HAS_EMAILPerson → Email
HAS_USERNAMEPerson → Username (social media handles)
REGISTERED_ONPerson → Website (owned or operated domain)
INTERESTED_INPerson → Topic (hobby, skill, technology)
LIVES_INPerson → Location
HOSTED_BYWebsite → Company (hosting provider)
REGISTERED_BYWebsite → Company (domain registrar)
USES_SERVICEWebsite → Company (Google Workspace, M365…)
ISSUED_BYWebsite → Company (SSL certificate authority)

Email pattern inference

When known org domains are present in the Engagement Context, ProfilerAgent automatically infers email address patterns by cross-referencing confirmed Email nodes against each domain and scoring format candidates:

first.last@domainflast@domainf.last@domainfirstlast@domainfirst@domain

Inferred patterns are stored as Email nodes with the property inferred_pattern: true for visual distinction in the graph.

Injection protection

Before calling the LLM, all OSINT data is sanitized against a blocklist of prompt injection patterns (</s>, <|system|>,[INST], ###, etc.). Blocked patterns are stripped silently so the injection attempt is defused without halting the pipeline.

AttackAgent

AttackAgent
Highest temperature for creative, unpredictable phishing content. Uses Graph RAG to ground email content in real OSINT data from the target's Neo4j subgraph.
temperature
0.85

Graph RAG retrieval

AttackAgent queries Neo4j for the target's 1-hop neighbors:

bash
MATCH (p:Person {name: $name})-[r]-(neighbor)
RETURN type(r), labels(neighbor), neighbor.name, neighbor.source_context
LIMIT 25

Retrieved neighbors (organizations, education, topics, usernames) are injected into the system prompt as structured context. This grounds the generated email in verifiable facts about the target rather than generic templates.

Persuasion angle variations

V1
Urgency / Authority
IT Security, HR, or management persona. Time-sensitive threat that requires immediate action. References company systems or compliance requirements.
V2
Reciprocity / Shared Interest
References a real shared interest, professional connection, or upcoming event. Offers value before asking. Builds rapport through demonstrated research.
V3
Opportunity / Exclusivity
Exclusive grant, tool access, early-adopter program, or award nomination. Creates positive urgency through scarcity and professional validation.

Output format

bash
{
"target": "John Doe",
"variation": 1,
"subject": "Urgent: Account verification required by EOD",
"body": "...",
"language": "en",
"context_used": ["Acme Corp", "GitHub", "Python", "San Francisco"]
}

ReviewerAgent

ReviewerAgent
Low temperature for objective, reproducible scoring. Acts as a QA analyst stress-testing each simulation against real-world email gateway heuristics.
temperature
0.2

Scoring criteria

Score range: 0 (obvious spam) to 10 (would likely bypass detection):

Score rangeInterpretation
0 – 3Low realism — obvious flags (generic template, wrong name, broken links)
4 – 6Medium — might fool some users but would flag most gateways
7 – 8High — convincing pretext, grounded details, natural tone
9 – 10Very high — personalized to the point of requiring specific counter-detection

Output format

bash
{
"score": 8,
"critique": "Strong authority pretext using real org name. The IT dept
signature and urgency cues would flag Proofpoint's TAP rules.
Subject line uses urgency keyword 'EOD'.",
"improved_subject": "Re: Action required — identity verification portal",
"improved_body": "...",
"variation": 1
}
OSINT Tools

Always-Active Tools

These tools require no API key and run on every scan:

ToolSourceWhat it finds
Google/DuckDuckGoHTML backendWeb profiles, job history, news mentions, conference talks
GitHub OSINTapi.github.comPublic repos, programming languages, topics, bio, README content
Wayback MachineCDX API (cdx.api)Archived page snapshots — old job titles, portfolio pages
WHOISpython-whoisDomain registrant org, registrar, creation/expiry dates, nameservers
DNSdnspythonMX (email provider), TXT (SPF/DMARC policy), A records
crt.shcrt.sh public APISubdomains via Certificate Transparency logs, cert issuers
HIBP (domain)HIBP public APIData breaches associated with an org domain (no key needed)
Domain-only passes (Wayback, WHOIS, DNS, crt.sh, HIBP domain) are skipped for person-name targets automatically. The system detects domain targets via a simple heuristic: contains a dot, no spaces, no @ symbol.

Optional Tools (API Keys)

ToolEnv varWhat it addsCost
GitHub (auth)GITHUB_TOKENRate limit: 60 → 5000 req/h. Also unlocks private org membership on some accounts.Free (personal token)
Hunter.ioHUNTER_API_KEYCorporate email finder: format + pattern discovery for a domain. Email verifier.25 searches/mo free
HIBP (email)HIBP_API_KEYIndividual email breach lookup + paste database search. Provides pretext context.Paid — $3.50/mo

Setting keys at runtime

API keys can be updated without restarting the backend. Open the dashboard Settings panel (gear icon in the sidebar) and expand the OSINT Tools section. Keys are saved to .env via POST /config/tools and take effect immediately. Use the Test button to verify each key before running a scan.

Social Media (Apify)

Set APIFY_API_TOKEN to enable social media OSINT via the Apify actor platform. The toggle in Settings lets you enable/disable Apify per-run without removing the key.

PlatformActorData collected
Instagramapify/instagram-profile-scraperBio, follower/following count, profile picture URL
TikTok0FXVyOXXEmdGcV88a + GdWCkxBtKWOsKjdchProfile + keyword search

Profile pictures from Apify are stored as profile_pic_url on the corresponding Username node in Neo4j. They are displayed in node tooltips in the dashboard graph.

Apify scraping may be subject to platform ToS restrictions. Use only for targets and platforms covered in your engagement authorization.
Use Cases

Red Team Engagement

Set USE_CASE=red_team in .env. This mode frames all LLM prompts as an authorized penetration test under a signed statement of work, maximizing realism while maintaining ethical guardrails.

Recommended workflow

  1. 1Fill the Engagement Context panel: org name, type (Corporation), known email domains, scope notes referencing the SoW number.
  2. 2Add employee names as batch targets — use hints like "Alice Johnson (IT Helpdesk)" to help the LLM disambiguate common names.
  3. 3Run in full mode with 3 variations to generate Authority, Rapport, and Opportunity angle emails for each target.
  4. 4Review results in the Compare pane — sort by Reviewer score to prioritize the most convincing simulations.
  5. 5Export as HTML report (Pro) or JSON for evidence documentation.
  6. 6Test top emails against your email gateway (Proofpoint, Mimecast) to measure detection rate.

Blue Team Training

Set USE_CASE=blue_team. Generates realistic phishing samples for SOC analyst training, detection rule development, and email gateway tuning.

Recommended workflow

  1. 1Run the pipeline on public personas related to your industry (e.g., public LinkedIn profiles of CISOs at peer companies).
  2. 2Export phishing emails from View Results — copy the raw email body or use the JSON export.
  3. 3Import into your phishing simulation platform (GoPhish, KnowBe4) as custom email templates.
  4. 4Use the Reviewer critique text as ground truth for what features make an email convincing — build detection rules targeting those features.
  5. 5Export the knowledge graph as GEXF to visualize organizational attack surface in Gephi.

Academic Research

Set USE_CASE=academic. All generated artifacts are labeled for academic/research context. Recommended for conference papers, security research, and educational use.

Research outputs

Knowledge Graph
Export as GEXF for Gephi or as CSV for pandas/networkx. Analyze network topology, centrality, and community structure.
Email Corpus
JSON export of generated simulations with metadata: variation angle, target, score, critique, detected language.
OSINT Provenance
Each graph node stores source_context with the raw OSINT snippet that produced it — full evidence trail.
Cost Analytics
Token usage and USD cost per phase tracked in the HTML report. Useful for LLM efficiency comparisons.

Security Awareness

Set USE_CASE=awareness. Personalized simulated phishing for authorized employee awareness campaigns — each email is tailored to the individual target using real OSINT.

Obtain explicit written authorization from the organization before running awareness campaigns against employees. Verify targets are within scope.

Recommended workflow

  1. 1Add employee names as batch targets (up to 10 at a time). The system processes them sequentially.
  2. 2Run in full mode — each email is personalized to the individual's public professional profile.
  3. 3Review scores in the results panel. Lower-scoring emails may need manual refinement before deployment.
  4. 4Use generated emails in your authorized simulated phishing platform.
  5. 5Include the Reviewer critique in post-campaign follow-up training materials to explain exactly what made the email convincing.
Dashboard

Interface Overview

The dashboard runs at http://localhost:3000 and provides real-time visualization of the pipeline as it runs.

PanelDescription
SidebarTarget input, mode selector, Engagement Context panel, Phase Timeline (5 phases with timings), Agent Console (live log stream)
Graph PanelInteractive force-directed knowledge graph. Nodes colored by type. Zoom, pan, fit-to-view.
ToolbarExport (CSV/GEXF), layout (force/radial), label toggle, fullscreen, node type filters, confidence filter (ALL/MED+/HIGH)
Results ModalGenerated emails grouped by target. Sub-tabs per variation. Side-by-side Compare mode for multi-variation analysis.
History PanelPrevious pipeline results. Search by target or filename. JSON download, HTML report viewer, PDF export (Pro).
Email AnalyzerStandalone phishing detection for pasting any email. Entropy or AI detection mode.
Settings ModalLLM config, OSINT tool keys (with Test button), Danger Zone (Clear Database with confirmation dialog).

Knowledge Graph

The graph panel renders the full Neo4j graph using react-force-graph-2d. All OSINT entities and relationships are visualized as a force-directed layout.

Right-click context menu

ActionDescription
Edit NodeUpdate node name or any property inline
Annotate NodeMark as Confirmed / False Positive / Needs Review with notes and tags. Color ring appears around the node.
Generate EmailRun AttackAgent + ReviewerAgent directly from any Person node. Shows result in GenerateEmailModal.
Delete NodeRemoves node and all its relationships from Neo4j
Add Node (canvas)Right-click on empty canvas background to add a new node of any type

Graph export

Click the FileDown icon in the toolbar to export:

CSV
ZIP archive containing nodes-DATE.csv and edges-DATE.csv. Compatible with any spreadsheet tool or pandas.
GEXF
XML format compatible with Gephi. Node attributes (type, profile, language) included. IDs sanitized (colon → underscore).

Confidence filter

The toolbar confidence control (ALL / MED+ / HIGH) hides low-confidence inferred nodes. Person nodes are always shown regardless of confidence. Useful for cleaning up cluttered graphs from large batch runs.

Annotation colors

ConfirmedVerified true positive
False PositiveInferred incorrectly
Needs ReviewUncertain, requires verification

Email Analysis

The standalone Email Analyzer panel allows you to paste any raw email and run SpearDetector analysis without running a full pipeline. Accessible from the dashboard via the mail icon in the sidebar.

ModeHow it worksAPI key needed
EntropyStatistical analysis: Shannon entropy, multilingual phishing keywords, link inspection, URL redirect chainsNo
AILLM-based analysis: semantic phishing pattern detection, contextualized scoringYes (configured LLM)

Rate limit: 10 analyses per minute per IP. Results show a risk score, flagged indicators, and entropy breakdown. The endpoint is POST /analyze-email.

Run History

The History panel (clock icon in the sidebar) lists all previous pipeline runs saved to results/. Results are saved as result_{target}_{timestamp}.json.

ActionDescription
SearchFilter history by target name or filename (real-time)
OpenView the full JSON result in the results modal
DownloadDownload the raw JSON result file
HTML ReportOpen the generated HTML report in a new browser tab (Pro)
PDF ExportDownload a Playwright-rendered A4 PDF (Pro)
DeletePermanently removes the result file (path-traversal protected)
Checkpoints are saved to results/checkpoints/ after each completed phase. If a pipeline run is interrupted, use POST /resume-pipeline/{run_id} to resume from the last checkpoint without repeating completed phases.
API Reference

Key Endpoints

The FastAPI backend exposes a REST API at http://localhost:8000. Interactive docs at /docs (Swagger UI) and /redoc.

MethodEndpointDescriptionRate limit
GET/healthService status (Neo4j, Ollama, Gemini, Pro features)
POST/run-pipelineStart pipeline. Body: PipelineRequest (targets, mode, variations_count, org_context)5/min
POST/resume-pipeline/{run_id}Resume from last checkpoint. run_id is a 12-char hex string.5/min
GET/pipeline-statusCurrent phase + logs snapshot (polling fallback)
WS/ws/logsReal-time log stream + status + batch_info + db stats
GET/POST/graph-dataFull graph as {nodes, links}
POST/run-queryExecute arbitrary Cypher query (max 2000 chars)20/min
POST/search-nodesSearch nodes by name substring
GET/analyticsGraph metrics: degree/betweenness centrality, density, components
POST/analyze-emailSpearDetector: paste email content, returns risk score10/min
POST/nodes/{node_id}/annotateAdd/update annotation (status, notes, tags)
PUT/nodes/{node_id}Update node properties
DELETE/nodes/{node_id}Delete node and all relationships
POST/nodesCreate (MERGE) a new node. Body: {label, name, properties?}
POST/generate-email/{node_id}Run AttackAgent + ReviewerAgent for a graph node
GET/historyList saved result files
DELETE/history/{filename}Delete a result file (path-traversal protected)
GET/export-graphExport full graph: ?format=csv or ?format=gexf
GET/config/toolsReturns which optional API keys are configured (never exposes values)
POST/config/toolsUpdate API keys at runtime, persists to .env
POST/config/tools/testValidate configured API keys for GitHub, Hunter.io, HIBP

Request Examples

bash
# Start a pipeline
curl -X POST http://localhost:8000/run-pipeline \
-H "Content-Type: application/json" \
-d '{
"targets": ["Alice Smith (Marketing)"],
"mode": "full",
"variations_count": 2,
"detection_method": "entropy",
"org_context": {
"org_name": "Acme Corp",
"org_type": "corporation",
"known_domains": ["acme.com"],
"scope_notes": "Authorized red team - signed SoW ref #2024-RT-001"
}
}'
bash
# Analyze a suspicious email
curl -X POST http://localhost:8000/analyze-email \
-H "Content-Type: application/json" \
-d '{
"content": "Subject: Urgent: Verify your account\n\nDear user, click here to verify...",
"method": "entropy"
}'
javascript
// WebSocket connection
const ws = new WebSocket('ws://localhost:8000/ws/logs');
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'log') {
console.log(`[${msg.level}] ${msg.message}`);
}
if (msg.type === 'status') {
console.log(`Phase ${msg.current_phase} -- running: ${msg.is_running}`);
// msg.batch_info: { total, current_index, current_target, completed, failed }
}
};

Graph Query Examples

Useful Cypher queries you can paste into POST /run-query or the dashboard's Query panel:

cypher
-- Get full profile of a person
MATCH (p:Person {name: "Alice Smith"})-[r]-(n)
RETURN p, type(r) AS rel, n
cypher
-- Find all inferred email addresses
MATCH (p:Person)-[:HAS_EMAIL]->(e:Email)
WHERE e.inferred_pattern IS NOT NULL
RETURN p.name AS person, e.name AS email, e.inferred_pattern AS pattern
ORDER BY person
cypher
-- List all companies with their employees
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
RETURN c.name AS company, collect(p.name) AS employees
ORDER BY size(employees) DESC
cypher
-- Export high-confidence nodes only
MATCH (p:Person)-[r]-(n)
WHERE n.confidence IS NOT NULL
AND ANY(v IN values(apoc.convert.fromJsonMap(n.confidence)) WHERE v = "High")
RETURN p.name, type(r), n.name, labels(n)

WebSocket

Connect to ws://localhost:8000/ws/logs to receive real-time events. The dashboard's WebSocketProvider manages a single shared connection.

Message types

bash
// Log message
{
"type": "log",
"message": "Phase 2: ProfilerAgent starting entity extraction...",
"level": "info", // info | warning | error | debug
"timestamp": "2026-03-23T14:32:01.123Z"
}
// Status update (sent every ~1 second while pipeline runs)
{
"type": "status",
"is_running": true,
"current_phase": 2,
"batch_info": {
"total": 3,
"current_index": 1,
"current_target": "john.doe@example.com",
"completed": 1,
"failed": 0
}
}

Subscribing in React

bash
import { useWSMessage } from '@/lib/WebSocketProvider';
// Subscribe to log messages
useWSMessage('log', (msg) => {
console.log(msg.level, msg.message);
});
// Subscribe to status updates
useWSMessage('status', (msg) => {
setIsRunning(msg.is_running);
setPhase(msg.current_phase);
});
Pro Features

HTML Reports

Requires Pro Package

The Pro package (spearai-pro) adds full HTML report generation after each pipeline run. Reports are saved alongside the JSON result in results/ and accessible from the History panel.

Report sections

SectionContents
Cover PageTarget name, date, USE_CASE mode, pipeline mode, run ID
Resource UsageTotal tokens, estimated USD cost, model name, per-phase token breakdown
ReconnaissanceOSINT sources used, full source list with categories, key findings
Knowledge GraphEntity counts by type, relationship counts, graph density, top connected nodes
Attack SimulationsAll generated emails organized by variation angle, subject, body, Reviewer score and critique
ConclusionsRisk summary, top-scoring simulations, recommended mitigations

Installing Pro

bash
# After purchasing, you receive a .whl file
$ pip install spearai_pro-1.0.0-py3-none-any.whl
# Verify installation
$ python -c "from spearai_pro import ReportingAgent; print('Pro installed')"
# Restart the backend — /health will show reports_available: true
$ python -m uvicorn src.api:app --reload --host 0.0.0.0 --port 8000

PDF Export

Requires Pro Package

PDF export uses Playwright / Chromium to render the HTML report at A4 dimensions and export a pixel-perfect PDF. Available from the History panel via the Download PDF button.

Technical details

ParameterValue
EnginePlaywright chromium (headless)
Viewport794 × 1123 px (A4 at 96 dpi)
Waitwait_until="load" + document.fonts.ready (Google Fonts)
FormatA4, portrait, no margin override
EndpointGET /export-pdf/{filename}
Runs inThread executor (avoids uvicorn event loop conflict)

Playwright setup

bash
# Install Playwright browsers (one-time)
$ playwright install chromium
# Or via Python
$ python -m playwright install chromium
PDF generation takes 5–15 seconds depending on report length. The dashboard shows a loading spinner in the History panel button while the PDF is being rendered.
Help

Troubleshooting

Common issues encountered when setting up or running SpearHead, with step-by-step resolution guidance.

Neo4j Connection Error

bash
Neo4j unavailable – Scout running without graph memory
Make sure Docker is running: docker-compose up -d. Check Neo4j at http://localhost:7474 (default credentials: neo4j / changeme). The pipeline continues without the graph but results won't be persisted.

LLM Provider Not Responding

For Ollama: verify the model is pulled (ollama pull llama3). For Gemini / Claude / OpenAI: check your API key in .env or Settings → LLM Config in the dashboard. The LLM retries up to 3 times with 1s / 5s / 15s backoff.

DuckDuckGo Returns No Results

DuckDuckGo rate-limits aggressive searches. Wait 30–60 seconds between runs or use the deep_search mode more sparingly. The Google dork auto-generator may also produce overly specific queries — try simplifying the target name.

Windows Encoding Errors (cp1252)

bash
UnicodeDecodeError: 'cp1252' codec can't decode...
Set your terminal to UTF-8: chcp 65001 in cmd / PowerShell, or set PYTHONUTF8=1 in your environment. All Python source files include # -*- coding: utf-8 -*-.

Apify Returns No Results

Verify APIFY_API_TOKEN is set and Apify is enabled in Settings → OSINT Tools. Instagram and TikTok results depend on profile visibility settings.

Pipeline Stuck / No Progress

Check the Agent Console for error messages. If the LLM is generating very long responses it may exceed the token window. Try switching to a smaller model or reducing max_google_results by using search mode instead of deep_search.

SpearHead Documentation · MIT License

Last updated: March 2026 · Built by Ismael Laya

GitHubAuthorized use only