The Fan-Out Architecture: Compiling Truth for Budgeted Agents
Hub-and-spoke content doesn’t fail because “AI can’t reason.” It fails because retrieval, latency, and token budgets force truth to be compressed. The Fan-Out Architecture turns verifiable claims into budgeted packets that survive decomposition.
Standard web architecture was designed for eyeballs (rendering). It fails for agents (reasoning).
When an agent visits your site, it doesn’t “read.” It scrapes, parses, and discards. If your truth is buried under 500 lines of CSS and divs, the agent will hallucinate or leave.
The industry lie is still the same: publish a hub, publish spokes, and “the model will assemble the answer.”
Runtime reality is uglier: even frontier long-context, tool-capable systems still answer under budgets — tokens, latency, retrieval limits, and evidence assembly constraints. Under pressure, systems either guess or skip.
Here’s the whole thesis, with no mystery:
You keep writing pages. We compile the truth inside them into packet-sized, machine-readable exports — so search engines and AI systems can cite you without guessing.
We are not optimizing for “Search.” We are optimizing for Ingestion.
Under fixed budgets, budget becomes selection pressure. Density becomes UX.
What This Looks Like on a Normal Business Website
If you already have a website, you’re 80% done.
This does not replace your website.
There is no AI runtime system. No special “LLM mode.” No parallel “machine site.”
This is a build-time compilation layer:
- You keep your normal pages: services, pricing, case studies, docs, FAQs.
- We add one internal file (
entity.json) that pins your identity, scope, and offers. - During the build, we extract the claims you already made on pages and compile them into bounded packets.
- We embed the same facts as JSON‑LD on the canonical pages (the guaranteed ingestion path).
- Optionally, we export packets as
/page.jsonfor integrators/agent systems that want contracts and versioning. - Discoverability isn’t magical: we link the JSON export from the page
<head>and/or your developer docs.
Nothing “thinks” at runtime. Nothing assembles a graph live. It’s compilation, export, and stable IDs.
Walkthrough: One Page → 3 AAOs → 2 Outputs → CI Gate
Take a normal page like /contact (this matters: your AAOs should point to a real, canonical page URL).
- Write (or update) three visible claims on the page and give them stable IDs:
pricing.model→ “Fixed weekly rate”sla.first_response→ “Typically within 24 hours”availability.regions→ “DACH + United States”
- Build emits two machine surfaces from those same claims:
- JSON‑LD on the canonical HTML (
/contact) for crawler ingestion - Optional export (
/contact.json) for integrators/agent systems
- JSON‑LD on the canonical HTML (
- CI enforces: no visible source → no emit → no ship.
Example JSON‑LD (embedded on /contact):
{
"@context": "https://schema.org",
"@type": "WebPage",
"@id": "https://argbe.tech/contact",
"url": "https://argbe.tech/contact",
"mainEntity": [
{
"@type": "PropertyValue",
"propertyID": "pricing.model",
"value": "Fixed weekly rate",
"url": "https://argbe.tech/contact#pricing.model"
},
{
"@type": "PropertyValue",
"propertyID": "sla.first_response",
"value": "Typically within 24 hours",
"url": "https://argbe.tech/contact#sla.first_response"
},
{
"@type": "PropertyValue",
"propertyID": "availability.regions",
"value": ["DACH", "United States"],
"url": "https://argbe.tech/contact#availability.regions"
}
]
}
Example export (/contact.json):
{
"canonical_url": "https://argbe.tech/contact",
"aaos": [
{
"id": "pricing.model",
"value": "Fixed weekly rate",
"source_url": "https://argbe.tech/contact#pricing.model"
},
{
"id": "sla.first_response",
"value": "Typically within 24 hours",
"source_url": "https://argbe.tech/contact#sla.first_response"
},
{
"id": "availability.regions",
"value": ["DACH", "United States"],
"source_url": "https://argbe.tech/contact#availability.regions"
}
]
}
One discoverability line is enough:
<link rel="alternate" type="application/json" href="https://argbe.tech/contact.json" />
This is a hint, not a standard: the reliable path is documenting exports + keeping JSON-LD on the canonical HTML.
What “Entity-Driven” Looks Like in MDX (getEntityValue)
If your article needs to reference stable facts (brand name, markets, pricing model), don’t hardcode them — derive them from public/entity.json so they can’t drift.
| Entity Path | Example Render |
|---|---|
identity.brand_name | Argbe.tech |
markets.regions | DACH, United States |
pricing.model | Fixed weekly rate |
sla.first_response.statement | Typically within 24 hours |
In plain MDX, you can also call the helper directly:
{brandName} serves {regions.join(' + ')}.
What “AAO-Backed” Looks Like on a Page (AAOMarker)
The compiler needs a stable, machine-readable declaration of the claim on the canonical page. That’s what <AAOMarker> is for (it remains visible-source anchored, because the marker sits next to visible copy).
This article also embeds real AAO markers (so parsers can lift the IDs and values without guessing):
- Pricing model: Fixed weekly rate Fixed weekly rate
- First response: Typically within 24 hours Typically within 24 hours
- Regions: DACH + United States ["DACH","United States"]
Example (on /contact or any canonical page section):
Our pricing model is fixed weekly rate.
<AAOMarker id="pricing.model" />
We typically respond within 24 hours.
<AAOMarker id="sla.first_response" />
We serve DACH + United States.
<AAOMarker id="availability.regions" />
The Three Layers of Truth
This only works if you hold a hard line:
- Entity = source of truth
- Packets = compiled facts, not new content
- API = export layer, not the primary discovery surface
Layer 1 — Entity (Single Source of Truth)
Start with entity.json. Treat it like package.json for your company:
- identity (name, brand, legal)
- scope (what you do / don’t do)
- offers (what you sell, constraints, pricing policy)
- locales (regions, languages, availability)
It’s internal. It’s boring. That’s the point: it stabilizes everything else.
Example sketch:
version: 1
last_updated: '2026-01-04'
identity:
brand_name: 'Argbe.tech'
canonical_url: 'https://argbe.tech'
author: 'argbe.tech'
languages: ['English', 'German']
markets:
regions: ['DACH', 'United States']
pricing:
model: 'Fixed weekly rate'
Layer 2 — Pages (Human Canonical Truth)
Your pages stay primary:
- SEO and conversions live here
- navigation and persuasion live here
- context and nuance live here
Pages still own the truth. Packets do not invent facts. Packets don’t “improve” copy. Packets are compiled artifacts of what the page already says.
Layer 3 — Packets + Export Layer (Machine Truth)
Packets are:
- extracted (from pages, plus entity constraints that already govern those pages)
- normalized (same structure every time)
- bounded (small enough to survive budget pressure)
The export layer produces alternate representations of the same truth:
- JSON‑LD embeds on canonical pages (machine-liftable facts with URLs)
- API exports (contract + versioning + bounded payloads)
Same truth, different packaging.
And to be explicit: packets do not replace pages. They make your pages citeable under budget.
Packets, in Plain Terms
A packet is not new content. A packet is a compiled fact already stated on your site.
Concrete example:
On your contact (or pricing) page, you write:
“Our pricing model is a fixed weekly rate.”
At build time, that sentence becomes a bounded object with a stable ID:
pricing.model- value normalized (
"Fixed weekly rate") - scope attached (if needed: eligibility, exclusions, effective dates)
- canonical source URL attached (the canonical page fragment)
That object is then emitted as:
- JSON export (for integrations):
/api/packets/pricing.model.json - JSON‑LD embed (for search): injected into the canonical page HTML
Only after you see the example do we name it: this bounded object is an Atomic Answer Object (AAO). AAOs are the units budgeted systems can afford to retrieve and cite.
The Kill Box: Why “Chunks” Fail
The industry relies on “chunking” — arbitrarily slicing text every N tokens. This is a logic error.
A sentence sliced away from its header loses its constraints. “Price is $50” is a lie if you lost the header “For Non‑Profits Only.”
We introduce the Atomic Answer Object (AAO): the smallest unit of truth that carries its own constraints (scope, eligibility, exceptions, effective dates) wherever it travels.
| Retrieval Unit | What It Is | Failure Mode | What Survives Under Budget |
|---|---|---|---|
| Raw text chunk | A slice of prose | Constraints get orphaned; meaning mutates | Words, not truth |
| AAO | A bounded claim + constraints + source URL | Harder to write; easier to validate | A citeable fact |
The API Is an Export Layer (Not Discovery)
APIs don’t “replace pages.” They don’t exist to be the primary thing crawled.
APIs provide:
- contracts (a predictable shape)
- versioning (explicit changes)
- bounded exports (small enough to pull under budget)
Required rules:
- Pages remain canonical.
- API routes mirror packet IDs.
- Every export points back to a canonical page URL.
- No new truth lives in the API.
If a packet only exists in an API and not on a page, it’s a ghost.
The Mirrored Output Pattern (Dual‑Head)
One source → two outputs.
- Human view:
https://argbe.tech/contact(HTML, layout, persuasion). - Optional export:
https://argbe.tech/contact.json(AAOs: pure key‑value facts, logic, constraints, and source URLs).
Agents shouldn’t have to parse your DOM to find your price. Give them the JSON. It lowers the compute cost of trusting you.
Compliance & SEO Guardrails
Fan‑Out only works long-term if it stays inside search and structured-data rules:
- Structured data must reflect visible page content. The compiler refuses to emit JSON‑LD if a claim can’t be traced to a visible source fragment on the canonical page 16 .
- Treat JSON‑LD on canonical HTML as the default. It’s the path most crawlers understand, and it stays attached to the page people actually read 17 .
- Prevent crawl bloat intentionally. If you publish
/*.json, decide whether it should be indexed; many sites mark exports asnoindexor block them inrobots.txtto keep the crawl focused on canonical HTML. - No duplicate-content panic. A JSON export that is a machine representation of the same canonical content is not a “penalty trigger” by itself; canonicalization and indexing directives are the guardrails 18 .
How Things Are Interlinked
Canonical flow:
entity.json
→ pages (HTML)
→ packets (AAOs + manifests)
→ JSON‑LD embeds
→ API exports
Rules:
- Everything points back to canonical page URLs.
- Packet IDs are stable across pages, JSON‑LD, and API exports.
- No circular dependency: pages don’t depend on the API to be “true.”
- No runtime graph assembly: edges are compiled; consumers read exports.
How This Fits into a Normal Development Workflow
This is a build step. Not runtime. Not expensive. Not fragile (if you treat it like a compiler).
Minimal flow:
- Author/update content on pages.
- Validate
entity.json(identity, offers, locales, constraints). - Compile packets (extract → normalize → bound → assign stable IDs).
- Generate:
- JSON‑LD embeds for canonical pages
- API exports that mirror packet IDs
- schema docs / manifests for integrators
- Enforce the gate: no evidence = no ship.
Honest difficulty table:
| Team | Difficulty | Why |
|---|---|---|
| Solo founder | High Velocity / Low Bureaucracy | You’re doing content, structure, and QA alone. |
| Small dev team | Medium | You can add a compiler step and validation without stalling shipping. |
| Serious SaaS | Easy | You already live on contracts, schemas, versioning, and CI gates. |
The Physics of Failure: Three Failure Modes (Each With a Metric)
| Failure Physics (Budgeted Systems) | What Breaks | What You See |
|---|---|---|
| Failure Mode A: Context dilution 7 | Retrieve more → accuracy declines | ”Ultimate guide” becomes hallucination fuel |
| Failure Mode B: Graph noise 13 | Structure explodes context size | GraphRAG pulls the whole map, not the street |
| Failure Mode C: Chunking trap 2 | Claim separates from scope/constraints | True words + wrong meaning |
Failure Mode A — Context Dilution (Inverted‑U)
The naive strategy is “retrieve more.”
But input length alone can degrade reasoning accuracy substantially — with reported degradations ranging from 13.9% to 85% depending on task and length 7 . In production, you get the same outcome via distractors and hard negatives: more words, less truth.
Implication: long-form “ultimate guides” can become hallucination fuel when they are your only retrieval surface.
Failure Mode B — Graph Noise (Structure Can Explode)
“Add structure” is good advice until your structure balloons the context.
In a page-level QA comparison, GraphRAG pulled ~46,949 tokens of context versus ~3,743 tokens for standard top‑k retrieval 13 . If you don’t budget graphs, you don’t get “more intelligence.” You get a token flood.
Implication: structure must be constrained, or it becomes expensive noise.
Failure Mode C — Chunking Trap (Truth Becomes a Widow)
Chunking often separates a claim from its constraints (an orphaned constraint): scope, date, plan, exceptions, and definitions.
Chunking strategy changes retrieval quality materially 2 . The failure mode in the wild is simpler: the model retrieves valid words with invalid meaning because the constraint chunk wasn’t co‑located.
Implication: if constraints aren’t attached to claims, your truth is inherently unstable under retrieval.
And yes: latency is the new bounce rate — not as a product claim, but as the physics of budgeted pipelines.
Diagrams (Where the System Breaks, Where It Works)
Diagram A — The Failure Mode (The Chunking Trap):
Diagram B — The Fan‑Out Solution:
Why Packet Discipline Already Exists (and Why It Works)
The Fan-Out Architecture is not speculative.
It is a generalization of an existing, battle-tested pattern already used in domains where errors are expensive and retrieval budgets are strict.
Those domains don’t publish “content.” They publish bounded facts with contracts: packets.
Until now, that discipline has been largely confined to:
- APIs
- infrastructure documentation
- legal texts
- clinical guidelines
Fan-Out’s claim is scope expansion: apply the same packet discipline to GEO / SEO / marketing domains, where agents — not humans — are increasingly the primary readers.
The Precedent — Contracts Beat Narratives Under Budget
APIs work well for machines because they are bounded, versioned, and constraint-coupled by default.
That’s the lesson. Not “APIs crawl better.” Not “APIs replace pages.”
Budgeted systems prefer units where:
- the claim and its constraints live together (constraint coupling)
- the object has a stable identifier
- exports are predictable and testable (a contract)
Fan-Out extracts that discipline and applies it to business truth claims.
Real-World Proof — Who Already Uses Packets (Even If They Don’t Call Them That)
1) Stripe (Payments)
What Stripe actually publishes:
- endpoints (e.g.,
POST /v1/payment_intents) - parameter tables
- versioned schemas
- explicit constraints (currency, region, capture mode)
Why this matters: an agent can answer “How do I create a delayed-capture EUR payment?” by retrieving one endpoint packet, not a guide.
Fan-Out equivalence:
- endpoint = AAO-like bounded fact unit
- API categories = facet manifest
- OpenAPI spec = export surface
2) AWS (Cloud Infrastructure)
AWS documentation is impossible to “read” end-to-end — yet it is extremely retrievable. Why? Because AWS decomposes truth into packets:
- service capability tables
- region availability matrices
- quota objects
- IAM policy statements
An agent answering “Is S3 Object Lock available in eu-central-1?” retrieves:
- one service packet
- one region constraint
- one eligibility rule
Fan-Out lesson:
- typed edges already exist (e.g.,
APPLIES_WHEN region == eu-central-1) - narrative is optional; bounded facts are mandatory
3) EUR-Lex (Law & Regulation)
EU law is indexed by article, paragraph, clause, and version.
Courts and systems don’t retrieve “GDPR explained.”
They retrieve Article 6(1)(f).
Fan-Out lesson:
- legal clauses are packets
- amendments are typed edges (
SUPERSEDES) - citations demand exactness
The Blueprint: The Mirrored Output Architecture
We stop treating “content” as text and start treating it as Data with a Skin.
Every URL on your site becomes a Dual‑Head Node:
- The Human Head (HTML): optimized for reading, design, and persuasion.
- The Machine Head (JSON): optimized for ingestion, logic, and citation.
The Protocol (How It Works)
You do not write two websites. You add a compilation step.
When you write your /contact page, the build process (Next.js, Astro, Hugo, etc.) extracts the claims into Atomic Answer Objects (AAOs) and deploys them as a static JSON file alongside the HTML.
The Routing Logic
- Human visits
argbe.tech/contact→ gets full UI, layout, persuasion. - Agent requests
argbe.tech/contact.json→ gets the AAOs:
{
"canonical_url": "https://argbe.tech/contact",
"aaos": [
{
"id": "pricing.model",
"value": "Fixed weekly rate",
"source_url": "https://argbe.tech/contact#pricing.model"
},
{
"id": "sla.first_response",
"value": "Typically within 24 hours",
"source_url": "https://argbe.tech/contact#sla.first_response"
},
{
"id": "availability.regions",
"value": ["DACH", "United States"],
"source_url": "https://argbe.tech/contact#availability.regions"
}
]
}
Why This Wins (The Physics)
- Token economy: an agent ingests ~150 tokens of pure logic (JSON) instead of 3,000 tokens of DOM noise (HTML). You just made yourself cheaper to cite.
- Context preservation: the
constraintsfield travels with the value. Disclaimers stop being “optional” because they’re structurally bound to the claim. - Zero drift: JSON is generated from the same source as the HTML during build, so the two outputs can’t contradict without failing your compile/validation gate.
Implementation Checklist: The Dual‑Head Build Protocol
This is not a content calendar. This is a deployment pipeline.
Phase 1 — The Model (Definition)
Isolate the “Function Call.” Stop asking “What keywords do we target?” Ask: “If this page were an API endpoint, what would it be named?”
Examples: getPricingDetails(), checkAvailability(), getServiceScope().
Define the AAO schema. Draft the minimal JSON shape required to answer that function call without ambiguity.
Rule: every AAO must include the raw value, the constraints, and the source URL (evidence), plus any promises that change expectations (e.g., SLA, lead time, eligibility).
Example (a generic “Contact” becomes a contract):
{
"id": "contact.primary_method",
"canonical_url": "https://argbe.tech/contact",
"claim": {
"promise": { "business_hours": "mon-fri" }
},
"source_url": "https://argbe.tech/contact"
}
Author the Facet Manifest. List the 15–25 facets you want budgeted systems to route to (planner inputs), and set explicit limits 3 .
Phase 2 — The Build (Compilation)
Implement the extractor. Write a build step (Astro/Next/Hugo) that compiles both outputs from the same source of truth.
Rule: do not hand-write the JSON. The .json head must be compiled from the same inputs as the HTML head, or drift becomes inevitable.
Assign stable IDs and bounded payloads. Keep AAOs ≤150 tokens where possible; normalize types; co-locate constraints with claims 2 .
Map typed edges (routing, not “internal linking”). Use explicit relations like DEPENDS_ON, APPLIES_WHEN, CONTRASTS_WITH, SUPERSEDES so consumers can reason deterministically 1 .
Compile the three surfaces. From the same AAOs, generate:
- canonical page (HTML)
- JSON‑LD embed (crawler lift)
- API export (versioned contract) 6
Phase 3 — The Deployment (The Mirror + The Gate)
Deploy the dual‑head. Serve both:
GET /contact→ HTML (human UX)GET /contact.json→ JSON (agent evidence)
Red-team validation. Before shipping, curl the .json endpoint and ask a generic model: “Based only on this JSON, what is the price / SLA / eligibility?”
Pass: the answer is precise, scoped, and cites the constraint fields. Fail: the model guesses. No evidence = no ship 5 .
Next Steps: Execute the Dual‑Head Build
Don’t overthink this. You don’t need a new CMS. You need a build script.
- Pick your money page. Identify the one page that answers: “How do I hire you?” or “What does this cost?”
- Define the AAO. Write the JSON shape that answers that question without ambiguity (value, scope, constraints, and canonical URL).
- Deploy the mirror. Ensure that adding
.jsonto that URL delivers the raw data export. - Test the agent. Point an LLM at the JSON URL and ask it to summarize your pricing. Watch it get the answer right, every time.
That is Fan‑Out.
You are still publishing pages — plus contracts for truth that budgeted systems can afford to ingest and cite.
The Mic Drop
The future of GEO/SEO isn’t keywords alone. It’s contracts alongside pages.
This is not “API instead of pages.” It’s contracts alongside pages.
If an agent has to burn $0.05 of compute just to figure out what you sell, it will skip you for a competitor who serves the answer in clear, 100‑token JSON.
You have two choices:
Keep building for humans and hope the bots figure it out.
Build the mirrored output and hand the truth to the machine on a silver platter.
Only one of these survives the budget cut.