Skip to content

Carry additionalProperties through the Anthropic tool input_schema so it matches functool strict validation - #724

Open
PratikDhanave wants to merge 1 commit into
microsoft:mainfrom
PratikDhanaveFork:carry-additionalproperties-anthropic-schema
Open

Carry additionalProperties through the Anthropic tool input_schema so it matches functool strict validation#724
PratikDhanave wants to merge 1 commit into
microsoft:mainfrom
PratikDhanaveFork:carry-additionalproperties-anthropic-schema

Conversation

@PratikDhanave

Copy link
Copy Markdown
Contributor

What

The Anthropic provider builds anthropic.ToolInputSchemaParam from a func tool's schema by copying only the properties and required keywords and discarding everything else. In particular it drops additionalProperties:false, which functool's strict schema always emits.

This change copies the remaining schema keywords into ToolInputSchemaParam.ExtraFields (which the anthropic-sdk-go marshals via MarshalWithExtras), so the model-facing schema stays in sync with the Go-side validation.

Why

funcTool.Call runs handler -> inputFormat.Unmarshal -> applySchema -> validate -> resolved.Validate, and the resolved schema rejects extra properties. Because the Anthropic path told the model nothing about additionalProperties, 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 (schemaToMap returns the full map) and the Gemini provider sets decl.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 TestToolInputSchemaCarriesAdditionalProperties in agent_test.go. It builds a tool via functool.MustNew over a struct argument, runs the agent through the existing fake-transport harness, captures the request body, and asserts tools[0].input_schema.additionalProperties == false. The test fails before the fix (keyword omitted) and passes after.

Copilot AI review requested due to automatic review settings July 24, 2026 03:19
@PratikDhanave
PratikDhanave requested a review from a team as a code owner July 24, 2026 03:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/required JSON Schema keywords into anthropic.ToolInputSchemaParam.ExtraFields so they are included in the serialized input_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.

@github-actions github-actions Bot added the parity-approved Go API consistency review found no parity issues label Jul 24, 2026
@github-actions

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.
@PratikDhanave
PratikDhanave force-pushed the carry-additionalproperties-anthropic-schema branch from af493ea to f118b3d Compare July 24, 2026 09:30
@github-actions

Copy link
Copy Markdown
Contributor

API Consistency Review — PR #724

Scope: Internal bug fix in provider/anthropicprovider — no exported Go APIs changed.

Parity verdict: ✅ This change restores cross-provider consistency rather than introducing divergence.

What was checked

  • Go internal change only: The affected code is in the unexported buildMessageParams function. No exported types, methods, functions, or option structs were added, removed, or changed. The public-api-change label is not warranted.

  • Cross-provider alignment (Go): The OpenAI provider already forwards the full schema map via schemaToMap, and the Gemini provider sets decl.ParametersJsonSchema = schema. The Anthropic provider was the only one stripping keywords like additionalProperties: false. This PR brings Anthropic in line with the other two Go providers.

  • Cross-SDK alignment (.NET / Python): In .NET (Microsoft.Agents.AI) and the Python SDK, the declared tool input schema and the schema used for server-side validation are the same object — there is no stripping of keywords before sending to the model. The fix matches that expectation: what the model sees now equals what funcTool.Call validates against.

  • No new behavior introduced: This is a correctness fix, not a feature addition. The schema forwarded to Anthropic now matches what OpenAI and Gemini already receive and what .NET/Python expose.

Conclusion: No parity issues. The parity-approved label remains appropriate.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • awmgmcpg

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

Generated by Go API Consistency Review Agent · 39.1 AIC · ⌖ 4.95 AIC · ⊞ 5.9K ·

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parity-approved Go API consistency review found no parity issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants