agentscope-ai / agentscope-ai/QwenPaw
[Bug]: Gemini returns 400 "Requests ending with a model turn are not supported" after background tool completion
- 主要語言
- Python
- 星號
- 34.9k
- 分支
- 3.1k
- 平均合併
- 1 天 15 小時
- 30 天內合併 PR
- 225
描述
## QwenPaw Version
2.2.0
Verified with:
```bash
qwenpaw --version
```
Output:
```text
QwenPaw, version 2.2.0
```
## Description
When using a Gemini model, QwenPaw can fail immediately after an offloaded/background tool call completes or is interrupted.
The next model request returns:
```text
openai.BadRequestError: Error code: 400 - {
'error': {
'code': 400,
'message': 'Requests ending with a model turn are not supported.',
'status': 'INVALID_ARGUMENT'
}
}
```
Investigation of the QwenPaw error dump shows that the final message in `agent_state.state.context` is an automatically injected background-tool notification with:
```text
role="assistant"
name="system"
```
For example:
```text
Background tool call `execute_shell_command` (...)
completed with state=interrupted. Result below.
```
This message is generated by `make_offload_hint_msg()` in:
```text
qwenpaw/tool_calls/_hint.py
```
QwenPaw 2.2.0 currently contains:
```python
return Msg(
name="system",
role="assistant",
content=[notification] + result_blocks,
)
```
When this notification becomes the final context message before the next inference, Gemini sees the conversation as ending with a model/assistant turn and rejects the request with:
```text
Requests ending with a model turn are not supported.
```
QwenPaw 2.2.0 already appears to flatten the previous `ToolResultBlock` structure, so this is not the orphan tool-result pairing issue. The remaining issue is specifically that the offload completion notification is still emitted with `role="assistant"`.
A local workaround changing:
```diff
return Msg(
name="system",
- role="assistant",
+ role="user",
content=[notification] + result_blocks,
)
```
successfully passes Python syntax validation and prevents the runtime notification from producing a trailing assistant/model turn.
Semantically, this notification is also closer to an external/runtime input than a model-generated assistant response.
**Related PR(s):** N/A
**Security considerations:** None identified.
## Component(s) Affected
* [x] Core / Backend (app, agents, config, providers, utils, local_models)
* [ ] Console (frontend web UI)
* [ ] Channels (DingTalk, Feishu, QQ, Discord, iMessage, etc.)
* [ ] Skills
* [ ] CLI
* [ ] Documentation (website)
* [ ] Tests
* [ ] CI/CD
* [ ] Scripts / Deploy
## Environment
* **QwenPaw version:** 2.2.0
* **OS:** Linux container
* **Install method:** Python virtual environment / pip-based installation
* **Python version (if applicable):** 3.11
* **Package path:** `/app/venv/lib/python3.11/site-packages/qwenpaw/`
* **Model/provider:** Gemini through an OpenAI-compatible API gateway
* **Channel where observed:** Feishu
## Steps to Reproduce
1. Configure QwenPaw 2.2.0 to use a Gemini model.
2. Start a conversation and invoke a tool such as `execute_shell_command`.
3. Let the command exceed the foreground execution period so that QwenPaw offloads it to background execution.
4. Wait for the background tool call to complete or become interrupted.
5. QwenPaw injects a completion notification generated by `make_offload_hint_msg()`.
6. QwenPaw performs the next model inference.
7. Gemini returns:
```text
400 INVALID_ARGUMENT
Requests ending with a model turn are not supported.
```
The corresponding error dump in my case was:
```text
/tmp/qwenpaw_query_error_rn1nsw14.json
```
Inspection of `.agent_state.state.context` showed the final messages as approximately:
```text
context[3]:
role="assistant"
context[4]:
role="assistant"
name="system"
content:
Background tool call `execute_shell_command` (...)
completed with state=interrupted.
Result below.
```
The second message is produced by:
```python
def make_offload_hint_msg(entry: Any) -> Any:
...
return Msg(
name="system",
role="assistant",
content=[notification] + result_blocks,
)
```
## Actual vs Expected
* **Actual:**
After a background/offloaded tool call completes or is interrupted, QwenPaw inserts the completion notification as an `assistant` message.
The resulting conversation ends with an assistant/model turn:
```text
assistant
→ system-notification with role="assistant"
→ next Gemini inference
```
Gemini rejects the request with:
```text
400: Requests ending with a model turn are not supported.
```
* **Expected:**
A runtime-generated background tool completion notification should not leave the conversation in a trailing assistant/model state before the next model invocation.
For Gemini-compatible providers, the next inference should proceed normally after the background tool completion notification.
One possible fix is to emit this runtime notification as an input/user turn:
```python
return Msg(
name="system",
role="user",
content=[notification] + result_blocks,
)
```
Alternatively, QwenPaw could handle this at the provider/formatter layer, but the automatically injected runtime notification should not result in an invalid trailing model turn.
貢獻指南
評估
這個 Issue 還沒有評估資料。