The Contract Test Is the Only Witness the Agent Cannot Author

A test the agent wrote against code the same agent wrote shares the agent's blind spot: a misunderstanding in the implementation becomes a matching misunderstanding in the test, the bar goes green, and the bug ships certified. Consumer-driven contract tests are the only category where a second team publishes the assertion the first team has to satisfy. That separation of authorship is exactly what tamper-resistant test design demanded, applied at the integration seam.

By Travis Frisinger · August 24, 2026 · 9 min read
TDDAI AgentsContract TestingTest Design

Related reading: The Test Pyramid Was an Economic Argument named seams as where truth hides; this post pins the mechanism. Tamper-Resistant Test Design Is What the Suite Now Owes the Codebase is the design-property companion; this post is the integration-boundary application. Your Test Suite Is Your API for Agents sets up the framing.

The agent renamed reservationId to bookingId in the warehouse client and every unit test stayed green.

The unit tests stayed green because the agent moved both sides of the wire in the same commit. The client sent bookingId. The mock warehouse in the unit suite received bookingId. The assertion checked that the mock received bookingId. The bar was green. The build shipped. The real warehouse, running in production against the same request, rejected the message because its API contract still specified reservationId. Every order placed for the next four hours failed. The rollback took ninety minutes. The post-mortem asked why the unit suite had not caught this.

The unit suite had not caught it because the unit suite was a mirror. The agent wrote the implementation. The agent wrote the mock. The agent wrote the assertion. Same author on all three sides of the transaction. Nothing in that arrangement can verify that the wire format agrees with the counterparty, because the counterparty is not part of the arrangement. A test written by the same optimizer that wrote the code shares the optimizer’s blind spot. When the blind spot is a renamed field on a service boundary, the test certifies the rename as correct. The green bar and the shipped bug are the same event, viewed from two sides.

A Test the Agent Wrote Against Code the Same Agent Wrote Is a Mirror

Same training distribution on both sides. Same priors about what a “reservation” field is called. Same tendency to normalize a name that looks awkward. Same instinct to make the code and the test agree with each other rather than with an external contract nobody in the current context is representing.

That is the structural failure. A unit test is a check on the implementation, and a check requires an authoring separation. When the author of the check is the author of the thing being checked, and neither has an independent line of sight to the external truth, the check reduces to an internal-consistency assertion. Internal consistency is a valuable property. It is not correctness. A pair of tautologies is internally consistent. So is a bug and the test that certified it.

The failure mode has a specific shape. A test the same agent wrote passes because both artifacts express the same assumption. The assumption might be right, in which case the test is redundant with the type system. The assumption might be wrong, in which case the test is worse than useless: it produces a green bar that the reviewer takes as verification, when in fact it is verification of an assumption whose truth was never checked against the world.

Two mirrors always agree. That is not verification. That is geometry.

The Seam Is the Place Where a Second Author Can Live

Two teams, two agents, two independent understandings of what the interface means. That gap is where truth about the integration actually lives.

The seam is a boundary between two systems with different owners. The client team owns the code that calls. The provider team owns the code that answers. Neither owns the interface between them; the interface belongs to both, and belongs to neither. A change on either side that breaks the interface breaks the pair. The interface is the object of the verification, and the two authoring contexts are what make the verification possible.

Before agents, the seam was already the place with the highest signal-per-test in the suite. Integration tests caught the bugs unit tests missed because the integration test crossed a boundary a single author could not lie across. That property was ambient rather than named; teams knew integration tests were valuable, but the reason was often framed as “they exercise more of the system.” The real reason was that the integration test crossed an authoring seam, and the crossing was what made the check meaningful.

The agent era makes the naming explicit. When both sides of a seam are agent-authored by the same session, the seam degenerates: two mirrors facing each other instead of two independent witnesses. When the two sides are authored by different agents in different contexts, or by different teams, the seam is restored. What matters is not the humanity of the author. What matters is the separation.

Consumer-Driven Contracts Codify the Gap

The consumer publishes the contract it needs. The provider verifies. Neither side authors both.

That is the mechanism, and it has been running at industrial scale in service-oriented architectures for over a decade. The consumer service authors a pact: a document describing the requests it makes and the responses it expects. The provider team pulls the pact into their build, runs their code against it, and reports whether the code can satisfy the requests as specified. The pact is versioned in a repository the consumer owns. The provider cannot edit it. If the provider changes the response shape, the pact fails. If the consumer changes what it needs, the consumer updates the pact and the provider’s build fails on the next run.

// Consumer side (published pact)
[Fact]
public void Warehouse_reservation_response_contains_reservation_id_and_estimated_ship_date()
{
    var expected = new WarehouseReservationResponse
    {
        reservationId = "resv-123",
        estimatedShipDate = someFutureDate()
    };

    pactBuilder
        .UponReceiving("a warehouse reservation request")
        .WithRequest(HttpMethod.Post, "/reservations")
        .WillRespondWith(200, expected);
}

