Профили и персональные черновики
Лид полезен, только если вы можете написать нужному человеку о нужном деле. Это руководство показывает, как 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.
| Profile | Behavior |
|---|---|
hunter | Harvest 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. |
analyst | Depth, sourcing and cross-checking. Denies save_contacts and git_push — a read-only researcher that returns cited findings without side effects. |
validator | Takes 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.
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.
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.
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.
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.
Hi [Name], I wanted to reach out about our solution.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.
| Field | Type | Default | Description |
|---|---|---|---|
name | string | filename stem | Display name shown in profiles list |
description | string | — | One-line summary for the profile list view |
prompt | string (multiline) | — | System prompt appended after the base prompt; controls tone, voice, focus area |
model | string | from config | Primary model override for planning and writing (e.g. gpt-4o) |
fast_model | string | from config | Cheap model for extraction, classification, verification |
temperature | float | 0.7 | Sampling temperature (0.0–2.0); lower = more deterministic |
max_depth | integer | 3 | Maximum spawn depth for sub-agents |
max_agents | integer | 8 | Maximum concurrent sub-agents in the swarm |
max_iterations | integer | 20 | Tool-call loop limit per agent before forced stop |
timeout_seconds | integer | 3600 | Hard wall-clock timeout per agent |
replan_rounds | integer | 1 | Number of Goal Mode gap-filling rounds after the first synthesis |
deny_tools | array 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.
[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"]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.
[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"]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.
[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"]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
~/.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.tomlCreating a profile from the CLI
fathom profiles new my-outreach — creates ~/.fathom/profiles/my-outreach.toml with all fields commented out and a prompt placeholder.
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.
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.
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.
[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"]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.
| Resolution | Source | Example |
|---|---|---|
| 1 — Profile | Profile TOML file | temperature = 0.3 in analyst.toml |
| 2 — Config | ~/.fathom/config.toml | [agent] temperature = 0.7 |
| 3 — Built-in | Compiled defaults | temperature = 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.
Hi Ann, I noticed your company has been growing rapidly and is probably
looking for solutions to scale its infrastructure.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.
Hi Ann, congratulations on Acme's recent $50M Series B led by Sequoia!
I saw your recent talk at RustConf 2025 about microservices.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.
Hi Ann, I wanted to introduce our platform and see if there's a fit.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.
[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 & parsingHow 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.
| Role | Tasks | Recommended model tier |
|---|---|---|
coordinator | Planning, decomposition, synthesis | Strong reasoning (GPT-4o, Claude Sonnet) |
researcher | Web search, page scraping, OSINT | Cheap + fast (DeepSeek, GPT-4o-mini) |
analyst | Cross-referencing, fact-checking | Strong reasoning (Claude Sonnet, GPT-4o) |
writer | Personalized outreach drafts | Best prose (GPT-4o, Claude Opus) |
verifier | Email/phone/social verification | Cheap (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
fast_model for all extraction and parsing — this is the biggest wintemperature = 0.2 for extraction tasks to reduce re-generationmax_iterations caps to prevent runaway loops on cheap modelsDraft 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:
"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 scrapeIn 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:
| Confidence | Source type | Draft behavior |
|---|---|---|
| High | Official page, press release, SEC filing | State as fact |
| Medium | News article, LinkedIn, job posting | State with attribution |
| Low | Single unverified source, social post | Hedge: “appears to”, “according to” |
| Unverified | No corroborating source found | Omit 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:
The writer produces a personalized draft grounded in research facts.
The draft enters a “pending” state. Any side effect (save_contacts, send_email, crm_push) is blocked.
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.
Approved drafts trigger their side effects: contacts are saved to DB, CRM pushes happen, exports are generated.