Skip to content

SDK: support the AdCP 3.2 account change feed #2669

Description

@bokelley

Context

Protocol draft adcontextprotocol/adcp#6811 adds the optional AdCP 3.2 account change feed:

  • list_account_changes
  • account.change_feed capability discovery
  • account.change_recorded account notification
  • durable cursors with CURSOR_EXPIRED rebootstrap
  • source-neutral repair reads and account-specific source-coverage watermarks

The protocol PR currently identifies generated SDK support for the closed notification enum as a merge gate. A conforming buyer also needs typed client and receiver surfaces so each adopter does not rebuild cursor/error and notification normalization locally.

This issue is blocked on ratification of adcontextprotocol/adcp#6810 and merge of the accepted wire contract.

Required SDK work

Generated contract

  • Regenerate JSON-schema data, TypeScript types, public Zod schemas, task catalogs, and the closed notification enum from the accepted protocol schemas.
  • Export the request, success/error response, change-record, source-coverage, and webhook notification types.
  • Preserve unknown resource/action values as forward-compatible invalidations while validating the bounded base shape.
  • Return CURSOR_EXPIRED as the structured AdCP failure rather than masking it behind output-schema validation.

Buyer client

  • Add a typed session-aware listAccountChanges() method for AgentClient / SingleAgentClient.
  • Project account.change_feed into the normalized capabilities surface, including support, read/registration task names, event type, retention, and advertised resource types.
  • Support initial earliest / latest reads, cursor continuation, resource filters, empty-tail cursor persistence, and discriminated failure handling.
  • Provide a typed helper or request builder for registering account.change_recorded through sync_accounts.accounts[].notification_configs[] without rewriting an account payload incorrectly.

Notification receiver

  • Export an authoritative parser/normalizer for account.change_recorded that distinguishes:
    • logical identity: notification_id === change_id;
    • delivery retry identity: idempotency_key;
    • account/subscriber identity;
    • resource/action metadata; and
    • advisory through_cursor, which must never be installed without draining intervening pages.
  • Validate the notification-level identity invariants and return typed errors for malformed deliveries.

MCP interoperability

The draft request JSON Schema uses a root allOf for the version envelope and the cursor/starting_position exclusion. Anthropic MCP rejects top-level input combinators and can hide the entire tool catalog when one tool emits them.

  • Ensure the generated MCP inputSchema for list_account_changes is a plain root object with no top-level oneOf, anyOf, or allOf.
  • Enforce the mutual exclusion at runtime if it cannot be represented safely on the wire.
  • Add a packed-artifact regression test against the exact emitted MCP schema, not only the source JSON Schema.

Ownership boundary

The SDK should own protocol negotiation, exact wire validation, typed client calls, notification normalization, and reusable bootstrap/drain primitives. It should not claim durable application state, 90-day seller retention, atomic seller state/change commits, or a buyer's local projection writes. Persistence hooks may be exposed, but the adopting runtime remains responsible for durable cursors and reconciliation transactions.

Acceptance criteria

  • A TypeScript buyer can discover support, register the notification, acquire C0, list/drain changes, and handle CURSOR_EXPIRED without casts or raw callTool usage.
  • Canonical account.change_recorded deliveries parse into a normalized typed result; malformed identity combinations fail closed.
  • The emitted list_account_changes MCP input schema is accepted by Anthropic-compatible tool-schema validation.
  • Packed SDK tests cover empty-tail checkpoints, filtered continuation, structured expiry, webhook retry/re-emission identity, and unknown resource/action values.
  • An integration test runs against the training seller scenario from feat(protocol): draft account change feed adcp#6811 after that scenario and regenerated schemas land.
  • Migration documentation explains that the webhook is a wake-up, the feed is ordered invalidation metadata, and authoritative reads remain current truth.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions