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

建议方案

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

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

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

状态可从 working.key_info、history_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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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