C4 diagrams your AI agents can actually read
Confluence PNGs are invisible to your coding agents. C4, ERD, and sequence diagrams belong in the repo as Mermaid text, not a picture nobody updates.
Every team I’ve worked with has an architecture diagram somewhere. It’s a PNG a solutions architect exported from Lucidchart eighteen months ago, dropped into a Confluence page titled “System Overview (final),” and it hasn’t been opened since the kickoff deck it came from. Nobody updates it, because updating it means hunting down the file, reopening a tool nobody has a seat for anymore, and redrawing boxes by hand. So the system drifts, the picture doesn’t, and everyone quietly agrees not to trust it.
That was always a bad trade. It’s a worse one now that an AI agent is reading your codebase and opening pull requests against it, because the agent can’t even see the PNG. It has no eyes on your Confluence space, no memory of the kickoff meeting, no sense that “the payments service” secretly means three different things depending on which engineer you ask. It infers your architecture from whatever it can grep, and if the true shape of the system only lives in a picture or in someone’s head, it will confidently rebuild the wrong one, in code, at agent speed.
The C4 model earns its keep here
The C4 model, designed by Simon Brown, gives you four zoom levels for the same system: Context (who and what talks to it), Container (the deployable pieces, like a web app, an API, a database), Component (what’s inside a container), and Code. Most teams only ever need the first two. That’s the point of C4: it replaces the two failure modes of architecture diagrams, either one tangled box-and-line poster that tries to show everything and communicates nothing, or no diagram at all, with something you can actually keep current because each level is small on purpose.
An ERD and a sequence diagram round it out. C4 shows you the static shape of the system; an ERD shows you what the data actually looks like; a sequence diagram shows you what happens, in order, when a specific thing occurs, like a webhook retry or a failed payment. Between the three, an engineer or an agent can answer “where does this belong” without reading the whole codebase first.
Format matters less than you’d think, and that’s the actual argument for Mermaid
The honest version of this claim isn’t “agents parse Markdown better than anything else.” A recent study on architecture descriptors for coding agents found that, in a controlled test, giving an agent structured architecture context cut navigation steps by 33 to 44%, but S-expression, JSON, YAML, and Markdown formats performed about the same for that. Format barely mattered. What mattered was whether structured context existed at all instead of the agent exploring blind.
So Mermaid doesn’t win because it’s the one format a model can read. It wins because it’s the one format that’s also legible to the human standing next to the model, in the same diff, with no separate viewer and no translation step. A .mmd block renders in GitHub, sits next to the code it describes, and shows up in git blame and git diff like any other line of text. Structurizr DSL and PlantUML both make the same trade well, and either is a fine choice if your team already knows them. What loses, every time, is a picture that lives outside the repo.
What to actually check in
Keep the stable subset. Mermaid’s ERD and sequence diagram syntax are mature. Its dedicated C4Context and C4Container diagram types, by contrast, are explicitly marked experimental, with syntax that can still break between releases, so I don’t build on them for anything I want to survive an upgrade. A plain flowchart with subgraphs gets you the same Context or Container diagram, more verbosely, on syntax that isn’t going to move under you:
flowchart TB
customer((Customer)) --> web
subgraph "Storefront system"
web["Web app (Next.js)"]
api["Order API (Go)"]
db[("Orders DB, Postgres")]
end
web --> api
api --> db
api --> payments["Payments gateway (external)"]
An ERD costs you four lines and answers the question “can order lines exist without an order” before anyone writes a migration to find out the hard way:
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE_ITEM : contains
PRODUCT ||--o{ LINE_ITEM : "ordered as"
Neither example is exotic. Which is the whole idea: this is markdown a reviewer reads in the pull request, not a separate artifact someone has to remember to open.
The alternative is somebody else’s Tuesday
We saw the other end of this at HAVI, mid-transformation on a large Azure estate. Nobody could tell us, with confidence, what was actually running, what it cost, or who could still reach what. The engagement was, in large part, mapping a cloud nobody could see, which turned up a 22% cost reduction and access risks that had been sitting there the whole time. None of that was hidden on purpose. It was hidden the ordinary way: undocumented, then reorganized, then undocumented again, until reconstructing the architecture was its own project before anyone could improve it.
That’s the cost a stale diagram actually defers. Not the ten minutes to update a box. The audit, months later, that has to rediscover what the picture was supposed to tell you for free, done by whoever draws the short straw, human or agent. We wrote about the other half of this same shift, a definition of done that an agent can execute: once you accept that a model is a reader of your repo, not just a writer to it, the architecture belongs in the same place as the tests. Version it, review it in the diff, and let it rot in public where a stale line jumps out in git blame instead of rotting quietly in a tool nobody opens. If you want that context built in from day one instead of reconstructed later, that’s the kind of thing our engineering teams set up before the first feature ships.