Персонализация

Профили и персональные черновики

Лид полезен, только если вы можете написать нужному человеку о нужном деле. Это руководство показывает, как Fathom превращает сырые факты в персональный аутрич — и как вы управляете его тоном, глубиной и голосом через профили.

A lead is only useful if you can write to the right person about the right thing. This guide shows how Fathom turns raw facts into personalized outreach — and how you steer its tone, depth and voice with profiles.

Персоны: меняйте поведение, а не код

Профиль — это именованный пресет: блок системного промпта, внедряемый в каждого агента, плюс переопределения модели, fast_model, температуры, max_depth, max_agents и запрещённых инструментов. Три встроены из коробки.

A profile is a named preset: a system-prompt block injected into every agent, plus overrides for model, fast_model, temperature, max_depth, max_agents and denied tools. Three ship built-in.

ProfileBehavior
hunterHarvest as many VERIFIED contacts as possible. Sets max_agents to 6 and forces extract_contacts + save_contacts + verification. The default for building a list fast.
analystDepth, sourcing and cross-checking. Denies save_contacts and git_push — a read-only researcher that returns cited findings without side effects.
validatorTakes your existing contacts and verifies / enriches them. Denies spawn_agent — focused, single-pass cleanup of a list you already have.

Создайте свои в ~/.fathom/profiles/<name>.toml и выбирайте через --profile в run или tui. Профили настраивают поведение агента под кампанию — аналитик только исследует и не пишет, агрессивный охотник не останавливается.

Define your own in ~/.fathom/profiles/<name>.toml, then select with –profile on run or tui. Profiles tune the agent’s behavior per campaign — a research-only analyst never writes, an aggressive hunter never stops.

Как факт становится строкой

Fathom не использует шаблоны с пропусками. Писатель составляет каждое сообщение из собранного контекста по четырём правилам.

Fathom does not use fill-in-the-blank templates. The writer composes each message from the gathered context using four rules.

A
Ground in facts

The writer only uses things the tools actually returned: a company’s funding round, an open role, a recent post. Every claim can point to a source URL.

B
Never fabricate

The iron rule in the system prompt: no invented facts, contacts, dates or sources. If a fact is missing, the draft says so or opens with what is known.

C
Layer memory

At depth 0 the agent receives a memory digest. Past touches, prior conversations and known role changes surface automatically — so repeat outreach is continuous, not from zero.

D
Human approval

Side effects wait for an explicit yes. Personalize, then review the batch in the TUI or via approve on the API before anything ships to CRM.

До и после

Без обоснования черновик обобщён. С ним первая строка ссылается на то, что агент реально нашёл.

Without grounding the draft is generic. With it, the opening line cites what the agent actually found.

generic
Hi [Name], I wanted to reach out about our solution.
grounded
Hi Ann, saw Acme just closed its Series B and is hiring 6 platform engineers. 
Given your background as CTO building high-scale systems in Rust, wanted to share how we
cut our own infra costs — happy to trade notes if useful.

Маршрутизация моделей по ролям

Different agent roles can run on different models. Via [agent].role_models you can give the Writer a stronger model for prose while a cheaper fast_model classifies and parses. With llm.fast_model unset, high-volume extraction and verification calls stay cheap.

Profile Configuration Reference

Every profile is a TOML file with a [profile] section. All fields are optional — unset keys inherit from config.toml. The table below lists every supported field.

FieldTypeDefaultDescription
namestringfilename stemDisplay name shown in profiles list
descriptionstring—One-line summary for the profile list view
promptstring (multiline)—System prompt appended after the base prompt; controls tone, voice, focus area
modelstringfrom configPrimary model override for planning and writing (e.g. gpt-4o)
fast_modelstringfrom configCheap model for extraction, classification, verification
temperaturefloat0.7Sampling temperature (0.0–2.0); lower = more deterministic
max_depthinteger3Maximum spawn depth for sub-agents
max_agentsinteger8Maximum concurrent sub-agents in the swarm
max_iterationsinteger20Tool-call loop limit per agent before forced stop
timeout_secondsinteger3600Hard wall-clock timeout per agent
replan_roundsinteger1Number of Goal Mode gap-filling rounds after the first synthesis
deny_toolsarray of strings[]Tool names the agent may not call (e.g. [“save_contacts”, “git_push”])

