Skip to content

[Bug] Context truncation breaks function call/tool response pairing, causing Gemini 400 error #5416

@Luna-channel

Description

@Luna-channel

What happened / 发生了什么

当对话历史中包含 function call(工具调用)时,ContextTruncator.fix_messages() 方法在截断消息时可能破坏 assistant(tool_calls)tool response 的配对关系,导致 Gemini API 返回 400 错误。

根本原因分析

astrbot/core/agent/context/truncator.pyfix_messages() 方法(第7-20行)只进行了单向检查:

  • ✅ 检查 tool 消息前面是否有足够的消息
  • 没有检查 包含 tool_callsassistant 消息后面是否紧跟对应的 tool response

根据 OpenAI Chat Completions API 规范(Gemini 也遵循此规范),function call 必须紧跟 tool response。当截断发生在 assistant(tool_calls)tool 之间时,会产生非法的消息序列,导致 API 拒绝请求。

Reproduce / 如何复现?

  1. 使用 Gemini 作为 LLM 提供者
  2. 在对话中触发工具调用(如使用 memes 插件、web-searcher 等)
  3. 继续对话直到触发上下文截断(通过插件裁剪历史记录,或达到 token 限制触发压缩)
  4. 如果截断后 assistant(含tool_calls) 消息后面不再紧跟 tool response,下次 LLM 请求会返回 400 错误

AstrBot version, deployment method (e.g., Windows Docker Desktop deployment), provider used, and messaging platform used. / AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器

  • AstrBot 版本: v4.18.2
  • 部署方式: Docker
  • LLM 提供商: Gemini (通过 OpenAI 兼容接口)
  • 消息平台: aiocqhttp (OneBot v11)

OS

Linux

Logs / 报错日志

[2026-02-24 23:28:24.678] [Core] [WARN] [v4.18.2] [runners.tool_loop_agent_runner:249]: Chat Model 额度gemini request error: Error code: 400 - {'error': {'message': 'Please ensure that function call turn comes immediately after a user turn or after a function response turn.', 'type': 'upstream_error', 'param': '', 'code': 400}}
Traceback (most recent call last):
  File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 224, in _iter_llm_responses_with_fallback
    async for resp in self._iter_llm_responses(include_model=idx == 0):
  File "/AstrBot/astrbot/core/agent/runners/tool_loop_agent_runner.py", line 201, in _iter_llm_responses
    yield await self.provider.text_chat(**payload)
  ...
openai.BadRequestError: Error code: 400 - {'error': {'message': 'Please ensure that function call turn comes immediately after a user turn or after a function response turn.', 'type': 'upstream_error', 'param': '', 'code': 400}}

消息序列日志(可以看到存在 assistant,user 的序列,如果该 assistant 包含 tool_calls 则格式非法):

[AftCompact] RunCtx.messages -> [32] system,user,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,tool,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user,assistant,user

Are you willing to submit a PR? / 你愿意提交 PR 吗?

  • Yes!

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:coreThe bug / feature is about astrbot's core, backendbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions