| name | probe-person |
| description | Conduct deep background investigation on a person (probe). Adaptive system that profiles the subject first, then selects relevant searches from global corporate registries, professional license databases, sanctions/PEP lists, court records, social media, and news sources. Use when user asks to probe, investigate, research, or conduct due diligence on a person. Outputs detailed prose report to Documents/Probe folder. |
| allowed-tools | Read, Bash, WebSearch, WebFetch, Grep, Glob, Write, Task |
Probe Person - Adaptive Background Investigation
Execution Model
CRITICAL: This skill uses a file-first map/reduce pipeline to prevent context overflow. Investigation agents write full findings to files and return only short summaries. A dedicated synthesis agent with fresh context reads the files and writes the final report.
Architecture: File-First Map/Reduce
CONTEXT = CONTROL PLANE (lightweight) FILES = DATA PLANE (unlimited)
────────────────────────────────── ─────────────────────────────────
Phase 0: Orchestrator ~/Documents/Probe/{run_dir}/
- Profile discovery manifest.json ← profile data
- Create run directory
- Write manifest.json
│
▼
Phase 1: Spawn investigation agents ──────→ raw/corporate.md
(parallel, background) raw/sanctions.md
Each agent: raw/media.md
- Writes FULL findings to file raw/legal.md
- Returns ONLY 300-token summary raw/network.md
│ raw/licenses.md (conditional)
▼ raw/digital.md (conditional)
Phase 2: Orchestrator collects summaries
- Updates manifest.json with summaries
- NEVER reads raw files
│
▼
Phase 3: Spawn synthesis agent ──────────→ report.md
(fresh context) report.html (if requested)
Reads: manifest + raw files
Writes: final report
Why This Architecture
The previous design had agents return all findings inline, flooding the orchestrator with ~50K tokens and causing context overflow before synthesis could happen. This design:
- Crash-proof: Files persist even if any agent or the orchestrator hits context limits
- Resumable: Can re-run synthesis without re-running investigation
- Debuggable: Can inspect each agent's raw output independently
- Scalable: Adding agents doesn't increase orchestrator context pressure
AGENT OUTPUT CONTRACT (HARD RULE)
Every investigation agent MUST follow this contract. No exceptions.
What agents MUST do:
- Write ALL findings, sources, and analysis to their assigned file in
{RUN_DIR}/raw/
- Return ONLY a short summary (max 300 tokens) containing:
STATUS: complete | partial | no_findings
KEY_FINDINGS: 3-5 bullet points of most important discoveries
RED_FLAGS: Any concerns or warnings (or "None")
SOURCE_COUNT: Number of sources searched
FILE: Path to the full findings file
What agents MUST NOT do:
- Return full search results inline
- Return lengthy analysis in the task response
- Skip writing to the file
Example agent return (what the orchestrator sees):
STATUS: complete
KEY_FINDINGS:
- 4 active directorships across UK and Singapore
- 199 Biotechnologies (SG) Pte Ltd incorporated 2021, active
- 2 dissolved companies in UK (dormant, no trading history)
- Co-director Zico Yip appears on 3 of 4 active companies
RED_FLAGS: Two dormant companies dissolved within 12 months of incorporation
SOURCE_COUNT: 14 (OpenCorporates, Companies House, ACRA, Crunchbase)
FILE: ~/Documents/Probe/Boris_Djordjevic_20260217/raw/corporate.md
This is ~100 tokens. The full 5000+ token analysis is in the file.
Run Directory Structure
Every investigation creates a run directory:
~/Documents/Probe/{Subject_Name}_{YYYYMMDD}/
├── manifest.json # Profile + agent status + summaries
├── raw/
│ ├── corporate.md # Corporate Registry agent full findings
│ ├── sanctions.md # Sanctions & PEP agent full findings
│ ├── media.md # News & Media agent full findings
│ ├── legal.md # Legal & Courts agent full findings
│ ├── network.md # Network & Associates agent full findings
│ ├── licenses.md # (conditional) Professional License agent
│ └── digital.md # (conditional) Digital Identity agent
├── report.md # Final synthesized report (written by synthesis agent)
└── report.html # HTML version (if requested, written by synthesis agent)
Manifest Schema
{
"subject": "Full Name",
"run_id": "Subject_Name_YYYYMMDD",
"run_dir": "~/Documents/Probe/Subject_Name_YYYYMMDD",
"created": "2026-02-17T14:30:00Z",
"profile": {
"locations": ["London, UK", "Singapore"],
"nationality": "Serbian",
"profession": "Biotechnology CEO",
"industry": "Longevity / Cellular Reprogramming",
"companies": ["199 Biotechnologies", "SenaClear"],
"identifiers": {},
"public_profile_level": "moderate",
"phase0_summary": "Brief narrative of what Phase 0 discovered..."
},
"agents": {
"corporate": { "status": "pending", "file": "raw/corporate.md", "summary": null },
"sanctions": { "status": "pending", "file": "raw/sanctions.md", "summary": null },
"media": { "status": "pending", "file": "raw/media.md", "summary": null },
"legal": { "status": "pending", "file": "raw/legal.md", "summary": null },
"network": { "status": "pending", "file": "raw/network.md", "summary": null }
},
"synthesis": { "status": "pending", "report_file": "report.md" }
}
Philosophy & Approach
This skill produces intelligence-grade background reports written in the tradition of investigative journalism and private intelligence firms. Reports must read as compelling narratives that illuminate the subject's character, trajectory, and significance—not as data dumps or checkbox exercises.
Core Principles:
-
Parallel Execution: Spawn multiple investigation agents simultaneously to cover maximum OSINT breadth. Don't search sequentially when you can search in parallel.
-
Adaptive, Not Checklist: Every investigation is different. A doctor in Sydney requires different searches than a hedge fund manager in London. Profile the subject first, then select relevant databases—don't run FINRA on a pastry chef.
-
Prose Over Bullet Points: Every section should be written as flowing narrative paragraphs. Tables are permitted only for dense factual data (company registrations, dates). Bullet points should be rare exceptions.
-
Depth Over Breadth: It is better to deeply explore five meaningful threads than to superficially list fifty facts. Follow interesting leads. Ask "why" and "so what" about every finding.
-
Precision of Language: Every word should be intentional. Avoid vague qualifiers ("various," "several," "some"). Be specific. Instead of "worked in finance," write "spent seven years structuring equity derivatives at JP Morgan's London desk."
-
Contextualisation: Raw facts without context are meaningless. A company directorship means nothing until you explain what the company does, why it matters, and what it reveals about the subject.
-
Narrative Arc: The report should tell a story. How did this person arrive at their current position? What patterns emerge across their career? What do their choices reveal about their priorities and character?
-
Investigative Rigour: Distinguish clearly between verified facts, reasonable inferences, and speculation. Flag gaps in the record. Note when sources conflict. Acknowledge limitations.
-
Verification of High-Profile Claims: If a subject claims major deals, company exits, executive roles at notable companies, or relationships with prominent figures, there MUST be independent corroborating evidence. High-profile achievements leave paper trails. If no corroboration exists, the claim must be explicitly flagged as UNVERIFIED.
Phase 0: Profile Discovery (ORCHESTRATOR EXECUTES DIRECTLY)
Before spawning any agents, the orchestrator must establish who this person is AND set up the run directory.
Step 1: Quick Discovery
Execute these searches yourself before spawning agents:
WebSearch: "[NAME] LinkedIn"
WebSearch: "[NAME] biography"
WebSearch: "[NAME] [COMPANY if known]"
Exa People Search (1B+ indexed profiles, LinkedIn deep coverage):
python3 ~/.claude/skills/probe-person/scripts/exa_search.py --query "[NAME] [ANY KNOWN CONTEXT]" --type people -n 15
Exa Company Search (company pages and profiles):
python3 ~/.claude/skills/probe-person/scripts/exa_search.py --query "[NAME] [COMPANY]" --type company -n 10
Brave Web Search (general web coverage):
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "[NAME] biography" --count 10
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "[NAME] LinkedIn" --count 5
Optionally fetch key profile pages (personal site, company about page, etc.) for additional context.
Step 2: Profile Determination
After quick discovery, determine:
| Attribute | How to Identify | Affects Which Agents |
|---|
| Primary Location(s) | LinkedIn, news, company addresses | Corporate Registry Agent parameters |
| Nationality | Passport jurisdiction, place of birth | Sanctions Agent scope |
| Profession | Job titles, credentials claimed | Whether to spawn License Agent |
| Industry | Company types, role descriptions | Context for all agents |
| Available Identifiers | Email, phone, usernames | Whether to spawn Digital Identity Agent |
| Public Profile Level | Media presence, speaking | Depth parameters for News Agent |
Step 3: Create Run Directory and Manifest
CRITICAL: Do this BEFORE spawning any agents.
RUN_DIR=~/Documents/Probe/[Subject_Name]_[YYYYMMDD]
mkdir -p "$RUN_DIR/raw"
Then use the Write tool to create manifest.json in the run directory with the profile data from Steps 1-2. Follow the manifest schema defined above.
Agent Selection Matrix
ALWAYS SPAWN:
├── Corporate Registry Agent (with jurisdiction-specific parameters)
├── Sanctions & PEP Agent
├── News & Media Agent
├── Legal & Court Records Agent
└── Network & Associates Agent
CONDITIONALLY SPAWN:
├── Professional License Agent
│ └── IF profession ∈ {Finance, Medicine, Law, Accounting, Engineering...}
│
└── Digital Identity Agent
└── IF email OR phone OR username provided
Phase 1: Spawn Investigation Agents
Spawn ALL agents using a single message with multiple Task tool calls. This ensures true parallel execution.
CRITICAL: Every agent prompt MUST include:
- The run directory path
- The specific file to write to
- The Agent Output Contract (write to file, return summary only)
- Subject profile context from Phase 0
- Specific registries/sources to search
Agent Specifications
Agent 1: Corporate Registry Agent
Purpose: Map the subject's corporate footprint across jurisdictions.
Output file: {RUN_DIR}/raw/corporate.md
Prompt Template:
You are investigating [NAME]'s corporate involvement. Based on their profile (location: [LOCATIONS], industry: [INDUSTRY]).
## OUTPUT CONTRACT (MANDATORY)
You MUST write ALL your findings to this file using the Write tool:
[RUN_DIR]/raw/corporate.md
Structure the file with markdown headings for each company found, including all details, sources, and analysis.
After writing the file, your response back MUST be ONLY a short summary (max 300 tokens):
STATUS: complete | partial | no_findings
KEY_FINDINGS: 3-5 bullet points
RED_FLAGS: concerns or "None"
SOURCE_COUNT: number
FILE: [path to file]
DO NOT return full findings in your response. Write them to the file.
## SEARCHES TO CONDUCT
ALWAYS:
- OpenCorporates: python3 ~/.claude/skills/probe-person/scripts/opencorporates.py --name "[NAME]"
JURISDICTION-SPECIFIC (based on profile):
[IF UK] - Companies House: python3 ~/.claude/skills/probe-person/scripts/companies_house.py --name "[NAME]"
[IF US] - SEC EDGAR: WebSearch "[NAME] SEC EDGAR filing"
[IF US] - State records: WebSearch "[NAME] [STATE] secretary of state"
[IF Singapore] - WebSearch "[NAME] ACRA Singapore director"
[IF Australia] - WebSearch "[NAME] ASIC Australia director"
[IF Germany] - WebSearch "[NAME] Handelsregister"
[IF Hong Kong] - WebSearch "[NAME] Hong Kong Companies Registry"
Brave searches (general web coverage):
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "site:crunchbase.com [NAME]" --count 10
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "[NAME] beneficial owner UBO" --count 10
For EACH company found, document in the file:
1. Company name, registration number, jurisdiction
2. Incorporation date and current status
3. Nature of business (not just SIC codes—what do they actually do?)
4. Subject's role and appointment date
5. Other directors (names recurring across companies?)
6. Financial status from latest filings
7. Any red flags: dormant, dissolved, late filings, charges
Agent 2: Professional License Agent
Purpose: Verify professional credentials in official registries.
Only spawn if: Subject's profession requires licensing.
Output file: {RUN_DIR}/raw/licenses.md
Prompt Template:
Verify professional credentials for [NAME], who claims to be a [PROFESSION] based in [LOCATION].
## OUTPUT CONTRACT (MANDATORY)
Write ALL findings to: [RUN_DIR]/raw/licenses.md
Return ONLY a short summary (max 300 tokens) with STATUS, KEY_FINDINGS, RED_FLAGS, SOURCE_COUNT, FILE.
## SEARCHES TO CONDUCT
[IF Finance + US]:
- FINRA BrokerCheck: python3 ~/.claude/skills/probe-person/scripts/finra_brokercheck.py --name "[NAME]"
- SEC IAPD: WebSearch "[NAME] SEC IAPD investment adviser"
[IF Finance + UK]:
- FCA Register: WebSearch "[NAME] FCA register"
[IF Medicine + UK]:
- GMC Register: https://www.gmc-uk.org/registrants?text=[NAME]&allProfessions=true
(Note: GMC uses Cloudflare protection - WebFetch may be blocked. Try direct URL first, fall back to WebSearch "[NAME] GMC register doctor" if blocked.)
[IF Medicine + US]:
- State boards: WebSearch "[NAME] medical license [STATE]"
- NPPES: WebSearch "[NAME] NPPES NPI"
[IF Medicine + Australia]:
- AHPRA: WebSearch "[NAME] AHPRA register"
[IF Law + US]:
- Bar associations: WebSearch "[NAME] bar association [STATE]"
[IF Law + UK]:
- SRA: WebSearch "[NAME] SRA solicitor"
- BSB: WebSearch "[NAME] Bar Standards Board barrister"
[IF Accounting]:
- NASBA CPAverify: WebSearch "[NAME] CPA license"
- ICAEW/ACCA: WebSearch "[NAME] chartered accountant"
For each credential, document in the file:
1. License found? Yes/No
2. Current status (active, expired, suspended, revoked)
3. Any disciplinary history or restrictions
4. Dates of licensure
5. Jurisdiction of registration
CRITICAL: If subject claims roles at major institutions but no license record exists, this is a MAJOR RED FLAG. Document explicitly.
Agent 3: Digital Identity Agent
Purpose: Map online presence and verify digital identity consistency.
Only spawn if: Email, phone number, or username is provided.
Output file: {RUN_DIR}/raw/digital.md
Prompt Template:
Map the digital footprint of [NAME] using the following identifiers:
- Email: [EMAIL if provided]
- Phone: [PHONE if provided]
- Username: [USERNAME if known]
## OUTPUT CONTRACT (MANDATORY)
Write ALL findings to: [RUN_DIR]/raw/digital.md
Return ONLY a short summary (max 300 tokens) with STATUS, KEY_FINDINGS, RED_FLAGS, SOURCE_COUNT, FILE.
## SEARCHES TO CONDUCT
EMAIL-BASED (if email provided):
- Social accounts: WebSearch "[EMAIL] site:linkedin.com OR site:twitter.com OR site:facebook.com"
- Professional presence: WebSearch "[EMAIL]"
- Breach exposure: WebSearch "[EMAIL] breach leak haveibeenpwned"
PHONE-BASED (if phone provided):
- Reverse lookup: WebSearch "[PHONE]"
- Associated accounts: WebSearch "[PHONE] site:linkedin.com"
USERNAME CORRELATION (if username known):
- GitHub: WebSearch "[USERNAME] site:github.com"
- Twitter/X: WebSearch "[USERNAME] site:twitter.com OR site:x.com"
- Instagram: WebSearch "[USERNAME] site:instagram.com"
- Reddit: WebSearch "[USERNAME] site:reddit.com"
PLATFORM-SPECIFIC (based on profession):
[IF Tech]: GitHub, Stack Overflow, HackerNews
[IF Academic]: Google Scholar, ResearchGate, ORCID
[IF Creative]: Behance, Dribbble, Medium
[IF Business]: Crunchbase, AngelList
LinkedIn deep search via Exa:
python3 ~/.claude/skills/probe-person/scripts/exa_search.py --query "[NAME] [CONTEXT]" --type people -n 10 --deep
Brave web searches:
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "[NAME] WHOIS registrant domain" --count 10
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "site:github.com [USERNAME]" --count 10
Document in the file:
1. All platforms where subject has presence
2. Consistency of identity across platforms
3. Account creation dates vs claimed career timeline
4. Activity levels (active vs dormant)
5. Public interactions and network
6. Any concerning content or red flags
7. Breach exposure status
Agent 4: Sanctions & PEP Agent
Purpose: Screen against global sanctions lists and politically exposed persons databases.
Always spawn: Yes (mandatory for every investigation).
Output file: {RUN_DIR}/raw/sanctions.md
Prompt Template:
Conduct sanctions and PEP screening for [NAME], nationality: [NATIONALITY if known].
## OUTPUT CONTRACT (MANDATORY)
Write ALL findings to: [RUN_DIR]/raw/sanctions.md
Return ONLY a short summary (max 300 tokens) with STATUS, KEY_FINDINGS, RED_FLAGS, SOURCE_COUNT, FILE.
## SEARCHES TO CONDUCT
PRIMARY SEARCH:
- OpenSanctions: python3 ~/.claude/skills/probe-person/scripts/opensanctions.py --name "[NAME]"
SUPPLEMENTARY SEARCHES:
- WebSearch "[NAME] OFAC sanctions SDN"
- WebSearch "[NAME] EU sanctions list"
- WebSearch "[NAME] UN sanctions"
- WebSearch "[NAME] UK sanctions"
- WebSearch "[NAME] sanctioned"
PEP SCREENING:
- WebSearch "[NAME] politically exposed person"
- WebSearch "[NAME] government minister official"
- WebSearch "[NAME] state-owned enterprise"
- WebSearch "[NAME] politician"
Document in the file for any matches:
1. Is this the same person or a name collision?
2. What list are they on and why?
3. When were they listed?
4. Current status (active listing, delisted, under review)
For PEP status:
1. Current or former government position?
2. Level of seniority
3. Family member or close associate of PEP?
4. Implications for due diligence
Final determination:
- CLEAR: No matches found (specify databases searched)
- PARTIAL MATCH: Similar name found, analysis of whether same person
- CONFIRMED MATCH: Subject is on sanctions/PEP list (full details)
Agent 5: News & Media Agent
Purpose: Analyze media presence, public narrative, and reputation.
Always spawn: Yes.
Output file: {RUN_DIR}/raw/media.md
Prompt Template:
Research media presence and public narrative for [NAME], known for [CONTEXT FROM PHASE 0].
## OUTPUT CONTRACT (MANDATORY)
Write ALL findings to: [RUN_DIR]/raw/media.md
Return ONLY a short summary (max 300 tokens) with STATUS, KEY_FINDINGS, RED_FLAGS, SOURCE_COUNT, FILE.
## SEARCHES TO CONDUCT
EXA NEWS SEARCH:
python3 ~/.claude/skills/probe-person/scripts/exa_search.py --query "[NAME] [CONTEXT]" --type news -n 25
Brave news (catches what Exa misses):
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "[NAME] [CONTEXT]" --type news --freshness pm --count 20
TARGETED SEARCHES:
- WebSearch "[NAME] interview"
- WebSearch "[NAME] profile feature"
- WebSearch "[NAME] controversy scandal"
- WebSearch "[NAME] accused allegations"
- WebSearch "[NAME] fraud"
- WebSearch "[NAME] podcast"
- WebSearch "[NAME] TED talk speech"
- WebSearch "[NAME] conference speaker"
- WebSearch "[NAME] press release"
- WebSearch "[NAME] quote"
Document in the file:
1. Volume of coverage (heavily covered vs obscure)
2. Quality of outlets (FT/WSJ/NYT vs blogs/press releases)
3. Tone of coverage (positive, negative, neutral)
4. Self-promotional vs earned media
5. Key narratives they promote
6. Any controversies or negative coverage
7. Evolution of coverage over time
8. Inconsistencies between public claims and documented facts
MEDIA QUALITY ASSESSMENT (tag each source):
- Tier 1 (verified): FT, WSJ, NYT, Reuters, BBC, Bloomberg
- Tier 2 (credible): TechCrunch, Law360, industry publications
- Tier 3 (verify claims): Press releases, sponsored content
- Tier 4 (self-reported): Personal blogs, own website
Agent 6: Legal & Court Records Agent
Purpose: Uncover litigation history, regulatory actions, and legal red flags.
Always spawn: Yes.
Output file: {RUN_DIR}/raw/legal.md
Prompt Template:
Search for legal history and court records involving [NAME], based in [LOCATIONS].
## OUTPUT CONTRACT (MANDATORY)
Write ALL findings to: [RUN_DIR]/raw/legal.md
Return ONLY a short summary (max 300 tokens) with STATUS, KEY_FINDINGS, RED_FLAGS, SOURCE_COUNT, FILE.
## SEARCHES TO CONDUCT
PRIMARY - Brave targeted court searches:
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "site:courtlistener.com [NAME]" --count 20
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "site:case.law [NAME]" --count 20
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "[NAME] PACER federal court filing" --count 20
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "site:insolvencydirect.bis.gov.uk [NAME]" --count 10
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "[NAME] disqualified director" --count 10
GENERAL LEGAL SEARCHES:
- WebSearch "[NAME] lawsuit"
- WebSearch "[NAME] court case"
- WebSearch "[NAME] plaintiff defendant"
- WebSearch "[NAME] litigation sued"
- WebSearch "[NAME] judgment against"
- WebSearch "[NAME] settlement"
CRIMINAL & FRAUD:
- WebSearch "[NAME] criminal charges arrested"
- WebSearch "[NAME] indicted fraud"
- WebSearch "[NAME] investigation convicted"
REGULATORY ACTIONS:
- WebSearch "[NAME] SEC enforcement FCA fine"
- WebSearch "[NAME] regulatory action banned barred"
- WebSearch "[NAME] disqualified director cease desist"
BANKRUPTCY & INSOLVENCY:
- WebSearch "[NAME] bankruptcy insolvency liquidation"
PROFESSIONAL MISCONDUCT:
- WebSearch "[NAME] struck off disciplinary misconduct"
JURISDICTION-SPECIFIC:
[IF US]: WebSearch "[NAME] PACER federal court"
[IF UK]: WebSearch "[NAME] Companies House disqualified"
[IF UK]: WebSearch "[NAME] insolvency service"
Document in the file for each finding:
1. Nature of the matter
2. Subject's role (plaintiff, defendant, witness, subject of action)
3. Outcome (pending, settled, judgment, dismissed)
4. Significance for due diligence
5. Source and date
If no adverse findings: State "No adverse legal findings identified" and list scope of searches.
Agent 7: Network & Associates Agent
Purpose: Map professional relationships and identify concerning associations.
Always spawn: Yes.
Output file: {RUN_DIR}/raw/network.md
Prompt Template:
Map the professional network of [NAME], known for [CONTEXT].
## OUTPUT CONTRACT (MANDATORY)
Write ALL findings to: [RUN_DIR]/raw/network.md
Return ONLY a short summary (max 300 tokens) with STATUS, KEY_FINDINGS, RED_FLAGS, SOURCE_COUNT, FILE.
## SEARCHES TO CONDUCT
NETWORK SEARCHES:
- WebSearch "[NAME] co-founder"
- WebSearch "[NAME] business partner"
- WebSearch "[NAME] backed by" OR "[NAME] invested in"
- WebSearch "[NAME] advisor to" OR "[NAME] board member"
- WebSearch "[NAME] mentor"
- WebSearch "[NAME] married spouse wife husband"
Brave searches (academic/patent networks):
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "site:scholar.google.com [NAME]" --count 10
python3 ~/.claude/skills/probe-person/scripts/brave_search.py --query "site:patents.google.com [NAME] inventor" --count 10
Document in the file for significant associates:
1. Nature of relationship
2. Duration and context
3. Their own background (brief)
4. Whether relationship is publicly disclosed
RED FLAG CHECK - Do any associates appear on:
- Sanctions lists
- Fraud convictions
- Disqualified directors lists
- Controversial figures lists
NETWORK ANALYSIS (document in file):
1. Who are the key people in their orbit?
2. Do the same names recur across companies/ventures?
3. What does the network reveal about how they operate?
4. Are there concerning patterns (shell companies, offshore structures, disqualified individuals)?
5. Are there notable/credible people vouching for them?
Phase 2: Collect Summaries and Update Manifest
After all agents complete, the orchestrator:
- Reads each agent's short summary return (these are already in context — ~300 tokens each, ~1500 total for 5 agents)
- Updates
manifest.json with each agent's summary and status
- Does NOT read any raw files — that is the synthesis agent's job
{
"agents": {
"corporate": {
"status": "complete",
"summary": "4 active directorships across UK and SG. 2 dissolved dormant companies...",
"red_flags": ["Two dormant companies dissolved within 12 months"],
"source_count": 14
}
}
}
Phase 3: Spawn Synthesis Agent
CRITICAL: The synthesis agent runs in a fresh context with no investigation baggage. It reads the files directly.
Spawn ONE synthesis agent using the Task tool:
Task: Synthesis Agent
- subagent_type: "general-purpose"
- description: "Synthesize probe report"
- prompt: [See template below]
Synthesis Agent Prompt Template
You are writing an intelligence-grade background investigation report. All investigation data has been collected by parallel agents and saved to files.
## YOUR TASK
Read the investigation files, cross-reference findings, and write a comprehensive narrative prose report.
## RUN DIRECTORY
[RUN_DIR]
## STEP 1: Read the manifest
Read [RUN_DIR]/manifest.json to understand the subject profile and agent summaries.
## STEP 2: Read raw files ONE AT A TIME
Read each file in [RUN_DIR]/raw/ and take notes on key findings:
- [RUN_DIR]/raw/corporate.md
- [RUN_DIR]/raw/sanctions.md
- [RUN_DIR]/raw/media.md
- [RUN_DIR]/raw/legal.md
- [RUN_DIR]/raw/network.md
[Add conditional files if they exist: raw/licenses.md, raw/digital.md]
## STEP 3: Cross-reference and verify
- Do corporate records match claimed biography?
- Do license checks verify credentials?
- Does media coverage align with self-presentation?
- Note contradictions between sources
- Apply verification standards:
- Official registry = VERIFIED
- Mainstream news (FT, WSJ, Reuters, BBC) = VERIFIED
- Subject's own website/LinkedIn only = UNVERIFIED - SELF-REPORTED
- No independent source found = UNVERIFIED - NO INDEPENDENT SOURCE
## STEP 4: Write the report
Write the report to [RUN_DIR]/report.md following the structure in REPORT_TEMPLATE.md (read it from ~/.claude/skills/probe-person/REPORT_TEMPLATE.md).
The report MUST:
- Be 3,000-6,000 words of flowing narrative prose
- Tell a story with a narrative arc
- Use third person throughout
- Be specific with dates and numbers
- Cite sources inline
- Flag unverified claims with [UNVERIFIED] tags
- Include risk assessment
- Acknowledge gaps and limitations
## STEP 5: Write HTML version (if requested)
If HTML was requested, also write [RUN_DIR]/report.html following the design system in ~/.claude/skills/probe-person/REPORT_DESIGN.md.
## RED FLAGS TO WATCH FOR
1. Single-source biography: All claims trace to subject-provided content
2. Vague institutional claims: "Advised Fortune 500 companies" without naming any
3. Credential creep: Qualifications that appear in later bios but not earlier ones
4. Unverifiable exotic roles: At defunct companies or in jurisdictions with no records
5. Name-dropping without reciprocity: Claims connection to VIP who never mentions them
6. Disproportionate obscurity: Major claimed achievements but almost no coverage
## CLAIMS REQUIRING VERIFICATION
- Executive roles at notable companies
- Investment by prominent figures
- Major deals or exits
- Educational credentials
- Professional licenses
- Awards and honours
After writing the report, return a brief confirmation:
REPORT_WRITTEN: [path]
WORD_COUNT: [approximate]
RISK_LEVEL: low | moderate | elevated | high
KEY_CONCLUSIONS: 2-3 sentences
Critical Verification Protocol
Verification Standards
| Evidence Type | Status |
|---|
| Official registry (Companies House, GMC, SEC, FINRA) | VERIFIED |
| Mainstream news (FT, WSJ, Reuters, BBC) | VERIFIED |
| Press release from reputable organization | VERIFIED |
| Third-party professional directory | VERIFIED |
| Subject's own website/LinkedIn only | UNVERIFIED - SELF-REPORTED |
| Conference bio supplied by subject | UNVERIFIED - SELF-REPORTED |
| No independent source found | UNVERIFIED - NO INDEPENDENT SOURCE |
Red Flags for Credential Inflation
- Single-source biography: All claims trace to subject-provided content
- Vague institutional claims: "Advised Fortune 500 companies" without naming any
- Credential creep: Qualifications that appear in later bios but not earlier ones
- Unverifiable exotic roles: At defunct companies or in jurisdictions with no records
- Name-dropping without reciprocity: Claims connection to VIP who never mentions them
- Disproportionate obscurity: Major claimed achievements but almost no coverage
Report Template
Use the canonical report template in REPORT_TEMPLATE.md. The report must follow the structure defined there, written as flowing narrative prose per the Philosophy section above.
Reports are saved by the synthesis agent to: {RUN_DIR}/report.md
HTML version (if requested): {RUN_DIR}/report.html (see REPORT_DESIGN.md for styling).
Quality Standards
Before considering an investigation complete:
- File-based handoff: Did every agent write to its file and return only a summary?
- Manifest updated: Does manifest.json reflect all agent statuses and summaries?
- Synthesis agent spawned: Was synthesis done by a fresh-context agent (not the orchestrator)?
- Parallel Execution: Were agents spawned in parallel (single message with multiple Task calls)?
- Adaptive Selection: Were agent parameters customized based on Phase 0 profile?
- Report exists: Does {RUN_DIR}/report.md exist and contain 3,000-6,000 words?
- Narrative Flow: Does the report read as a coherent story?
- Cross-Referencing: Have findings from different agents been compared for consistency?
- Claim Verification: High-profile claims independently corroborated or flagged?
- Gaps Acknowledged: Limitations clearly stated?
API Keys & Tools
Exa API: ${EXA_API_KEY} (must be set in environment — export EXA_API_KEY="..." in ~/.zshrc)
- Supports: people search (1B+ profiles), company search, news, general web, deep search mode
- Categories:
people, company, news, research paper, tweet, personal site, financial report
Brave Search API: ${BRAVE_API_KEY} (must be set in environment — export BRAVE_API_KEY="..." in ~/.zshrc)
Scripts available:
~/.claude/skills/probe-person/scripts/brave_search.py - Brave web/news search
~/.claude/skills/probe-person/scripts/exa_search.py - Exa people/news search
~/.claude/skills/probe-person/scripts/opensanctions.py - Sanctions/PEP screening
~/.claude/skills/probe-person/scripts/opencorporates.py - Global corporate registry
~/.claude/skills/probe-person/scripts/companies_house.py - UK Companies House
~/.claude/skills/probe-person/scripts/finra_brokercheck.py - US FINRA BrokerCheck
~/.claude/skills/probe-person/scripts/report_generator.py - Report compilation
Quick Reference
ORCHESTRATION FLOW:
Phase 0: Profile discovery + create run dir + write manifest
Phase 1: Spawn agents (parallel) → agents write to files, return summaries only
Phase 2: Collect summaries (~1500 tokens total) + update manifest
Phase 3: Spawn synthesis agent (fresh context) → reads files, writes report
AGENT CONTRACT:
WRITE: Full findings → {RUN_DIR}/raw/{agent_name}.md
RETURN: Summary only (max 300 tokens) → STATUS, KEY_FINDINGS, RED_FLAGS, SOURCE_COUNT, FILE
CONTEXT BUDGET:
Phase 0: ~5K tokens (searches + profile)
Phase 1: ~0 tokens (agents run independently)
Phase 2: ~1.5K tokens (5 agents × 300 tokens)
Phase 3: ~0 tokens (synthesis agent has own context)
Total orchestrator context: ~6.5K tokens (vs ~50K+ before)