Built-in Profiles Deep Dive

hunter

The hunter profile is optimized for contact harvesting at maximum volume. It forces max_agents = 6, keeps temperature at 0.4 for consistent extraction, and always includes extract_contacts, save_contacts, and verification in the tool chain.

hunter.toml
[profile]
name = "hunter"
description = "Harvest maximum verified contacts fast"
prompt = """
You are a contact-harvesting agent. Your sole objective is to find and
verify as many contacts as possible. Prioritize volume but never save
unverified contacts. Always run email syntax + MX checks before saving.
For each company, search for C-suite, VP Engineering, and Head of Product.
"""
temperature = 0.4
max_agents = 6
max_depth = 2
deny_tools = ["git_push"]
usage
fathom run --profile hunter "Find engineering leaders at YC W24 companies"

What changes: the agent spawns up to 6 parallel sub-agents, each tackling a slice of the search space. The system prompt steers toward breadth — search every company, extract every visible contact, verify email and phone, and save immediately. The git_push denial prevents accidental code pushes when the research folder is a git repo.

analyst

The analyst profile is a read-only deep researcher. It denies save_contacts and git_push, so no side effects occur. Temperature is set to 0.3 for precise, cited output. Best for competitive analysis, technical deep-dives and due diligence.

analyst.toml
[profile]
name = "analyst"
description = "Deep, cited, read-only research"
prompt = """
You are a research analyst. Produce thoroughly sourced findings with
inline citations. Every claim MUST link to a source URL. Cross-reference
facts across multiple sources. Flag conflicting information explicitly.
Never save contacts or modify external systems — you are read-only.
"""
model = "gpt-4o"
temperature = 0.3
max_agents = 4
max_depth = 3
max_iterations = 30
deny_tools = ["save_contacts", "git_push"]
usage
fathom run --profile analyst "Evaluate the competitive landscape of vector databases"

What changes: the agent uses max_iterations = 30 for longer exploration chains and max_depth = 3 to allow deeper sub-agent nesting. The prompt forces citation of every claim and explicit flagging of contradictions.

validator

The validator profile is a single-pass contact cleaner. It takes an existing contact list, verifies every entry, and enriches what it can. It denies spawn_agent so it runs as a focused, single-process agent.

validator.toml
[profile]
name = "validator"
description = "Verify and enrich existing contacts"
prompt = """
You are a contact validation agent. You have been given an existing
contact list. For each contact: verify the email (syntax + MX + SMTP),
normalize the phone to E.164, check the social profile URL, and enrich
with any missing fields (title, company, LinkedIn). Mark invalid entries
but do not delete them. Return a clean, enriched list.
"""
temperature = 0.2
max_agents = 1
max_depth = 1
max_iterations = 50
deny_tools = ["spawn_agent"]
usage
fathom run --profile validator "Validate and enrich contacts in ./contacts.csv"

What changes: no sub-agents spawn — the entire validation runs in a single agent loop. max_iterations = 50 gives the agent room to verify large lists without hitting the limit. Temperature is the lowest of all profiles (0.2) for deterministic, mechanical work.

Creating Custom Profiles

Custom profiles live in ~/.fathom/profiles/ as TOML files. The filename (without .toml) becomes the profile name used with –profile.

File location and naming

directory layout
~/.fathom/profiles/
├── hunter.toml       # built-in (shipped with the binary)
├── analyst.toml      # built-in
├── validator.toml    # built-in
├── my-outreach.toml  # your custom profile
└── due-diligence.toml

Creating a profile from the CLI

01
Generate a template

fathom profiles new my-outreach — creates ~/.fathom/profiles/my-outreach.toml with all fields commented out and a prompt placeholder.

02
Edit the TOML file

Uncomment and set the fields you need. At minimum, provide a prompt — that’s what makes the profile useful. All other fields inherit from config.toml if unset.

03
Verify with show

fathom profiles show my-outreach — prints the resolved profile with all inherited defaults filled in, so you can see exactly what the agent will receive.

04
List all profiles

fathom profiles list — shows built-ins and custom profiles with their descriptions.

