# AoAH Day 24: Tuatara, an evolving Atom aggregator that mutates

*2025-12-24 — note*


My original purpose for starting this [AoAH](https://anil.recoil.org/notes/aoah-2025) series was to build a
feed aggregator for my group website, so I had to finish up with something to show\!

I'm not sure if taking the [longest way around](https://www.goodreads.com/quotes/6001-think-you-re-escaping-and-run-into-yourself-longest-way-round)
was wise here but I ended up building **[tuatara](https://tangled.org/anil.recoil.org/tuatara)**, an
aggregator to pull together all my colleagues' writing into one place.
They're a quirky bunch with many diverse homegrown feeds in various
states of brokenness, so it's difficult to build a one-size-fits-all tool.

So given it's the end of the year and I'm sozzled on Christmas eve on
mulled wine, I decided to make Tuatara **mutate its own code** by linking with my [Claudeio](https://anil.recoil.org/notes/aoah-2025-4) library to
force it to evolve and modify itself as it runs across feed errors. Every deployment of
Tuatara is meant to be slightly [different](https://anil.recoil.org/papers/2025-internet-ecology).


## Evolving code like it's 2026

The initial generation of the code was pretty straightforward, using Sqlite to
store a database with all the posts and importing metadata from my previously
created [Sortal](https://anil.recoil.org/notes/aoah-2025-8) contacts manager.

```bash
> tuatara import-sortal
Sortal Import Results:

  Total contacts scanned: 420
  Contacts with feeds: 15
  Feeds imported: 16
  Feeds skipped (already exist): 0

Run 'tuatara fetch' to download posts from the imported feeds.
```

But when we actually get the feeds, I rapidly realised that there are lots of
parsing quirks needed:

```bash
> tuatara fetch
Fetching Anil Madhavapeddy...
  340 posts (0 new)
Fetching David Allsopp...
  Not modified
Fetching Jessica Man...
  Not modified
Fetching Jon Ludlam...
  28 posts (0 new)
Fetching Jon Sterling...
  Not modified
Fetching Mark Elvers...
  Not modified
Fetching Martin Kleppmann...
  Error: Feed parse error: document MUST contains exactly one <feed> element at l.0 c.0
  URL: http://feeds.feedburner.com/martinkl
Fetching Onkar Gulati...
  Error: Not_found
  URL: https://onkargulati.com/feed.xml
Fetching Patrick Ferris...
  Error: Feed parse error: <entry> elements MUST contains at least an <author> element or <feed> element MUST contains one or more <author> elements at l.1460 c.7
  URL: http://patrick.sirref.org/weeklies/atom.xml
Fetching Richard Mortier...
  79 posts (79 new)
Fetching Ryan Gibb...
  38 posts (38 new)
Fetching Sadiq Jaffer...
  10 posts (10 new)

Total: 127 new posts (3 errors)
```

Either we skip content, or talk to the people involved to fix their feeds, but
it's Christmas eve so that's unlikely. And anyway, we want to be [liberal in
what we accept](https://en.wikipedia.org/wiki/Robustness_principle) so why
can't I fix my own software first?\!

<figure class="image-center"><img src="/images/aoah-tuatara-ss-1.webp" alt="Like the amazing Tuatara, why don't we build evolution directly into our software? Time to take off the semantics seatbelt..." title="Like the amazing Tuatara, why don't we build evolution directly into our software? Time to take off the semantics seatbelt..." loading="lazy" srcset="/images/aoah-tuatara-ss-1.768.webp 768w, /images/aoah-tuatara-ss-1.640.webp 640w, /images/aoah-tuatara-ss-1.480.webp 480w, /images/aoah-tuatara-ss-1.320.webp 320w, /images/aoah-tuatara-ss-1.1920.webp 1920w, /images/aoah-tuatara-ss-1.1600.webp 1600w, /images/aoah-tuatara-ss-1.1440.webp 1440w, /images/aoah-tuatara-ss-1.1280.webp 1280w, /images/aoah-tuatara-ss-1.1024.webp 1024w"><figcaption>Like the amazing Tuatara, why don't we build evolution directly into our software? Time to take off the semantics seatbelt...</figcaption></figure>

## Medice, cura te ipsum

The non-obvious and probably-terrible answer here is to use our fancy coding
models to force the Tuatara source code to heal itself.  I added an `--evolve`
flag to allow tuatara to invoke [Claude/OCaml](https://anil.recoil.org/notes/aoah-2025-4) upon errors and patch its own code.
Turns out self help works, as Martin's blog feed was just fine\!

```bash
Fetching Martin Kleppmann...
  Error: Feed parse error: document MUST contains exactly one <feed> element at l.0 c.0
  URL: http://feeds.feedburner.com/martinkl

Invoking Claude Code to fix parse error...

The feed from `http://feeds.feedburner.com/martinkl` is an **RSS 2.0 feed** (it
starts with `<rss version="2.0">`), but tuatara was incorrectly detecting it as
an **Atom feed**. This caused the Syndic Atom parser to fail with "document
MUST contains exactly one \<feed\> element".

The root cause was that the `detect_feed_type` function prioritized the HTTP
`Content-Type` header over the actual content. FeedBurner (and other feed
aggregators) often serve RSS feeds with an incorrect `application/atom+xml`
content-type header.

This is a generic fix that will work for any feed aggregator or CDN that
mis-labels RSS feeds as Atom (or vice versa), so no domain-specific quirk was
needed.
```

But the parsing drama continued, as [Michael Dales](https://mynameismwd.org) uses the wrong date format in his
feed (tsk tsk I'd send the RFC police out if it wasn't Christmas), but Tuatara
[evolves a quirk](https://tangled.org/anil.recoil.org/tuatara/commit/a56c4a877936a1ae49c0fab301fb6afbcc74b3bb) that gets past it:

> The quirk module converts ISO 8601 dates (2025-10-22T12:24:00-00:00) to RFC
> 822 format (Wed, 22 Oct 2025 12:24:00 GMT) which is what Syndic's RSS2 parser
> expects.

And [Onkar Gulati](https://www.cst.cam.ac.uk/people/og309) and [Patrick Ferris](https://patrick.sirref.org) both have an empty author field which would
ordinarily give us a dreaded `Not_found` exception:

> Fetching Patrick Ferris...Error: Feed parse error: <entry> elements MUST contains at least an <author> element or <feed> element MUST contains one or more <author> elements at l.1460 c.7 URL: http://patrick.sirref.org/weeklies/atom.xml

But never fear, the inexorable `--evolve` flag figures it out and patches its own code\!

There were some non-trivial quirks as well; [Andres Zuñiga-Gonzalez](https://ancazugo.github.io/) uses Quatro for his website which puts the entire HTML blob into the summary field, but the evolution managed to use [html5rw](https://anil.recoil.org/notes/aoah-2025-15) to parse [its way out of this](https://tangled.org/anil.recoil.org/tuatara/commit/7f29b37e1c647f984589e42164a0fc2ec0cda5c4). This sort of fix is very hard to generalise, so it's actually quite useful for the tool to fix itself on demand for our small group.

## Using the Claude frontend design

Then I needed a quick way to do a clean frontend output so I can visualise the
JSONfeed. Claude has a `/plugin frontend-design` skill that is built in, and
prompting it to give me a few designs let me integrate a `--html` output.

And because it's Christmas, I added some snowflakes as well. Yay\!

<a href="https://www.cl.cam.ac.uk/~avsm2/eeg-xmas"> <figure class="image-center"><img src="/images/aoah-tuatara-ss-4.webp" alt="Ho ho ho merry xmas everyone from the EEG feed that isnt live yet but will be after the new year" title="Ho ho ho merry xmas everyone from the EEG feed that isnt live yet but will be after the new year" loading="lazy" srcset="/images/aoah-tuatara-ss-4.768.webp 768w, /images/aoah-tuatara-ss-4.640.webp 640w, /images/aoah-tuatara-ss-4.480.webp 480w, /images/aoah-tuatara-ss-4.320.webp 320w, /images/aoah-tuatara-ss-4.1600.webp 1600w, /images/aoah-tuatara-ss-4.1440.webp 1440w, /images/aoah-tuatara-ss-4.1280.webp 1280w, /images/aoah-tuatara-ss-4.1024.webp 1024w"><figcaption>Ho ho ho merry xmas everyone from the EEG feed that isnt live yet but will be after the new year</figcaption></figure> </a>

## Reflections

The paper I enjoyed writing the most this year was [Steps towards an Ecology for the Internet](https://anil.recoil.org/papers/2025-internet-ecology) for
[Aarhus 2025](https://anil.recoil.org/notes/ecology-at-aarhus). In the back of my head since has been a desire
to start figuring out what self-evolving software actually might be. It's a
strange, and probably impractical idea, but I'm delighted that I took a tiny
step towards it with this project.

Back in March, I had the honour of being invited to a [Bellairs](https://bellairs.net) meeting to discuss a heady combination of semantics and computational science. [Jon Sterling](https://jonmsterling.com) demonstrated his wonderfully organised Forester website. And I... showed how my mismash of semi-structured writings can kind of be connected together in a vaguely coherent way to build my website. Next year will have me thinking much harder about the implications of [self-evolving code](https://anil.recoil.org/papers/2025-internet-ecology), of how radically [transformative to global biodiversity](https://anil.recoil.org/papers/2025-biodiversity-9recs) semi-structured agentic processing might be, and other heavy matters. But to close this year, I'm disproportionately pleased to have gotten my tiny website under control a little\!

<figure class="image-center"><img src="/images/aoah-tuatara-ss-2.webp" alt="Sitting indoors in Barbados with a gigantic beach outside: a classic sign of semanticists in the wild" title="Sitting indoors in Barbados with a gigantic beach outside: a classic sign of semanticists in the wild" loading="lazy" srcset="/images/aoah-tuatara-ss-2.768.webp 768w, /images/aoah-tuatara-ss-2.640.webp 640w, /images/aoah-tuatara-ss-2.480.webp 480w, /images/aoah-tuatara-ss-2.3840.webp 3840w, /images/aoah-tuatara-ss-2.320.webp 320w, /images/aoah-tuatara-ss-2.2560.webp 2560w, /images/aoah-tuatara-ss-2.1920.webp 1920w, /images/aoah-tuatara-ss-2.1600.webp 1600w, /images/aoah-tuatara-ss-2.1440.webp 1440w, /images/aoah-tuatara-ss-2.1280.webp 1280w, /images/aoah-tuatara-ss-2.1024.webp 1024w"><figcaption>Sitting indoors in Barbados with a gigantic beach outside: a classic sign of semanticists in the wild</figcaption></figure>

As I noted in my [letter to the ACM](https://anil.recoil.org/notes/acm-ai-recs), it's important that we can use AI for things that boost the
human condition; I really enjoy reading my colleagues' long form thoughts much
more than doomscrolling on the web, and so making it easier to gather their
thoughts digestibly and easily is a nice end to my [agentic humps](https://anil.recoil.org/notes/aoah-2025)
effort. Tomorrow on [Christmas](https://anil.recoil.org/notes/aoah-2025-25) I'll publish all the skills I used so others can try them out.
Synopsis: Tuatara is a feed aggregator that integrates Claude to evolve and patch its own code when encountering parsing errors, embodying the concept of self-healing software.
Words: 1126

## Related

- [Webbplats update (part 1)](https://digitalflapjack.com/weeknotes/webbplats-update/) (feed, 2026-05-28)
- [.plan-26-18: From tropical forest protection to oi swallowing its oxcaml tail](https://anil.recoil.org/notes/2026w18) (note, 2026-05-03)
- [The Internet needs an antibotty immune system, stat](https://anil.recoil.org/notes/internet-immune-system) (note, 2026-04-08)
- [Nine changes needed to deliver a radical transformation in biodiversity measurement](https://anil.recoil.org/papers/2025-biodiversity-9recs) (paper, 2026-01-01)
- [2025 Advent of Agentic Humps: Building a useful O(x)Caml library every day](https://anil.recoil.org/notes/aoah-2025) (note, 2025-12-26)
- [AoAH Day 25: Claude OCaml Marketplace for all your festive coding needs](https://anil.recoil.org/notes/aoah-2025-25) (note, 2025-12-25)
- [Dear ACM, you're doing AI wrong but you can still get it right](https://anil.recoil.org/notes/acm-ai-recs) (note, 2025-12-22)
- [AoAH Day 15: Porting a complete HTML5 parser and browser test suite](https://anil.recoil.org/notes/aoah-2025-15) (note, 2025-12-15)
- [AoAH Day 8: Building a contacts CLI manager with Sortal](https://anil.recoil.org/notes/aoah-2025-8) (note, 2025-12-08)
- [AoAH Day 4: Going recursive with Claudeio for Claude](https://anil.recoil.org/notes/aoah-2025-4) (note, 2025-12-04)
- [Presenting our Ecology of the Internet ideas at Aarhus 2025](https://anil.recoil.org/notes/ecology-at-aarhus) (note, 2025-08-22)
- [Steps towards an Ecology for the Internet](https://anil.recoil.org/papers/2025-internet-ecology) (paper, 2025-08-01)
- [OxCaml Labs](https://anil.recoil.org/projects/oxcaml) (project, 2025-01-01)

---
Canonical: https://anil.recoil.org/notes/aoah-2025-24
Type: note
License: CC BY 4.0 <https://creativecommons.org/licenses/by/4.0/>
Tags: ai, ocaml, oxcaml, llms, aoah, networks
