Why did a simple task take 50 turns?
Why Did a Simple Task Take 50 Turns? V4.1 Flash × DSH
- Author
- DeepSeekAgent.io Editorial Team
- Published
- Updated
A simple task ran for 33–50 assistant turns in DeepSeek Harness and produced 32–70 tool calls. The model found the required answer early, and the file change occupied one to three turns. After the task was complete, the Agent continued calling tools, increasing context size and token use.
This article starts with a community V4.1 Flash trace, checks it against a pinned DSH source revision, and applies the framework from When Agents Do Not Stop: Uncovering Infinite Agentic Loops in LLM Agents. The central question is why an Agent can keep taking locally reasonable steps without reaching an effective definition of “enough.”
The incident: a simple task took 33–50 turns
The community report ran the same prompt in four fresh Sessions. The task added high and max reasoning-effort choices to an existing model configuration and made high the default. Runs covered PTC and Standard; three loaded no rule file or Skill.
| Run | Mode | Rule file | Assistant turns | Tool calls |
|---|---|---|---|---|
| 1 | PTC | Loaded | 39, then interrupted | Not recorded |
| 2 | PTC | None | 50 | 59 |
| 3 | PTC | None | 33 | 32 |
| 4 | Standard | None | 43 | 70 |
In the three complete traces, the model understood the field semantics by step 8–12. The file edit took one to three steps. Repeated confirmation before the edit consumed 14–28 steps, followed by another 4–18 steps of validation and wrap-up.
One instrumented run recorded 2,946,619 input tokens: roughly 1.6 million during exploration, 90,603 around the write, and 1.25 million during post-write verification. The write represented 3% of input tokens; exploration, confirmation, and verification accounted for the rest.
Distinguish it from an ordinary stuck tool
| Symptom | Typical signal | Response |
|---|---|---|
| One stuck tool | A single command never returns | Tool timeout, process termination, sandbox checks |
| Exact repetition | The same tool and arguments repeat | Duplicate-call detection |
| Long reasoning with no action | No tool or text event for a long period | Effort, output limit, and model-state checks |
| Unbounded verification | Tools succeed and arguments change, but checks keep expanding | Turn-level steps, progress, and termination |
The 33–50 turn case matches the fourth row. Every read, search, and verification can be individually defensible. A per-tool timeout never fires because tools return normally; an exact-repeat guard misses calls whose arguments keep changing. The missing view is the accumulated work of the whole turn.
How the DSH loop continues
The follow-up source analysis pins DSH commit c291e7961a515f6d7af9304e7fd1d257929aef26. In packages/core/agent-loop/src/agent.ts, the turn controller begins with while (true). Every step calls the model, parses the output, and executes any tool calls.
The relevant feedback path is:
model emits a tool call
→ DSH executes the tool
→ the result enters next-step
→ the next step derives messages again
→ the model evaluates the expanded state
A step completes the turn when the model emits no tool call or a tool explicitly concludes the turn. Otherwise, each tool result supplies fresh input for another step. As long as the model finds one more fact worth checking, the loop has a valid continuation.
The same file shows buildRequest() calling session.deriveMessages() for every step and sending the derived message history in the next model request. Later verification steps therefore carry a longer history. Extra actions increase both step count and subsequent input cost. Post-write verification in the community trace consumed about 1.25 million input tokens.
What the Infinite Agentic Loops research adds
These 33–50 turn traces show an excessively long Agent Loop: three runs eventually ended and one was stopped by the user. When Agents Do Not Stop studies the next level of engineering risk: when a feedback path can repeatedly reach model calls, tool execution, growing state, or agent handoffs without an effective whole-path bound, it can develop into an Infinite Agentic Loop (IAL). This article uses that diagnostic framework to explain why DSH could run for so many turns.
IALs emerge across several layers:
- an Agent controller admits another iteration;
- the model proposes another locally useful action;
- the action updates state and returns new observations;
- termination depends on the model declining to continue;
- local timeouts or exits fail to bound the complete feedback path.
Termination currently depends on finish_reason, tool calls, and routing outcomes. The pinned revision has no turn-level step, time, or spend limit.
IAL-Scan analyzed 6,549 LLM Agent repositories. It reported 74 candidates; manual review confirmed 68 IAL failures across 47 projects, for 91.9% precision. The reported risks include cost exhaustion, context growth, loss of availability, and repeated external side effects.
Applying the paper's checks to this DSH case
| Diagnostic check | Corresponding DSH element |
|---|---|
| Loop controller | while (true) inside turn() |
| Costly invocation | A model request and tool calls on each step |
| Growing state | Tool results, Session events, and message history |
| Feedback edge | Tool output enters next-step |
| Model-dependent exit | The model stops calling tools, or a tool concludes the turn |
| Whole-turn bound | No total turn-step budget in the pinned revision |
The model does not need to repeat the same sentence or tool call for a feedback path to run for a long time. Searching file A, reading configuration B, checking parser C, and returning to A are different local actions while Steps, context, and tokens keep growing. The case has no whole-turn bound and shows amplification of both loop length and cost.
Immediate recovery for users
- Inspect the last ten steps and decide whether the acceptance target is already complete.
- Steer the Agent to stop adding checks and report only: completed, remaining, next action.
- Cancel the current turn if tool use continues; retain the Session and trajectory.
- Start from the completed edit in a fresh Session and run only an explicit acceptance command.
- Compare tool count and input tokens. When late-stage input grows quickly, reduce steps instead of focusing only on shorter outputs.
Switching between Standard, PTC, or different Skill sets is not a termination mechanism. The reported shape appeared in both PTC and Standard. Mode changes remain useful experiments, but the active turn still needs a boundary.
How to save tokens before the loop starts
Much of the cost appears after the answer already exists. Defining completion conditions and reducing the history carried by later steps can lower token use.
1. Put the stopping condition in the task
Do not stop at “make the change and check it.” State the allowed scope, the one required acceptance command, and what should happen after it passes:
Task: complete the change below.
Scope: inspect and modify only the specified directory; do not add unrelated refactors.
Done when: the target behavior is present and the specified validation command passes.
Validation: run only the listed command; when it passes, end the Turn and report the result.
If 3 consecutive Steps produce no new conclusion, file change, or test change, stop and report the blocker.
A prompt-level stopping condition reduces the model's reasons to keep searching, but it remains model-dependent. Long-running tasks still need a deterministic Harness-level budget.
2. Narrow the read and validation scope
Name the directory, file types, and acceptance command instead of repeatedly searching from the repository root. For a configuration edit, validate parsing and the relevant tests. A full build, repository-wide check, or second code-review pass should follow the task's risk rather than accumulate automatically.
3. Separate implementation from extended validation
End the first Turn after the change and required acceptance checks. If broader regression testing is necessary, start a new Session with only the change summary and validation target. The new Session does not need to carry the entire exploration history through every step.
4. Watch the Steps after the final edit
Record the Step that produced the last file change. If another 5–8 Steps add no file change, test result, or deliverable, Steer the Agent to close out; cancel the Turn if it still continues. This range is a troubleshooting starting point to adjust for task complexity, not a universal hard threshold.
5. Enforce hard budgets in the Harness
Prompts can improve behavior; step, time, token, and spend limits provide deterministic boundaries. At a soft limit, ask the Agent to report remaining work. After a grace period, end the Turn while preserving the Session and Trajectory so completed work does not keep accumulating context cost.
Boundaries an Agent Harness needs
1. A turn-level step budget
At a threshold, require a concrete report of what remains. If the Agent continues beyond a grace window, stop the turn. The limit must cover the entire feedback path rather than one tool invocation.
2. Time and spend budgets
Equal step counts can carry different history sizes. Production telemetry should track elapsed time, cumulative input and output tokens, and billed cost per turn, with visible soft ceilings.
3. Progress-aware detection
Exact argument repetition catches only the simplest loops. Better signals include changes to acceptance items, modified-file sets, test results, and the number of consecutive steps without a new deliverable.
4. An executed-action ledger after compaction
Keep a compact record of tools already run and their outcomes after context compaction. This prevents an Agent from losing its own operational history and re-verifying the same facts.
5. Auditable termination reasons
Record whether a turn ended normally, hit a step/time/spend budget, or was canceled by a user. Recovery logic can then distinguish completion from forced termination.
What the community Turn Budget Guard does
The discussion produced @argszero/cordis-plugin-turn-budget-guard. Its default configuration injects a wrap-up request after 20 steps, allows eight grace steps, then cancels the turn while preserving messages the user sent during execution.
- insert:
- id: turn-budget-guard
name: '@argszero/cordis-plugin-turn-budget-guard'
config:
maxSteps: 20
gracefulSteps: 8
The plugin demonstrates a mountable mitigation. It is community-maintained; review its source and test the threshold in an isolated Profile before using it on long-running work. If DSH Core gains a native step budget, the native mechanism should own termination records and recovery behavior.
A reproducible troubleshooting record
| Dimension | Record |
|---|---|
| Environment | DSH version, model ID, mode, reasoning effort, endpoint |
| Task | Original prompt, workspace state, acceptance criteria |
| Actions | Step count, tool names, key arguments, outcomes |
| Progress | Step where the answer appeared and the edit completed |
| Cost | Input/output tokens, elapsed time, billed amount by phase |
| Termination | Normal completion, user cancel, budget stop, or error |
Run the same task at least three times and retain one complete trajectory. The most useful metric is not total “thinking time.” Measure how many actions occur after the answer is available and whether those actions change the final deliverable.
Related reading
- V4.1 Flash: DSH Minimal, Standard, or PTC
- Configure DeepSeek V4.1 Flash in Harness
- Reproduce DeepSeek V4.1 Flash DeepSWE
- DeepSeek Harness security guide
FAQ
Is this a DeepSeek V4.1 Flash model bug?
All four community runs used V4.1 Flash, so the model can trigger this behavior. The DSH source also supplies a mechanism through which the loop can keep expanding. Diagnose it as an interaction between model behavior and Harness termination, then use the same task across models and versions to separate the variables further.
Does switching to PTC fix it?
Mode switching is not a reliable fix. The case produced 33–50 turn runs in both PTC and Standard. PTC can compress suitable batch tool work, but it does not automatically add a whole-turn step ceiling.
Why are the final verification steps so expensive?
DSH derives the current message history for the next step. As a Session grows, later requests commonly carry more context, so repeated post-write verification pays again to process accumulated history.