Most teams treat error responses as diagnostics. An agent does not. It reads the error, classifies it, and picks the next action: retry, fix the request, escalate, or abandon. The error body is therefore the control-flow input for the retry loop, and every field the agent touches becomes an interface it depends on.
The general principle is well established in API design: an error should carry an application-specific code and a message so that software can decide what to do next without parsing prose the Speakeasy error guide. The same guide stresses that errors should help computers act, which is exactly why the shape of those fields matters. MCP tool contracts make the point explicitly: a tool is a contract that includes its error behavior and result structure, and a change to either can break an agent even when the server code still compiles contract tests for MCP tools.
The AdCP error specification shows what a mature version looks like. Level 1 is code plus message so agents can match codes to classify failures. Level 2 adds recovery, plus optional retry_after, field, and suggestion, so agents can auto-retry transient errors and self-correct correctable ones AdCP error handling. The moment you ship Level 2, those hint fields are load-bearing. An agent that reads recovery to decide whether to retry has a dependency on a field that did not exist in the previous version, and the compatibility question flips direction: it is now the older agents that need protection.
There is a second, quieter reason the contract matters. A schema mismatch inside a tool call surfaces as an exception, and most retry libraries default to retrying on any exception, because the alternative is enumerating every recoverable class forever. A parse failure is not transient, but the retry layer cannot tell it apart from a network blip, so it spends its attempts proving the same thing the silent contract drift write-up. The visible symptom is a retry budget that stays green while the success rate on that path sits at zero.