Custom profile example

Here’s a profile for due-diligence research on potential acquisition targets. It uses a strong reasoning model, denies side effects, and asks for a structured report format.

due-diligence.toml
[profile]
name = "due-diligence"
description = "Structured M&A due-diligence research"
prompt = """
You are a due-diligence research agent. For the given company:
1. Financial signals — funding rounds, revenue estimates, layoffs
2. Technical signals — tech stack, GitHub activity, patent filings
3. Market signals — competitors, market share, customer reviews
4. Risk signals — litigation, regulatory issues, key-person risk

Format your findings as a structured report with sections and ratings:
[GREEN] = no concerns, [YELLOW] = monitor, [RED] = deal-breaker.
Cite every claim with a source URL.
"""
model = "claude-3.5-sonnet"
temperature = 0.3
max_agents = 4
max_depth = 3
max_iterations = 40
deny_tools = ["save_contacts", "git_push", "send_email"]
usage
fathom run --profile due-diligence "Full due-diligence on Acme Corp"
fathom tui --profile due-diligence "Analyze Acme Corp and its top 3 competitors"

Profile Inheritance & Resolution

When a profile omits a field, the runtime resolves it from config.toml. The resolution order is: profile TOML → [agent] section → built-in defaults. This means a minimal profile only needs a prompt — everything else works out of the box.

ResolutionSourceExample
1 — ProfileProfile TOML filetemperature = 0.3 in analyst.toml
2 — Config~/.fathom/config.toml[agent] temperature = 0.7
3 — Built-inCompiled defaultstemperature = 0.7

The prompt field is appended to the base system prompt, not a replacement. This means your profile prompt adds role-specific instructions on top of the standard safety, grounding and tool-use instructions that every agent receives.

Grounding Rules in Detail

The four grounding rules are the difference between spam and signal. Each rule has a concrete before/after example showing how it transforms the draft.

Rule A — Ground in facts

The writer only uses things the tools actually returned. If a web search found a Series B announcement and a job posting for 6 engineers, those facts — and only those — go into the draft. Every claim is traceable to a source URL.

before (no grounding)
Hi Ann, I noticed your company has been growing rapidly and is probably
looking for solutions to scale its infrastructure.
after (grounded in facts)
Hi Ann, saw that Acme closed its Series B last month (TechCrunch, Feb 12)
and is hiring 6 platform engineers (careers page). Given your team's
Rust stack and the scaling challenges that come with a 3x headcount bump,
wanted to share how we cut our own infra costs by 40%.

Rule B — Never fabricate

The iron rule: no invented facts, contacts, dates or sources. If a fact is missing, the draft either says so explicitly or opens with what is known. The model is penalized in the system prompt for hallucinating — fabrications cause an immediate generation restart.

before (fabricated)
Hi Ann, congratulations on Acme's recent $50M Series B led by Sequoia!
I saw your recent talk at RustConf 2025 about microservices.
after (honest)
Hi Ann, saw that Acme closed a funding round last month — congrats to
the team. I couldn't find details on the lead investor, but the scale
of your recent engineering hires suggests significant growth ahead.

Rule C — Layer memory

At depth 0 the agent receives a memory digest — a compact summary of all prior interactions with this contact or company. Past touches, prior conversations and known role changes surface automatically, so repeat outreach is continuous, not from zero.

before (no memory)
Hi Ann, I wanted to introduce our platform and see if there's a fit.
after (memory-aware)
Hi Ann, following up on our chat from January — you mentioned the
migration to Rust was your Q1 priority. Now that it's Q2, I noticed
Acme is hiring platform engineers, which suggests you've made progress.
Curious how the rollout went and whether our earlier benchmarks would
still be useful.

The memory digest includes: contact name, company, known role (and any role changes), last interaction date, previous topics discussed, and any facts stored from prior runs. This data is injected as a frozen prompt block at depth 0 to keep the prefix cache warm.

Rule D — Human approval

Side effects wait for an explicit yes. The agent drafts, then pauses. In the TUI the operator presses y to approve or n to reject. Via API, a POST /sessions/:id/approve call is required. Nothing ships to CRM, no emails are sent, no files are modified until a human says go.

