Skip to content

[compatibility] Z.AI (Zhipu GLM) rejects any tool_choice other than "auto" with HTTP 400 — "Tool choice must be auto" #4246

Description

@kxlion

Summary

Hindsight's Reflect agent loop forces a retrieval tool on its first turn by sending
tool_choice: "required" (named tool_choice is normalized to required with the tools
list pre-filtered to the single forced tool, per openai_compatible_llm.py). The Z.AI
(Zhipu) endpoint — used for GLM models, e.g. z-ai/glm-5.3-flash — rejects every
tool_choice value except "auto" with HTTP 400. This is behaviorally identical to
Meta Model API, which is already handled via _NON_AUTO_TOOL_CHOICE_UNSUPPORTED_PROVIDERS.

Reproduction

Via OpenRouter with provider.only: ["z-ai"] — the error originates from the Z.AI
backend (see metadata.provider_name in the payload):

Request Result
tool_choice: {"type":"function","function":{"name":"recall"}} + tools ❌ HTTP 400
tool_choice: "required" + tools ❌ HTTP 400
tool_choice: "auto" + same single tool ✅ 200, tool called 5/5

Error payload:

{"error":{"message":"Tool choice must be auto","code":400,"metadata":{"provider_name":"Z.AI"}}}

The "auto" row was verified with 5/5 successful tool calls on memory-retrieval style
prompts (system prompt instructing mandatory tool use, single tool available), so the
model does not need the forced tool_choice to reliably call the tool.

Impact

Every Reflect (and any other forced-tool) operation against GLM models routed to Z.AI
fails after retries. Retain/Consolidation are unaffected (no forced tool_choice).

Tested on z-ai/glm-5.3-flash with Hindsight 0.9.2, September 2026 — still current.

Suggested fix

Add Z.AI (zai) to _NON_AUTO_TOOL_CHOICE_UNSUPPORTED_PROVIDERS. The downgrade to auto
is functionally safe here: named tool_choice is already normalized to required with the
tools list narrowed to the single forced tool, so under auto the call remains practically
forced — the same reasoning as the existing DeepSeek and Meta branches.

Workaround currently in use

HINDSIGHT_API_REFLECT_LLM_EXTRA_BODY={"tool_choice":"auto"}

Verified working (Reflect succeeds end-to-end on Z.AI), but it relies on extra_body
merge precedence and is not an API contract. Alternative: route Reflect to a
tool-forcing-compatible host (e.g. Novita).

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions