What happened / 发生了什么
问题描述
使用 Gemini 模型触发工具调用时发生异常。原因是框架在提交工具执行结果时,向 function_response 中赋予了 id 字段。而最新的 Gemini API 存在严格的 Schema 校验,其 FunctionResponse 结构中不存在也不允许传入 id 字段,导致请求被 Google 服务器 400 拒绝。
参考google提供的文档:https://docs.cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference?hl=zh-cn#parameters
报错日志
Chat Model gemini-3.1-pro-preview-customtools request error: 400 None. {'error': {'message': 'Invalid JSON payload received. Unknown name "id" at \'contents[4].parts[0].function_response\': Cannot find field.', 'type': 'upstream_error', 'param': '', 'code': 400}}
原因分析与修复建议
问题出在 /AstrBot/astrbot/core/provider/sources/gemini_source.py 中的 _prepare_conversation 方法处理 role == "tool" 的逻辑处(大约在第 403 行):
elif role == "tool" and not native_tool_enabled:
func_name = message.get("name", message["tool_call_id"])
part = types.Part.from_function_response(
name=func_name,
response={
"name": func_name,
"content": message["content"],
},
)
# 下面这两行给 id 赋值的代码导致了 400 报错,建议直接删除或注释掉
if part.function_response:
part.function_response.id = message["tool_call_id"]
Reproduce / 如何复现?
使用Gemini模型,与AstrBot对话,要求调用网络搜索功能总结任意话题即可复现
AstrBot version, deployment method (e.g., Windows Docker Desktop deployment), provider used, and messaging platform used. / AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器
- AstrBot 版本: v4.22.2
- 部署方式:服务器Docker Compose部署
- 模型提供商: Google Gemini (NewAPI转接)
- 使用的消息平台适配器:QQ官方机器人
OS
Linux
Logs / 报错日志
[2026-04-04 14:27:11.921] [Core] [WARN] [v4.22.2] [runners.tool_loop_agent_runner:350]: Chat Model Vertex/gemini-3.1-pro-preview-customtools request error: 400 None. {'error': {'message': 'Invalid JSON payload received. Unknown name "id" at 'contents[4].parts[0].function_response': Cannot find field.', 'type': 'upstream_error', 'param': '', 'code': 400}}
Traceback (most recent call last):
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 305, in _iter_llm_responses_with_fallback
async for attempt in retrying:
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 170, in anext
do = await self.iter(retry_state=self._retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 157, in iter
result = await action(retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/_utils.py", line 111, in inner
return call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/init.py", line 393, in
self._add_action_func(lambda rs: rs.outcome.result())
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 449, in result
return self.__get_result()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
raise self._exception
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 309, in _iter_llm_responses_with_fallback
async for resp in self._iter_llm_responses(
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 272, in _iter_llm_responses
yield await self.provider.text_chat(**payload)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/provider/sources/gemini_source.py", line 822, in text_chat
if await self._handle_api_error(e, keys):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/provider/sources/gemini_source.py", line 129, in _handle_api_error
raise e
File "/AstrBot/astrbot/core/provider/sources/gemini_source.py", line 820, in text_chat
return await self._query(payloads, func_tool)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/provider/sources/gemini_source.py", line 588, in _query
result = await self.client.models.generate_content(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/models.py", line 7854, in generate_content
return await self._generate_content(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/models.py", line 6642, in _generate_content
response = await self._api_client.async_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/_api_client.py", line 1578, in async_request
result = await self._async_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/_api_client.py", line 1511, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 112, in call
do = await self.iter(retry_state=retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 157, in iter
result = await action(retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/_utils.py", line 111, in inner
return call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/init.py", line 413, in exc_check
raise retry_exc.reraise()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/init.py", line 184, in reraise
raise self.last_attempt.result()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 449, in result
return self.__get_result()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
raise self._exception
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 116, in call
result = await fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/_api_client.py", line 1443, in _async_request_once
await errors.APIError.raise_for_async_response(response)
File "/usr/local/lib/python3.12/site-packages/google/genai/errors.py", line 247, in raise_for_async_response
await cls.raise_error_async(status_code, response_json, response)
File "/usr/local/lib/python3.12/site-packages/google/genai/errors.py", line 269, in raise_error_async
raise ClientError(status_code, response_json, response)
google.genai.errors.ClientError: 400 None. {'error': {'message': 'Invalid JSON payload received. Unknown name "id" at 'contents[4].parts[0].function_response': Cannot find field.', 'type': 'upstream_error', 'param': '', 'code': 400}}
Are you willing to submit a PR? / 你愿意提交 PR 吗?
Code of Conduct
What happened / 发生了什么
问题描述
使用 Gemini 模型触发工具调用时发生异常。原因是框架在提交工具执行结果时,向
function_response中赋予了id字段。而最新的 Gemini API 存在严格的 Schema 校验,其FunctionResponse结构中不存在也不允许传入id字段,导致请求被 Google 服务器 400 拒绝。参考google提供的文档:https://docs.cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference?hl=zh-cn#parameters
报错日志
原因分析与修复建议
问题出在
/AstrBot/astrbot/core/provider/sources/gemini_source.py中的_prepare_conversation方法处理role == "tool"的逻辑处(大约在第 403 行):Reproduce / 如何复现?
使用Gemini模型,与AstrBot对话,要求调用网络搜索功能总结任意话题即可复现
AstrBot version, deployment method (e.g., Windows Docker Desktop deployment), provider used, and messaging platform used. / AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器
OS
Linux
Logs / 报错日志
[2026-04-04 14:27:11.921] [Core] [WARN] [v4.22.2] [runners.tool_loop_agent_runner:350]: Chat Model Vertex/gemini-3.1-pro-preview-customtools request error: 400 None. {'error': {'message': 'Invalid JSON payload received. Unknown name "id" at 'contents[4].parts[0].function_response': Cannot find field.', 'type': 'upstream_error', 'param': '', 'code': 400}}
Traceback (most recent call last):
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 305, in _iter_llm_responses_with_fallback
async for attempt in retrying:
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 170, in anext
do = await self.iter(retry_state=self._retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 157, in iter
result = await action(retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/_utils.py", line 111, in inner
return call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/init.py", line 393, in
self._add_action_func(lambda rs: rs.outcome.result())
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 449, in result
return self.__get_result()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
raise self._exception
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 309, in _iter_llm_responses_with_fallback
async for resp in self._iter_llm_responses(
File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 272, in _iter_llm_responses
yield await self.provider.text_chat(**payload)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/provider/sources/gemini_source.py", line 822, in text_chat
if await self._handle_api_error(e, keys):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/provider/sources/gemini_source.py", line 129, in _handle_api_error
raise e
File "/AstrBot/astrbot/core/provider/sources/gemini_source.py", line 820, in text_chat
return await self._query(payloads, func_tool)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/AstrBot/astrbot/core/provider/sources/gemini_source.py", line 588, in _query
result = await self.client.models.generate_content(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/models.py", line 7854, in generate_content
return await self._generate_content(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/models.py", line 6642, in _generate_content
response = await self._api_client.async_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/_api_client.py", line 1578, in async_request
result = await self._async_request(
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/_api_client.py", line 1511, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 112, in call
do = await self.iter(retry_state=retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 157, in iter
result = await action(retry_state)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/_utils.py", line 111, in inner
return call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/init.py", line 413, in exc_check
raise retry_exc.reraise()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/tenacity/init.py", line 184, in reraise
raise self.last_attempt.result()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 449, in result
return self.__get_result()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
raise self._exception
File "/usr/local/lib/python3.12/site-packages/tenacity/asyncio/init.py", line 116, in call
result = await fn(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/google/genai/_api_client.py", line 1443, in _async_request_once
await errors.APIError.raise_for_async_response(response)
File "/usr/local/lib/python3.12/site-packages/google/genai/errors.py", line 247, in raise_for_async_response
await cls.raise_error_async(status_code, response_json, response)
File "/usr/local/lib/python3.12/site-packages/google/genai/errors.py", line 269, in raise_error_async
raise ClientError(status_code, response_json, response)
google.genai.errors.ClientError: 400 None. {'error': {'message': 'Invalid JSON payload received. Unknown name "id" at 'contents[4].parts[0].function_response': Cannot find field.', 'type': 'upstream_error', 'param': '', 'code': 400}}
Are you willing to submit a PR? / 你愿意提交 PR 吗?
Code of Conduct