This means you can run –profile hunter to generate 50 personalized emails, review each one in the batch, and only approve the ones that pass your quality bar.

Role-Based Model Routing

The [agent].role_models table in config.toml lets you assign different LLMs to different agent roles. This is the primary cost optimization lever: use expensive models where prose quality matters, and cheap models everywhere else.

config.toml
[agent]
# Default model for all roles
model = "gpt-4o-mini"

# Override specific roles
[agent.role_models]
writer = "gpt-4o"            # best prose quality
researcher = "deepseek-v3"   # cheap, good at extraction
analyst = "claude-3.5-sonnet" # strong reasoning
verifier = "gpt-4o-mini"     # simple checks, keep it cheap
coordinator = "gpt-4o"       # planning needs strong model

[llm]
fast_model = "gpt-4o-mini"   # high-volume extraction & parsing

How role_models works

When the coordinator spawns a sub-agent, it assigns a role based on the sub-task type. The runtime checks [agent.role_models] first; if a role-specific model is set, that model is used. Otherwise it falls back to [agent].model.

RoleTasksRecommended model tier
coordinatorPlanning, decomposition, synthesisStrong reasoning (GPT-4o, Claude Sonnet)
researcherWeb search, page scraping, OSINTCheap + fast (DeepSeek, GPT-4o-mini)
analystCross-referencing, fact-checkingStrong reasoning (Claude Sonnet, GPT-4o)
writerPersonalized outreach draftsBest prose (GPT-4o, Claude Opus)
verifierEmail/phone/social verificationCheap (GPT-4o-mini, local models)

fast_model for high-volume extraction

The llm.fast_model setting is used for tasks that need speed over quality: parsing HTML, extracting structured JSON from pages, classifying page types, normalizing data. These calls happen hundreds of times per session, so a cheaper OpenAI-compatible model saves significant cost without affecting output quality.

Cost optimization strategies

✓Use fast_model for all extraction and parsing — this is the biggest win
✓Keep the coordinator on a strong model — bad planning wastes more than it saves
✓Use a strong model for the writer — prose quality is the deliverable
✓Use a cheap model for verification — it’s mostly regex and DNS lookups
✓Set temperature = 0.2 for extraction tasks to reduce re-generation
✓Use max_iterations caps to prevent runaway loops on cheap models

Draft Quality Controls

Fathom has multiple layers of quality control to ensure drafts are accurate, sourced, and safe to send. These controls run automatically — no configuration needed.

Hallucination avoidance

The system prompt contains an explicit anti-hallucination directive. The writer is instructed to only reference facts that appear in the tool results provided to it. If a fact is not in the context, the writer either omits it or uses a hedging phrase (“I couldn’t verify…”). The runtime also validates that any URL cited in the draft actually appeared in the research results.

Source citation requirements

Every factual claim in a draft must trace back to a tool result. The writer uses inline references:

citation format
"Acme raised $50M in Series B" → sourced from: web_search result #3 (TechCrunch)
"Currently hiring 6 engineers" → sourced from: web_fetch of careers page
"CTO since 2022" → sourced from: LinkedIn profile scrape

In the TUI, each claim in the draft can be traced back to its source tool call in the Log panel.

Confidence thresholds

The writer assigns implicit confidence levels to claims based on source quality. The runtime enforces these rules:

ConfidenceSource typeDraft behavior
HighOfficial page, press release, SEC filingState as fact
MediumNews article, LinkedIn, job postingState with attribution
LowSingle unverified source, social postHedge: “appears to”, “according to”
UnverifiedNo corroborating source foundOmit from draft or flag as unverified

Human approval workflow

The approval workflow is the final gate before any side effect. Here’s the complete flow:

01
Agent drafts

The writer produces a personalized draft grounded in research facts.

02
Pending state

The draft enters a “pending” state. Any side effect (save_contacts, send_email, crm_push) is blocked.

03
Operator reviews

In the TUI: press y to approve or n to reject. Via API: POST /sessions/:id/approve. Batch mode: review all pending drafts as a list.

04
Side effects execute

Approved drafts trigger their side effects: contacts are saved to DB, CRM pushes happen, exports are generated.