Lead session follow-ups (same chat, same lead)
Question: "Rerun Hunt Forge and resynthesize with our current info."
One lead per chat
Each demo/API chat binds one CRM lead (contact_id + user-pasted fields).
Follow-up hunts must reuse that bound record — not a legal entity name
discovered during enrichment (e.g. user pasted "Hoops & Gears" but the graph
found HG AutoTech LLC).
| Do | Don't |
|---|---|
Reuse first enrich_lead_session lead (contact_id intact) |
Rebuild lead from summary_markdown / entities[] |
Pass prompts: ["<user request verbatim>"] |
Pass refresh: true for partial retries |
Let the server load prior_backfill from the chat |
Drop chat_session_id on follow-up |
Tool
POST /api/v1/enrich/lead-session or MCP enrich_lead_session
{
"lead": {
"contact_id": 1737992709,
"company": "Hoops & Gears and Clark",
"domain": "hgautotech.com",
"source_system": "demo_chat"
},
"chat_session_id": "ab62eb36cd134d70a58bc174d6b09185",
"prompts": [
"Rerun the Hunt Forge dig-deeper pass and resynthesize the summary with the current graph."
]
}
refresh vs follow-up
| User intent | Args |
|---|---|
| "From scratch" / "ignore cache" | refresh: true + same bound lead |
| "Rerun Hunt Forge" / "resynthesize" / "dig deeper on X" | prompts: [...] only — no refresh |
| Gap button from UI | prompts: [<button text>] |
refresh: true bypasses agent warm-seed and re-runs all hunt slots from zero.
It does not mean "retry one model."
Hunt Forge / Swift / Deep (dig-deeper)
Middle-pass parallel slots (UI labels Hunt Forge, Hunt Swift, Hunt Deep)
map to internal dig-deeper models. They are not research_model picker values.
- During an active hunt: use the hunt board ↻ (retry one slot) or × (cancel).
- After a hunt completes: use partial routes below — not
refresh: truefull session. - Batch pending/error: hosted UI Run pending & failed (N) reruns all
pending+errorslots in one async job (parallel vendor hunts, one delta synth). API:enrich/lead-session/slots-rerunviaPOST /api/v1/enrich/jobs(see below).
There is no public research_model: data411-hunt-forge arg on enrich_lead_session.
Slot rerun (one model)
POST /api/v1/enrich/lead-session/slot-rerun or MCP rerun_hunt_slot
{
"lead": { "contact_id": 1737992709, "company": "Hoops & Gears and Clark" },
"chat_session_id": "ab62eb36cd134d70a58bc174d6b09185",
"model_id": "data411-hunt-forge",
"prior_backfill": { "...": "from last enrich_lead_session backfill" },
"refresh_summary": true
}
model_id accepts public ids (data411-hunt-forge, data411-hunt-swift) or provider
slugs (x-ai/grok-build-0.1). Runs one slot with refresh=true, delta-merges into
prior_backfill, updates tool_trace.parallel_results for that model.
Hosted UI: Hunt controls panel on the last hunt turn → ↻ per slot row.
Prefer async jobs for slot reruns (hosted UI and headless agents):
{
"route": "enrich/lead-session/slot-rerun",
"payload": {
"lead": { "contact_id": 1737992709, "company": "Hoops & Gears and Clark" },
"chat_session_id": "ab62eb36cd134d70a58bc174d6b09185",
"model_id": "data411-hunt-forge",
"prior_backfill": { "...": "from last enrich_lead_session backfill" }
}
}
Submit at POST /api/v1/enrich/jobs — default precharge $0.35 per slot (bill-on-match refund on no usable rows). Sync POST /api/v1/enrich/lead-session/slot-rerun remains for one-shot callers.
Batch slot rerun (pending + error)
POST /api/v1/enrich/jobs with route: enrich/lead-session/slots-rerun (no sync HTTP route).
Runs every pending or error parallel slot in one job: vendor hunts in parallel, trace upsert per slot, one delta synthesis at the end (not N synth passes).
{
"route": "enrich/lead-session/slots-rerun",
"payload": {
"lead": { "contact_id": 1737992709, "company": "Hoops & Gears and Clark" },
"chat_session_id": "ab62eb36cd134d70a58bc174d6b09185",
"model_ids": ["data411-hunt-ground", "data411-crimson-span"],
"prior_backfill": { "...": "current graph" },
"progress_key": "job:slots:optional"
},
"bill_up_to_usd": 0.70
}
| Field | Notes |
|---|---|
model_ids |
Public ids (data411-hunt-forge, …) or provider slugs; server rejects ids that are not pending or error in the latest trace |
bill_up_to_usd |
Default N × $0.35 when omitted (N = non-empty model_ids count); override up to job max |
progress_key |
Optional live board key for poll progress |
Hosted UI: Run pending & failed (N) in hunt controls (post-hunt only; disabled while streaming or another slot job is busy).
Excludes done, cancelled, repetition, and running slots. Does not auto-resynthesize the summary — use Resynthesize if prose is stale after batch completes.
Resynthesize only
POST /api/v1/enrich/lead-session/synthesize-patch or MCP resynthesize_lead_graph
{
"lead": { "contact_id": 1737992709, "company": "Hoops & Gears and Clark" },
"chat_session_id": "ab62eb36cd134d70a58bc174d6b09185",
"prior_backfill": { "...": "current graph" },
"refresh_summary": true,
"prompts": ["Emphasize owner phones and legal contacts in the summary."]
}
No vendor spend — LLM resynthesis from the existing graph only. Hosted UI: Resynthesize in the hunt controls panel.
Summary history (hosted UI)
Each time a follow-up session, slot rerun, batch slot rerun, or synthesize-patch changes
summary_markdown, the server archives the prior version on
backfill.summary_history[] (with graph_fingerprint for phones/contacts/emails).
- Chat shows only the latest summary; older enrich turns collapse to a one-line stub.
- Summary history on the latest enrich turn opens a diff modal:
- Graph changes — added/removed fingerprint keys (primary view).
- Markdown diff — line-level prose comparison between any two versions.
Partial routes return the updated backfill including summary_history; no extra API.
Investigate unmerged finding
POST /api/v1/enrich/lead-session/finding-rerun or MCP investigate_unmerged_finding
{
"lead": { "contact_id": 1737992709, "company": "Hoops & Gears and Clark" },
"chat_session_id": "ab62eb36cd134d70a58bc174d6b09185",
"candidate_id": "a1b2c3d4e5f6g7h8",
"prior_backfill": { "unmerged_candidates": [{ "id": "a1b2c3d4e5f6g7h8", "label": "…" }] }
}
candidate_id is on backfill.unmerged_candidates[].id (stable SHA1 at merge time).
Hosted UI: Investigate on each row in Findings not merged.
Agent behavior checklist
- Read the user's latest message into
promptsif the model omitted it. - Copy the first
enrich_lead_sessionleadobject for every follow-up. - Never set
lead.companyto a discovered DBA/legal name unless the user pasted a new CRM export. - Explain
MULTI_LEAD_REFUSEDas "same chat, different lead shape" — fix by reusing boundcontact_id.
Related
- enrich_websearch_when — when to escalate to websearch
- bill_on_match — refunds on empty hunts
- filter_discipline_meta — tool choice before spending