惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
Jina AI
Jina AI
雷峰网
雷峰网
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
美团技术团队
V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell
小众软件
小众软件
博客园 - Franky
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
爱范儿
爱范儿
Hugging Face - Blog
Hugging Face - Blog
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
Apple Machine Learning Research
Apple Machine Learning Research
量子位
IT之家
IT之家
人人都是产品经理
人人都是产品经理
博客园_首页
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
How to make an AI research agent label facts vs inference...
John · 2026-06-23 · via DEV Community

John

Originally published on hexisteme notes, part of a series on building and running an AI agent fleet.

To stop an AI research or RAG agent from presenting its own inferences as retrieved facts, split the work so the LLM never decides what is a fact: let the LLM only extract and summarize, and let a deterministic, non-LLM pipeline do all scoring, cross-checking, and labeling. Tag a claim FACT only when a rule is satisfied — corroboration by ≥2 independent sources, or one official API — and downgrade everything else to INFERENCE. Because labeling is rule-based, the agent can't launder a guess into a fact, and the same query produces the same labels every run.

An AI agent that gathers information has two kinds of output tangled together: things it retrieved and things it concluded. A web page said the market was 1.2 trillion won (retrieved); the agent inferred the market is "growing fast" (concluded). Both come out in the same confident prose. For anything you'll act on, that blend is the problem — you can't tell which sentence is grounded and which is the model filling a gap.

The fix isn't a better prompt ("only state facts you can cite"). Prompts are probabilistic; under pressure the model reverts. The fix is structural: take the fact/inference decision away from the model entirely and put it in code.

The split: LLM extracts, code judges

Draw a hard line through the pipeline:

The LLM does Deterministic code does
Extract claims from a fetched page; summarize a passage Score, cross-check, sort, deduplicate, label FACT/INFERENCE, decide freshness

The LLM is excellent at reading messy text and pulling out a structured claim. It is unreliable at judging that claim — ask it to "rate confidence 0–1" and it will turn a guess into 0.85, and give a different number next run. So nothing downstream of extraction is allowed to be an LLM call. Scores are token matches, source counts, and recency math. Labels are rule outputs. This buys two things at once: reproducibility (same query → same labels, which you can unit-test) and no laundering (the model can't promote its own inference to a fact, because it never holds the pen on labeling).

Reproducibility is the tell. If your research agent gives different confidence on the same question across runs, an LLM is scoring somewhere in the pipeline. Find it and replace it with a function. The goal is: re-run the exact query, get the exact same FACT/INFERENCE split.

A six-phase pipeline

Make the stages explicit so each is testable in isolation:

PLAN → HARVEST → NORMALIZE → CORROBORATE → SCORE → RENDER

  • PLAN — turn the question into concrete sub-queries and the sources to try.
  • HARVEST — fetch from multiple paths (see below). LLM-free; just collection.
  • NORMALIZE — LLM extracts structured claims from each fetched item. This is the only place the model touches the data.
  • CORROBORATE — group claims; count independent sources per claim.
  • SCORE — assign labels and scores by rule.
  • RENDER — emit FACTs, INFERENCEs, and an explicit gap list.

The FACT gate: earn the label

FACT is not a default; it's a status a claim must earn, enforced as a type invariant:

# A claim constructed as FACT without evidence is a bug, not a soft warning.
Claim(provenance=FACT, evidence_ids=[])   # -> raises

# The corroboration rule (the knob is the count; the principle is independence)
def label(claim):
    independent = count_independent_sources(claim)   # distinct domains, not pages
    if independent >= 2 or claim.from_official_api:
        return FACT          # carries the evidence_ids that corroborated it
    return INFERENCE         # single-source or model-derived

"Independent" is doing real work: one blog quoting another blog is one source, not two. Two different domains, or a single authoritative API (a government dataset, an exchange's own endpoint), clear the bar. Everything else is rendered as INFERENCE — visible to the reader as exactly that.

⚠️ Watch for order-dependence. An early version of this scored a cross-corroborated FACT lower than a single-source INFERENCE because the score depended on processing order. That silently breaks reproducibility. Scores must be a pure function of the claim and its evidence, independent of the order claims were processed.

Multi-path harvest, without redundancy

Diversity of sources is what makes corroboration meaningful, but firing every source at once is wasteful and noisy. Use escalation, not broadcast: try a primary search, and only escalate to the next path when the first is insufficient.

Path Order
Web search primary → escalate to a news-grade engine (ad/spam pollution) → escalate to a semantic engine (papers, near-duplicates)
Official API a government/first-party dataset; one official source may stand alone as FACT

Never send the same query to three engines simultaneously — read the first result, then decide whether to escalate. And when a source fails or is rate-limited, log the failure and the escalation; never substitute a guess for a missing fetch.

Freshness and gaps are first-class

Two more rules complete the provenance picture. Freshness: every datum carries a confirmation date, and a rule marks it stale when it ages past a threshold — a fact true last quarter is labeled as such, not silently presented as current. Gaps: the render step emits an explicit list of what was asked but not found or not corroborated. A silent gap reads as completeness and is the most dangerous output a research agent can produce; surfacing it is what makes the FACT list trustworthy.

Why this is worth the structure

The payoff is a research output a reader (or a downstream AI) can trust per-claim: every FACT points at the independent sources that earned it, every INFERENCE is flagged as the agent's own leap, stale data says so, and the gaps are named. The model still does what it's good at — reading and extracting — but it never gets to decide what's true. In an era where AI answers are increasingly cited as sources themselves, the agents worth citing are the ones that label their own confidence honestly, by rule, and reproducibly.


More notes on building an AI agent fleet — falsifier-driven AI decisions, reusable decision units, a file-based agent work-bus — at hexisteme.github.io/notes.