AI retrievability is mostly not about llms.txt

A five-agent audit of my own site found its highest-value bug was a missing space only a machine could see. llms.txt was the least load-bearing fix in it.

1 missing space the highest-value fix in a five-agent retrievability audit

Until yesterday, an answer engine reading the two pages of this site it hits first would have found this string on both of them:

569,000impressions

The markup is <b>569,000</b><span>impressions</span>, and CSS puts a gap between them. In a browser it reads correctly. It read correctly in every screenshot, every design review, and every time I looked at it. Flatten the DOM, which is exactly what an extractor does, and the number fuses to its own label.

That figure is the most citable thing on the site. Glued, it is not liftable at all.

The space that existed only in CSS

I ran a full audit against the live site yesterday: five specialist agents in parallel, nine pages, working from live fetches rather than from the repo. Technical came back 91. Brand authority came back 23, and almost every point lost was an entity problem rather than a code problem, which I will get to.

The stat bug was already known, and already fixed. In one template out of four. Stats.astro, the /work/ index and the ResultBox component were all still gluing value to label.

Here is why it survived a fix. Putting the two elements on separate source lines does not solve it, because Astro collapses whitespace-only text nodes between elements. The source reads as spaced and the compiled output is not. Only an explicit {' '} survives. All four files looked correct in source, and three of them shipped wrong.

The engine read the page and still got the person wrong

The single most useful measurement in the audit was the cheapest one. Ask a search-grounded model who Christian Mauerer is.

It fetched /about/. It cited /about/. It then answered “Founder & Head of Design”, based in Miami, working in web design, branding and e-commerce rather than AI.

Access was never the constraint. Eleven AI and search user agents were tested against live routes: all 200, identical byte counts, no cloaking, no user-agent gating. robots.txt allows GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot and Google-Extended by name. The crawl worked perfectly and produced a confident description of somebody else.

The page simply never stated, in extractable third person, who its subject was. It was written in the first person, which is correct for a reader and useless as an attributable claim. “I build agentic systems” cannot be lifted as a fact about a named human. So the model filled the gap from the strongest third-person source it could find, which was a stale profile elsewhere.

Two other people already own the name

Gemini scored worst of the five platforms, 37 out of 100, and the reason is mechanical rather than editorial. It grounds in the Knowledge Graph, and the Knowledge Graph seeds from Wikidata, where there was no item for me.

There were two for my exact name. Q133335653 is a Christian Mauerer whose declared occupation is physician. Q132922616 is a Christian Mauerer whose declared occupation is business consultant.

That second one reversed a decision I had already shipped. The Person node briefly carried jobTitle: ['AI Solutions Architect', 'AI Consultant']. Both are true, both get searched, and schema.org permits the array. It also aims my node straight at the namesake who already holds “consultant” in that graph. The title is one string now, and the consulting term moved to knowsAbout, where it describes a topic instead of asserting an identity.

An engine that cannot tell two people apart does not abstain. It picks one.

An item for me now exists, created yesterday. Whether the engines take it up is not something I can claim, and I am not going to pretend the fix is finished because the edit is.

Where llms.txt actually sits in this

The file is generated rather than static. The bio comes from the same constant that is Person.description and the visible lede on /about/, and the page list comes from the content collections, so adding a post updates all of it or none of it. The robots.txt above it carries Content-Signal: ai-train=yes, search=yes, ai-retrieval=yes, which makes the intent machine-readable instead of a comment.

All of that took an afternoon, and it is the least load-bearing work described in this post.

The one line in the file doing real work is the disambiguation: “Not the paraglider, the philosopher, or the physician.” That is not a feature of the format. It is a fact about the world I had to go and learn before I could write it, and I could have written it into a plain paragraph on any page.

What actually generalises

Three things, roughly in the order they cost me.

Flatten your own DOM before an engine does it for you. Take whatever you most want quoted, run it through a text extractor, and read what comes back. Visual review cannot find this class of bug, because the bug is defined by the absence of the thing the browser is adding for you.

Identity is a graph problem, not a copy problem. Rewriting the About page in better prose would not have moved any of it. What moved it was stating a location in visible text, resolving the name against the people who share it, and refusing a job title that pointed at one of them.

Attributability beats fluency. An engine will cite the sentence it can carry away intact and attach to a named entity. First-person prose, undated numbers and stats that only look spaced are all, from the outside, the same thing: content that reads well and cannot be quoted.

llms.txt is the easiest of these to add and the least likely to change an outcome. Ship it, generate it so it cannot rot, then go and do the part that is actually hard.

Sources

  1. Profile page (ProfilePage) structured dataGoogle Search Central
  2. Wikidata Q133335653: Christian Mauerer, occupation physicianWikidata
  3. Wikidata Q132922616: Christian Mauerer, occupation business consultantWikidata
  4. The /llms.txt file proposalllmstxt.org
  5. Content Signals PolicyCloudflare