Skip to content

Bug: 15+ turn tasks can exit without calling start_long_term_update #789

Description

@kjore

Problem

The tool schema states that start_long_term_update must be called when a task taking 15+ turns completes. However, a task can return its final response and exit without calling the tool because this requirement is not enforced by the runtime.

This is a completion-time requirement, not a request to perform memory consolidation periodically every 15 turns.

Reproduction

I ran two long travel-planning tasks using the same model and the unmodified upstream code.

Experiment LLM turns start_long_term_update calls
Beijing → Lanzhou A 39 0
Beijing → Lanzhou B 20 0

Both tasks completed successfully and returned their final responses, but neither session called start_long_term_update.

This occurred even though both tasks exceeded the documented long-task threshold.

Expected Behavior

When a normal task attempts to complete after reaching the long-task threshold, GenericAgent should perform exactly one long-term memory evaluation unless:

  • long-term settlement has already started;
  • the task is running in an exempt autonomous flow; or
  • start_long_term_update is unavailable, such as when using --no-user-tools.

The evaluation may conclude that no information qualifies for storage. The requirement should force evaluation, not unconditional memory modification or SOP creation.

Actual Behavior

For an ordinary final response:

  1. The model returns no tool call.
  2. do_no_tool() returns StepOutcome(response, next_prompt=None).
  3. agent_runner_loop() treats the missing next prompt as CURRENT_TASK_DONE.
  4. The loop exits without checking whether the documented long-term memory evaluation occurred.

do_start_long_term_update() rejects early calls below 10 turns, but there is no corresponding runtime check that starts settlement when a 15+ turn task completes.

Root Cause

The requirement exists only in the tool description:

Must call when a task that took 15+ turns is completed.

Tool descriptions are advisory to the LLM. The task-exit path does not track whether long-term settlement was requested or completed.

As a result, compliance depends entirely on the model remembering and following the tool description after a long execution trace.

Suggested Direction

Add a one-time completion gate around the existing handler completion boundary:

  1. Track whether long-term settlement has started.
  2. When do_no_tool() receives a normal completion at or above the threshold, start the settlement phase instead of immediately exiting.
  3. Reuse the existing start_long_term_update implementation rather than duplicating its prompt and SOP-loading logic.
  4. Allow normal exit after evaluation, including when no memory qualifies for storage.
  5. Preserve the autonomous-flow and --no-user-tools exemptions.
  6. Ensure the gate cannot trigger recursively.

This can likely remain localized to GenericAgentHandler and its construction without adding dependencies or coupling the generic agent loop to a specific tool name.

Threshold Wording

The Chinese schema says 超15轮, while the English schema says 15+ turns. These have different boundary semantics: > 15 versus >= 15.

The wording and implementation should use one definition consistently. I suggest 15+ turns / 达到15轮, implemented as turn >= 15.

Suggested Tests

  • A task completing on turn 14 exits normally.
  • A task completing on turn 15 enters settlement once.
  • A task completing after turn 15 enters settlement once.
  • A prior explicit start_long_term_update call prevents another gate.
  • A no-op evaluation can exit without modifying memory.
  • --no-user-tools does not request an unavailable tool.
  • Autonomous flows preserve their documented exemption.
  • Settlement cannot recursively trigger itself.

Environment

  • OS: Windows
  • Python: 3.12.7
  • Model: qwen3.7-max

Privacy Note

The full response logs contain unrelated browser and conversation content, so they are not attached. The reported turn counts and tool-call results were extracted from the local logs.

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