Assure Disambiguation During Research
Strengthens entity disambiguation to prevent research agents from conflating similarly-named organizations. Adds both improved prompt language and a mechanical post-synthesis override that forces correct company identity regardless of what the LLM returns.
Changelog - 2026-03-23_03
Assure Disambiguation During Research
Strengthens entity disambiguation to prevent research agents from conflating similarly-named organizations. Adds both improved prompt language and a mechanical post-synthesis override that forces correct company identity regardless of what the LLM returns.
Why
The Metabologic deal has been plagued by disambiguation failures across four versions (v0.0.1 through v0.2.3). Despite the company JSON containing explicit disambiguation exclusions for metabolic.nl, metabolic.ai, and metabolic.com, Perplexity consistently returned research about "Metabolic AI" (a different company at metabolic.ai) instead of Metabologic (metabologic.ai).
The contamination path:
research_enhanced.py sends queries to Perplexity
→ Perplexity finds metabolic.ai (more prominent company)
→ Claude synthesizes results into JSON with website: "metabolic.ai"
→ fact_checker detects entity mismatch
→ ALL sections flagged for rewrite, overall score forced to 0%The entity mismatch cascaded through the entire pipeline, making the memo useless despite most content being accurate.
What Changed
Layer 1: Improved Prompt Language
Both research_enhanced.py and perplexity_section_researcher.py now use stronger disambiguation prompts that frame the problem from the LLM's perspective:
Before:
EXCLUDED ENTITIES - DO NOT USE DATA FROM THESE DOMAINS:
- metabolic.nl (WRONG company, different entity)
- metabolic.ai (WRONG company, different entity)
If you find information from these domains, DISCARD IT completely.After:
WARNING — COMMONLY CONFUSED ORGANIZATIONS:
Research agents often find similar-sounding organizations, then incorrectly
include information about them in the research. The following have been
identified as confusing and require disambiguation. These are NOT Metabologic:
- metabolic.nl — This is a DIFFERENT organization, NOT Metabologic
- metabolic.ai — This is a DIFFERENT organization, NOT Metabologic
- metabolic.com — This is a DIFFERENT organization, NOT Metabologic
MANDATORY RULES FOR DISAMBIGUATION:
1. Do NOT include any information sourced from the domains listed above.
2. Do NOT reference, cite, or describe the organizations at those domains.
3. If a search result comes from one of those domains, SKIP IT entirely.
4. If you cannot find information about Metabologic specifically
(website: https://www.metabologic.ai/), say "Data not available"
rather than substituting information from a similar-sounding organization.
5. The ONLY correct company is at https://www.metabologic.ai/.Key changes: leads with why LLMs make this mistake, gives explicit safe fallback ("say Data not available"), anchors the correct entity positively.
Commit: 39bad3d
Layer 2: Mechanical Post-Synthesis Override
After Claude synthesizes web research into structured JSON, the agent now mechanically overrides company.website and company.name with known-correct values from state. This runs regardless of what the LLM decided.
# After LLM returns research JSON:
if company_url and "company" in research_data:
llm_website = research_data["company"].get("website", "")
if llm_website and llm_website != company_url:
llm_domain = extract_domain(llm_website)
is_excluded = any(llm_domain == excl for excl in disambiguation_excludes)
if is_excluded:
print(f" DISAMBIGUATION OVERRIDE: '{llm_website}' is an excluded domain")
# Always force the known-correct URL
research_data["company"]["website"] = company_url
if company_name and "company" in research_data:
llm_name = research_data["company"].get("name", "")
if llm_name and company_name.lower() not in llm_name.lower():
print(f" DISAMBIGUATION OVERRIDE: LLM returned '{llm_name}', expected '{company_name}'")
research_data["company"]["name"] = company_nameCommit: 06e71be
What This Does NOT Fix
The mechanical override prevents wrong-company identity from propagating (URL, name). It does NOT filter wrong-company content — if Perplexity returns team bios, funding data, or metrics about the wrong company, those may still appear in the research narrative. Content-level filtering would require a post-research validation agent that semantically evaluates each research finding against the known company identity.
Verification (Metabologic v0.2.3 → v0.2.4)
| Metric | v0.2.3 (before) | v0.2.4 (after) |
| Entity mismatch detected | Yes (metabolic.ai vs metabologic.ai) | None |
| Fact-check overall score | 0% (forced by mismatch) | 66% |
| Disambiguation override fired | N/A | Yes (both website and name) |
| Sections flagged for rewrite | 7/7 (all) | Based on actual claim quality |
| Scorecard score | 2.8/5 | 3.2/5 |
Files Changed
| File | Change |
src/agents/research_enhanced.py | Rewrote disambiguation prompt; added mechanical post-synthesis override |
src/agents/perplexity_section_researcher.py | Rewrote disambiguation prompt with same stronger language |