Skip to content

The shadow copy was the wrong layer

Last week I set out to build two companion WordPress plugins. One would turn PDF attachments into markdown so AI agents could read them. The other would run a local vision model over every image and write a description an agent could use. Generally speaking, agents can't read PDFs or images well (although they're getting...

@dgw.ltd
Jul 13, 2026 · 5 min read

ast week I set out to build two companion WordPress plugins. One would turn PDF attachments into markdown so AI agents could read them. The other would run a local vision model over every image and write a description an agent could use. Generally speaking, agents can’t read PDFs or images well (although they’re getting better). So I thought: generate a machine-readable copy alongside the human one.

This work grew out of the Markdown for Agents and Statistics plugin, (100+ installs!! 🥳) which generates a markdown version of posts to reduce energy usage by AI agents and host servers. Images are included, but I wondered if they should have a more detailed description to add context. Likewise PDF attachments were the same idea.

So I built them, both plugins worked. Both are, I now think wrong in the same way, the answer is content. Always has been always will. Accessibility, Marketing, SEO, LLMs.

The shadow is a symptom fix

A PDF is a print-layout artifact. It exists to be printed. But people love a PDFs – we pepper websites with them even when HTML is right there. HTML is baked into the web, readable on all devices and doesn’t cause us to try and figure out how to save a document only to find Apple files has swallowed it. When an agent – or a screen reader, or a phone, or a search index, or reader mode – meets a PDF, it has to reverse-engineer structure back out of something designed to throw structure away. My documents plugin does that reverse-engineering off-production with pdfparser a very good mature PHP library and ships a clean .md. Useful. But look at what it is: a second, machine-only representation of content I already control. If I control the content, why is it a PDF at all? A PDF that carries primary content is already failing the human who can’t handle a PDF well. The markdown copy doesn’t fix that failure at all – it just gives the machine a way around it.

The images plugin was the same shape. It generated a rich description so a text-only agent wouldn’t hit ![alt](src) and nothing more. But “a description of the image for the machine” is just an alt text fork. The thing I was generating for agents was the thing accessibility has asked editors to write for decades. I’d built a parallel pipeline to produce, for one audience, an artefact the primary artefact already has the ability to declare itself.

In both cases: I was generating a shadow copy – a second content stream I’d then have to keep in sync, cache-bust, and reconcile against the original. The shadow copy is a duplicate source of truth. And two representations of one thing drift. Always.

The images plugin’s original plan produced two outputs per image: a concise alt for the HTML front end, and a richer description for the agent-facing markdown. Two authored representations of one image. A few weeks in and they’d likely drift – an edit to one didn’t reach the other – so I did the only thing that ends drift: I collapsed them. The concise alt became the single source of truth for both the HTML and the markdown. One canonical field. The agent surface and the human surface now draw from the same well, because there is only one well.

LLMs as assistive technology

An agent and a screen-reader user hit the same barrier – so does the person on a slow phone, and the search crawler behind them. An untagged PDF stops all four. An image with no alt text stops all four. The human is always more important, but I want to make a point about how we should consider our content.

If we consider that an LLM reading your site is, functionally, assistive technology (as the Safari web team does) – a thing that mediates your content for someone who can’t consume it in its native form – then the content it accesses stops being a side concern and becomes the only show in town. The strategy stops being “generate a machine copy” and becomes “make the one artefact legible, and let everyone read it”. Accessibility-first isn’t adjacent to the agent strategy. Accessibility-first is the agent strategy.

Which means the correct fix for my two plugins was never “make the shadow copy better.” It was:

  • PDFs → HTML. If it’s content I author, it should be semantic HTML. Then there’s nothing to convert – the structure the markdown was lossily re-deriving is already there, serving humans and machines from one source.
  • Images → real alt text. Write it once, at the attachment level, as the canonical record. The agent-facing description already exists, in the right place, doing double duty.

In both cases the generation step negates itself. Do the source right and the shadow has nothing left to do.

So the plugins worked but were effectively Chindōgu.

Instead, this gave me an idea – I could build an agent-readiness audit utility that scans a site both externally (as a visitor would see it) and internally (via the WordPress media library). Its rule: fix it for people first – nothing built for agents matters if humans can’t read it. The audit flags missing alt text and content that won’t survive extraction, on the explicit grounds that fixing either serves reader mode, agents, and screen readers at once.

Now, the shadow isn’t always wrong. Some PDFs really can’t be anything else – a signed contract, a report someone else wrote, a scan of a paper original. You can’t turn those into HTML, and for those, the documents plugin still earns its place as a fallback. I still think there is some interesting use cases with local LLMs, why use a cloud based water guzzling data centre, when you can use increasingly competent open weight models. The WordPress PHP AI Client makes connecting to these super easy.

What we end up with isn’t “never generate a copy.” It’s “don’t generate a copy of something you could have just written properly in the first place”.

I started building machinery that generates agent-readable copies of my content. I’m finishing with two plugins mostly deprecated, one narrowed to the fallback case it’s actually good for, and an audit that measures the thing that was the real work all along: is the source legible, to everyone and everything?

There was nothing to generate. There was only content to fix.

Did you enjoy this article?

Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.

Across the AtmosphereDiscussions