Skip to content
Closed
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
8 changes: 6 additions & 2 deletions MIGRATION_v9_to_v10.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ 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`, and `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 them 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 | Every response root now composes `core/protocol-envelope.json` (adcontextprotocol/adcp#8547), which composes `core/version-envelope.json`. The generated response classes inherit `ProtocolEnvelope` alone (it carries `adcp_version`, `adcp_major_version`, `status`, `task_id`, `context_id`, `message`, `timestamp`, `replayed`, `adcp_error`, `push_notification_config` and `governance_context`) instead of listing `AdcpVersionEnvelope` beside it, so typed responses gain those fields through the base. `status` is REQUIRED on a 3.3 response, including `list_products` and a synchronous `decline_proposals`, which carried none under 3.2.x. Roots are open (`additionalProperties: true`); `replayed` is no longer pinned to `true`; `task_id` and `message` come from `core/task-id.json` and `core/task-message.json`. |
| `status` on `list_products` and `decline_proposals` follows the served release | The SDK no longer decides from a tool list alone. `adcp.validation._response_envelope.uses_task_status_envelope(tool, version)` asks the release's own response schema whether it composes `core/protocol-envelope.json`: under 3.3 the SDK fills `status: "completed"` on a synchronous response that has none and validators require it; under 3.2.x (closed `list_products`, `decline_proposals` permitting `status` only on its submitted arm) it neither requires nor emits it, and a 3.3 → 3.2 conversion drops it. A 3.2.x release that later composes the envelope flips the answer with no SDK change. Nothing is stripped for any other tool or release. |
| `task_id` and `message` are shared scalars on every response | `core/task-id.json` and `core/task-message.json` are the one definition of each, so a response's `task_id` is `TaskId` (a `str` subclass, `minLength: 1`) and `message` is `TaskMessage` (`maxLength: 2000`) instead of plain `str`. Build one with `TaskId("task_1")`, imported from `adcp.types.domains.core.task_id` (as for `PropertyTag`); a plain string still validates at runtime, but `mypy --strict` flags it as an argument to a typed constructor. A submitted arm is `class X(ProtocolEnvelope, TaskSubmitted)` with `status` pinned to `submitted` and `task_id` required; the compliance controller's `task_id` keeps its own `maxLength: 128` beside the shared definition. |
| AdCP 3.3.0-beta.3 adds live creative updates, staged-update notifications and tighter reporting-subscription coverage | Experimental `creative.live_updates` capability (`LiveUpdatePolicy`, `LiveUpdateServingMode`), `staged_update` on `list_creatives` / `sync_creatives` items (`CreativeStagedUpdate`), the `creative.staged_update_changed` notification (`CreativeStagedUpdateChangedWebhook`), the `CREATIVE_LIVE_UPDATE_UNSUPPORTED` error code (`CreativeLiveUpdateUnsupportedDetails`), and `force_creative_status` for a pending staged update. Reporting subscriptions gain the `inactive` coverage status with `deactivated_at`, billing `stub` obligations, `cancellation_effective_at`, `flight_history`, `authorization.regranted_at`, `destination_overrides[]`, and the `reporting_subscription_probe` controller scenario; resolved `request_account` outcomes carry `account`, `effective_at` and `not_carried_over`. The seller-offered `available_from` / `withdrawn_at` fields are generated, so `adcp.types._reporting_subscription_preview` now only widens the extensible reporting-dimension vocabulary. Collection-list mutation responses no longer carry `replayed` as a body field; read it from the envelope. |
| 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.3`, 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.3`. |
| `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