I delegated to an agent, it checked its own work, and it was still wrong
I handed this site's dark theme to an AI agent. It computed the contrast ratios itself, said everything passed, and shipped cards whose borders you could not see. Then I fixed it, and my fix failed too. 24 measurements and the one rule I took from it.
Bu yazının Türkçesi: Türkçe sürüm.
I did not build the dark theme on this site. I delegated it to an AI subagent. The agent did a good job: it built the palette, computed the contrast ratios itself, and then ran a second pass over its own work, caught one of its own mistakes and fixed it. Its final report said everything passed.
The report was true. The result was wrong. In dark mode you could not see the borders of the cards.
This post is the record of that. The interesting part is not "the AI made a mistake" — that is boring. It is that the mistake reached me through the agent's own verification step. The rule that falls out of it is what actually makes delegation useful.
What I handed over
The MCALAB site is a warm, heavy-bordered design with hard offset shadows. In light mode, two things tell you where a card ends: a 2px border and a solid shadow dropped beneath it.
That was the brief: build the dark theme tokens, verify contrast. The agent worked in its own context window. I did not watch it step by step.
The report was good, and that was the problem
What came back read like a professional's report: text-on-background pairs enumerated one by one, ratios computed, one failing pair caught and refreshed, whole list confirmed passing.
Reading it, I relaxed. That is where I went wrong. What the report was actually telling me was this: the unit of counting was the text/background pair. Nothing that wasn't text ever entered the count.
Then I measured the borders
Dark mode quietly kills shadows. A black shadow is invisible on a dark ground, so we had shifted the shadow color to something lighter than the background (#46352A). I measured it: 1.62:1 against the page. In dark mode the only thing drawing a card's boundary is the border. The shadow is decoration.
The border token the agent left behind was #6B5343. I computed it against all eight dark surfaces this site actually draws borders on — and put my own fix next to it:
| Surface | Color | Agent #6B5343 | My fix #7B5F4D | Final #92715C |
|---|---|---|---|---|
| Page background | #15100C | 2.65 | 3.23 | 4.26 |
| Card | #20170F | 2.47 | 3.01 | 3.98 |
| Secondary ground | #241A13 | 2.39 | 2.91 | 3.85 |
| Product panel | #2A1F18 | 2.25 | 2.74 | 3.62 |
| Info box | #20264A | 2.05 | 2.49 | 3.30 |
| Support box | #3B241A | 2.03 | 2.47 | 3.26 |
| Trust badge | #143221 | 1.95 | 2.38 | 3.14 |
| Highlight strip | #3A2E12 | 1.86 | 2.27 | 3.00 |
| Below 3:1 | 8 / 8 | 6 / 8 | 0 / 8 |
Threshold is 3:1. The agent's value failed on all eight surfaces, worst case 1.86.
Now look at the third column, because that is the uncomfortable part. #7B5F4D was my fix. I caught the agent's mistake, sat down, did the arithmetic, lightened the color, and called it done. It still failed on six surfaces out of eight.
Why? Because I checked two surfaces: the page background and the card. Both passed — 3.23 and 3.01 — so I assumed the rest did too. I never accounted for the dark counterparts of the pastel boxes.
So while assembling the entire argument of this post, I made the same mistake as the agent I was auditing, one level up. The agent built a frame called "text" and worked flawlessly inside it; I built a frame called "page and card" and worked flawlessly inside that. I only reached #92715C after listing all eight surfaces one by one.
The sneakiest row is the top one, and that is exactly why: on the plain page background both wrong values pass. If I had spot-checked this — opened one card and looked at its border — I would probably have landed on a card sitting on the plain ground, and it would have looked fine. The failure only showed up on the colored surfaces.
The final value clears all eight. But let me be honest about it: the last one lands on 3.00. That passes by the width of a rounding. I can't write that up as comfortable headroom.
There are two criteria, and the agent knew one
Contrast in the accessibility guidelines is not one rule, it is two:
- SC 1.4.3 Contrast (Minimum) — for text: 4.5:1 normally, 3:1 for large text.
- SC 1.4.11 Non-text Contrast — for non-text: 3:1. It covers user interface components and meaningful graphics, and where a border is what indicates a component is there, that border has to meet the threshold.
The agent knew the first one and applied it flawlessly. The second never occurred to it. It did not work badly. It worked perfectly inside an incomplete frame. I knew both of them and still failed to check enough surfaces — so a frame error is not a knowledge gap, it is a question of where your attention is bounded.
Self-verification does not widen the frame
The agent double-checking itself is good behavior, and it genuinely caught a real error. But self-verification validates the inside of the frame, not the frame itself. Asking the same question twice does not surface the question you never asked.
And this is not specific to agents. I "verified" my own fix too — measured two surfaces, both passed, closed the tab. Being the auditor does not protect you from a framing error; it just moves the frame up one level.
There is a second-order harm too. A report that has survived self-verification arrives confident and numeric. "N pairs checked, all pass" is what made me drop my guard. A vague report ("looks fine to me") would have made me suspicious. A precise report on the wrong axis is the most dangerous artifact an agent can hand you.
What I do now
The rule: don't audit the work, audit the frame. The good news is the frame isn't hidden — it sits inside the report's own numbers. When a report tells you what it counted, it is simultaneously telling you what it did not count. The information in "40 text/background pairs" is not the 40, it is the text/background. Find the unit of counting, then ask what falls outside it.
I have turned that into three habits:
- I ask "what did you not check?" This is the single highest-value line I have. An agent won't spontaneously ask the question it didn't ask, but it answers that one surprisingly well. I put it to the same agent afterwards and non-text contrast came out second on its own list.
- I name the axis in the acceptance criteria. Not "verify contrast" but "1.4.3 for text and 1.4.11 for non-text". If you don't name the axis, the agent picks one for you and doesn't mention that it picked.
- I ask for the count on the inputs, not the results. Not "how many pairs passed" but "list every surface this token is drawn against". A short input list is visible to the eye. A short result list isn't.
What didn't work
So this doesn't read as an advertisement, here is the other half.
The agent never saw the page. The browser extension couldn't inject a script into the local dev server, so no screenshot. It reasoned about the colors purely as numbers and never once looked. With eyes on the page it would probably have spotted a card with no visible edge. A setup limitation rather than a model one — but the outcome is identical.
Delegation is not free. Claude Code's subagent docs state that subagents run in isolated context windows and return summaries to the main conversation, and list conversation history and previous tool calls in the main session among the things a subagent does not see. The same page notes that subagents can spawn their own (three levels deep by default) and that in that case only the top-level summary returns to the main conversation.
That is the mechanism behind what happened to me. You don't see the agent's tool output, you see its summary — written from inside the agent's frame. What you buy is a clean context. What you pay is visibility.
"Have a second agent review it" would not have saved me. A second agent told to "verify the contrast" would have looked from the same place — as it happens, I was the reviewer, and I did. A framing error doesn't get corrected by duplication, it gets copied. The reviewer has to stand in a different frame: not "check the contrast" but "what visual information disappears under this palette?"
The part you can't delegate
I'm not hiding the AI involvement: the dark theme on this site, the blog compiler, and the first draft of this post were all done with AI. The 24 ratios in the table above I computed myself and read off one by one — because the entire claim of this post is about what it costs to trust an unaudited report. Fittingly, the first draft of this post stated that the agent's border color was #7B5F4D. It wasn't; that was my own fix. I caught it by measuring.
The real cost of delegating isn't the work — the agent does that, and does it well. The cost is looking at a clean, confident summary and seeing which question was never asked. That part is still yours.
Advertise on this blog, or work with us
MCALAB is an independent studio. For sponsorship, cross-promotion or a partnership:
ads@mcalab.com.trDetails: Advertise & partner. For user support, see the support page.