agentscope-ai / agentscope-ai/agentscope

[Bug]: Gemini 3 tool calls fail with 400 — `function_call` loses `thought_signature` on history round-trip

オープン
#2,462 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Python
スター
31.5k
フォーク
3.5k
平均マージ
1日 23時間
マージ済み PR(30日)
95

説明

### Prerequisites

- [x] I have searched the existing [issues](https://github.com/agentscope-ai/agentscope/issues) and [discussions](https://github.com/agentscope-ai/agentscope/discussions), and this is not a duplicate.
- [x] This is a bug, not a usage question. (For questions, please use [Discussions](https://github.com/agentscope-ai/agentscope/discussions/new?category=general) instead.)

### Background / Description

When using the native `GeminiChatModel` with a Gemini 3 model
(`gemini-3-flash-preview`) and function calling, the *first* tool-call round
succeeds, but the *next* request (which re-sends the assistant message
containing the previous `function_call`) is rejected by the API:

**Root cause**

- `agentscope/model/_gemini/_model.py` (lines ~376 and ~433) parses the
response and stores `part.thought_signature` **base64-encoded into
`ToolCallBlock.id`**.
- `agentscope/formatter/_gemini_formatter.py` (line ~204) re-serializes
history but only writes `function_call: {id, name, args}` — it never
restores the `thought_signature` field.

So the signature is effectively dropped on the round-trip.

### Error Messages

```shell
google.genai.errors.ClientError: 400 Bad Request. {
"error": {
"code": 400,
"message": "Function call is missing a thought_signature in functionCall parts.
This is required for tools to work correctly, and missing
thought_signature may lead to degraded model performance.
Additional data, function call `get_weather`, position 3.
Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures
for more details.",
"status": "INVALID_ARGUMENT"
}
}

Gemini 2.5 models tolerate the missing `thought_signature` (it is optional);
**Gemini 3 enforces it** — hence the 400.
```

### Steps to Reproduce

import base64
from agentscope.formatter import GeminiChatFormatter
from agentscope.message import Msg, ToolCallBlock

call_id = base64.b64encode(bytes(range(32))).decode("utf-8")
msg = Msg(name="assistant", role="assistant", content=[
ToolCallBlock(id=call_id, name="get_weather", input='{"city": "Beijing"}'),
])
body = asyncio.run(GeminiChatFormatter().format([msg]))
# -> {"function_call": {"id": "...", "name": "get_weather", "args": {...}}}
# ^^^ no "thought_signature" key

### Environment

- agentscope 2.0.4.post1 (bug still present in 2.0.7.post1, verified against
the released wheel)
- google-genai 2.19.0
- Python 3.12, macOS

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。