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
  •  
  •  
  •  
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1254,8 +1254,10 @@ jobs:
if child.is_dir()
}
# Ship released lines and the frozen 3.1.15 source snapshot offline.
# The bundles setup.py's build_py ships: the historical 3.0 / 3.1 /
# 3.1.15 inputs, the 3.2 contract and the current pin.
assert packaged_versions == {
"3.0", "3.1", "3.1.15", current_bundle
"3.0", "3.1", "3.1.15", "3.2", current_bundle
}
error_schema = json.loads(
(schema_root / current_bundle / "enums/error-code.json").read_text(encoding="utf-8")
Expand Down
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +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.0 *.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.
prune src/adcp/_schemas
Expand All @@ -19,6 +20,7 @@ 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.0 *.json
prune schemas/cache/2.5
prune schemas/cache/3.2.0-beta.6
prune schemas/cache/3.2.0-rc.3
Expand All @@ -28,3 +30,4 @@ prune schemas/releases
include schemas/releases/3.2.1.json
include schemas/releases/3.2.4.json
include schemas/releases/3.1.27.json
include schemas/releases/3.3.0-beta.0.json
18 changes: 17 additions & 1 deletion MIGRATION_v9_to_v10.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
# Migrating from SDK 9 to 10

SDK 10 targets AdCP 3.3. Review the changes below before upgrading.
SDK 10 targets AdCP 3.3. SDK 9 stays on AdCP 3.2 and keeps releasing from
`main`; SDK 10 pre-releases come from `next` (`pip install --pre adcp`). Review
the changes below before upgrading each client, server and reporting worker.
The protocol-side rules are in the AdCP
[3.2 to 3.3 migration guide](https://docs.adcontextprotocol.org/docs/reference/migration/3-2-to-3-3);
the SDK-relevant inventory is [docs/adcp-3.3-sdk-inventory.md](docs/adcp-3.3-sdk-inventory.md).

| Change | Update your integration |
| --- | --- |
| The wire pin is AdCP `3.3.0-beta.0` | `get_adcp_version()` returns `3.3.0-beta.0`; the SDK speaks `adcp_version: "3.3-beta.0"` by default and advertises `3.0`, `3.1`, `3.2`, `3.3-beta.0` and the `3.2-rc.7` alias. A stable `"3.3"` is not an accepted pin until the protocol's 3.3 GA. Pin `adcp_version="3.2"` on a client or server that must keep a 3.2 contract. Generated types, bundled schemas and the versioned validators follow the 3.3 bundle. |
| A server that restricts `supported_versions` pins to its newest listed release | A `PlatformHandler` or `create_adcp_server_from_platform(...)` with `supported_versions=["3.2"]` and no `adcp_version` serves 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"`). |
| Translation covers the 3.3 line | Handlers receive requests upgraded to `3.3-beta.0`; `resolve_requested_adcp_version(params)` returns that inside a handler. Read a buyer's negotiated version from `ToolContext.resolved_adcp_version`. Responses to 3.2, 3.1 and 3.0 buyers are converted down; a downgrade the older schema refuses fails as `ADCPVersionConversionError` instead of reaching the peer invalid. |
| `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. |
| RFC 9421 signing warns by default | AdCP 3.3 deprecates the `adcp/request-signing/v1` and `adcp/webhook-signing/v1` profiles for Web Bot Auth. Constructing `SigningConfig` or `RequestSignatureVerification` without Web Bot Auth emits a `DeprecationWarning`; both profiles keep working through 3.x. |
| `evaluator_id` is gone from evaluator specs | AdCP 3.3 removes the experimental `build_creative.evaluator.evaluator_id` source form. Use inline `exemplars` or `agent_url`; put the seller's evaluator in `creative_policy.accepted_verifiers[]`. |
| Schema defaults appear in dumps for new 3.3 fields | `GetProductsRequest.include_collections` (`false`) and `proposal_refinement.hold_extension` (`false`) carry schema defaults, so a dumped model declares them. Tests that compare whole dictionaries need the new keys; a 3.3 → 3.2 downgrade drops them with a recorded loss. |
| Delivery rows may omit `impressions` | Every `by_*` delivery-metrics row makes `impressions` optional. Treat absence as "not measured", never as zero. |
| Pixel trackers for AdCP 3.3 playback events are dropped when downgraded to the v1 url-tracker shape | `downgrade_pixel_tracker` returns `PixelTrackerDowngrade(v1=None, ...)` with a `PIXEL_TRACKER_LOSSY_DOWNGRADE` advisory for `start`, `first_quartile`, `midpoint`, `third_quartile` and `complete`, and for their 3.2 interim form (`event: custom` with `custom_event_name` set to one of them). SDK 9 put the interim form in the `impression_tracker` slot, which counted every impression as a quartile view. Check `result.v1 is not None` before reading it. `downgrade_pixel_trackers` leaves dropped trackers out of `items`. See the AdCP [3.2 to 3.3 migration guide](https://docs.adcontextprotocol.org/docs/reference/migration/3-2-to-3-3#hosted-video-and-audio-playback-trackers). |
| brand.json fetches accept up to 2 MiB, and refuse a larger configured cap | The default brand.json cap rises from 256 KiB to 2 MiB, as AdCP 3.3 requires. `BrandJsonJwksResolver` and the other brand.json fetchers raise `ValueError` when `max_body_bytes` is above 2 MiB or not positive. Remove a larger override. Documents nested deeper than 32 are refused as `request_signature_brand_json_malformed`, and a fetch has a 10 s total deadline. JWKS and capabilities caps are unchanged. |
| `WebhookReceiver` bounds the body before verifying it | The default body cap falls from 10 MiB to 1 MiB, the AdCP webhook delivery limit. Set `WebhookReceiverConfig.max_body_bytes` per endpoint if you need more. Over-limit bodies, and JSON deeper than 64 or with more than 100,000 members, get HTTP 413 before signature verification. New rejection reasons: `body_too_complex` (413), `content_encoding_unsupported` (415) and `body_framing_invalid` (400). Update code that matches on every reason. Use `read_inbound_body` / `check_inbound_body` in your own push receivers. |
Expand Down
38 changes: 4 additions & 34 deletions SCHEMA_DELTAS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,7 @@

## Field changes

- `account/list_account_changes_request.py`
- `ListAccountChangesRequest`: `+adcp_major_version`, `+adcp_version`
- `bundled/protocol/get_adcp_capabilities_response.py`
- **classes added**: C2paAction, MediaType, Method3, Persistence, Position
- **classes removed**: C2PAWatermarkAction, Disclosure3, Disclosure4, Disclosure5, Disclosure6, DisclosurePersistence, DisclosurePosition, EmbeddedProvenanceItem2, EmbeddedProvenanceItem3, EmbeddedProvenanceItem4, EmbeddedProvenanceItem5, EmbeddedProvenanceMethod, Logo1, Logo2, Logo3, Logo4, Provenance2, Provenance3, Provenance4, Provenance5, Watermark2, Watermark3, Watermark4, Watermark5, WatermarkMediaType
- `Method`: `+manifest_wrapper`, `+provenance_markers` `-access_mode`, `-destination_modes`, `-format`, `-orchestration`, `-pattern`, `-producer_identity`, `-provider`, `-reader_compatibility`, `-transport`
- `core/provenance.py`
- **classes added**: VerifyAgent10
- **classes removed**: VerifyAgent18
- `core/reporting_status_issue.py`
- `Code`: `+REVISION_UNREADABLE`
- `ReportingStatusIssue`: `+reporting_revision_id`
- `media_buy/accept_proposal_request.py`
- `AcceptProposalRequest`: `+adcp_major_version`, `+adcp_version`
- `media_buy/buy_products_request.py`
- `BuyProductsRequest`: `+adcp_major_version`, `+adcp_version`
- `media_buy/control_media_buy_request.py`
- `ControlMediaBuyRequest`: `+adcp_major_version`, `+adcp_version`
- `media_buy/decline_proposals_request.py`
- `DeclineProposalsRequest`: `+adcp_major_version`, `+adcp_version`
- `media_buy/list_products_request.py`
- `ListProductsRequest`: `+adcp_major_version`, `+adcp_version`
- `media_buy/refine_proposals_request.py`
- `RefineProposalsRequest`: `+adcp_major_version`, `+adcp_version`
- `media_buy/request_proposals_request.py`
- `RequestProposalsRequest`: `+adcp_major_version`, `+adcp_version`
- `media_buy/sync_reporting_status_request.py`
- `SyncReportingStatusRequest`: `+adcp_major_version`, `+adcp_version`
- `protocol/get_principal_response.py`
- **classes added**: Result2, Result3, Result5
- **classes removed**: Result6, Result7, Result9
- `protocol/sync_principal_response.py`
- **classes added**: Result13, Result15
- **classes removed**: Result17, Result19
- `core/hold_policy.py`
- `PositiveDuration`: `+__slots__`, `+_constraints`, `+_json_schema_extra` `-root`
- `trust/v1/trust.py`
- `Domain`: `+__slots__`, `+_constraints`, `+_json_schema_extra` `-root`
6 changes: 3 additions & 3 deletions docs/agent-identity-3-3-migration.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Experimental AdCP 3.3 agent identity

This SDK supports an opt-in preview of issue [#1500](https://github.com/adcontextprotocol/adcp-client-python/issues/1500). The Web Bot Auth wire profile follows `wba-profile.mdx` in adcontextprotocol/adcp#7894 at `9f472d63` (vectors from adcontextprotocol/adcp#8298 at `f44785a5` in `tests/conformance/vectors/wba-profile/`, provenance in its `UPSTREAM.json`); the identity schemas are pinned to the commits in `src/adcp/signing/_identity_schemas/UPSTREAM.json`. Both may change before the protocol release. The stable wire pin and `COMPATIBLE_ADCP_VERSIONS` do not advertise 3.3 yet.
This SDK supports an opt-in preview of issue [#1500](https://github.com/adcontextprotocol/adcp-client-python/issues/1500). The Web Bot Auth wire profile follows `wba-profile.mdx` in adcontextprotocol/adcp#7894 at `9f472d63` (vectors from adcontextprotocol/adcp#8298 at `f44785a5` in `tests/conformance/vectors/wba-profile/`, provenance in its `UPSTREAM.json`); the identity schemas are the ones in the signed AdCP 3.3.0-beta.0 bundle the SDK pins (`schemas/releases/3.3.0-beta.0.json`). Both may change before the protocol's 3.3 GA. The wire pin is `3.3.0-beta.0` and `COMPATIBLE_ADCP_VERSIONS` advertises `3.3-beta.0` as the exact pre-release, beside 3.0, 3.1 and 3.2.

The behavior below follows the final spec decisions (adcontextprotocol/adcp#8162, #8168, #8169, #8170) and matches the Go (`adcp-go`) and TypeScript (`@adcp/sdk/identity-3.3`) SDKs, except where [Differences from the other SDKs](#differences-from-the-other-sdks) says otherwise.

Expand Down Expand Up @@ -224,9 +224,9 @@ Typed client results preserve `adcp_error`, including its code, recovery guidanc

Use the preview `RequestSigning` model (`adcp.types.experimental_identity`) to advertise `profiles=["adcp/request-signing/v1", "web-bot-auth"]` on a server accepting both. The preview reader models preserve unknown onboarding requirement kinds so applications can fall back to the posture's message and URL; unknown kinds cannot be satisfied automatically. Authoring validation still enforces the pinned schema, including its conditionals: `aao_verified` requires `role`, and `storyboard` and `experimental_feature` require `id`. A trust record whose posture breaks them fails validation, for readers as for authors.

The schemas are copied from adcp main at the commit in `src/adcp/signing/_identity_schemas/UPSTREAM.json`, after #8168, #8169 and #8170 merged: the buyer posture lives only in trust.json, at `profiles.adcp.onboarding` on the record and on an agent entry; one mode enum (`open`, `application`, `invite_only`) serves sellers and buyers; the `agent_identity` requirement kind and `documentation_url` are gone; `aao_verified` uses `verified_specialisms`; `relationship.status` uses `pending_approval`.
The schemas are the 3.3.0-beta.0 bundle's (`core/agent-onboarding.json`, `core/buyer-onboarding-posture.json`, `core/principal-relationship.json`, `trust/v1/trust.json` and their enums), the same documents the earlier preview vendored from adcp main after #8168, #8169 and #8170 merged: the buyer posture lives only in trust.json, at `profiles.adcp.onboarding` on the record and on an agent entry; one mode enum (`open`, `application`, `invite_only`) serves sellers and buyers; the `agent_identity` requirement kind and `documentation_url` are gone; `aao_verified` uses `verified_specialisms`; `relationship.status` uses `pending_approval`.

Import experimental models from `adcp.types.experimental_identity`: `AgentOnboarding`, its modes/tiers/requirements, `BuyerOnboardingPosture`, `TrustRecord`, `GetPrincipalResponse`, `PrincipalRelationship`, `PrincipalRelationshipStatus`, `PrincipalChangedWebhook`, and `GrantAbsentDetails`. Generate the private models offline with `python scripts/generate_identity_preview.py`; validate behavioral constraints with the trust helpers.
Import experimental models from `adcp.types.experimental_identity`: `AgentOnboarding`, its modes/tiers/requirements, `BuyerOnboardingPosture`, `TrustRecord`, `GetPrincipalResponse`, `PrincipalRelationship`, `PrincipalRelationshipStatus`, `PrincipalChangedWebhook`, and `GrantAbsentDetails`. They are the generated 3.3 types (`adcp.types.domains.core.*`, `adcp.types.domains.trust.v1.trust`) under those names; validate behavioral constraints with the trust helpers.

For preview `principal.changed` reasons, pass `experimental_agent_identity=True` to `WebhookSender.prepare_principal_changed` or `send_principal_changed`, and again to `send_prepared` or `resend` when publishing persisted events.

Expand Down
Loading
Loading