Skip to content

[Bug] Anthropic-compatible API defers tools without defer_loading under the advanced-tool-use beta #172

Description

@uwuclxdy

Pre-submission checklist

  • I searched existing issues and confirmed this isn't a duplicate.
  • I've read CONTRIBUTING.md.
field value
Category Tool use / MCP (工具调用 / MCP)
Agent framework Claude Code
Severity Major, works but degraded (影响体验)
Reproducibility Always (必现)

Description

The z.ai Anthropic-compatible endpoint (https://api.z.ai/api/anthropic), when a /v1/messages request carries the advanced-tool-use-2025-11-20 beta, defers tools that were sent with full schemas and no defer_loading flag. Per that beta, only tools with defer_loading: true should be deferred behind the tool_search tool. On z.ai the always-loaded core tools (Bash, Read, Edit, Write, …) are not presented to the model, so it has to make a tool_search round-trip to reach them. api.anthropic.com handles the byte-identical request correctly and keeps those tools loaded.

This surfaces through Claude Code with ENABLE_TOOL_SEARCH=true pointed at z.ai (GLM). Every core-tool call then costs an extra tool_search round-trip. Any tool that tool_search fails to resolve is lost entirely.

Steps to reproduce

  1. Point Claude Code at z.ai: ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic, an Anthropic-compatible key, ENABLE_TOOL_SEARCH=true, plus at least one MCP server so tool search engages.
  2. Ask the model to run Bash, for example echo test.
  3. The model reports Bash is not directly available. It calls the tool_search tool first, then runs the command. It takes one extra turn versus the same setup on api.anthropic.com.

Provider-level repro (no Claude Code needed): POST /v1/messages with header anthropic-beta: advanced-tool-use-2025-11-20 and a tools array holding several tools with a full input_schema and no defer_loading, alongside one tool with defer_loading: true. The tools without the flag do not reach the model and have to be retrieved via tool_search.

Expected behavior

Honor defer_loading per tool. Tools without defer_loading (or with defer_loading: false) stay directly available in the tool set. Only tools carrying defer_loading: true are deferred behind tool_search.

Actual behavior

Tools sent without defer_loading are deferred anyway. The model must call tool_search to reach core tools like Bash / Read / Edit.

I captured the outgoing request off the wire for both endpoints under ENABLE_TOOL_SEARCH=true. The tools array is byte-identical: 10 core tools with full schemas and no defer_loading (Agent, Bash, Edit, Read, ReportFindings, ScheduleWakeup, Skill, ToolSearch, Workflow, Write), a single DeferredToolPlaceholder carrying defer_loading: true, and the advanced-tool-use-2025-11-20 beta. Functional check:

endpoint Bash directly available turns
api.anthropic.com (Opus) yes 2
z.ai (glm-5.2) no 3

Caveat: I logged the request bytes, not z.ai's response, so the re-defer is inferred from the model's round-trip rather than read from the response payload.

Version & environment

  • Endpoint: https://api.z.ai/api/anthropic (Anthropic-compatible), model glm-5.2.
  • Client: Claude Code 2.1.217, Linux. This is the API endpoint reached through Claude Code, not ZCode.

Related upstream report on the Claude Code side: anthropics/claude-code#52121.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions