Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 5 additions & 3 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ recursive-include src/adcp py.typed
recursive-include src/adcp/reporting/materializer/assets *.json
recursive-include src/adcp/_compliance/3.2.1 *.json *.jsonl *.yaml *.md
recursive-include src/adcp/_compliance/3.2.4 *.json *.jsonl *.yaml *.md
recursive-include src/adcp/_compliance/3.3.0-beta.2 *.json *.jsonl *.yaml *.md
recursive-include src/adcp/_compliance/3.3.0-beta.3 *.json *.jsonl *.yaml *.md
recursive-include src/adcp/_compliance/3.2.7 *.json *.jsonl *.yaml *.md
# build_py copies the tracked cache into wheels. Do not duplicate those
# inputs with ignored, generated package copies in the source distribution.
Expand All @@ -15,6 +15,7 @@ prune src/adcp/_compliance/3.2.0-rc.6
prune src/adcp/_compliance/3.2.0-rc.7
prune src/adcp/_compliance/3.3.0-beta.0
prune src/adcp/_compliance/3.3.0-beta.1
prune src/adcp/_compliance/3.3.0-beta.2
# A clean VCS source tree has no ignored ``src/adcp/_schemas`` directory.
# Keep the tracked inputs needed by the build_py hook in source distributions
# so wheels built from an sdist have the same schema set as direct VCS wheels.
Expand All @@ -23,17 +24,18 @@ recursive-include schemas/cache/3.0 *.json
recursive-include schemas/cache/3.1 *.json
recursive-include schemas/cache/3.1.15 *.json
recursive-include schemas/cache/3.2 *.json
recursive-include schemas/cache/3.3.0-beta.2 *.json
recursive-include schemas/cache/3.3.0-beta.3 *.json
prune schemas/cache/2.5
prune schemas/cache/3.2.0-beta.6
prune schemas/cache/3.2.0-rc.3
prune schemas/cache/3.2.0-rc.6
prune schemas/cache/3.2.0-rc.7
prune schemas/cache/3.3.0-beta.0
prune schemas/cache/3.3.0-beta.1
prune schemas/cache/3.3.0-beta.2
prune schemas/releases
include schemas/releases/3.2.1.json
include schemas/releases/3.2.4.json
include schemas/releases/3.2.7.json
include schemas/releases/3.1.27.json
include schemas/releases/3.3.0-beta.2.json
include schemas/releases/3.3.0-beta.3.json
7 changes: 5 additions & 2 deletions MIGRATION_v9_to_v10.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ the SDK-relevant inventory is [docs/adcp-3.3-sdk-inventory.md](docs/adcp-3.3-sdk

| Change | Update your integration |
| --- | --- |
| The wire pin is AdCP `3.3.0-beta.2` | `get_adcp_version()` returns `3.3.0-beta.2`; the SDK speaks `adcp_version: "3.3-beta.2"` by default and advertises `3.0`, `3.1`, `3.2`, `3.3-beta.2` and the `3.2-rc.7` alias. A stable `"3.3"` is not an accepted pin until the protocol's 3.3 GA. `10.0.0-beta.0` and `10.0.0-beta.1` pinned `3.3.0-beta.0`, and `10.0.0-beta.2` pinned `3.3.0-beta.1`; neither beta is advertised or accepted as an `adcp_version` pin any more (`ConfigurationError`), and a `3.3-beta.0` or `3.3-beta.1` peer is negotiated like any other unserved prerelease (down to `3.2`). Re-pin to `3.3-beta.2`, or omit the pin. Pin `adcp_version="3.2"` on a server whose handlers must keep running on the 3.2 contract (see "A server pin governs its handlers" below). On a client, `adcp_version` is a negotiation ceiling; its application models remain current. Generated types, bundled schemas and the versioned validators follow the 3.3 bundle. |
| The wire pin is AdCP `3.3.0-beta.3` | `get_adcp_version()` returns `3.3.0-beta.3`; the SDK speaks `adcp_version: "3.3-beta.3"` by default and advertises `3.0`, `3.1`, `3.2`, `3.3-beta.3` and the `3.2-rc.7` alias. A stable `"3.3"` is not an accepted pin until the protocol's 3.3 GA. `10.0.0-beta.0` and `10.0.0-beta.1` pinned `3.3.0-beta.0`, `10.0.0-beta.2` pinned `3.3.0-beta.1`, and `10.0.0-beta.3` pinned `3.3.0-beta.2`; none of those betas is advertised or accepted as an `adcp_version` pin any more (`ConfigurationError`), and a `3.3-beta.0`, `3.3-beta.1` or `3.3-beta.2` peer is negotiated like any other unserved prerelease (down to `3.2`). Re-pin to `3.3-beta.3`, or omit the pin. Pin `adcp_version="3.2"` on a server whose handlers must keep running on the 3.2 contract (see "A server pin governs its handlers" below). On a client, `adcp_version` is a negotiation ceiling; its application models remain current. Generated types, bundled schemas and the versioned validators follow the 3.3 bundle. |
| AdCP 3.3.0-beta.1 adds account requests, media-buy issues and reporting subscriptions | New tasks are wired through `ADCPClient` / `ADCPMultiAgentClient`, `ADCPHandler` (each returns `not_supported()` until overridden), the MCP and A2A adapters, the MCP tool list and the CLI: `request_account` (experimental `account.requests`; it opens, matches or, with `account_id`, changes an account, guarded by `revision`), `report_media_buy_issue` and `get_media_buy_issue`. `RequestAccountRequest` / `Response`, `ReportMediaBuyIssueRequest` / `Response` and `GetMediaBuyIssueRequest` / `Response` are exported from `adcp.types`. `list_accounts` gains `include_requests`, `request_ids` and `requests_pagination`, returning `account_requests[]` and `account_requests_pagination`. Experimental principal-level `reporting_subscriptions` land on `sync_principal` / `get_principal`, with `subscription_coverage[]` on `get_reporting_status`, `configuration_tasks[]` on `media_buy.reporting_delivery`, the `ReportingDimension` enum and the `principal.changed` reason `reporting_subscription_changed`. `sync_accounts` is unchanged and stays supported. Generated class names that the generator numbers can renumber with the bundle; import the semantic names from `adcp.types` rather than a numbered class from a domain module. |
| AdCP 3.3.0-beta.2 withdraws definition pins, purchase rights and installment selection | adcontextprotocol/adcp#8537 moves all three to 4.0, so their generated types leave `adcp.types.domains.*`, `adcp.types._generated` and `adcp.types.error_details`: `DefinitionPin*`, `DefinitionPinReferenceKind`, `ReferenceDefinitionChangedDetails` (and `ErrorCode.REFERENCE_DEFINITION_CHANGED`), `DriftedPin`, `RightsScope`, `InstallmentChangeSet`, `commercial_terms.definition_pins`, `purchases[].rights` / `installments`, `installment_changes` and the `definition_changed` refinement reason. `TestControllerStore.definition_pin_probe` and the `definition_pin_probe` controller scenario are removed. Delete code that builds or reads them; a seller stops listing `media_buy.purchase_rights` and `media_buy.installment_selection` in `experimental_features`. |
| AdCP 3.3.0-beta.2 adds separate-account outcomes, seller offers and measurement provenance | `RequestAccountRequest.allow_separate_account` (default `false`) lets a change request resolve as `created` (a new account carrying the change) or `matched` (an account the caller already holds), and the new correctable error code `ACCOUNT_CHANGE_REQUIRES_NEW_ACCOUNT` reports a change the seller would take only on a new account. Experimental seller offers add `proposal_initiator`, `offer_reason` on `list_proposals` rows and the `proposal.offered` notification (`ProposalOfferedWebhook`); experimental measurement provenance adds `CollectionMechanism`, `counting_mechanisms` and `vendor_metric_provenance[]` (`VendorMetricProvenance`). The reporting-subscription fields settled after beta.1 (`standard_dimensions`, `unmapped_dimensions`, `inactive_intervals`, `prior_versions[].configuration`, per-offering `offering_id`, `previous_timezone`) are now generated. `principal_kind` and `expected_principal_kind` are deprecated. `NotificationConfig.product_payload_view` loses its schema default: it is `None` when unset, and a product subscription's dump no longer adds `product_payload_view: "legacy"` (absent means legacy); read `config.product_payload_view or "legacy"`. These are generated types, imported from their domain packages (for example `adcp.types.domains.core.ProposalOfferedWebhook`); no task was added. |
| AdCP 3.3.0-beta.3 composes the protocol envelope on every task response | adcontextprotocol/adcp#8547: every response root composes `core/protocol-envelope.json`, which composes `core/version-envelope.json`, so generated responses inherit `ProtocolEnvelope` alone (no separate `AdcpVersionEnvelope` base) and the local copies of envelope fields are gone. Submitted, working and input-required bodies compose `core/task-submitted.json` / `task-working.json` / `task-input-required.json`: a submitted arm still pins `status` to `submitted` and requires `task_id`. `task_id` (non-empty) and the task-level `message` (at most 2,000 characters) each have one definition (`core/task-id.json`, `core/task-message.json`); fields that refer to them stay typed `str` with those constraints, so no caller has to wrap a value. `TaskId`, `TaskMessage`, `TaskSubmitted`, `TaskWorking` and `TaskInputRequired` are generated. Consequences for handlers: `list_products` and `decline_proposals` now carry `status` (the server stamps `completed`; the 3.3 → 3.2 conversion still drops it for 3.2 callers); an absent `replayed` reads as `false` and `replayed: false` is valid; and on governance responses `status` is the task status, so a `check_governance` result names its decision in `verdict` and `report_plan_outcome` in `outcome_state`, never in `status`. `create_mcp_webhook_payload` gives a `result` without `status` the webhook's task status, and replaces a model result's defaulted envelope status with it, so a failed task's result never reads `completed`. |
| AdCP 3.3.0-beta.3 adds live creative updates, account-request money terms and reporting-subscription fields | Experimental `creative.live_updates` (`LiveUpdatePolicy`, `CreativeStagedUpdate`, `creative.staged_update_changed` and `CreativeStagedUpdateChangedWebhook`, error code `CREATIVE_LIVE_UPDATE_UNSUPPORTED` with `CreativeLiveUpdateUnsupportedDetails`). `request_account` outcomes carry `account` money terms on `matched` / `created`, `effective_at` on an `updated` money change, and `not_carried_over`. Reporting subscriptions gain `destination_overrides[]`, the paged readback (`prior_versions_count`, `accounts_with_exceptions_count`, `accounts_unauthorized_count`, `get_principal` `reporting_subscription_page`), `authorization.regranted_at`, `flight_history[]` and `cancellation_effective_at` on media buys, `available_from` / `withdrawn_at` on offerings and `stub` on billing obligations. `comply_test_controller` adds the `reporting_subscription_probe` scenario: override `TestControllerStore.reporting_subscription_probe` to serve it. Generated renames: `PriorVersion` is `ReportingSubscriptionPriorVersion`, `AccountsWithException` is `ReportingSubscriptionAccountExceptions`, and `AccountsUnauthorizedItem` is `ReportingSubscriptionUnauthorizedAccount`. |
| The reporting-subscription surface is served from 3.3.0-beta.3 on, unprojected | The beta.1 / beta.2 field projections are gone, with the preview module that patched the fields onto the models: `project_offering`, `project_reporting_delivery`, `project_subscription_state`, `project_subscription_coverage` and `serves_settled_subscription_fields` are removed from `adcp.reporting.subscriptions`, and `ReportingSubscriptionEngine.subscription_coverage()` no longer takes `adcp_version`. One predicate, `adcp.reporting.subscriptions.serves_subscriptions(adcp_version)` (from `SUBSCRIPTIONS_MIN_ADCP_VERSION`, `3.3.0-beta.3`), gates the whole surface: capabilities, `get_reporting_status` coverage (including `status: "inactive"` with `deactivated_at`) and the principal readback. A caller served an earlier release gets none of it. The extensible `reporting-dimension` vocabulary accepts unknown values on selectors, offerings and the capability block. |
| A server that restricts `supported_versions` runs on its newest listed release | Any server (`create_mcp_server`, `create_a2a_server`, `serve`, `MCPToolSet`, `ADCPAgentExecutor`, `create_tool_caller`, `PlatformHandler`, `create_adcp_server_from_platform`) with `supported_versions=["3.2"]` and no `adcp_version` runs its handlers on 3.2, instead of raising because the SDK default is outside the list. Pass `adcp_version` explicitly to choose another listed release. |
| `server_version` pins keep wire precision | `ADCPClient(server_version=...)` and `get_server_version()` keep a 3.x pin at release precision: `"3.1.0-beta.1"` reads back as `"3.1-beta.1"` (SDK 9 reported the bundle key, `"3.1.0-beta.1"`). Stable pins still collapse (`"3.0.7"` → `"3.0"`). |
| A server pin governs its handlers | Handlers run on one *application version*: the server's `adcp_version` pin, else the newest release in its `supported_versions`, else the packaged `3.3-beta.2`. Every dispatch path (MCP, A2A, `create_tool_caller`, the Decisioning dispatcher) converts a buyer's request to that release before validation, unknown-field policy and typed parsing, and converts the handler's response back to the buyer's release: up to `3.3-beta.2`, unchanged for a same-release buyer, or down to 3.1 / 3.0. `resolve_requested_adcp_version(params)` inside a handler returns the application version; `ToolContext.application_adcp_version` reports it directly, and `ToolContext.resolved_adcp_version` still reports the buyer's negotiated version. A 3.2-pinned seller's dict handlers therefore see exactly 3.2 payloads, its requests and responses are validated against the 3.2 schemas (with strict validation, a response its own 3.2 contract refuses fails before conversion), and a conversion the target schema refuses fails as `ADCPVersionConversionError` / `VERSION_UNSUPPORTED` instead of reaching the peer invalid. Typed handler parameters (`params: GetProductsRequest`) and typed responses still use the generated 3.3 classes: they are additive supersets of 3.2, so a 3.2 payload parses into them unchanged and dumps back as the same 3.2 payload, but a field 3.3 added reads as unset (its model default) on a 3.2 server. The unpinned default is unchanged: handlers receive `3.3-beta.2`. |
| A server pin governs its handlers | Handlers run on one *application version*: the server's `adcp_version` pin, else the newest release in its `supported_versions`, else the packaged `3.3-beta.3`. Every dispatch path (MCP, A2A, `create_tool_caller`, the Decisioning dispatcher) converts a buyer's request to that release before validation, unknown-field policy and typed parsing, and converts the handler's response back to the buyer's release: up to `3.3-beta.2`, unchanged for a same-release buyer, or down to 3.1 / 3.0. `resolve_requested_adcp_version(params)` inside a handler returns the application version; `ToolContext.application_adcp_version` reports it directly, and `ToolContext.resolved_adcp_version` still reports the buyer's negotiated version. A 3.2-pinned seller's dict handlers therefore see exactly 3.2 payloads, its requests and responses are validated against the 3.2 schemas (with strict validation, a response its own 3.2 contract refuses fails before conversion), and a conversion the target schema refuses fails as `ADCPVersionConversionError` / `VERSION_UNSUPPORTED` instead of reaching the peer invalid. Typed handler parameters (`params: GetProductsRequest`) and typed responses still use the generated 3.3 classes: they are additive supersets of 3.2, so a 3.2 payload parses into them unchanged and dumps back as the same 3.2 payload, but a field 3.3 added reads as unset (its model default) on a 3.2 server. The unpinned default is unchanged: handlers receive `3.3-beta.2`. |
| `UniversalMacro` is a union | AdCP 3.3 adds the parameterized `GDPR_CONSENT_<gvl_id>` family, so `adcp.types.UniversalMacro` is now a `RootModel` over the closed enum (`UniversalMacro3`) and the pattern string (`UniversalMacro4`). Replace `UniversalMacro.MEDIA_BUY_ID` with `UniversalMacro3.MEDIA_BUY_ID` (or compare strings), and read `.root` on a parsed value. |
| The experimental identity preview is the generated 3.3 surface | `adcp.types.experimental_identity` keeps every name (`AgentOnboarding`, `BuyerOnboardingPosture`, `PrincipalRelationship`, `TrustRecord`, `GetPrincipalResponse`, ...) but binds the generated 3.3 types. `adcp.types._identity_preview`, `adcp.signing._identity_schemas` and `scripts/generate_identity_preview.py` are gone. `RequestSigning.profiles` is `list[Profile]` (an enum) rather than `list[str]`; `PrincipalChangedWebhook.reason` is the generated `Reason` enum, which now includes `relationship_changed` and `relationship_expiring`. `AgentOnboardingRequirement.kind` stays open (`AgentOnboardingRequirementKind | str`). `adcp.signing.validate_identity_value` validates against the pinned bundle; `identity_schema_bundle()` is removed. |
| `reporting_webhook.operation_id` is a generated field | The field, its constraints and its never-null marker come from the 3.3 schema. The SDK 9 runtime patch is gone; nothing changes on the wire. |
Expand Down
2 changes: 1 addition & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ releases ([#1525](https://github.com/adcontextprotocol/adcp-client-python/issues
| --- | --- | --- |
| `main` | Work against the latest ratified AdCP version (3.2.x today) | The current major (9.x), through release-please |
| `release/N.x` (`release/8.x`, `release/7.x`) | Fixes for an older major | Patch releases of that major, from the branch's own release workflow |
| `next` | SDK 10 on AdCP 3.3 (the 3.3.0-beta.2 bundle, agent identity, Web Bot Auth) | Pre-releases only (`10.0.0-beta.N`), from its own release-please configuration |
| `next` | SDK 10 on AdCP 3.3 (the 3.3.0-beta.3 bundle, agent identity, Web Bot Auth) | Pre-releases only (`10.0.0-beta.N`), from its own release-please configuration |

Open a PR against the branch that carries the spec it implements. Code written
to an unratified spec (an open adcontextprotocol/adcp PR or a draft) targets
Expand Down
Loading
Loading