Skip to content

长对话达到最大轮次后续跑时,Agent 仅执行 1–2 turns 便提前结束 #737

Description

@ZexinLiang

问题描述

在长时间运行的任务中,Agent 第一次可以正常执行大量 turns;但达到单次任务最大轮次后,再次要求继续时,新任务虽然已获得新的 turn 配额,却往往只执行 1~2 turns 就自行结束。

该问题在 Goal Mode / Reflect 持续唤醒场景下尤其明显。它并非简单的 max_turns=180 限制:后续任务的 turn 计数已重新从 1 开始,但仍会远未达到 180 turns 就提前结束。

复现步骤

  1. 启动一个需要长期持续执行的 Goal Mode 任务。
  2. 让 Agent 进行多轮分析、验证和优化,使 LLM session history 变长。
  3. 第一次任务结束或达到最大轮次后,通过 Goal Mode / Reflect 再次唤醒 Agent。
  4. 在续跑提示中明确要求 Agent 不得直接宣告完成,应继续检查和改进。
  5. 观察续跑任务的实际执行轮数。

实际表现

一次实际运行中:

  • 第一次唤醒:约 122 turns
  • 第二次唤醒:约 6 turns
  • 第三次唤醒:约 2 turns

每次唤醒的内部 turn 均已重新从 1 开始。续跑时,模型通常很快生成总结性文本,不再调用工具,随后 Agent 将任务判定为完成并退出。

预期表现

  1. 新一次唤醒应正常获得完整的 turn 配额;
  2. 前序长对话不应导致模型在 1~2 turns 内错误判断任务已完成;
  3. Goal Mode 应基于当前状态继续进行实质性操作;
  4. 引擎应能区分真正完成、异常提前收尾、达到最大轮次、用户中止和后端错误。

初步根因分析

初步定位到以下链路:

  1. 不同 put_task 之间复用了同一个 LLM session history;
  2. 第一次长任务的历史中积累了大量“全部完成”“最终交付”“收口”等完成态内容;
  3. 再次唤醒时,虽然注入了 CONTINUATION_PROMPT,但模型仍会看到此前完整或裁剪后的长历史;
  4. 模型受完成态历史影响,很快输出总结而不再调用工具;
  5. 无工具调用进入 no_tool 路径;
  6. do_no_tool 返回的 StepOutcome 没有 next_prompt
  7. agent_loop.py 将其判定为 CURRENT_TASK_DONE 并退出。

调用链可概括为:

long session history
  → completion-state semantic pollution
  → model outputs final text without tool calls
  → do_no_tool(...)
  → StepOutcome(..., next_prompt=None)
  → CURRENT_TASK_DONE
  → exits after 1–2 turns

因此,这更像是长上下文中的完成态语义污染,而不只是最大轮次配置问题。

相关代码

  • agent_loop.pynext_prompt is None 时将任务视为 CURRENT_TASK_DONE,无法区分真正完成和异常提前收尾。
  • ga.pydo_no_tool 返回 StepOutcome(response, next_prompt=None)
  • llmcore.py:现有 trim_messages_history 主要按容量/字符量裁剪,缺少语义感知;裁剪后仍可能保留大量完成态内容。
  • reflect/goal_mode.pyCONTINUATION_PROMPT 无法稳定覆盖长历史中积累的完成态语义。

建议方案

1. Goal Mode 续跑时重建精简上下文

新唤醒时不直接继承完整原始 history,而是构造:

System Prompt
+ 结构化任务状态摘要
+ 当前目标
+ 已完成事项
+ 待验证事项
+ 交付物路径
+ 本轮继续执行要求

状态可从 working.key_infohistory_info、checkpoint、Goal Mode state file 和工作目录恢复。

2. 增加有上限的 early-exit guard

Goal Mode 新唤醒后,若模型在前 N turns 内直接进入 no_tool,先注入一次恢复提示,要求检查当前产物并执行至少一项实质性验证或改进;设置重试上限,避免真正完成时无限循环。

3. 细化退出原因

建议区分:

  • CURRENT_TASK_DONE
  • MAX_TURNS_EXCEEDED
  • EARLY_NO_TOOL
  • USER_ABORTED
  • BACKEND_ERROR
  • GOAL_BUDGET_EXHAUSTED

不建议仅调大 max_turns,因为续跑任务本身并未耗尽新的 turn 配额。

相关 Issues

暂未发现完全相同的问题。可能相关:

其中 #417 和本问题可能同属长上下文下的行为退化,但一个表现为重复/死循环,本问题表现为过早总结退出。

环境信息

Repository: lsdefine/GenericAgent
Mode: Goal Mode / Reflect
Configured max turns per task: 180
First long run: approximately 122 turns
Second continuation: approximately 6 turns
Third continuation: approximately 2 turns

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions