When you drop an AI agent into an unfamiliar codebase, the obvious move is to point it at the code. That is where the logic lives, so that is where understanding should start. It feels right, and it is half wrong.

Code answers one question well: what does this system do right now. It is silent on a different and more important question: what is this system supposed to do. Those are not the same thing. Code contains bugs, dead branches, workarounds, and decisions nobody would make again. Read it as the source of truth and you learn the current behavior faithfully, including the parts that are mistakes. An agent that grounds itself in the code alone will reproduce your bugs with perfect fidelity, because it cannot tell which lines are intent and which are accident.

The place intent actually lives, in a form a machine can read and check, is the tests.

Tests encode intent; code only encodes behavior

A good test is a claim about what the system should do, written down and made executable. it("refunds the full amount when the order is cancelled within 24 hours") tells you something the implementation never states outright: that this rule exists, that the 24 hour window matters, that a full refund is the expected outcome. The code enforces the rule. The test explains that the rule was intended.

This is why tests as ground truth is a more reliable starting point than the implementation. When behavior and tests agree, you have learned the intended behavior, confirmed. When they disagree, you have found either a bug or a stale test, which is exactly the kind of thing worth knowing early rather than discovering after an agent has confidently built on top of it.

Tests are an executable spec

Requirements documents rot the moment they are written. Comments drift. Wikis go stale. Tests are the one form of specification that fails loudly when it stops matching reality, because CI runs them. That property, tests as spec, is what makes them uniquely valuable to an agent.

A prose spec says "the export should handle large files." A test says "a 2 GB export completes without loading the whole file into memory," and it either passes or it does not. The agent does not have to interpret intent from ambiguous language. It has a concrete, checkable definition of done. This is the same reason test-driven AI development tends to produce more reliable results than freeform generation: the target is unambiguous, and the agent can check its own work against it instead of declaring victory on vibes.

What reading tests first actually buys an agent

Point an agent at the test suite before the implementation and several things get easier at once.

A verifiable definition of done. The agent knows what "correct" means for this change, because the tests spell it out. It can run them, see red, make them green, and have earned confidence rather than assumed it.

Real usage examples. Tests call the code the way it is meant to be called. They show the agent the intended entry points, the expected inputs, and the shapes that come back, which is often clearer than reading the implementation and inferring the contract.

The edge cases someone already cared about. A test for the empty list, the expired token, the concurrent write, is a record of a failure mode a human hit and decided to guard against. That is institutional memory the agent gets for free, and would not reconstruct from the happy-path code alone.

Reading tests first is the natural companion to writing acceptance criteria an agent can actually test against: the acceptance criteria define the intent for new work, and the existing tests define the intent for everything already built. Both point the agent at what should be true, not just what happens to be.

When the tests are thin

Here is the honest complication for real, brownfield codebases: the tests are often weak. Low coverage, happy-path only, or a suite everyone stopped trusting years ago. If that is your situation, reading tests first does not magically produce intent that was never written down.

But it still helps, in two ways. First, it tells you where the intent is documented and where it is not, which is itself a map of risk. The well-tested modules are safe to change with confidence; the untested ones need a human to supply the intent before an agent touches them. Second, it turns "improve reliability" into a concrete backlog: the gaps you find are exactly the places worth adding a test before the next change, so the ground truth exists next time. Thin tests are not a reason to skip reading them. They are a reason to read them and notice what is missing.

The honest limitation

Tests are the best available proxy for intent. They are not intent itself, and treating them as infallible is its own failure mode.

Tests can be wrong. A test can assert buggy behavior, in which case "make the tests pass" faithfully preserves the bug. Tests can be stale, asserting a rule that no longer holds. They can be over-fit, locking in an implementation detail so tightly that any reasonable refactor breaks them for no good reason. And a green suite proves only that the tested cases pass, never that the untested cases are correct. Coverage gaps are invisible to an agent that trusts the suite completely.

There is also the case a test cannot settle: the genuinely new feature, whose intent does not exist in any test yet because it has never been built. There, tests give you the surrounding constraints but not the answer, and something (or someone) has to supply the missing intent. Knowing the difference between "the tests do not say" and "the tests say no" matters, which is the whole point of treating a blocked task as different from a failed one.

So the rule is not "trust the tests." It is "read the tests first, believe them provisionally, and flag the disagreements instead of silently resolving them."

Where this lands

An agent that reads code first learns your system as it is, bugs included. An agent that reads tests first learns your system as it was meant to be, and can tell the two apart. For anything that ships to production, the second is the grounding you want.

This is one of the principles behind making an AI coding agent reliable on a real codebase. Loopsfinity has its agents treat the acceptance criteria and existing tests as the definition of done, so a change is measured against intent rather than against the model's own confidence, with a human still accountable for the parts the tests do not cover. The mechanism is ours. The principle, read intent before implementation, is worth adopting whatever you build with.