agentscope-ai / agentscope-ai/QwenPaw
[Bug]:
- 主要言語
- Python
- スター
- 34.9k
- フォーク
- 3.1k
- 平均マージ
- 1日 15時間
- マージ済み PR(30日)
- 225
説明
name: Bug Report about: Report a bug or unexpected behavior title: "[Bug]: Mission Mode spawns unbounded sub-sessions — no server-side iteration cap, only stops when LLM account runs out of balance" labels: ["bug", "triage"] assignees: []
QwenPaw Version
2.0.1 (AgentScope 2.0.4.post1)
Description
Mission Mode (/mission) entered an uncontrolled loop, spawning worker/verifier sub-sessions indefinitely. The configured max_iterations=20 was not enforced by any server-side mechanism — the controller (an LLM) kept dispatching spawn_subagent calls until the LLM provider account ran out of balance (HTTP 429 insufficient balance), which is the only thing that stopped it.
In ~54 minutes the controller session produced 54 sub-session files in the agent's sessions/console/ directory, with 51 SpawnSubagent calls, 55 newly-registered chats, 32 session forks, and 29 CancelledError cancellations. Each worker failure led to re-dispatch, inflating session count and token cost with no hard ceiling.
Expected: Mission Mode must enforce max_iterations (and ideally a sub-session / spawn budget) on the server side, terminating the loop when the limit is reached — not rely solely on the LLM obeying prompt instructions.
Related PR(s): —
Security considerations: The runaway loop consumed the LLM provider balance and piled up HIGH-severity Bash approvals (including del, git commands). Log lines containing the API account/key fragment must be redacted before sharing (see note at the bottom).
Component(s) Affected
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.0.1
OS: Windows 11 (AMD64)
Install method: Portable edition (self-contained python + uv + data)
Python version: 3.12.13
AgentScope: 2.0.4.post1
Controller model: kimi-cn/kimi-k2.6 (general agent, id b6mNir)
Steps to Reproduce
Start a mission on a general agent with a non-trivial document task, e.g.:
/mission 按照党建模板的ppt风格和模板,并根据另外三个word的内容,写一个PPT,至少6页。注意找专家支持
(mission id mission-20260727-222750, controller chat e9ee7f6e-ea5e-4874-a496-052e87178cc0)
Confirm the PRD when the controller asks (this flips loop_config.json current_phase to execution_confirmed and activates MissionGate).
Observe the controller enter Phase 2: it dispatches workers via spawn_subagent(fork=True, background=True), polls with check_agent_task, then dispatches verifiers.
When workers fail / get cancelled, the controller re-dispatches instead of stopping. Session files keep accumulating in /sessions/console/default_sub-*.json. Approvals pile up. Token spend climbs.
The loop does not stop at max_iterations. In my case it only stopped because the LLM account hit 429 insufficient balance.
Actual vs Expected
Actual:
54 new sub-session files generated after the controller session started (22:27:50 → 23:21).
Log totals: 51 SpawnSubagent allowed, 55 new chats auto-registered, 32 Fork session written, 29 cancel_cleanup ... CancelledError.
loop_config.json shows max_iterations: 20 and current_phase: execution_confirmed — the max_iterations_reached terminal phase was never set.
Loop terminated only on provider 429 insufficient balance, not by Mission Mode.
Expected:
Mission Mode enforces max_iterations server-side: once the iteration count reaches the cap, set current_phase = max_iterations_reached and TERMINATE.
Optionally enforce a hard budget on spawn_subagent calls / active sub-sessions per mission so a misbehaving controller cannot exhaust resources.
Logs / Screenshots
Controller session registration (the baseline):
2026-07-27 22:27:50 | INFO | app/chats/manager.py:153 | Auto-registered new chat: e9ee7f6e-ea5e-4874-a496-052e87178cc0 -> 1785162397168-rchpb82
Repeated, unbounded worker dispatch (sample; this pattern repeats 51 times):
2026-07-27 23:14:16 | INFO | governance/resource_governor.py:292 | governance decision: tool=SpawnSubagent target='' action=allow source=No rule hit sandbox=- reason=internal
2026-07-27 23:14:16 | INFO | app/routers/fork.py:171 | Fork session written: .../sessions/console/default_sub-1e732549.json (1 keys)
2026-07-27 23:14:26 | INFO | app/chats/manager.py:153 | Auto-registered new chat: 3082f5f4-... -> sub-e7f961f5
Workers cancelled then re-dispatched (29 times):
2026-07-27 23:13:58 | INFO | hooks/error/error_hook.py:90 | cancel_cleanup: cancelled (session=sub-3f785371): CancelledError
2026-07-27 23:13:58 | INFO | runtime/runtime.py:283 | cancel-save: persisted interrupted turn (session=sub-3f785371)
HIGH-severity Bash approvals piling up from workers:
2026-07-27 23:13:35 | INFO | app/approvals/service.py:193 | Approval pending created: request_id=93679124 agent_id=b6mNir tool=Bash severity=HIGH session=sub-39cc root=17851623
Final stop — provider balance exhausted (key/account redacted):
2026-07-27 23:21:25 | WARNING | providers/retry_chat_model.py:543 | LLM call failed (attempt 1/4): Error code: 429 - {'error': {'message': 'Your account is suspended due to insufficient balance ...'}}. Retrying in 1.0s ...
loop_config.json of the mission (cap is 20, never enforced):
{
"max_iterations": 20,
"current_phase": "execution_confirmed",
"session_id": "1785162397168-rchpb82",
"max_retries_per_story": 3
}
Additional Notes
Root cause (from reading installed 2.0.1 source)
modes/mission/gates.py — MissionGate.check() only inspects:
current_phase ∈ {completed, max_iterations_reached} → TERMINATE
all stories passes: true → TERMINATE
otherwise → INTERRUPT_AND_CONTINUE
It never reads max_iterations and keeps no iteration counter. The max_iterations value exists only in:
loop_config.json (stored, not consumed for enforcement),
the MASTER_PROMPT text ("or you reach {max_iterations} total iterations") — a soft instruction relying on the LLM,
the continuation summary shown to the LLM ("Max iterations: {max_iter}").
Meanwhile loop/gates/limits.py already provides hard resource gates — TokenBudgetGate, TimeoutGate, ToolCallBudgetGate (with per_tool budgets) — but MissionGate does not wire any of them in. So when the controller LLM ignores the soft cap (or keeps re-dispatching after CancelledError), nothing stops it.
Suggested fix directions
Add iteration counting to MissionGate: persist an incrementing counter in loop_config.json on each INTERRUPT_AND_CONTINUE; when it reaches max_iterations, set current_phase = max_iterations_reached and return TERMINATE.
Attach a ToolCallBudgetGate with a per_tool cap on SpawnSubagent (and/or a max active sub-session count) so a runaway controller is bounded regardless of LLM compliance.
Ensure worker CancelledError re-dispatches count against max_retries_per_story, not just verifier FAILs.
Reproducibility note
This was observed on a real user task (not a minimal repro), but the failure mode is deterministic given the source: any controller that does not self-enforce max_iterations will run unbounded, because no server-side gate enforces it for Mission Mode.
⚠️ Before submitting
The raw qwenpaw.log line at 23:21:25 contains the LLM provider account org id and API key fragment (org-... / ak-...). I redacted it above as . If you attach the original log file to the issue, strip that line first.
コントリビューションガイド
評価
この issue はまだ評価されていません。