I ended the last post with a question: what happens when the implementation layer can reason?
The contract gets thinner.
Think about a notification capability. A traditional interface needs you to spell everything out: send_notification(title: str, body: str, priority: int, format: str). Four parameters, all required, because the thing on the other end is a function that maps inputs to outputs with zero interpretation. You hand it a priority of 3 and it has no idea whether that means "urgent" or "low" without a spec telling it so. The contract must be exhaustive because the implementation can't bridge any gaps.
Now put a reasoning engine behind that interface. The contract becomes: "Alert the user with a message. Delivery must succeed or return explicit failure." One input string. The provider — backed by AI — derives the email subject, body, and priority from that single string. It reads "server is on fire, page the oncall" and knows that's urgent. It reads "weekly digest ready" and knows that's not.
That's not hand-waving. That's a structural dependency on a specific kind of implementation.
I want to be careful here, because the history I walked through in post 1 might sound like a list of mistakes. It wasn't. HTTP's verbose RFCs were the right call. Terraform writing a separate provider schema for every cloud service was the right call. Kubernetes CRDs specifying every single field of a custom resource — right call. These systems were built for dumb implementations. I mean that technically, not dismissively. The code reading those contracts couldn't infer anything. It parsed a spec and followed instructions. So the spec had to leave zero ambiguity.
The tradeoff was real: completeness buys correctness, but it costs you rigidity.
Every new Terraform provider is a massive spec compliance effort. Every new Kubernetes operator starts with hundreds of lines of type definitions before it does anything useful. Every HTTP extension goes through years of draft RFCs. The ecosystem friction is enormous. But the alternative — ambiguous contracts with dumb implementations — gives you silent failures and undefined behavior. So you eat the friction. You write the spec. You were right to.
The constraints just changed.
Here's the thing I keep coming back to: every provider in this kind of system runs inside an AI coding agent. There's no execution path that doesn't pass through a reasoning engine. That's not a feature you can toggle off. It's not an optimization. It's a structural fact about the runtime, and it enables a different contract shape entirely.
I've been calling these "semantic contracts." The contract describes behavior, not method signatures. Inputs and outputs, yes. Determinism guarantees, yes. But not parameter lists. Not type schemas for every field. The contract says what should happen and what success looks like. The provider figures out how.
This needs a concrete example.
Traditional contract for notifications: title is a string, max 120 characters. Body is a string, supports markdown subset. Priority is an integer 1-5 where 1 is lowest. Format is an enum of "email", "sms", "push". You need all four. Miss one, get an error. Want to add a sixth format? Version bump the contract, update every consumer, update every provider.
Semantic contract for the same capability: "Alert the user with a message. Delivery must succeed or return explicit failure." That's the mandatory part. Then there's a hints registry — a separate document listing suggested keys like urgency, url, source. Providers can read hints or ignore them. Consumers can send hints or skip them. The hints registry works like HTTP's header registries: a coordination mechanism, not a mandate.
I think of it as send_notification(message, hints={}). Message is required. Hints is an optional dict. That's the whole interface.
The obvious objection: where do you draw the line? If the provider can "figure it out," what stops the contract from being empty?
Determinism. That's the boundary.
"Did the thing happen?" must be deterministic code. The notification must send. Every time. That's not up to interpretation — it's a hard pass/fail checked by conventional code. "How did it look?" can vary. How the email subject gets formatted from the message string is non-deterministic, and that's acceptable variation. One provider might write "Alert: server is on fire" as the subject. Another might write "Urgent notification from deploy-monitor." Both are fine. Both delivered the notification.
I don't have a great answer for where exactly every capability draws this line. I think it's something you discover per-capability. But the principle is clear: outcomes are deterministic, presentation is not.
There's an evolution model here that I find compelling.
You start thin. Ship the minimal contract — message string, success/failure return. Watch what happens. Maybe every consumer starts sending an urgency hint. Maybe every provider starts parsing it. That hint just proved itself. Promote it to the core contract in a version bump. Now urgency is required and typed.
This is the same mechanism that turned HTTP headers into standards. X-Forwarded-For started as a convention, became universal, got promoted to a spec. The difference: you can start from a much thinner baseline because AI covers the gap while you're waiting for patterns to emerge. You don't need to guess which parameters matter on day one. You ship and observe.
I keep thinking about what this means for ecosystem friction. A new provider for a traditional plugin system means months of spec compliance work. A new provider for a semantic contract means: implement the behavior described in one paragraph, handle the hints you understand, ignore the ones you don't. The barrier to entry drops by an order of magnitude.
And the contracts still mean something. They're not vague wishlists. "Delivery must succeed or return explicit failure" is a testable statement. You can write a conformance test for it. The contract is thin, not empty.
I realize I'm describing a system that only works under a very specific condition: the provider must have a reasoning engine. Take that away and you're back to needing exhaustive specs. This isn't a general-purpose pattern. It's a pattern for a world where AI is in the execution path — not as an optional accelerator, but as a load-bearing dependency.
That's a strong assumption. I'm comfortable with it because I'm building for that world specifically.
There's a class of problem this handles beautifully. I've been calling them "delegated" capabilities: the consumer hands off a payload, the provider handles everything, the consumer gets back a result. Notifications, search, summarization, translation — anything where the consumer says "do this thing" and walks away.
But some capabilities aren't like that. Some capabilities are environmental. The consumer's logic runs inside the provider's execution context. A cron scheduling provider runs your code on its own infrastructure. A remote execution provider gives you a shell — but it's their shell, with their filesystem, their network constraints, their installed tools.
The provider's environment leaks into the contract. A consumer that needs browser automation can't run inside a headless server provider. A consumer that writes to /tmp can't run inside a read-only sandbox. The contract needs to describe not just behavior but where the behavior runs.
How thin can a contract be when it needs to encode environmental constraints? I'll get into that next.