Repository navigation
Fix strict-mode wire schema to actually be strict-tool-use compatible - #101
Merged
Merged
Conversation
v0.2.3's strict: true broke every Anthropic-backed review outright -- Finding.confidence's ge/le bounds and _FindingsResponse.findings' max_length render as minimum/maximum/maxItems, none of which strict tool use's supported JSON Schema subset allows, so the API rejected the request with a 400 on every single call. Strips those keywords from the wire schema (pydantic still enforces them locally on the response) and rewrites a nullable anyOf into the single-type-array form Anthropic's docs describe. Includes a regression test built directly against _FindingsResponse. Relates to ISSUE-96 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The denylist in the previous commit was missing uniqueItems -- a gap found by review. Switched to two explicit lists: keywords confirmed unsupported (stripped, pydantic still enforces them locally) and keywords confirmed supported (kept as-is). Anything in neither list raises ValueError immediately instead of silently passing an unvetted keyword through, which is exactly how v0.2.3 shipped broken in the first place. Relates to ISSUE-96 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <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
This fixes a production regression from v0.2.3, which made every Anthropic-backed review fail 100% of the time.
AnthropicProvider.generate_structured'sstrict: truetool definition was rejected outright by the API (400 invalid_request_error:"For 'number' type, properties maximum, minimum are not supported") on every single call, becauseFinding.confidence'sge=0.0, le=1.0and_FindingsResponse.findings'max_lengthrender asminimum/maximum/maxItems-- keywords outside strict tool use's supported JSON Schema subset. Unlike the pre-v0.2.3 failure mode (intermittent, sometimes worked), this failed deterministically every time, making v0.2.3 strictly worse than v0.2.2 for anyone with an Anthropicmodels.reviewerconfigured._strict_input_schemanow adapts the wire schema before sending it: strips confirmed-unsupported keywords (minimum,maximum,exclusiveMinimum,exclusiveMaximum,multipleOf,minLength,maxLength,maxItems,uniqueItems), rewrites a nullable field'sanyOf: [{type: X}, {type: "null"}](pydantic's rendering ofX | None) into the{"type": [X, "null"]}form Anthropic's docs describe, and validatesadditionalProperties: falsewherever it appears. Pydantic's own validation of the response still enforces the stripped bounds locally -- only the server-side guarantee for that bound is lost, not the check itself.uniqueItems, caught in review): the final version checks every schema keyword against two explicit lists -- confirmed-unsupported (stripped) and confirmed-supported (kept) -- and raisesValueErrorimmediately on anything in neither. A keyword nobody's vetted yet now fails a test the moment a new constrained field is added, instead of silently shipping to production the way this regression did._FindingsResponseschema, plus tests for the allowlist's fail-loud behavior on an unvetted keyword (e.g.pattern) and theuniqueItemsgap specifically.Relates to #96 -- not a new issue, this is the correction to the fix from #99.
Test plan
make lint-- cleanmake test-- 165 passed, including:_FindingsResponseschema asserting no forbidden keyword leaks into the sent requestconfidence'sge/le) still reject an out-of-range value locally, proving the server-side guarantee loss doesn't become a client-side gap toopattern) raisesValueErrorbefore any request is sentuniqueItems(the exact gap found in review of the first draft) is confirmed stripped🤖 Generated with Claude Code