Carry additionalProperties through the Anthropic tool input_schema so it matches functool strict validation - #724
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the Anthropic provider’s tool schema construction to preserve full JSON Schema semantics (notably additionalProperties: false) so the schema sent to the model matches the stricter Go-side functool validation behavior, aligning Anthropic with the existing OpenAI/Gemini providers.
Changes:
- Forward non-
properties/requiredJSON Schema keywords intoanthropic.ToolInputSchemaParam.ExtraFieldsso they are included in the serializedinput_schema. - Add a regression test that captures the outbound Anthropic request and asserts
tools[0].input_schema.additionalProperties == false.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| provider/anthropicprovider/agent.go | Preserves additional JSON Schema keywords by copying them into ToolInputSchemaParam.ExtraFields when building Anthropic tool params. |
| provider/anthropicprovider/agent_test.go | Adds a request-capture test asserting additionalProperties: false is present in the tool input_schema. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This comment has been minimized.
This comment has been minimized.
The Anthropic provider built ToolInputSchemaParam from only the schema's properties and required keywords, discarding additionalProperties:false that functool's strict schema emits. funcTool.Call validates decoded arguments against the resolved schema, so a hallucinated extra argument passed the model but was rejected Go-side. Carry the remaining schema keywords through ExtraFields so the model-facing schema matches functool validation, mirroring the OpenAI and Gemini providers which forward the full schema.
af493ea to
f118b3d
Compare
API Consistency Review — PR #724Scope: Internal bug fix in Parity verdict: ✅ This change restores cross-provider consistency rather than introducing divergence. What was checked
Conclusion: No parity issues. The Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
What
The Anthropic provider builds
anthropic.ToolInputSchemaParamfrom a func tool's schema by copying only thepropertiesandrequiredkeywords and discarding everything else. In particular it dropsadditionalProperties:false, which functool's strict schema always emits.This change copies the remaining schema keywords into
ToolInputSchemaParam.ExtraFields(which the anthropic-sdk-go marshals viaMarshalWithExtras), so the model-facing schema stays in sync with the Go-side validation.Why
funcTool.Callrunshandler -> inputFormat.Unmarshal -> applySchema -> validate -> resolved.Validate, and the resolved schema rejects extra properties. Because the Anthropic path told the model nothing aboutadditionalProperties, a hallucinated extra argument would pass the model but then fail functool validation on the Go side — an asymmetry that only affected Anthropic.This restores cross-SDK parity: the OpenAI provider forwards the whole schema map (
schemaToMapreturns the full map) and the Gemini provider setsdecl.ParametersJsonSchema = schema. Only Anthropic was stripping keywords. Matching the other providers keeps behavior aligned with the .NET/Python semantics where the declared tool schema and the validated schema are the same.How it is tested
Added
TestToolInputSchemaCarriesAdditionalPropertiesinagent_test.go. It builds a tool viafunctool.MustNewover a struct argument, runs the agent through the existing fake-transport harness, captures the request body, and assertstools[0].input_schema.additionalProperties == false. The test fails before the fix (keyword omitted) and passes after.