JohnnyCode.ai Blog

The Adversarial Audit

Why every agentic workflow needs a second agent whose only job is to break the first one’s work.

Published

Illustration for The Adversarial Audit

Every developer who has worked with agentic AI for more than a week has seen this pattern. You ask Claude Code to implement a feature. It runs for ten minutes, produces files, commits changes, and declares the work complete. You check the branch. The code compiles. The tests pass. Then you actually run the thing and discover that half the requirements were silently skipped.

An agent in the middle of an implementation is a terrible judge of whether the implementation is done.

This is where adversarial agents come in.

The Pattern

An adversarial agent is an agent whose only job is to find fault with what another agent has produced. It has no stake in the implementation. It did not write the code. It does not know how hard the problem was, how many times the first agent refactored, or which shortcuts felt unavoidable. It only knows the spec and the result, and it has been told to break the result against the spec until it cannot break it anymore.

In practice, this looks like a second Claude session with a prompt that reads something like: “Here is the original requirement. Here is the diff. Your job is to find every way this implementation fails to meet the requirement. Be specific. Cite file and line. Do not be polite.”

The output is a list of gaps, regressions, half-implementations, and untested paths. Some of it will be wrong. Most of it will be embarrassingly correct.

Why It Works

The first agent and the adversarial agent are the same model. Same weights, same training, same capability. So why does the second one catch what the first missed?

Context contamination. When an agent has been working on a problem, its context window is full of the reasoning it used to justify every decision. By the time it reaches the end, it has convinced itself that those choices were necessary. Introduce a fresh context with only the spec and the output, and the model suddenly sees things the implementer could not see.

This mirrors how human code review works, with one advantage. Humans get tired and miss things after the third pull request of the day. Adversarial agents stay sharp through the tenth, the hundredth, and every one after that.

Three Places to Deploy It

I use this pattern in three distinct layers of my workflow.

Spec conformance. After a coding agent finishes a task, a second agent reads the original ticket and the resulting diff. Its only question is whether the diff actually satisfies the ticket. This catches the most common failure mode in agentic coding, which is an agent that completes eighty percent of a task and confidently declares victory.

Security and abuse surface. After a feature is built, an adversarial agent gets the code and a prompt asking it to think like an attacker. What inputs would break this? What assumptions about the caller are unstated? What happens if the user is malicious? This is cheap, it is fast, and it catches classes of bugs that normal testing never touches.

Documentation truth. When an agent writes documentation for a feature, another agent reads the documentation and the code and asks whether the documentation describes reality. Agents are fluent writers of plausible documentation that describes behavior that does not exist.

The Prompting Shape

The adversarial prompt has a specific shape that outperforms a generic “review this”:

  1. State the spec or requirement verbatim.
  2. Provide the artifact under review with no commentary from the implementer.
  3. Give the adversarial agent a named role that frames the task (”You are a staff engineer doing a final review before merge,” or “You are a penetration tester with thirty minutes to find issues”).
  4. Demand specificity. File, line, reproduction steps, expected versus actual behavior.
  5. Tell it that polite language is not required and soft findings will be ignored.

Without item four, adversarial agents produce vague suggestions that cannot be acted on. Without item five, they apologize their way around real issues.

What It Does Not Fix

An adversarial agent works as a filter. It catches a class of failures that would otherwise reach production, and it catches them quickly enough that iteration stays fast. Tests still matter. Human judgment still matters. Understanding the problem yourself still matters.

There are also failure modes unique to the pattern. An adversarial agent run against the same model that produced the output will share some blind spots with the implementer. Both will fail on problems that require knowledge the model does not have. If your primary agent cannot reason about concurrency correctly, your adversarial agent probably cannot either.

The honest mitigation is to use a stronger model for adversarial review when the stakes justify it, or to orient the adversarial prompt toward empirical verification: run the code, check the output, compare against the spec. Empirical checks are harder for a model to hallucinate past than logical arguments.

The Larger Pattern

Adversarial audits are one instance of a broader pattern that shows up repeatedly in agent architecture. The pattern is role separation. A single agent wearing multiple hats gives the worst of each. Split the hats across agents with clean contexts and narrow mandates, and the quality of the overall system goes up sharply.

This is why code review exists. It is why auditors cannot be employees of the firm they audit. It is why scientific peer review is double-blind. Whenever you want a judgment to be useful, you separate the judge from the party whose work is being judged.

We are rebuilding these conventions inside agent systems, one failure at a time. The adversarial audit is one of the cheaper and more immediately useful ones.

Practical Next Step

If you are running agentic coding workflows and you do not already have an adversarial pass, add one. It does not need to be elaborate. A second Claude session, a prompt that pastes the original request and the resulting diff, an instruction to find every way it falls short. Run it before you merge.

You will be surprised, a few times a week, by what it catches. After a while you will stop being surprised, and you will start writing less careful code because you know the next layer will catch it. That is a separate problem. It is also a good one to have.

First published April 19, 2026 on 42 Insights.

← All posts