Tool Result Schema Evolution: Producer and Active Consumer Compatibility Matrix
Passing the latest validator does not mean legacy Agents, renderers, and audit jobs still in production can read a new result. This article combines producer revisions, the real consumer set, decoding proofs, and representation routing into a compatibility gate purpose-built for tool results.
Key Points
- Topic Focus: AI Agent、MCP、TypeScript
- Suitable for: indie hackers, full-stack engineers, AI application developers
- Core value: quickly understand background, practical paths, common pitfalls, and engineering advice
A tool adds "deferred" to status: "open". The producer's new tests pass, but an exhaustive switch in an old Agent may throw an exception. Changing a missing nextCursor to null may cause the UI to paginate forever. Even a supposedly additive field can break a strict deserializer. Result compatibility must be judged by the behavior of consumers still reading it in production, not declared unilaterally by the schema author.
MCP Tool Schema Design covers the basic shape of input and output fields, while Agent Tool Output Guardrails block oversized, malicious, or cross-tenant content. This article assumes the result is already trusted and focuses on which representation can be consumed by which component when the producer, Agent planner, UI, log transformer, and asynchronous jobs for the same tool are running different versions.
Register Both Representation and Semantics in the Contract
Publish an immutable toolResultRelease.v1 for every release, binding the stable tool ID, descriptor digest, representation ID, schema dialect, schema digest, semantic revision, producer artifact, field lifecycle, error model, and support window. schemaRevision describes the machine-readable structure, while semanticRevision marks changes to units, ordering, nullability, truncation, or enum meanings. Even if the structure remains unchanged, changing monetary values from cents to dollars requires a new semantic revision.
schema: toolResultRelease.v1
tool: ticket.search
release: 4
representation: ticket.search.result.v3
dialect: https://json-schema.org/draft/2020-12/schema
schemaDigest: sha256:3b8...
semanticRevision: 6
producer: ticket-mcp@sha256:77a...
predecessor: ticket.search.result.v2
MCP tools can declare an outputSchema, and results can return structured content in structuredContent; when a schema is declared, the Server should ensure that structured results conform to it. For compatibility with older clients, the specification also recommends providing text content containing serialized JSON. This compatibility representation must be generated deterministically from the same canonical object and share its result digest. Two handwritten mappers must not produce different facts. The JSON Schema 2020-12 dialect, vocabulary, reference closure, and format assertion mode must all be included in the digest; merely stating "JSON Schema" is insufficient to reproduce validation.
Derive the Active Consumer Set from Evidence
The compatibility registry maintains consumerAttestation.v1: the consumer ID and artifact digest, owner, tool/representation read, parser configuration, accepted revisions, fixture root, and expiration time. activeConsumerSetGeneration is computed from the union of signed deployment and artifact manifests, schedules and queue subscriptions, minimum supported client versions, disaster recovery images, owner declarations, and traffic observed at the gateway. A 30-day observation window can only discover unregistered consumers; it cannot remove monthly jobs, offline workers, dormant clients, or disaster recovery readers. Those consumers can be removed only after their owner submits a versioned retirement receipt. Identity must not be inferred from User-Agent. Unattributed traffic is assigned to UNKNOWN_CONSUMER and blocks breaking cutovers.
The matrix must test at least four directions: old consumers reading old and new producers, and new consumers reading old and new producers. Fixtures include success, business errors, empty lists, pagination, truncation, unknown enums, large integers, null versus absent, reordered fields, and additional fields. Compatibility means more than "it can parse." The consumer's decision oracle must also remain consistent. For example, an unknown status must degrade to UNKNOWN, not be mistaken for CLOSED; a missing cursor must not be interpreted as the first page.
In Protobuf binary evolution, field numbers must never be reused, and removed fields should have their numbers and names reserved. Unknown fields can be preserved through a binary message chain but may be lost during JSON conversion, so passing Protobuf tests does not prove that an MCP JSON consumer is safe. Added enums, changed numeric types, and switched representations must all be tested against actual readers. For general REST and event changes, see Contract Compatibility Gates for Agent-Authored API Changes. This matrix is additionally scoped to tool-call receipts and planner/renderer versions that may coexist within the same session.
Activating a Producer Has One Acceptance Point
Release states are DRAFT -> SHADOW -> COMPATIBLE -> ACTIVE -> DEPRECATED -> RETIRED. The sole acceptance point is a registry transaction that performs CAS on the producer alias for (toolId, representation). The alias can be switched and an activation receipt written only when the candidate's entire cross-version matrix passes, activeConsumerSetGeneration remains unchanged, every valid consumer attestation covers the candidate or has a verifiable bridge, and UNKNOWN traffic is 0. If a new consumer comes online during validation, the generation comparison fails and the candidate must rerun the matrix.
The invocation gateway selects the producer using the authenticated consumer ID, negotiated representation, and active alias. The receipt records the consumer artifact, release, schema/semantic revision, and result digest. Agent Tool Capability Catalogs bind the output descriptor digest to the plan, but the routing receipt here remains authoritative for the result actually returned. Clients that have not negotiated a representation receive only the declared legacy representation; they must not be sent the latest structure by default.
A migration can begin with the new producer generating v3 in shadow mode while still delivering v2, allowing the canonical facts in both representations to be compared. V3 can then be enabled for 1% of consumers proven compatible. A time-limited down-converter may be used when necessary, but it must explicitly return UNREPRESENTABLE for a new enum that cannot be expressed losslessly; it must not silently change the value. Old readers and old producers must continue running against regression fixtures until the support window has elapsed and real traffic has fallen to zero.
Expose False Compatibility Through Consumer Drift
Fault injection includes an old decoder that strictly rejects unknown fields, a crash caused by exhaustive handling of an unknown enum, swapping null and absent, large integers exceeding JavaScript's safe range, disagreement between text and structuredContent, a cached old schema, a consumer joining before the cutover transaction, an expired attestation, a bridge dropping a field, and a new consumer that can read only v3 after rollback. Agent Replay Evaluation can replay real tool traces, but its oracle must be layered by consumer artifact.
The gate requires 100% coverage of deployments, schedules, subscriptions, client support windows, and disaster recovery inventories; a 100% pass rate for structural and semantic fixtures across the consumers in their union; UNKNOWN traffic of 0; divergence between the digests of the two MCP representations of 0; and silent conversions of 0. If even one incorrect decision occurs or the decoding error rate exceeds 0.01%, CAS must switch the producer alias back to the previous version. Before switching back, confirm that new consumers can still read the old representation; otherwise, enable a verified bridge first. Old schemas, producers, and fixtures must be retained for at least the full support window. A database backup must not be treated as a rollback plan.
Related
Related Content
Article
From Copilot to Codex: AI Coding Tools Enter the Agent Era
Technical trends, engineering practices, and indie-developer perspectives around AI, AI Agents, and Vibe Coding.
Article
Why Does MCP Matter? Understanding the AI Tool Protocol
Technical trends, engineering practices, and an independent developer perspective on MCP and AI Agents.
Article
Core Architecture of AI Agents: Planning, Memory, Tools, and Execution
Technical trends, engineering practices, and independent developer perspectives around AI Agents and large language models.
Article
SEO Design for a Content Community with Next.js
Technical trends, engineering practices, and an indie developer's perspective on Next.js and TypeScript.