Skip to content

fix: sanitize tool input_schema for Anthropic adapter#4346

Closed
qinlinwang wants to merge 1 commit into
Hmbown:mainfrom
qinlinwang:fix/anthropic-schema-sanitize
Closed

fix: sanitize tool input_schema for Anthropic adapter#4346
qinlinwang wants to merge 1 commit into
Hmbown:mainfrom
qinlinwang:fix/anthropic-schema-sanitize

Conversation

@qinlinwang

Copy link
Copy Markdown
Contributor

Summary

When using Anthropic as the provider, any tool whose input_schema
contains a top-level oneOf/anyOf/allOf causes the API to reject
the entire request with HTTP 400:

Anthropic API error (HTTP 400 Bad Request invalid_request_error):
tools.1.custom.input_schema: input_schema does not support oneOf,
allOf, or anyOf at the top level

This makes the Anthropic provider completely unusable whenever a tool
definition includes composition constraints - which is the case for
several built-in tools.

Root cause: The Anthropic adapter (crates/tui/src/client/anthropic.rs)
passes tool.input_schema to the API as-is, without sanitizing
top-level composition keywords. The OpenAI Responses adapter
(crates/tui/src/client/responses.rs:596-611) already solves this by
calling schema_sanitize::sanitize_for_responses, which:

  1. Strips root-level oneOf/anyOf/allOf
  2. Merges alternative properties into the root object
  3. Surfaces dropped constraints as a description note so the model
    still knows which parameters are expected

Fix: Apply the same sanitize_for_responses call in the Anthropic
adapter before sending tool definitions, aligning both adapters for
consistent schema handling across providers.

Testing

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --all-features
  • cargo test --workspace --all-features

Checklist

  • Updated docs or comments as needed
  • Added or updated tests where relevant
  • Verified TUI behavior manually if UI changes
  • Harvested/co-authored credit uses a GitHub numeric noreply address

When configuring Anthropic as the provider, any tool whose input_schema
contains a top-level oneOf/anyOf/allOf causes the API to reject the
entire request with HTTP 400:

  Anthropic API error (HTTP 400 Bad Request invalid_request_error):
  tools.1.custom.input_schema: input_schema does not support oneOf,
  allOf, or anyOf at the top level

The OpenAI Responses adapter already handles this via
schema_sanitize::sanitize_for_responses, which strips root-level
composition keywords, merges alternative properties into the root
object, and surfaces dropped constraints as a description note so the
model still knows which parameters are expected.

Apply the same sanitization in the Anthropic adapter before sending
tool definitions, aligning both adapters for consistent schema
handling across providers.
@qinlinwang qinlinwang requested a review from Hmbown as a code owner July 11, 2026 12:06
@github-actions

Copy link
Copy Markdown

Thanks @qinlinwang for taking the time to contribute.

This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered.

Please read CONTRIBUTING.md for the expected contribution shape. A maintainer can grant recurring PR access by commenting /lgtm on a pull request.

Hmbown pushed a commit that referenced this pull request Jul 12, 2026
When configuring Anthropic as the provider, any tool whose input_schema
contains a top-level oneOf/anyOf/allOf causes the API to reject the
entire request with HTTP 400:

  Anthropic API error (HTTP 400 Bad Request invalid_request_error):
  tools.1.custom.input_schema: input_schema does not support oneOf,
  allOf, or anyOf at the top level

The OpenAI Responses adapter already handles this via
schema_sanitize::sanitize_for_responses, which strips root-level
composition keywords, merges alternative properties into the root
object, and surfaces dropped constraints as a description note so the
model still knows which parameters are expected.

Apply the same sanitization in the Anthropic adapter before sending
tool definitions, aligning both adapters for consistent schema
handling across providers.

Harvested from PR #4346 by @qinlinwang
Hmbown added a commit that referenced this pull request Jul 12, 2026
Add canonical GitHub-noreply identities for moduvoice (PR #4347),
qinlinwang (PR #4346), and knqiufan (PR #4348) so the co-author gate can
verify machine-readable credit on the harvested commits. ci4ic4 was
already mapped.
Hmbown added a commit that referenced this pull request Jul 12, 2026
Summarize the underwater interaction system, treatment/motion
independence, compact-room fixes, footer notice ownership, ASCII tier,
and localization parity work in the 0.8.68 changelog section, and credit
the harvested community work: Korean locale (PR #4347 @moduvoice),
Anthropic schema sanitization (PR #4346 @qinlinwang), Anthropic
cache-write pricing (PR #4348 @knqiufan), NetBSD bindgen (PR #4349
@ci4ic4), and the #4208 copy-pollution report (@eugenicum).
@github-actions

Copy link
Copy Markdown

Thanks @qinlinwang — your contribution landed in f8e7573227d1 on main:

fix: sanitize tool input_schema for Anthropic adapter

Closing this PR now that the code is on main. Credit lives in the commit message and (where applicable) the CHANGELOG.md entry for the next release. Apologies for not closing this at the time of the merge — the auto-close workflow is new in v0.8.31.

If you want to land more work and would prefer your future PRs merge cleanly without a harvest step, the CONTRIBUTING.md doc has a short note on what makes a contribution mergeable as-is.

@github-actions github-actions Bot closed this Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant