[Bug] OpenAI-compatible Gemini 工具 schema const 导致 400
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 77/100
Research direction
Read astrbot/core/agent/tool.py and inspect ToolSet.openai_schema(), where the issue says tool.parameters is passed through. Trace how nested tool schemas are built, then check the existing schema tests or add a focused regression case for nested const values. Done means OpenAI compatible tool parameters convert each const to a single value enum and the reported Gemini 400 is avoided.
Written by the indexing model from the issue text.
Description
问题描述
问题
使用 OpenAI 兼容的 Gemini 网关时,只要工具(function declaration)的 JSON Schema 里出现 const,请求就会直接 400,导致所有聊天模型失败。
报错示例:
LLM 响应错误: All chat models failed: BadRequestError: Error code: 400 -
{'error': {'message': 'Invalid JSON payload received. Unknown name "const" ### at
\'***.tools[0].function_declarations[34].***.properties[0].***.properties[2].***.***.properties[10].***.properties[0].value\':
Cannot find field.', 'type': 'upstream_error', 'param': '', 'code': 400}}
Gemini 的 function calling schema 只支持 OpenAPI 3.0 Schema 的一个子集;const 是合法 JSON Schema,但不在 Gemini 支持的字段里。ToolSet.google_schema() 会过滤不支持的字段,但 OpenAI 兼容路径没有做同样的清洗。
期望行为 / Expected behavior
AstrBot 在把工具 schema 发给 OpenAI 兼容 provider 前,应做一次 provider-safe 清洗,至少把:
{ "const": "value" }
转换成:
{ "enum": ["value"] }
两者对“参数必须逐字等于该值”的约束等价,OpenAI、Anthropic、Gemini 兼容网关都能接受。
根因 / Root cause
astrbot/core/agent/tool.py 的 ToolSet.openai_schema() 目前直接透传 tool.parameters:
func_def["function"]["parameters"] = tool.parameters
我也检查了 v4.29.1 的同一文件,仍然没有 const 清洗逻辑;4.29.0 / 4.29.1 的更新日志也没有相关修复。
建议修复 / Suggested fix
在 openai_schema() 里递归转换 const:
def _provider_safe_schema(value):
if isinstance(value, dict):
result = {}
for key, item in value.items():
if key == "const":
result["enum"] = [item]
else:
result[key] = _provider_safe_schema(item)
return result
if isinstance(value, list):
return [_provider_safe_schema(item) for item in value]
return value
func_def["function"]["parameters"] = _provider_safe_schema(tool.parameters)
如果担心影响非 Gemini provider,也可以只在模型名包含 gemini 时启用这个转换;不过 const -> enum 本身语义等价,通用转换也安全。
临时绕过 / Workaround
• 切换到非 Gemini 模型(DeepSeek / Claude / OpenAI 等)。
• 或使用原生 Gemini provider(googlegenai_chat_completion),它会走 google_schema() 的字段过滤。
• 或本地给 openai_schema() 打补丁。
环境 / Environment
• Provider:[OpenAI-compatible Gemini gateway / gemini-3.8-flash]
• 相关插件:[astrbot_plugin_memory_companion, astrbot_plugin_private_companion]
补充 / Additional context
• 这个问题和 #7572(examples)、#7357(id)属于同一类 Gemini schema 严格校验问题。
• 修掉 const 后,如果 schema 里还有 oneOf / allOf,Gemini 可能继续报不支持的字段;长期看可能需要一个按 provider 维护的 schema 兼容层,但本 issue 先聚焦 const。
• 本地验证:把 Memory Companion v3 schema 过一遍转换后,const 数量为 0,enum 数量为 63,请求不再触发该 400。
### 如何复现?
1. 配置一个 OpenAI 兼容的 Gemini provider(例如 gemini-3.x 系列)。
2. 启用一个工具参数里带 const 的插件。例如 Memory Companion 的 memory_companion_query / memory_companion_events,其嵌套 schema 中有:
{
"type": "object",
"properties": {
"time": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "const": "unknown" }
}
}
]
}
}
}
3. 发送一条会带上工具声明的消息。
4. 请求返回 400:Unknown name "const"。
### AstrBot 版本
4.28.2
### 操作系统
Linux
### 部署方式
Docker
### 使用的消息平台适配器
onebot v11
### 错误日志
```text
LLM 响应错误: All chat models failed: BadRequestError: Error code: 400 - {'error': {'message': 'Invalid JSON payload received. Unknown name "const" at \'***.tools[0].function_declarations[34].***.properties[0].***.properties[2].***.***.properties[10].***.properties[0].value\': Cannot find field.', 'type': 'upstream_error', 'param': '', 'code': 400}}
辅助信息
No response
检查清单
- Dominant language
- Python
- Stars
- 42.1k
- Forks
- 3.1k
- Avg merge
- 1d 17m
- Merged PRs (30d)
- 148
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from AstrBotDevs/AstrBot
-
[Bug] Default PyPI mirror disables TLS certificate verification for plugin dependenciesPossibly taken @DOTBave claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
AstrBotDevs/AstrBot#10684 ·
Maintainers usually reply within 1 day
-
[Bug] 现实世界时间感知文案需要更新Possibly taken @rudycelekli claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
AstrBotDevs/AstrBot#10682 ·
Maintainers usually reply within 1 day
-
[Bug] Discord slash command sync aborts with KeyError when a plugin handler is defined in a submodulePossibly taken @yuexia5 claimed this 4 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
AstrBotDevs/AstrBot#10626 · 1 comment ·
Maintainers usually reply within 1 day
-
[Bug] QQ频道消息无法回复:markdown 回退顺序有误,误用主动消息导致 304049 限频Possibly taken @he-yufeng claimed this 16 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
AstrBotDevs/AstrBot#10420 · 4 comments ·
Maintainers usually reply within 1 day
-
[Feature] 移除「切换到旧版知识库」入口Possibly taken @lingyun14beta claimed this 12 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
AstrBotDevs/AstrBot#10340 · 1 reaction ·
Maintainers usually reply within 1 day
All issues in AstrBotDevs/AstrBot
Similar issues
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
fossasia/visdom-dev#77 ·
Maintainers usually reply within 4 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
aws-cloudformation/cfn-lint#4890 ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
volcengine/OpenViking#6521 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
fix(xiaomi): curated picker list still offers six ids that return 400 (plan-limited vs retired)Opencause/upstream comp/cli P2 provider/other tool/file type/bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
NousResearch/hermes-agent#143900 ·
Maintainers usually reply within 1 day