Skip to content

feat(adagents): add validate_adagents_structure helper#708

Merged
bokelley merged 3 commits into
mainfrom
bokelley/validate-adagents-helper
May 12, 2026
Merged

feat(adagents): add validate_adagents_structure helper#708
bokelley merged 3 commits into
mainfrom
bokelley/validate-adagents-helper

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Summary

  • Adds validate_adagents_structure(data) -> AdagentsValidationReport in adcp.adagents. Lets callers distinguish a schema-invalid adagents.json from a valid file that doesn't list the caller's agentget_properties_by_agent() collapses both into [] today, which made the wonderstruck.org-style bare-entry case from feat: helper to distinguish schema-invalid adagents.json from "agent not authorized" #707 indistinguishable from "publisher hasn't authorized us yet."
  • New result types: AdagentsValidationReport (with schema_valid, errors, authorized_agents_count, properties_count) and AdagentsEntryError (with index, url, kind, message). Error kinds: missing_url, missing_authorized_for, missing_authorization_type, unknown_authorization_type, missing_selector_for_type, not_an_object.
  • Checks every authorized_agents entry against the AdCP schema's oneOf discriminated union (six authorization_type variants, each with its required selector array).

Naming

The issue proposed validate_adagents; I went with validate_adagents_structure to avoid colliding with the existing adcp.validation.validate_adagents (legacy raise-on-error helper, exported at top level and still used internally). The new name pairs cleanly with the existing validate_adagents_domain (network fetch + discovery) — domain validates a publisher domain end-to-end, structure validates pre-fetched data per-entry.

Closes #707

Test plan

  • 13 new tests in TestValidateAdagentsStructure covering: all six authorization types valid, bare entries (the wonderstruck case from the issue), unknown authorization_type, mismatched selector for type, empty selector array (minItems:1), missing url/authorized_for, non-object entries, authoritative_location URL-reference variant, non-dict/non-list raises, and the headline "distinguishes invalid file from unlisted agent" case.
  • pytest tests/test_adagents.py — 119 passed.
  • pytest tests/test_adagents.py tests/test_registry_new.py tests/test_registry_types_drift.py tests/test_schema_validation.py — 292 passed.
  • ruff check src/ tests/test_adagents.py — clean.
  • mypy src/ — clean (801 source files).

🤖 Generated with Claude Code

bokelley and others added 3 commits May 12, 2026 17:58
Distinguishes a schema-invalid adagents.json from a valid file that
doesn't list the caller's agent. get_properties_by_agent() collapses
both cases into [], which makes "publisher hasn't authorized us yet"
indistinguishable from "publisher's file is structurally broken" and
forces callers to inspect entries themselves.

The new validate_adagents_structure(data) -> AdagentsValidationReport
checks every authorized_agents entry against the AdCP schema's oneOf
discriminated union (six authorization_type variants, each with a
required matching selector). Returns per-entry errors with index, url,
kind, and message — so callers like aao_lookup_service can show
"publisher's file is invalid" vs "you aren't listed" without
re-implementing the schema.

The companion helper validate_adagents_domain (network fetch +
discovery) is unchanged. Naming pairs with that existing function;
avoids collision with the legacy adcp.validation.validate_adagents.

Closes #707

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add is_reference flag on AdagentsValidationReport so callers can
  distinguish a legitimate authoritative_location URL-reference file
  from an inline file with zero entries (which is itself invalid).
- Enforce authorized_agents minItems: 1 on inline variant via new
  empty_authorized_agents error kind (file-level error, index=-1).
- Tighten authorized_for check to require a non-empty string; previously
  truthy non-strings (e.g., numbers, lists) silently passed.
- Normalize empty-string url to None so AdagentsEntryError.url is
  always either a usable identifier or None.
- Export EntryErrorKind from top-level adcp so callers can pattern-match
  exhaustively.
- Cross-link validate_adagents_structure from fetch_adagents docstring;
  document 3.0 schema target and selector-item validation as
  out-of-scope.
- Tests: 3 new (authoritative_location is_reference, empty array
  invalid, non-string authorized_for/url) + tighten FrozenInstanceError
  assertion + non-empty fixture for the immutability test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds AdagentsEntryError, AdagentsValidationReport, EntryErrorKind, and
validate_adagents_structure to the snapshot — all intentional additions
in this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley merged commit ccd1955 into main May 12, 2026
16 checks passed
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.

feat: helper to distinguish schema-invalid adagents.json from "agent not authorized"

1 participant