@RestController

public class OrderController {

    @PostMapping("/orders")

    public Order createOrder(@RequestBody Order order) {

        return orderService.create(order);

    }

}

Five lines. Spring "abstracts away" JSON deserialization, transaction management, connection pooling, thread handling. You don't need to think about any of that.

Until the first production incident. Then you need to know Jackson's null handling, @Transactional propagation levels, HikariCP timeout behavior, and GC pause characteristics. Every "abstracted" layer becomes something you must understand.

The Paradox

Path A: You understand what's behind it
The abstraction is just an API over knowledge you already carry. Nothing was actually hidden.

Path B: You don't understand what's behind it
You can't debug failures that cross the boundary. Code works in demos, breaks in production.

There is no Path C where you productively ignore the abstraction and everything works. Spolsky called this the Law of Leaky Abstractions. The paradox goes further: even when the abstraction doesn't leak, you still need to understand it to use it well.

For Agents, It's Worse

An LLM already knows Spring, Jackson, HikariCP. Standard abstractions are free. But your abstractions don't exist in the weights:

// In the training data — agent knows exactly what this does

@Transactional

public Order createOrder(Order order) { ... }



// NOT in the training data — agent will hallucinate

orderPipeline.execute(order, PipelineMode.ASYNC_WITH_ROLLBACK);

Your custom service layer, your internal SDK, your domain patterns. If they're not in the context window, they don't exist for the agent. Hiding them behind a vague description is the worst of both worlds: the agent can't fall back on training knowledge, and you've removed the only source of truth.

This is why the Context Matrix works the way it does. Spec plus architecture equals implementation. You don't get to skip one side:

Spec alone (no architecture)
"Build a cart service with checkout" — Agent invents its own auth model, state strategy, payment flow.

Architecture alone (no spec)
"We use OAuth2, Redis, Stripe" — Agent has no idea what to build.

Spec + Architecture
"Cart service with checkout. OAuth2+JWT auth, Redis sessions, Stripe tokenized payments, saga pattern." — Agent produces a correct implementation.

Abstracting either side away doesn't simplify the problem. It hides the information needed to solve it.

Abstraction doesn't reduce complexity. It relocates it. From "things you deal with now" to "things that ambush you later." For humans and agents alike, the total complexity is conserved.