Part II · agent design — module 2.08 · ~35 min
Multi-agent fact-checking: two channels, one arbiter
How agents check a claim against the world
specimen: config/agents/examples/augustin.yaml
by the end you can:
- State the delegation contract: both channels report before a word of the answer is written
- Explain the separation of labor: the collectors never interpret, the arbiter never collects
- Apply the corroboration gate: bare fact, attributed claim, named rumor, or reported contradiction
- State what an empty channel supports: a finding to report, never a story about why it is empty
- Describe the output contract: a conversational lead, then one sourced fact per line
Ask a language model what happened in the world this week and it will answer, fluently, whether or not it knows. Module 1.01 gave you the mechanism: the machinery optimizes for the shape of a correct answer, and a confident paragraph about a negotiation is the same shape whether the negotiation is real or remembered from training data that ended months ago. For most questions that risk is a nuisance. For questions about live events (an election claim, a disputed strike, a rumor moving through your feed) it is the whole problem, because the reader cannot tell the two paragraphs apart either.
The fix is an architecture in which the agent that writes the answer is structurally unable to invent one: it holds no search tools, it may use only what two independent research reports contain, and every fact it states carries the source that has to answer for it. This module studies that architecture on a working specimen — a syndicate called Augustin, a fact-checking arbiter of world events. It is one definition file, config/agents/examples/augustin.yaml, and it is not a classroom mock-up: the same file answers live questions daily as a working desk agent, and what ships in the starter pack is that production prompt, verbatim.
You already hold every part this syndicate is built from. Delegation with a mandatory consultation contract came from module 2.04. The discipline of separating the eye that gathers from the mind that judges came from module 2.07’s image pipeline. What is new here is where the separations are drawn when the subject is the news, and one rule, the corroboration gate, that decides what may be stated as fact.
the shape: collection apart from interpretation
The syndicate is three agents. Two collectors and one arbiter, and the entire design is in what each one is refused.
XResearcher sweeps X (Twitter). Its model line reads grok-4.5, and that choice is wiring, not preference: the x_search tool runs on xAI’s live index of the platform, and on any other provider the tool declaration is an inert sentinel that returns nothing. The researcher’s contract tells it to run several query formulations before concluding anything — official and wire accounts first, then the loudest voices deliberately sampled from opposing camps, then what is being disputed and amplified. Its report is a plain text block with fixed sections: numbered claims, each tagged with its handle and its corroboration status; the spectrum of camps and what each emphasizes or omits; the dominant reactions; and the gaps, meaning what it searched for and did not find. What its contract refuses it is analysis. It finds and records; it never interprets.
WebResearcher verifies. It runs on gemini-3.7-flash with web_search and web_extract, and it receives two things: the user’s question and the specific claims XResearcher surfaced. Its method is read-before-ruling: search each claim, then open the most authoritative results and read the page text, under a fixed extraction budget so it cannot browse forever. Its report is the documented record: established facts labeled CONFIRMED or REPORTED by how many independent sources carry them, a line-by-line check of each handed claim — confirmed, contradicted, or unverified — and the domains consulted. It, too, is refused analysis.
The Arbiter writes the answer, and it holds no tools at all. It cannot search X, cannot search the web, cannot open a page. On every substantive question its instruction makes the two consultations mandatory and ordered — X first, because that is where live claims surface; web second, because verification needs to know what it is verifying — and only after both reports are in does it write. Even a question the model believes it already knows goes through both channels, for the reason the instruction states plainly: the model was trained in the past, and the question is about the present.
The evidence boundary: the answer is built only from what the two reports contain. A tool-free arbiter cannot slip its own searching into the answer; whatever it states, one of the two reports has to carry.
Hold this next to module 2.07’s division of visual labor and the pattern becomes a discipline rather than a trick. There, the observer saw only the image and the auditor saw only text, so expectation could not contaminate perception. Here, the collectors gather but may not judge, and the judge may not gather. Both are the same engineering move: when you need a system to be honest about evidence, you split gathering from grading so that no single context window ever holds the temptation to do both. There is also a quieter, mechanical reason the jobs stay apart, learned in production: a model that is grounding itself in live search results struggles to hold a strict output contract in the same call. Give search and structure to different agents and each does its one job well.
two channels are a modality choice
Module 2.07 used “multi-modal” to mean pixels and text — two kinds of signal needing two kinds of eye. This module stretches the word one deliberate step: the two channels here are both text, but they are different modalities of evidence, and the difference is what makes the architecture work.
The X sweep reads the live claim stream: what is being asserted right now, by whom, in which camps, with what fury. It is fast, raw, and unaccountable; it is where a story exists first, and where a fabricated story exists at all. The web check reads the documented record — wire services, primary sources, official statements, published data. It is slower and more accountable, and it lags the claim stream by hours or days. Neither channel alone can answer “what is actually known”: the stream without the record is rumor with reach, and the record without the stream misses what your reader is actually seeing in their feed and needing checked.
The design keeps the channels independent the same way 2.07 kept the observer blind. XResearcher does not see the web report; WebResearcher receives X’s claims as things to check, never as things to believe. Corroboration between the channels means something precisely because nothing upstream let them agree by copying each other.
The specimen’s whole mechanism in one pass. The figure idealizes one thing: in the running syndicate the gate is a rule in the Arbiter’s instruction, applied claim by claim as it writes — not a separate machine the text physically passes through.
the corroboration gate
Everything the Arbiter is allowed to say is governed by one rule with four outcomes. A claim may be stated as bare fact only when it is corroborated across both channels, or confirmed by a primary or authoritative source in the web report. Everything short of that keeps its attribution attached: X posts claim, Reuters reports. A claim carried by a single source travels with the word unverified. And when the web check contradicts an X claim, the claim does not enter the record at reduced confidence — the contradiction itself becomes the finding the reader is given.
The corroboration gate: corroborated across channels or primary-sourced → fact. Attested but unconfirmed → attributed claim. Single-source → labeled unverified. Contradicted → the contradiction is the news.
Two companion rules keep the gate honest at its edges. The first governs absence. When one channel comes back empty — the stream is loud but the record is silent, or the record is settled but the stream has moved on — the Arbiter may say the record is thin there, and nothing else. An empty channel supports no story about why it is empty; suppression, consensus, and controversy are all theories about silence, and silence carries evidence for none of them.
Silence is a finding, not a motive: an empty sweep is reported as an empty sweep. Suppression, consensus, and controversy are all theories about an absence, and the absence supports none of them.
The second governs sourcing prejudice. The instruction tells the Arbiter to judge the text, not the account: an established outlet can editorialize and an anonymous account can commit accurate journalism, so weight goes to what a post or article actually says and sources, never to the prestige of who posted it. The rule holds every source to one question: what does this text establish, and how? A masthead and an anonymous account answer that question the same way, and the answer is what carries the weight.
None of these rules require the model to be neutral in its soul. That is the point. Neutrality here is an output property enforced by doctrine — the same move as module 2.03’s voice engineering, where register was a set of countable laws rather than a personality trait. The one opinion the Arbiter is permitted is about mechanisms — selection, framing, what a telling includes and omits — and never about which side of a controversy is right.
the output contract: a lead and its receipts
The syndicate’s answer format is two movements, fixed by instruction. First a conversational lead, two to four sentences of plain prose that answer the user directly — the true narrative as far as the record supports one, with the sharpest divergence or rumor named in passing when it matters. No label, no preamble, no “here’s what I found”. Then the facts: a bullet list, one load-bearing fact per line, ordered by importance, each line ending with its source in parentheses, a domain or a handle, and carrying its gate label inline when it failed corroboration. No section headers, no closing synthesis block. A simple factual question skips the bullets entirely and gets one to three sentences with the source named inline.
The format is doctrine, not styling, and it earns its place twice over. The lead exists because the user asked a person a question, and a person answers before itemizing; an agent that opens with a labeled taxonomy is handing the reader homework. The bullets exist because a fact without its source is just the agent’s word — the per-line source is the receipt that lets a reader check any single claim without re-litigating the whole answer. And the brevity budget in the instruction (a target near 1,200 characters) is itself an honesty device: an agent allowed to be long will pad the thin parts of the record until they look thick.
the run
Here is the specimen answering the kind of question people actually bring a fact-checker: a claim a relative is circulating, which the reader wants to answer well rather than merely dismiss. The trace is reconstructed rather than captured, with the machinery drawn true to life, so grade the instrument as you read. The facts in its answer are real and every source named is the one that holds them.
Read the run against those rules. The Arbiter consulted both channels before writing, in order, and handed the second channel the first channel’s claims. Every bullet ends in a source. The absence is itself reported: nobody circulating the briefing has produced one, and the lead states that without offering a theory as to why. The doctrine allows one kind of opinion, about mechanism rather than about people, and the lead spends it naming what the story is built from, a real 1946 expedition retold as something else. The last bullet shows the corroboration gate: a claim that failed it appears in the answer carrying the label of its failure.
try it, then gut it
The full syndicate, comments included, is yours: augustin-arbiter.md mirrors the YAML verbatim. In a clone of the melchizedek-agents repo it runs with one command:
npm run syndicate:augustin -- "What is actually known about <the thing in your feed> right now?"
This is the first specimen in the course that requires two paid providers at once: XAI_API_KEY for the grok collector, since x_search runs nowhere else, and GOOGLE_GENAI_API_KEY for the other two agents. If you carry only the Gemini key, the syndicate still teaches: swap XResearcher’s model for gemini-3.7-flash and its tool for web_search, and you have a two-channel arbiter whose channels are two differently-instructed sweeps of the same web — weaker independence, same doctrine. The engine also ships as the melchizedek-agents npm package, so the same file runs from your own repo: copy it out of node_modules/melchizedek-agents/config/agents/examples/, drop it in your config/agents/, and npx melchizedek-chat --syndicate augustin.
Then make it yours, one clearance at a time. Point the collectors at your own domain — product reviews, scientific preprints, sports transfer rumors — and keep the boundaries: collectors that never interpret, an arbiter that never collects, a gate that decides what may be stated plainly, and a per-line source on everything. When a question in your feed makes you reach for this agent, notice the habit it is teaching you back: the lead is the narrative, the bullets are the receipts, and anything without a receipt is carrying a label.