What happened / 发生了什么
In AstrBot local agent runner (tool loop runner), tool calling fails when using the OpenRouter model z-ai/glm-4.5-air:free.
The request returns:
openai.BadRequestError: 400 Tool choice must be auto
From local logs and code investigation, AstrBot local runner explicitly passes:
in some tool-calling stages, while this OpenRouter model path appears to require:
As a result, the downstream request is rejected.
Reproduce / 如何复现
Current real-world scenario:
- AstrBot local agent runner
- chat provider through OpenRouter
- model:
z-ai/glm-4.5-air:free
- a conversation that triggers tool calling (in my case, an image-generation related request)
The failure happens in the tool-calling stage.
It does not look like a prompt understanding issue, and it does not look like the image tool itself is failing.
Logs / 报错日志
Core error:
openai.BadRequestError: Error code: 400 - ... Tool choice must be auto
Related logs also show:
openrouter/z-ai/glm-4.5-air:free
provider_name: Z.AI
The direct issue here appears to be an incompatible tool_choice value during tool calling.
Code investigation / 代码排查结果
I found explicit tool_choice="required" calls in AstrBot local runner:
astrbot/core/agent/runners/tool_loop_agent_runner.py:1002
astrbot/core/agent/runners/tool_loop_agent_runner.py:1035
The provider abstraction also allows:
Relevant file:
astrbot/core/provider/provider.py
And the OpenAI-compatible source forwards this value into the request payload:
astrbot/core/provider/sources/openai_source.py
So the current path appears to be:
- local tool loop runner forces tool calling with
tool_choice="required"
openai_source forwards it downstream
- downstream path is OpenRouter ->
z-ai/glm-4.5-air:free
- that path rejects this and expects
auto
- request fails with
400 Tool choice must be auto
Expected behavior / 期望行为
For models like OpenRouter z-ai/glm-4.5-air:free that do not accept tool_choice="required", AstrBot should ideally do one of the following:
- downgrade to
tool_choice="auto" in runner logic
- handle compatibility in the OpenAI/OpenRouter provider adapter
- detect incompatible models earlier and avoid sending an unsupported request
Additional notes / 补充说明
- This issue happens when using OpenRouter with
z-ai/glm-4.5-air:free.
- I have not tested whether a direct native Zhipu/Z.AI provider call behaves the same way, so this report is only about the OpenRouter path.
- Since
glm-4.5-air is already a relatively older model, maintainers can evaluate whether this specific compatibility issue is worth fixing. Even if no fix is planned, documenting this limitation would still be helpful.
- This issue text was organized with the help of an OpenClaw agent, then reviewed and confirmed by the user before posting.
What happened / 发生了什么
In AstrBot local agent runner (tool loop runner), tool calling fails when using the OpenRouter model
z-ai/glm-4.5-air:free.The request returns:
From local logs and code investigation, AstrBot local runner explicitly passes:
in some tool-calling stages, while this OpenRouter model path appears to require:
As a result, the downstream request is rejected.
Reproduce / 如何复现
Current real-world scenario:
z-ai/glm-4.5-air:freeThe failure happens in the tool-calling stage.
It does not look like a prompt understanding issue, and it does not look like the image tool itself is failing.
Logs / 报错日志
Core error:
Related logs also show:
openrouter/z-ai/glm-4.5-air:freeprovider_name: Z.AIThe direct issue here appears to be an incompatible
tool_choicevalue during tool calling.Code investigation / 代码排查结果
I found explicit
tool_choice="required"calls in AstrBot local runner:astrbot/core/agent/runners/tool_loop_agent_runner.py:1002astrbot/core/agent/runners/tool_loop_agent_runner.py:1035The provider abstraction also allows:
autorequiredRelevant file:
astrbot/core/provider/provider.pyAnd the OpenAI-compatible source forwards this value into the request payload:
astrbot/core/provider/sources/openai_source.pySo the current path appears to be:
tool_choice="required"openai_sourceforwards it downstreamz-ai/glm-4.5-air:freeauto400 Tool choice must be autoExpected behavior / 期望行为
For models like OpenRouter
z-ai/glm-4.5-air:freethat do not accepttool_choice="required", AstrBot should ideally do one of the following:tool_choice="auto"in runner logicAdditional notes / 补充说明
z-ai/glm-4.5-air:free.glm-4.5-airis already a relatively older model, maintainers can evaluate whether this specific compatibility issue is worth fixing. Even if no fix is planned, documenting this limitation would still be helpful.