// Provider side (verifies the pact against the running service)
[Fact]
public async Task Warehouse_service_satisfies_the_published_consumer_pact()
{
    var results = await pactVerifier
        .ServiceProvider("warehouse", warehouseUnderTest)
        .PactBroker(brokerUri)
        .VerifyAsync();

    results.Failed.Should().BeEmpty();
}

Neither side of that pair can pass on its own. The consumer’s pact is stored on infrastructure the provider does not write to. The provider’s verification runs on infrastructure the consumer does not write to. A coding agent working on either side can edit the code on its side but cannot rewrite the contract on the other side, because the contract is not in its writable tree. The authoring separation is enforced structurally, not through policy. That is why it holds.

Decades of separation of duties encoded in ten lines of pipeline configuration. The contract-testing category built the primitive before the era needed it. The era needs it now.

This Is Tamper-Resistant Test Design Applied to the Seam

The tamper-resistant test design argument named the general principle: separate the assertion authority from the code authority. Held-out partitions, hidden invariants, verifiers on infrastructure the agent cannot control: all applications of the same idea at the level of individual tests.

The contract test is the industrial-scale form of it, applied at the module or service boundary. The assertion authority is the consumer team. The code under test is the provider team’s. Neither has write access to the other’s tree. The verification runs on infrastructure both agree to and neither controls unilaterally. The design property “the writer cannot rewrite the checker” is enforced by repository boundaries and pipeline configuration, not by trust or policy.

The parallel corrects a common misreading. Contract tests get introduced as a distributed-systems technique for microservices, valuable in that setting and optional otherwise. The tamper-resistance framing sharpens the claim: contract tests are the general primitive for any interface where the assumption of “the same author will honor the interface” no longer holds. Microservices were where the assumption broke first. Agent-authored code is where it breaks everywhere.

The Failure Mode Contract Tests Catch Is the Failure Mode Agents Produce Fastest

An agent that “cleans up” a response shape, renames a field, or changes the meaning of a status code will ship silently past a unit suite the agent controls.

The reservationId example at the top is a real class of incident. It recurs at every team that runs agent-paired code without a contract-level check on the seams. The agent’s incentive gradient points at consistency: the field name reads more naturally as bookingId, so the agent renames it, updates the client, updates the mock, updates the assertion, and reports “all tests pass.” The mock does not know it is supposed to be simulating the real warehouse. The real warehouse is not in the loop.

A contract the consumer team owns fails the moment the change lands. The pact is a versioned document stored outside the writable tree of both agents. Any wire-format change on either side that does not first update the pact triggers a build failure at the verify stage. The change cannot merge without either updating the pact (which requires a conversation with the counterparty) or reverting the field-shape change. The check runs at build time, not deploy time: a contract failure at deploy time is a rollback, a contract failure at build time is a red bar the agent has to fix before merge. Ten lines of pipeline configuration is the difference.

Contract Testing Is Not a Distributed-Systems Practice Anymore

Any interface between two modules with different owners qualifies. Frontend and backend. Two bounded contexts in the same repo. A public SDK and its consumers. Anywhere the assumption of “the same author will honor the interface” no longer holds.

In the human era, “different owners” almost always meant “different teams on different services,” so contract testing was pitched as a microservices practice. In the agent era, it means “any authoring context whose priors are not shared with the other side.” A much larger set. The frontend team and the backend team, working in the same monorepo, become two authoring contexts the moment their code is written by different sessions. Two bounded contexts inside the same service are two authoring contexts. A shared library and its consumers are two authoring contexts.

Where the seam is, a contract belongs. Frontend-to-backend calls used to be verified by end-to-end tests running in a browser harness, which caught contract breaks eventually and slowly. A pact catches the same break at build time and identifies the specific field that moved. The team running contract tests only at microservice boundaries is running the play from the previous era. The team running them at every seam where authorship separates is running the play the current era requires.

The Green Bar Only Means Something When the Assertion’s Author Has Skin in the Game

Two mirrors will always agree. A witness with independent stakes will not.

That is the closing observation and the whole reason contract tests are load-bearing now. A unit test written by the code’s author is a check on internal consistency. A contract test authored by the counterparty is a check on the interface’s fitness for the counterparty’s purposes. The two are not the same category of test. Both should exist. Only one of them tells the truth about whether the seam holds.

The green bar the agent produces on a suite the agent authored is evidence of internal consistency. It is not evidence of correctness at the seam. The team that treats the two as interchangeable ships the renamed field on Thursday and rolls back on Friday morning. The team that separates them (unit tests for local behavior, contract tests for the seam) ships neither the internal inconsistency nor the seam-level break. Both classes of bug get caught by the test category built to catch them.

The agent renamed reservationId to bookingId in the warehouse client and every unit test stayed green. That was the opening. It is also the shape of the era, because unit tests written by the same author as the code will always stay green through a rename that both sides moved with. The witness that catches that class of failure is a contract, published by the counterparty, verified on infrastructure the coding agent does not write to.

Two mirrors always agree. A witness with independent stakes does not.