An AI agent can prepare a valid tool call and still execute the wrong operation after the tool changes. A field that remains a string may switch from an internal case ID to a customer-visible reference. An optional flag may acquire a new default. A read-only lookup may begin creating an audit record or sending a notification. The JSON still validates; the contract no longer means the same thing.
The release decision is therefore larger than “does the new schema accept the old payload?” Teams need to decide whether the old planner can use the new executor, whether the new planner can fall back to the old executor, and whether a stored or approved plan remains safe to run after either side changes.
Treat each tool as three contracts—shape, meaning and authority—and version it when any one changes incompatibly. Ship in place only when old callers receive the same reasonable result and the same side-effect boundary. Otherwise expose a parallel version, migrate deliberately and keep previously planned calls bound to the contract under which they were formed.
A schema is only one layer of the contract
The Model Context Protocol tools specification gives each tool a unique name, an input schema and optionally an output schema. It requires servers to validate inputs and enforce access control, while clients should validate results and confirm sensitive operations. That separation matters: schema validation and authorisation are different controls.
| Contract layer | What must remain stable | Example of an invisible break |
|---|---|---|
| Shape | names, types, required fields, ranges, enums and result structure | case_id is renamed while old planned calls still contain it |
| Meaning | units, defaults, identifiers, error semantics and business interpretation | duration still accepts an integer but changes from minutes to seconds |
| Authority | side effects, target scope, approval requirements and commit boundary | save_draft starts notifying the customer |
JSON Schema is strong at the first layer. Its 2020-12 core specification defines how keywords such as properties, additionalProperties and unevaluatedProperties apply constraints to JSON instances. It cannot establish that a field still means the same thing or that an operation has not gained authority. Those are application contracts that need explicit tests and owners.
This three-layer model is an AIEngine implementation framework, not a new claim about JSON Schema. Use the schema to reject malformed calls, then use business validation and live authorisation at the destination as described in the five action-validation gates.
Test compatibility in four directions
Compatibility is directional. “The services deployed together” is not enough because tool lists can be cached, workers can roll back and plans can wait in queues.
| Pair to test | Question | Typical failure |
|---|---|---|
| Old planner → new executor | Does every old valid call retain its result and side-effect meaning? | A new required field rejects a queued call |
| New planner → old executor | Can rollback or regional skew still execute the new call safely? | The planner emits a new enum the old server rejects |
| Stored plan → current executor | Is the exact approved intent still executable under its original contract? | A default changed after approval |
| Current result → old consumer | Can existing parsers and workflow steps handle the response? | A new result variant falls into a dangerous catch-all branch |
Google's approved AIP-180 compatibility guidance distinguishes source, wire and semantic compatibility. It says new required request fields must not be added within a major version, old clients must retain the prior default behaviour, and renaming is effectively removal plus addition. Its most useful lesson for AI tools is semantic: a wire-compatible change can still break what a reasonable caller expects.
Stored calls add a time dimension. Protocol Buffers' official compatibility practices warn that clients and servers never update at exactly the same time, rollback remains possible, and serialized old messages may survive in logs. AI plans, approval records, retry queues and incident replays create the same persistence problem even when the live transport is JSON.
Classify the proposed change before deployment
Run every change through a producer-consumer review. The producer is the planner or upstream tool; the consumer is the executor or downstream workflow.
| Proposed change | Default classification | Safe release condition |
|---|---|---|
| Add an optional input with identical omitted behaviour | Potentially additive | Old calls produce the same outcome; rollback ignores or rejects the new field safely |
| Add a required input | Breaking | New tool version or explicit migration |
| Rename or remove a field | Breaking | Parallel field or tool until every stored and live caller has moved |
| Narrow an enum, range or accepted format | Breaking for old producers | No old valid value can arrive, including from queues and replay |
| Add a response enum or variant | Potentially breaking for consumers | Every consumer handles unknown values safely |
| Change a unit, identifier format, default or error meaning | Semantic break | New version even if the JSON type is unchanged |
| Expand data access or add a side effect | Authority break | New authorisation, approval and usually a new tool identity |
| Tighten validation to match already documented behaviour | Risk-dependent | Production evidence shows rejected values were never valid business inputs |
Do not let a schema-diff tool make the final decision. It can find structural deltas; it cannot know that notify_customer: false was an operational promise or that a broader search scope exposes another tenant. Review description text, defaults, downstream calls, permissions, retry behaviour, result consumers and audit obligations beside the schema.
Bind every plan to an immutable contract identity
A tool name alone is weak evidence if its definition can change underneath a plan. At planning time, record:
- tool name and explicit interface version;
- schema dialect plus canonical input- and output-schema digests;
- immutable operation or plan identity;
- arguments after deterministic normalisation;
- planner, policy and authorisation versions;
- approval evidence and its exact scope; and
- expiry or revalidation conditions.
At execution, resolve that exact interface version and compare the stored digest. Revalidate the arguments, business preconditions and authority. A mismatch should enter a migration or replanning state; it should not silently run against “latest”. This complements the model change-control baseline: model and prompt versions explain why the call was proposed, while the tool contract explains what the call was allowed to mean.
Version identity can live in a tool name such as schedule_visit_v2, in a protocol-negotiated registry or in an internal binding that the model never sees. The mechanism matters less than two properties: execution cannot resolve ambiguously, and rollback can still locate the older contract during its supported window. If tool descriptions are placed in model context, keep the exposed set small and deterministic rather than showing several near-identical versions without routing rules.
Worked example: evolve a scheduling tool without changing consent
Consider a hypothetical field-service tool:
schedule_visit_v1(case_id, slot_id) reserves a slot but does not contact the customer. A proposed replacement accepts window_start, window_end and optional notify_customer; the product team wants omitted notify_customer to default to true.
Replacing v1 in place fails all three contract layers. Old calls have the wrong shape. A slot identifier and a time window are not necessarily the same scheduling promise. Most importantly, omission changes from no message to a customer-facing side effect.
A safe migration is explicit:
- Freeze v1 semantics and keep its executor available for already approved plans.
- Publish
schedule_visit_v2withnotify_customerrequired, not inferred. - Translate a v1 slot into a v2 window only in a deterministic adapter with a tested slot-version lookup.
- Never translate the absent notification choice into consent; preserve
falseunless fresh approval says otherwise. - Let the new planner see only v2 while old queued plans remain pinned to v1.
- Store the returned reservation version so concurrent changes are rejected at commit.
The final step belongs with the AI-agent concurrency controls. Schema versioning prevents a call from changing meaning; operation identity and conditional state prevent the correctly interpreted call from committing twice or against stale availability.
Roll out with parallel contracts and shadow evidence
Build a conformance corpus from recorded, minimised call shapes plus designed boundaries. Include omitted optional fields, every enum, maximum lengths, unknown properties, old error responses, delayed plans and outputs consumed by each downstream step.
Then run a guarded release sequence:
- compare old and new schemas in both request and response directions;
- execute read-only or side-effect-free calls against both versions and compare meaning, not only status codes;
- for mutating tools, shadow through validation and planning but stop before commit;
- canary the new registry to a bounded planner population while retaining the old executor;
- inject cached tool lists, rollback, queue delay and mixed-version workers;
- record every rejection, translation and attempted version mismatch; and
- remove the old contract only after its live calls, stored plans and rollback dependency reach zero.
The OpenAPI 3.2 specification keeps deprecated operations and parameters usable while telling consumers to transition away. For HTTP resources, RFC 9745 similarly states that announcing deprecation does not itself change resource behaviour; a separate Sunset signal can state when it is expected to stop responding. Use that discipline internally even when the agent protocol is not HTTP: deprecation begins an observable migration period, not a same-day rename.
Measure contract safety, not migration activity
| Measure | What it reveals | Release or removal gate |
|---|---|---|
| Calls by tool version and schema digest | Which contracts are actually in use | No unexplained or mutable digest |
| Stored plans by version and age | Hidden future callers | Zero executable plans past support |
| Validation failures by field and producer | Shape incompatibility | No unreviewed increase |
| Translation count and failure reason | Dependence on migration logic | Declining to zero before removal |
| Semantic differential cases | Same JSON, different outcome | Zero unexplained differences |
| Authority deltas | New data or side effects | Fresh policy and approval evidence |
| Unknown result variants | Consumer forward-compatibility | Safe rejection or explicit handling |
| Rollback conformance pass rate | Whether the old path still works | 100% for the supported window |
Preserve the contract identity in the privacy-safe trace so an incident can reconstruct which definition planned, validated and executed the action without retaining unnecessary prompt content. The incident replay guide provides the wider evidence model.
The final review question is concrete: would every old, new, delayed and rolled-back participant interpret this call with the same shape, meaning and authority? If not, do not hide the change behind an unchanged tool name. Publish a parallel contract, bind plans to it and retire the old version only when evidence—not deployment intent—shows that nothing can still call it.



