Concept doc captures the design for coordinated API evolution in agent ecosystems: InterfaceChange entity, draft→published→resolved lifecycle, TPSC-derived dependency routing, inbox-based notifications, pre-change coordination via planned_for, and deliberate deferral of webhooks. CUST-WP-0033 workplan: 6 tasks (model, API, dispatch integration, MCP tools, dashboard, webhook EP). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
163 lines
7.1 KiB
Markdown
163 lines
7.1 KiB
Markdown
---
|
|
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.
|