Skip to content

feat(schema): address 17 schema gaps that block autonomous agent operation#1252

Merged
bokelley merged 31 commits intomainfrom
bokelley/fix-schema-issues
Feb 28, 2026
Merged

feat(schema): address 17 schema gaps that block autonomous agent operation#1252
bokelley merged 31 commits intomainfrom
bokelley/fix-schema-issues

Conversation

@bokelley
Copy link
Contributor

@bokelley bokelley commented Feb 27, 2026

Summary

Resolves 17 must-have schema gaps identified in issues #1223-#1239 that prevent agents from operating autonomously, plus 7 additional consistency issues (#1242-#1250). Issue #1230 (targeting_overlay semantics) was already resolved in a prior commit.

Original schema gaps (#1223-#1239)

Consistency fixes (#1242-#1250)

Additional refinements

  • Package.catalogPackage.catalogs (array) for multi-catalog packages (breaking)
  • PackageUpdate.catalogPackageUpdate.catalogs (array) to match
  • Remove idempotency_key from CreateMediaBuyRequest (buyer_ref is the dedup key)
  • Soften x-adcp-version from MUST HTTP header to MAY
  • product_ids and proposal_id forbidden via false in brief/wholesale schema variants
  • PRODUCT_NOT_FOUND added to error-code enum (distinct from PRODUCT_UNAVAILABLE)
  • Filter-vs-brief precedence documented (filters are hard constraints on publisher curation)
  • reach optimization goal documented with reach_unit and target_frequency fields
  • account field added to sync-creatives-request embedded examples

Specification alignment

All RFC-style specification docs updated to match schema changes:

  • Error handling docs: recovery field, recovery-based categorization, RATE_LIMITED code
  • Media buy spec: rejected status, idempotency_key, buying_mode: refine with product/proposal refinement
  • Signals spec & task docs: account ref, destinations, action field, signal metadata
  • Property list spec & task docs: optional countries_all/channels_any filters
  • Task reference index: updated descriptions and workflow sections, fixed step numbering
  • Product discovery docs: "Iterating on Proposals" rewritten for explicit refine mode
  • get_products docs: all examples include buying_mode, refinement section with product/proposal/refresh examples
  • Optimization docs: reach metric added to metrics table and strategy guide

Split to separate PRs (per review)

Tracked for future work

Expert decisions (no change needed)

Breaking changes

  • SyncCreativesRequest.assignments type changed from object to typed array
  • ActivateSignalRequest.deployments renamed to destinations
  • ActivateSignalRequest.account_idaccount: AccountReference
  • GetSignalsRequest.account_idaccount: AccountReference
  • Package.catalogPackage.catalogs (array)
  • PackageUpdate.catalogPackageUpdate.catalogs (array)
  • buying_mode now required on get_products (was optional)
  • product_ids and proposal_id rejected in brief/wholesale modes

Changeset set to major.

Test plan

  • 304/304 tests pass (npm test)
  • OpenAPI spec rebuilt and committed
  • All new schemas registered in index.json
  • Doc examples updated for field renames
  • Specification docs aligned with all schema changes
  • All doc examples include buying_mode
  • Schema enforces refine-only fields via false boolean schema
  • Four rounds of expert review (protocol, product, code) — all findings addressed
  • Pre-commit hooks pass (schema validation, broken links, accessibility)
  • CI: all checks green

Closes #1223, #1224, #1225, #1226, #1227, #1229, #1231, #1232, #1233, #1234, #1235, #1237, #1238, #1239, #1242, #1244, #1245, #1246, #1247, #1248, #1250

🤖 Generated with Claude Code

bokelley added a commit that referenced this pull request Feb 27, 2026
Update specification and task reference docs to match schema changes
from PR #1252:

- Signals: deployments → destinations in request-side docs, add action
  and account fields to activate_signal and get_signals docs
- Property governance: mark countries_all/channels_any as optional
- Error handling: add recovery field, standard error codes from
  enums/error-code.json, update code examples to use recovery
- Media buy: add get_forecast task reference page and spec section,
  document rejected status, add idempotency_key for mutations,
  fix conformance task count

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 27, 2026

Schema Link Check Results

Commit: 3b38684 - fix: replace undocumented BILLING_MODEL_NOT_SUPPORTED error code

⚠️ Warnings (schema not yet released)

These schemas exist in source but haven't been released yet. The links will be broken until the next version is published:

  • https://adcontextprotocol.org/schemas/v1/media-buy/get-media-buy-delivery-request.json
    • No releases found for version v1 yet
  • https://adcontextprotocol.org/schemas/v1/media-buy/get-media-buy-delivery-response.json
    • No releases found for version v1 yet
  • https://adcontextprotocol.org/schemas/v2/media-buy/sync-audiences-request.json
    • Schema exists in latest (source) but not yet released in v2
    • Action: This link will work after next 2.x release is published
  • https://adcontextprotocol.org/schemas/v2/media-buy/sync-audiences-response.json
    • Schema exists in latest (source) but not yet released in v2
    • Action: This link will work after next 2.x release is published

To fix: Either:

  1. Wait for the next release and merge this PR after the release is published
  2. Use latest instead of a version alias if you need the link to work immediately (note: latest is the development version and may change)
  3. Coordinate with maintainers to cut a new release before merging

bokelley and others added 13 commits February 27, 2026 16:28
…ation (#1223-#1239)

Error handling: add `recovery` classification field to Error, new error-code enum vocabulary
Idempotency: add `idempotency_key` to CreateMediaBuyRequest, UpdateMediaBuyRequest, SyncCreativesRequest
Media buy lifecycle: add `rejected` status and `rejection_reason` to MediaBuy
Protocol version: document x-adcp-version header requirement in capabilities response
Async polling: add `polling` object to capabilities media_buy section
Capabilities completeness: add `async_tasks`, `supports_proposals`, `limits` to capabilities
Package response: echo `catalog` and `format_ids` back from create request
Signal deactivation: add `action: activate | deactivate` to ActivateSignalRequest
Signal metadata: add `categories` and `range` to signal entries in GetSignalsResponse
Property list filters: make `countries_all` and `channels_any` optional
Content standards response: replace flat object with success/error discriminated union
Forecast task: new `get_forecast` task with GetForecastRequest and GetForecastResponse
Performance feedback: add metric_value, metric_unit, measurement_provider, measurement_methodology, feedback_type; deprecate performance_index
Creative assignments: replace ambiguous map with typed array including weight and placement_ids
Batch preview: add required success/creative_id to results, fix errors array type
Creative delivery pagination: replace limit/offset with standard PaginationRequest

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ssues

PR review comments:
- catalog → catalogs (array) on Package and PackageRequest (#comment-1)
- Remove idempotency_key from CreateMediaBuyRequest; buyer_ref is the dedup key (#comment-3)
- Soften x-adcp-version from MUST HTTP header to MAY; version via capabilities handshake (#comment-4)
- Revert async_tasks, supports_proposals, limits from capabilities (split to separate PR) (#comment-5)
- Revert metric_value/metric_unit/feedback_type from performance feedback (split to separate PR) (#comment-6)

New issues:
- #1242: signals account_id: string → account: $ref account-ref.json
- #1244: activate-signal deployments → destinations
- #1245: add optional account to get-creative-features-request
- #1246: extract consent_basis to enums/consent-basis.json
- #1247: extract date-range.json and datetime-range.json, replace inline periods
- #1248: clarify get_creative_features description (evaluation, not discovery)
- #1250: remove ajv-specific errorMessage from sync-audiences-request

Expert decisions (no change):
- #1243: keep AccountReference implicit discrimination (protocol expert)
- #1249: keep signal_agent_segment_id (protocol expert)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update specification and task reference docs to match schema changes
from PR #1252:

- Signals: deployments → destinations in request-side docs, add action
  and account fields to activate_signal and get_signals docs
- Property governance: mark countries_all/channels_any as optional
- Error handling: add recovery field, standard error codes from
  enums/error-code.json, update code examples to use recovery
- Media buy: add get_forecast task reference page and spec section,
  document rejected status, add idempotency_key for mutations,
  fix conformance task count

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rkflow

Address review comment: explain why get_forecast operates on one product
(parameters are product-specific), how to compare products (parallel
calls), and that portfolio-level cross-product forecasting is out of scope.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of a separate get_forecast task, extend get_products with a
product_ids array for refreshing forecasts on known products. This keeps
the iterative discovery workflow in-band — agents call get_products with
a brief for discovery, then re-call with product_ids to refine budgets,
dates, and targeting without re-discovering inventory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the standalone product_ids approach with a proper buying_mode
variant. buying_mode is now always required with three values: brief
(curated discovery), wholesale (raw catalog), and refine (iterate on
known products with updated forecasts, pricing, and packages).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Polling is a transport-level concern that applies to all async tasks
across all domain protocols, not just media buys. Move it to
adcp.polling alongside major_versions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refine mode now accepts product_ids, proposal_id, or both. This lets
agents iterate on a seller's proposed media plan — adjusting budgets,
dates, and allocations — using the same refinement loop as individual
products.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add PRODUCT_NOT_FOUND and PROPOSAL_EXPIRED error codes
- Add refresh-only refine example (product_ids without brief)
- Document combo semantics (product_ids + proposal_id)
- Add notes on proposal lifecycle and product ID stability
- Fix duplicate step numbering in Getting Started
- Align media-products.mdx with refine mode patterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…y fields

- Add PRODUCT_NOT_FOUND error code to enum (distinct from PRODUCT_UNAVAILABLE)
- Forbid product_ids and proposal_id in brief/wholesale variants via `false`
- Fix "package details" → "product configurations" in schema description
- Clarify expires_at is optional on proposals
- Clarify filter-vs-brief precedence in docs
- Update doc: refine-only fields are rejected, not silently ignored
- Remove stale .md files (Docusaurus → Mintlify migration artifacts)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Align PRODUCT_NOT_FOUND description with enum (were never valid, not no longer available)
- Rename package-update.json catalog → catalogs array (matches package.json)
- Add required account field to sync-creatives-request examples
- Document reach optimization in optimization goals (schema already has it)
- Add reach metric to metrics table and choosing-a-strategy table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix RATE_LIMIT_EXCEEDED → RATE_LIMITED across 5 doc files (matches enum)
- Add ACCOUNT_SETUP_REQUIRED and ACCOUNT_AMBIGUOUS to error-code enum
- Add rejected to delivery response inline status enum (matches media-buy-status)
- Remove TIMEOUT from isRetryable() example (not a domain error code)
- Update index.json lastUpdated to 2026-02-27

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… review

- media-products.mdx: formats → format_ids, add publisher_properties and
  delivery_measurement to field list, add publisher_properties to product examples
- specification.mdx: add sync_audiences task (twelve → thirteen), add requirements
- task-reference/index.mdx: add sync_audiences to overview table, response time
  categories, and workflow categories
- update_media_buy.mdx: add catalogs, keyword_targets_add/remove,
  negative_keywords_add/remove to Package Update Object table
- list-creatives-response.json: add missing delivery_type discriminator to VAST
  asset example

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bokelley and others added 2 commits February 28, 2026 07:13
Billing periods are calendar dates, but the buyer needs to know the
seller's timezone to interpret where day boundaries fall. A seller
billing in America/Los_Angeles and a buyer in America/New_York will
see different spend for the same calendar date without this.

Required field — sellers MUST return their billing timezone as an IANA
timezone string alongside period, currency, and account.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use UNSUPPORTED_FEATURE (already in error-code enum) in financials
response example and docs error table.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bokelley bokelley merged commit 544230b into main Feb 28, 2026
8 checks passed
This was referenced Feb 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error.code has no standardized vocabulary; agents cannot classify errors for autonomous recovery

2 participants