#23507: fix(tools): strip patternProperties from schemas for OpenAI-compatible providers
agents
size: S
Cluster:
Tool Schema Fixes and Enhancements
## Summary
- TypeBox's `Type.Record(Type.String(), ...)` compiles tool parameter schemas with a `patternProperties` key, which most OpenAI-compatible APIs (e.g. RouteLLM) reject with HTTP 400 `"Validation Error: \"patternProperties\" - Extra inputs are not permitted"`
- Add a recursive `stripPatternProperties()` helper in `normalizeToolParameters()` that removes `patternProperties` before the schema is sent to non-Anthropic, non-Gemini providers
- Anthropic handles the field natively; Gemini already goes through the more aggressive `cleanSchemaForGemini()` path which covers this keyword
## Test plan
- [ ] Run agent with RouteLLM model — `exec` tool (which has `env: Type.Record(...)`) no longer causes HTTP 400
- [ ] Verify Anthropic and Gemini providers are unaffected
- [ ] Existing unit/e2e tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Added a `stripPatternProperties()` helper function that recursively removes `patternProperties` from JSON schemas before sending them to OpenAI-compatible providers like RouteLLM. TypeBox's `Type.Record(Type.String(), ...)` generates schemas with `patternProperties`, which most OpenAI-compatible APIs reject. The fix applies only to non-Anthropic, non-Gemini providers - Anthropic handles the field natively, while Gemini already uses the more aggressive `cleanSchemaForGemini()` which removes this keyword.
The implementation correctly:
- Strips top-level `patternProperties` keys
- Recursively processes nested schemas in `properties`, `items`, `anyOf`, `oneOf`, and `allOf`
- Integrates cleanly into all three code paths in `normalizeToolParameters()`
- Preserves existing behavior for Anthropic and Gemini providers
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The implementation is well-documented, follows existing code patterns, and correctly addresses the OpenAI-compatible provider issue. The recursive stripping logic appropriately handles all cases where `patternProperties` would appear in TypeBox-generated schemas. The fix is properly scoped to only affect non-Anthropic, non-Gemini providers, preserving existing behavior for those providers.
- No files require special attention
<sub>Last reviewed commit: 30d90c1</sub>
<!-- greptile_other_comments_section -->
<sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#22214: fix(tools): sanitize google-antigravity schemas for Gemini-compatib...
by Kansodata · 2026-02-20
83.8%
#22321: fix: sanitize tool schemas for all Cloud Code Assist providers
by Sr-0w · 2026-02-21
83.2%
#21835: fix: apply schema cleaning for google-antigravity in normalizeToolP...
by ephraimm · 2026-02-20
80.4%
#12642: feat(tools): typed tool schemas for xAI/Grok compatibility
by 2nd-ren · 2026-02-09
79.5%
#20249: fix(schema): ensure normalizeToolParameters always includes propert...
by aldoeliacim · 2026-02-18
78.9%
#13976: fix(anthropic): include Anthropic in tool call ID sanitization
by omair445 · 2026-02-11
76.1%
#13831: fix(agents): include Anthropic in tool call ID sanitization
by lailoo · 2026-02-11
75.5%
#12812: fix(transcript-policy): sanitize tool call IDs for all non-OpenAI p...
by justin-nevins · 2026-02-09
75.3%
#4964: fix: strip null-valued optional parameters from tool calls for prov...
by umut-polat · 2026-01-30
75.2%
#14499: fix: strip propertyNames from tool schemas for Gemini API [AI-assis...
by pm990320 · 2026-02-12
74.4%