--- id: CUST-CPT-CUST-2026-000002 type: concept title: "Interface Change Registry — Coordinated API Evolution for Agent Ecosystems" status: active owners: ["Bernd", "Custodian"] created: "2026-04-26" updated: "2026-04-26" scope: domains: ["custodian"] sensitivity: internal tags: ["interface", "api-evolution", "agent-coordination", "ecosystem", "change-management"] related_workplan: CUST-WP-0033 --- # Interface Change Registry — Coordinated API Evolution for Agent Ecosystems ## Problem In a distributed ecosystem of closely coupled repos and services, APIs and interfaces evolve continuously. Without coordination, breaking changes propagate silently: a service updates its REST API, and dependent agents or services discover the breakage only at runtime — typically as a 422, a 307 redirect, or a schema validation failure. Human-operated systems address this with release notes and changelogs. Agent-operated systems need something machine-readable and actionable: a record of what changed, who depends on it, and a channel to trigger adaptation before the breakage hits. The trailing-slash normalisation performed on 2026-04-26 is a concrete example: it was a deliberate, coordinated breaking change. Without a registry, every consumer had to be found by manual grep. With one, the change record names the affected repos, their agents receive inbox notifications, and each can adapt autonomously. ## Core Abstraction: InterfaceChange An `InterfaceChange` record describes a single, versioned mutation to a published interface boundary. It carries: | Field | Purpose | |---|---| | `repo_slug` | The repo that owns the interface | | `interface_type` | What kind of interface: `rest_api`, `mcp_tool`, `cli`, `schema`, `capability` | | `change_type` | Nature of change: `breaking`, `additive`, `deprecation`, `removal` | | `title` | Short human-readable summary | | `description` | Full description with before/after detail | | `affected_paths` | Specific endpoints, tool names, CLI commands, or schema fields changed | | `affected_repo_slugs` | Repos known to consume this interface | | `status` | `draft` → `published` → `resolved` | | `planned_for` | Optional date — set when change is announced before it ships | | `published_at` | When the change became live | | `resolved_at` | When all known dependents have adapted | ## Lifecycle ``` draft ──publish──▶ published ──resolve──▶ resolved │ │ │ auto-notify affected │ repo agents (inbox) └── edit freely; no notifications yet ``` **draft** — change is being documented but not yet live or announced. Safe to edit. Can be used to pre-announce a planned breaking change before it is merged. **published** — the change is live (or imminently scheduled). On publish, the hub automatically sends an inbox message to the agent of each `affected_repo_slug`. The message contains enough context for the agent to identify what needs updating. **resolved** — all known dependents have adapted and confirmed. Can be closed by the originating agent or by any affected agent once it has updated its side. ## Dependency Routing `affected_repo_slugs` can be populated in two ways: 1. **Explicit** — the author lists known consumers when creating the record. 2. **Derived** — the hub queries the TPSC graph: repos that have a TPSC snapshot declaring a dependency on the originating repo's service are automatically included as candidates. The author confirms or trims the list before publish. This means the TPSC catalog (`tpsc.yaml` files) is the underlying dependency map for routing interface change notifications. Keeping TPSC current is what makes automatic routing accurate. ## Pre-Change Coordination Setting `planned_for` and publishing in `draft` status (then moving to `published` on merge) enables a coordination window: ``` day 0 — change drafted, planned_for set to day 7 day 0 — dependent agents receive notification, begin adapting day 7 — change lands, status set to published day 7+ — agents confirm adaptation, change resolved ``` This is the proactive adaptation model: the breaking change announcement travels faster than the change itself, giving dependents time to prepare. At scale, this enables the ecosystem to self-heal around planned migrations. ## Agent Session Integration Two integration points keep agents aware of pending changes without requiring active polling: **Session start (pull):** The `/repos/{slug}/dispatch` endpoint includes a `pending_interface_changes` field — published changes that affect this repo and are not yet resolved. Agents reading dispatch at session start see what they need to adapt to. **Inbox notification (push):** On publish, the hub sends an inbox message to each affected repo's agent. The message includes the change title, description, and `affected_paths` so the agent can locate the relevant code without additional API calls. Together, these ensure no published breaking change is invisible to an agent working in an affected repo. ## Relationship to Existing State-Hub Entities | Entity | Relationship | |---|---| | `ManagedRepo` | InterfaceChange.repo_id FK; affected_repo_slugs reference repo slugs | | `TPSC` / `TPSCSnapshot` | Source for derived affected_repo_slugs via service dependency graph | | `Decision` | A planned breaking change is conceptually a pending decision; consider linking | | `ProgressEvent` | Publishing a change auto-appends a progress event to the originating repo | | `Message` | Publish action sends inbox messages to affected agents | ## Webhook Extension (Deferred) Inbox messages cover agents that poll at session start. Services that need real-time push — CI pipelines, external webhooks, non-Custodian agents — require a separate subscription mechanism. This is explicitly deferred. The design leaves room for it: - `InterfaceChange` records are immutable once published (safe to deliver idempotently) - `affected_repo_slugs` is the routing key; a subscription table maps slugs to URLs - Delivery semantics: at-least-once with exponential backoff A dedicated EP (`EP-CUST-ICR-001`) will track this when the inbox-first approach proves insufficient. ## Long-term Vision The Interface Change Registry is a first step toward a **self-healing ecosystem**: 1. A repo publishes a breaking change with `planned_for = T+7`. 2. The hub identifies all dependents via TPSC and notifies their agents. 3. Each dependent agent opens a task, locates the affected code, and creates an adaptation PR before T+7. 4. At T+7, the change ships; all dependents are already adapted. 5. The originating agent marks the change resolved. No human coordination is needed for routine interface evolution. Humans remain in the loop for non-routine changes — architectural decisions, security-sensitive migrations, or changes that require cross-domain agreement — via the Decision entity and the existing escalation protocol. At greater scale, the dependency graph enables **contract testing**: two repos can register a formal interface contract, and the hub can detect when a proposed change would violate it before the change is merged.