AGENT EVENTS · CONSUMER CONTRACTS
Agent event release gate: protect a required consumer field
Change the agent event schema in a producer release and see which gate notices that a downstream consumer can no longer parse it.
Your experiment
Three consumers read agent events: billing, analytics and audit. Start with v2 removing taskId behind the producer-schema gate, then switch to consumer contract tests, try each schema change, unregister the analytics contract and add dual-write.
Play replays the computed run over sixty inspection seconds; Next event steps, Restart rewinds, Speed changes the pace and Inspection time scrubs. Any input change recomputes the run and rewinds it without autoplay.
Event trace
Computed data
Final metrics
Teaching model of consumer-driven contracts, not a schema registry or an ADK event API. Each contract is a fixed predicate over one sample event, consumers dead-letter every event they cannot parse, and the broker runs exactly the registered contracts. Real registries add compatibility modes, versions per subject and replay of retained events.
The producer passes its own tests
Agent events carry taskId, type, ts in epoch seconds, agent and payload. Three consumers read them: billing needs taskId and type, analytics needs type and a numeric ts and rejects unknown fields, and audit needs taskId but ignores anything new. The opening Producer change in v2 removes taskId. Its own updated schema and unit tests pass, the Release gate, set to Producer schema and unit tests, publishes it, and billing and audit dead-letter all six events: CONSUMER BROKEN. A producer schema check cannot fail here, because the producer wrote the schema it is checked against.
Run every consumer contract before publishing
Set Release gate to Consumer contract tests. Before publishing, each registered consumer contract runs against a v2 sample: billing and audit fail, the release is held and v1 keeps flowing: HELD BEFORE PUBLISH. The same gate holds the rename to task_id, which breaks billing and audit, the ISO-8601 ts, which breaks analytics, and the new field model, which also breaks analytics because it rejects unknown fields. An additive field is safe only for tolerant readers.
An unregistered contract is never run
analytics contract registered with the broker matters only when the contract gate runs a change that analytics cares about. With the ISO-8601 ts and analytics unregistered, the gate runs the billing and audit contracts, both pass, v2 is published and analytics dead-letters all six events: CONSUMER BROKEN. A contract gate is only as complete as its list of consumers.
Migrate with dual-write
Check Dual-write the old field during migration. The rename emits task_id and keeps taskId, the ts change keeps the numeric ts and adds ts_iso, and the removal keeps taskId for a deprecation period, so every consumer parses every event: COMPATIBLE RELEASE, even with no gate. The old field can be dropped later, once each consumer has moved and its contract says so. With No schema change every gate publishes cleanly.
Reading the run and its limits
Play, Next event, Restart, Speed and Inspection time step through the candidate, the producer tests, each contract, the gate decision and six consumed events across sixty inspection seconds; the table lists each consumer, what it needs, whether its contract is registered and how many v2 events it parsed. Contracts are fixed predicates over one sample event and a consumer dead-letters every event it cannot parse. Real schema registries add compatibility modes, versions per subject and replay, which are omitted.