fix: default empty input_schema for Anthropic function tools with nil params - #1872
fix: default empty input_schema for Anthropic function tools with nil params#1872mvanhorn wants to merge 1 commit into
Conversation
… params
When a function tool has nil or empty Parameters, the Anthropic API now
requires input_schema to be present. Default to {"type":"object","properties":{}}
to prevent HTTP 422 errors for no-argument function tools (fixes looplj#1843).
Greptile SummaryThis PR fixes a regression introduced in v1.0.0-beta3 where function-type tools with no parameters caused HTTP 422 errors from the Anthropic Messages API because the
Confidence Score: 4/5Safe to merge; the change is minimal and directly fixes the HTTP 422 regression for no-parameter function tools. The fix is a targeted two-line guard with clear test coverage for all three parameter states. The only residual concern is that llm/transformer/anthropic/model.go — the Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Client
participant convertToolsAnthropic
participant AnthropicAPI
Note over Client,AnthropicAPI: After fix
Client->>convertToolsAnthropic: "Tool{Type: function, Parameters: nil}"
Note over convertToolsAnthropic: len(inputSchema) == 0
Note over convertToolsAnthropic: default to {type:object,properties:{}}
convertToolsAnthropic->>AnthropicAPI: "input_schema: {type:object,properties:{}}"
AnthropicAPI-->>Client: 200 OK
Note over Client,AnthropicAPI: Before fix
Client->>convertToolsAnthropic: "Tool{Type: function, Parameters: nil}"
Note over convertToolsAnthropic: omitempty drops input_schema
convertToolsAnthropic->>AnthropicAPI: (input_schema omitted)
AnthropicAPI-->>Client: 422 Unprocessable Entity
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Client
participant convertToolsAnthropic
participant AnthropicAPI
Note over Client,AnthropicAPI: After fix
Client->>convertToolsAnthropic: "Tool{Type: function, Parameters: nil}"
Note over convertToolsAnthropic: len(inputSchema) == 0
Note over convertToolsAnthropic: default to {type:object,properties:{}}
convertToolsAnthropic->>AnthropicAPI: "input_schema: {type:object,properties:{}}"
AnthropicAPI-->>Client: 200 OK
Note over Client,AnthropicAPI: Before fix
Client->>convertToolsAnthropic: "Tool{Type: function, Parameters: nil}"
Note over convertToolsAnthropic: omitempty drops input_schema
convertToolsAnthropic->>AnthropicAPI: (input_schema omitted)
AnthropicAPI-->>Client: 422 Unprocessable Entity
Reviews (1): Last reviewed commit: "fix: default empty input_schema for Anth..." | Re-trigger Greptile |
| case llm.ToolTypeFunction: | ||
| inputSchema := tool.Function.Parameters | ||
| if len(inputSchema) == 0 { | ||
| inputSchema = json.RawMessage(`{"type":"object","properties":{}}`) | ||
| } |
There was a problem hiding this comment.
omitempty on InputSchema still latent in model.go
The fix correctly supplies a default value before constructing the Tool struct, so the immediate bug is resolved. However, Tool.InputSchema in model.go still carries json:"input_schema,omitempty". The guard in convertToolsAnthropic is the only thing standing between a future caller that builds a Tool directly (bypassing the helper) and another HTTP 422. Removing omitempty from the struct tag in model.go would make the invariant hold at the serialisation layer for all code paths, not just this one.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
https://platform.claude.com/docs/en/api/go/messages/create#web_search_tool_20260209 The web search tool is not function type, and no input schema field. |
|
Agreed that The default only fires inside the case llm.ToolTypeFunction:
inputSchema := tool.Function.Parameters
if len(inputSchema) == 0 {
inputSchema = json.RawMessage(`{"type":"object","properties":{}}`)
}
// ...
case llm.ToolTypeWebSearch:
// builds Tool{Type: ToolTypeWebSearch20250305, Name: ...} with no InputSchemaThe So a no-arg function tool gets If you're seeing a specific tool reaching the function branch when it shouldn't (e.g. a server-side tool arriving with |
Summary
input_schemafield was omitted entirely when a tool had nil or emptyParameters, due tojson:",omitempty"on the field.input_schemato be present (even if empty) for allfunction-type tools; omitting it causes HTTP 422.InputSchemato{"type":"object","properties":{}}whentool.Function.Parametersis nil or zero-length.Why this matters
Fixes #1843. After upgrading to v1.0.0-beta3, any Anthropic channel request containing a function tool with no parameters (e.g. a client sending a
web_searchfunction tool without a parameter schema) fails with HTTP 422 from the Anthropic API becauseinput_schemais missing. The canonical empty JSON Schema object satisfies Anthropic's validation for no-argument tools.Testing
TestConvertToolsAnthropic_NilParametersinoutbound_convert_test.gocovering:Parametersproduces valid{"type":"object","properties":{}}asInputSchemaParameters(json.RawMessage{}) gets the same defaultParameterswith a schema are passed through unchangedanthropicpackage continue to pass.gofmt,go vet, andgo buildclean.Fixes #1843