OSINT workflow example

Every lead, sourced
and verified.

OSINT is one workflow a universal autonomous worker can run: plan subtasks, inspect configured public sources, preserve evidence in memory, and ask for review before saving or contacting anyone. Connectors and integrations are optional, not guaranteed.

Data sources

Where a configured worker can look

search_business_directory

Business registries

When configured, registry connectors can provide public company records, identifiers, founders and executives for a worker to inspect.

find_leads

Maps & directories

Optional map and directory connectors can add public addresses, phones and opening hours; availability depends on operator setup and source limits.

parse_corporate_site

Corporate sites

Workers can parse fetched team, about, contact and press pages, including Schema.org and JSON-LD where present.

search_social

Social networks

Configured public LinkedIn, X/Twitter or Telegram access can add context; blocked or unavailable sources remain explicit.

search_news

News & mentions

An enabled news connector can provide press, funding, hiring or launch context for the investigation.

Pipeline

A worker loop from plan to report

01

Plan

A universal worker scopes the question, selects configured tools and delegates source-specific subtasks.

02

Extract

extract_contacts gathers public emails, phones, social profiles and entities while retaining provenance.

03

Verify

verify_email, verify_phone and verify_social_profile apply available checks and label confidence without guessing.

04

Enrich

enrich_company and enrich_person add context from matching evidence; missing fields stay marked as gaps.

05

Persist

SQLite or PostgreSQL can store worker findings, memory and review receipts with normalized deduplication.

06

Govern

Policy and approval gates can pause side effects such as CRM writes, outreach or notifications.

07

Report

The worker synthesizes a cited report and can export findings or hand off to configured integrations.

Verification

Make uncertainty visible before saving

A worker can apply MX, disposable-domain and role-based checks when those network lookups are available. Obfuscated addresses such as name [at] domain [dot] com may be decoded and marked lower confidence; governance can require review before persistence or outreach.

verify_email("[email protected]")
→ is_valid_syntax: true
→ domain_exists:   true
→ mx_records:      ["mx1.company.com"]
→ is_disposable:   false
→ is_role_based:   true      # info@ admin@ support@
→ confidence:      0.85

# deobfuscation
"name [at] company [dot] com"
→ [email protected]           # confidence 0.70
"[email protected]"           # plain → confidence 0.95

Phones & patterns

Normalize phones, propose candidates

Phones can be normalized to E.164 via libphonenumber when the tool is available. When only a name and domain are known, suggest_emails proposes candidates from observed naming patterns for a worker or human to review and verify.

verify_phone("+7 (495) 710-75-80")
→ normalized:   "+74957107580"    # E.164
→ country_code: "RU"
→ is_valid:     true
→ is_mobile:    false             # landline

suggest_emails("John Doe", "acme.com")
→ [email protected]
→ [email protected]
→ [email protected]  …
→ additional candidates follow the observed
  domain pattern and require review

Storage

Persist findings with memory and review

Workers can persist findings in SQLite or PostgreSQL, depending on configuration. Normalized emails and phones support deduplication, while tags, notes, evidence and approval receipts keep context queryable across runs.

save_contacts · db_path = "./contacts.db" · pg_url = "postgres://…"

TableColumns
contactsid, email, phone, name, title, company, source, timestamps
social_profilescontact_id, platform, url, username
companiesname, website, industry, size, location
tagscontact_id, tag
notescontact_id, note

Query examples

Prompt examples for a governed workflow

Moscow — IT CEOs
fathom run \
  "Find contacts of CEOs and CTOs at
   small IT companies in Moscow.
   Extract emails, phones and
   LinkedIn profiles." \
  --output ./leads/

# agents fan out over rusprofile,
# list-org and sbis, parse corporate
# sites, enrich persons
# → INN/OGRN table + emails + phones
#   + LinkedIn candidates (CSV, md)
Berlin — SaaS landscape
fathom run \
  "Map SaaS companies in Berlin,
   collect public evidence and
   identify founders or CTOs where
   sources support the match." \
  --output ./berlin-saas/

# → cited company and contact findings
#   with confidence, gaps and review
#   status; export only after approval
Dubai — fintech market
fathom run \
  "Research the Dubai fintech
   startup market and identify
   decision-maker evidence where
   public sources support it." \
  --output ./dubai-fintech/

# → market overview with cited evidence,
#   contact hypotheses, gaps and review
#   status; export or hand off when allowed

Ethics & compliance

Responsible by default

GDPR & Law 152-FZ

Personal data is processed in line with GDPR and Russia's Federal Law 152-FZ on Personal Data: lawful basis, scoped purpose, deletion on request.

Public data only

Agents read open, publicly available sources — nothing scraped behind logins, paywalls or private APIs.

robots.txt & rate limits

Crawling respects robots.txt and built-in throttling; bot-blocked pages (403) are skipped gracefully, never hammered.

Honest statuses

Uncertainty is explicit: "requires verification", "not found", "HTTP 999", "low-confidence match" — never silent guesses.

LinkedIn HTTP 999

LinkedIn answers bots with HTTP 999. Stable parsing needs proxies/cookies; agents surface the block instead of inventing data.

No spam

Extracted contacts are for qualified outreach and research — not bulk unsolicited mailings. Confidence scores help you filter.

Use OSINT as one worker workflow

Review workflow details →