fix: fix broken tool spec with composition keywords #1301
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.
fix: Handle all JSON Schema composition keywords in tool property normalization
Description
This PR extends #1226 to handle all JSON Schema composition keywords, not just
anyOf. The original fix addressed issue #1190 where MCP tools withList[str] | Noneparameters caused models to return string-encoded JSON ('["foo", "bar"]') instead of proper arrays.Root Cause:
_normalize_property()was addingtype: "string"to properties that already had type constraints defined via composition keywords, creating invalid JSON Schema.Fix: Skip setting default
type: "string"when any composition keyword is present:anyOf- Union types (e.g.,Optional[T],str | int)oneOf- Exclusive unions (exactly one must match)allOf- Schema intersection (all must match)not- Negation (value must not match)Added
COMPOSITION_KEYWORDSconstant for maintainability and applied fix to bothtools.pyandregistry.py.Related Issues
Changes
src/strands/tools/tools.pyCOMPOSITION_KEYWORDSconstant, updated_normalize_property()src/strands/tools/registry.pyvalidate_tool_spec()tests/strands/tools/test_registry.pyTesting
Test Results
Tool Types Tested
@tooldecorator withOptional[List[str]],Optional[Dict],UniontypesPythonAgentTool) with anyOf in TOOL_SPECReal LLM Integration Tests
Verified agent correctly passes Python types (not string-encoded JSON):
Backwards Compatibility Verified
type: "string"✓$refproperties not modified ✓Checklist
hatch run prepare