Your Internal API Became a Public API the Day an Agent Called It
Internal APIs survive on a quiet arrangement: nobody writes the contract down because everybody already knows it. The fields that happen to be there, the error you throw that a caller secretly parses, the endpoint that returns 200 with an empty list instead of 404 — these are load-bearing behaviors held together by the fact that you can name every caller and Slack them before you change anything. That arrangement works right up until it doesn't.
It stops working the day you wire an agent to that API. Not because the agent is malicious or careless, but because the agent is a caller you cannot reach. It has no Slack handle. It did not read your migration note. It depends on response shapes it absorbed from an example payload or a schema snapshot, and it will keep depending on them long after you've moved on.
The uncomfortable truth is that "internal" was never a property of the API. It was a property of the caller list. Shorten that list to people you know and the API is internal; add one participant you can't coordinate with and the API is public — with all the discipline that word implies, and none of the infrastructure you'd have built if you'd known.
Hyrum's Law Was Always True — The Agent Just Made It Visible
Hyrum's Law states that with enough users, every observable behavior of your system will be depended on by somebody, regardless of what the contract promises. Most internal teams quietly violate this and get away with it, because their user count is small and reachable. You change a field name, the build breaks, someone fixes it that afternoon. The dependency was real, but the feedback loop was fast enough that it never felt like a contract.
An agent caller breaks that loop in two ways at once. First, it widens the set of observable behaviors that get depended on. A human integrator reads your docs and uses the three fields the docs describe. An agent ingests the entire response and may key its next decision off any of it — the ordering of an array, the presence of a nullable field, the exact wording of a status string. Behaviors you never considered part of the interface are now part of the interface.
Second, it removes the fast feedback. When a human integration breaks, something throws, a test goes red, a pager fires. When an agent integration breaks, the agent often does not crash. It does something worse: it adapts. It sees a response that no longer matches its expectation and it improvises — retries with different arguments, picks a different tool, or hallucinates a plausible path forward. The API change you shipped does not produce an error. It produces a slow, silent degradation in the quality of everything downstream of that agent, and no stack trace points back to your commit.
That is the core hazard. You did not just gain a new caller. You gained a caller that converts your breaking changes from loud failures into quiet ones.
The Caller You Cannot Reach Changes the Economics of Every Change
Think about what coordination actually buys you on an internal API. It lets you make breaking changes cheaply. You can rename a field, tighten a type, or drop an endpoint, because the cost of doing so is one message and one afternoon of someone else's time. The informal contract is fine precisely because renegotiating it is fine.
Remove the ability to coordinate and the math inverts. Every breaking change now carries an unbounded, undiagnosable cost, because you cannot enumerate who depends on the behavior and you cannot tell them in advance. The agent's dependency on your response shape was set when it last saw your schema — possibly weeks ago, possibly in a cached tool definition the agent has not refreshed since. LLM clients cache tool and schema definitions aggressively; even after your server updates, an agent may keep sending arguments that match the old contract until something forces a re-fetch.
This is why an agent caller imposes public-API discipline on a service that never earned it. Not because anyone decided the API was now public, but because the cheap-coordination assumption that justified skipping that discipline is gone. The disciplines you now need are the ones public APIs have always needed:
- Explicit contracts. The behavior an agent depends on must be the behavior you wrote down, not the behavior that happened to be there. If it is not in the schema, it is not promised — and you need a way to detect when an agent is depending on something unpromised.
- Versioning. A breaking change must be a new version, not a mutation of the existing one. Old callers keep hitting the old shape until they migrate.
- Deprecation windows. "We changed it" is not an event an agent can respond to. "This is deprecated, here is the replacement, it disappears in N months" is a window long enough for a migration you do not control to happen.
- Stable error semantics. An agent reasons about failure from the error you return. If your 429 sometimes arrives as a 500, or your "not found" sometimes arrives as an empty 200, the agent cannot build a reliable policy on top of it.
None of this is new. It is the standard public-API playbook. The only new thing is that you now have to apply it to a service whose README still says "internal."
The Tool Schema Is the Contract — Treat It Like One
For an agent, the API contract is not your OpenAPI document or your tribal knowledge. It is the tool schema the agent was given: the names, descriptions, parameter types, and enum values that tell the model what it can call and how. That schema is the entire surface the agent reasons about. Which means a few things follow directly.
- https://www.hyrumslaw.com/
- https://nordicapis.com/how-llms-are-breaking-the-api-contract-and-why-that-matters/
- https://minherz.medium.com/the-silent-breakage-a-versioning-strategy-for-production-ready-mcp-tools-fbb998e3f71f
- https://nordicapis.com/the-weak-point-in-mcp-nobodys-talking-about-api-versioning/
- https://dev.to/nesquikm/my-mcp-tools-broke-silently-schema-drift-is-the-new-dependency-hell-5c49
- https://www.buildmvpfast.com/blog/idempotent-ai-agent-retry-safe-patterns-production-workflow-2026
- https://zuplo.com/learning-center/api-readiness-gap-agent-callable-apis
- https://www.truefoundry.com/blog/rate-limiting-ai-agents-preventing-llm-api-exhaustion
