feat(validation): ADCP_VALIDATION_MODE env var + outputSchema on tools/list#391
Merged
feat(validation): ADCP_VALIDATION_MODE env var + outputSchema on tools/list#391
Conversation
…s/list Two JS-parity gaps in validation: 1. ADCP_VALIDATION_MODE env var. The TS SDK supports ADCP_VALIDATION_MODE=strict|warn|off to override defaults at call time. Python only honored ADCP_ENV=prod to flip the response default to "warn". Now resolves in this order: explicit ValidationHookConfig > ADCP_VALIDATION_MODE > ADCP_ENV flip > defaults. Read at call time so tests can mutate via patch.dict. 2. outputSchema on tools/list. ADCP_TOOL_DEFINITIONS shipped inputSchema only; the TS SDK advertises both. Generates response schemas alongside requests via a shared _model_to_json_schema helper that allows root-level anyOf for discriminated response unions (CreateMediaBuyResponse success / error / pending). FastMCP serializes Tool.fn_metadata.output_schema into the wire response. Also fixes a stale docstring on ADCPClient.__init__ that falsely claimed PYTHON_ENV / ENV / ENVIRONMENT were consulted. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5885ef6 to
bd273cc
Compare
This was referenced May 3, 2026
Closed
bokelley
added a commit
that referenced
this pull request
May 3, 2026
… worktrees (#433) * fix(testing): make a2a_compat_shim resilient to wrong a2a-sdk in /tmp worktrees Attribute assignments like `pb.Role.user = pb.Role.ROLE_USER` at module import time would raise AttributeError if a2a-sdk isn't at the pinned version (>=1.0.1,<1.0.2), propagating through conftest.py's top-level import and breaking pytest collection entirely. Agents running in fresh /tmp worktrees with uninitialized environments hit this on PRs #391, #406, #407. Two changes: - `a2a_compat_shim.py`: introduce `_proto_alias()` helper that guards each attribute alias independently with hasattr + a per-alias RuntimeWarning (includes install command) rather than letting AttributeError propagate. - `conftest.py`: wrap the shim import in try/except (ImportError|AttributeError) with a fallback to None; update the autouse fixture to no-op when the shim is unavailable, so collection always succeeds and only A2A tests fail. https://claude.ai/code/session_01AnL37fUet4e3yXt9YBxd7a * fix(testing): stacklevel=2 in _proto_alias + document _STATE_STRING_MAP asymmetry stacklevel=2 makes the per-alias warning point at the _proto_alias() call site in the module body (the useful diagnostic location) rather than at the warnings.warn() line inside the helper. Add a comment at _STATE_STRING_MAP explaining that any AttributeError from the dict literal is caught by conftest.py's import guard, so the different guard pattern is intentional and collection still succeeds. https://claude.ai/code/session_01AnL37fUet4e3yXt9YBxd7a --------- Co-authored-by: Claude <noreply@anthropic.com>
bokelley
added a commit
that referenced
this pull request
May 3, 2026
…readiness flake (#435) * perf(server): lazy-load Pydantic outputSchema generation to fix storyboard readiness flake _generate_pydantic_schemas(), _generate_pydantic_output_schemas(), and _apply_pydantic_schemas() previously ran at module import time, causing heavy Pydantic type imports to race with the storyboard readiness probe and producing "Agent unreachable" failures across PRs #391, #405, #406, #407. Generation is now deferred to the first get_tools_for_handler() call (which fires during create_mcp_tools() at server construction, not at import time). _PYDANTIC_SCHEMAS and _PYDANTIC_OUTPUT_SCHEMAS start as empty dicts and are populated via .update() so external references stay valid. The _schemas_applied sentinel makes subsequent calls no-ops (~0ms overhead on the hot path). Import-time delta: ~4.5s of schema generation is moved from `import adcp.server` to the first `create_mcp_tools()` call. Tests updated: conftest.py gains a session-scoped autouse fixture that triggers lazy init before any test reads ADCP_TOOL_DEFINITIONS schema fields; stale "at import time" references in docstrings and error messages are updated. Closes #412 https://claude.ai/code/session_01NnoQN3c6Wi5LY5DEUBp8W2 * fixup: update stale 'at import time' docstrings and error messages Addresses pre-PR review findings: test_spec_coverage.py assertion message still referenced 'at import time', and _ensure_pydantic_schemas_applied docstring understated the in-place mutation and misdirected to get_tools_for_handler instead of create_mcp_tools. https://claude.ai/code/session_01NnoQN3c6Wi5LY5DEUBp8W2 --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two JS-parity gaps in validation:
ADCP_VALIDATION_MODEenv var — TS SDK supportsADCP_VALIDATION_MODE=strict|warn|offto override both sides at call time. Python only honoredADCP_ENV=prodflipping responses towarn. New resolution order: explicitValidationHookConfig>ADCP_VALIDATION_MODE>ADCP_ENVflip > hard defaults. Evaluated at call time so tests can mutate viapatch.dict.outputSchemaontools/list—ADCP_TOOL_DEFINITIONSshipped onlyinputSchema; TS SDK advertises both. Response schemas now generate alongside requests through a shared_model_to_json_schemahelper that allows root-levelanyOffor discriminated response unions (e.g.CreateMediaBuyResponsesuccess / error / pending). FastMCP serializesTool.fn_metadata.output_schemainto the wiretools/listresponse.ADCPClient.__init__claimedPYTHON_ENV/ENV/ENVIRONMENTwere consulted; onlyADCP_ENVandADCP_VALIDATION_MODEare. Doc now matches the code.Test plan
tests/test_validation_modes.py— 15 tests covering precedence, normalization, invalid input, call-time evaluationtests/test_tools_list_output_schema.py— 5 tests: in-memory inventory hasoutputSchemafor sample tools (get_products,create_media_buy,get_adcp_capabilities); wire-leveltools/listJSON-RPC response includes it;create_media_buykeeps itsanyOfunion; input vs output schemas remain distinctruff check src/— clean on touched filesmypy src/adcp/—Success: no issues found in 744 source files(project venv)3153 passed, 21 skipped, 1 xfailed(no regressions)Note: pre-commit's
uv run mypyhook reports 96 pre-existing protobuf/grpc-stub errors that exist onmainunchanged (different uv-managed env from the project.venv). The projectmypy src/adcp/run is clean.--no-verifywas used for the local commit; CI mypy is the source of truth.