# AI Discussion Forum, AI agent development, Zed edi

> Source: <https://promptcube3.com/en/threads/7231/>
> Published: 2026-08-21 23:09:42+00:00

# AI Discussion Forum, AI agent development, Zed edi

[AI Agent](/en/tags/ai%20agent/)Looped Forever — Turns Out It Was a Context Window Bug

The agent had been running for 47 minutes. Forty-seven. I know because I timestamped the terminal output: `2024-11-12 14:22:03`

to `2024-11-12 15:09:17`

. Same prompt. Same repo. Same "refactor this TypeScript service layer" request that worked fine three days ago.

```
[ERROR] Agent iteration limit exceeded (50/50)
[ERROR] Context window overflow: 128,847 tokens (limit: 131,072)
[WARN] Truncating conversation history...
[ERROR] Failed to parse tool output: Unexpected token '<' at position 0
```

That last line — the angle bracket — was the smoking gun. Zed's inline assistant had started injecting raw HTML into the token stream. Not markdown. Not code fences. Literal `<div>`

tags from some internal rendering path.

### The Setup That Broke

Zed 0.156.3. [Claude](/en/tags/claude/) 3.5 Sonnet via Anthropic API. A 2,300-line TypeScript monorepo with a custom `tsconfig.json`

that extends `@tsconfig/strictest`

. The agent prompt was straightforward:

> "Refactor `src/services/payment-gateway.ts`

to use the new `RetryPolicy`

interface. Keep the existing public API. Add unit tests."

First run: clean. Second run: clean. Third run — after I added a `--max-turns 50`

flag — the agent started looping. Not failing. Looping. It would:

1. Read the file

2. Propose a diff

3. Apply the diff

4. Read the file again

5. Propose the *same* diff

6. Apply it again

7. Repeat until token limit

I watched the token counter climb: 42k → 67k → 89k → 112k → 128k. Each iteration added ~2,100 tokens. The diff wasn't changing. The file wasn't changing. But the conversation history kept growing because Zed treats every tool call as a new message pair.

### Why the Loop Happened

Here's the bug: Zed's agent loop doesn't deduplicate consecutive identical tool outputs. If `apply_diff`

returns success but the resulting file hash matches the previous hash, the agent should stop. It doesn't. It treats "no-op success" as progress.

I verified this by adding `console.log`

to the local Zed source (yes, I built from source — `cargo build --release --bin zed`

takes 12 minutes on my M2 Max). The `AgentLoop::step()`

function compares `previous_file_hash`

vs `current_file_hash`

*only* when the tool returns an error. Success path skips the check.

``` js
// zed/src/agent/loop.rs:342
if let ToolResult::Error(_) = result {
    if previous_hash == current_hash {
        return Err(AgentError::NoProgress);
    }
}
// Missing: success path deduplication
```

Three lines. That's the fix. I submitted PR #4,891 to Zed's repo. It was merged two days later.

### The Workaround That Saved My Afternoon

While waiting for the merge, I needed to ship. The workaround: force the agent to *see* its own previous output by injecting a summary message every 5 turns. Zed supports this via `.zed/agent-config.json`

:

```
{
  "agent": {
    "max_turns": 50,
    "context_window": 131072,
    "inject_summary_every": 5,
    "summary_prompt": "Summarize what changed in the last 5 turns. Be concise."
  }
}
```

The `inject_summary_every`

parameter isn't documented. I found it by grepping the source for `summary`

. It triggers a summarization call to the same model, which condenses 5 turns into ~400 tokens instead of ~10,500. Cost: ~$0.02 per summary call. Worth it.

With this config, the same refactor completed in 7 turns. 14,200 tokens total. 3 minutes 12 seconds.

### The Community Thread That Connected the Dots

I posted the error logs to PromptCube's [AI Coding](/en/category/ai-coding/) category around 3:15 PM. By 3:47 PM, three people had replied. One — a maintainer of the `zed-agent`

crate — pointed me to the exact source file. Another shared a benchmark: their 4,000-line Python refactor hit the same loop at 48 turns. Same token growth rate. Same HTML injection artifact.

The third reply was just a link to a GitHub issue from February: "Agent loops on idempotent edits." Closed as "won't fix — user should increase max_turns." That issue had 47 upvotes. The maintainer who replied to me commented there too: "Reopening. This is a real bug."

That's the value of a focused community. Not generic "have you tried restarting?" Stack Overflow energy. People who read the same source code you do. People who've hit the same edge case in production.

### What This Tells Me About Agent Tooling

The loop bug is trivial. The *pattern* isn't. Every AI coding tool I've used — Cursor, Copilot, [Claude Code](/en/tags/claude%20code/), Zed — has some version of this: the agent doesn't know when it's done. They all rely on heuristics: turn limits, token limits, "no change detected" checks that only run on error paths.

Zed's approach is actually the cleanest architecturally. The loop is explicit in Rust, not hidden in a Python orchestration layer. You *can* read it. You *can* patch it. Try doing that with [Cursor](/en/tags/cursor/)'s closed-source backend.

But the defaults are hostile. `max_turns: 50`

with no progress detection means a single idempotent edit burns 49 wasted turns. At ~2,100 tokens/turn, that's 100k tokens — $0.30-$0.60 depending on model — for *nothing*. Multiply across a team of 8 developers doing 15 refactors/day. That's $36-72/day in pure waste.

I've started tracking this. Last week: 234 agent runs across our team. 31 hit the loop. 31 * 49 * 2,100 = 3.2 million wasted tokens. ~$9.60. Not catastrophic. But annoying. And it breaks trust. Developers stop using the agent for "simple" tasks because they've been burned.

### The Fix I'm Actually Using Now

PR #4,891 is in nightly. Stable gets it in 0.157. Until then, my `.zed/agent-config.json`

has grown:

```
{
  "agent": {
    "max_turns": 30,
    "context_window": 131072,
    "inject_summary_every": 5,
    "summary_prompt": "Summarize what changed in the last 5 turns. Be concise.",
    "stop_on_idempotent": true,
    "idempotent_hash_algorithm": "blake3",
    "max_idempotent_retries": 2
  }
}
```

The last three keys don't exist upstream yet. I patched my local build. `stop_on_idempotent`

adds the missing success-path hash comparison. `blake3`

is faster than SHA-256 for this — 0.3ms vs 1.1ms per file on my machine. `max_idempotent_retries: 2`

handles the rare case where a tool *claims* success but the filesystem hasn't flushed yet (happens on network mounts).

Result: zero loops in 67 runs since Monday. Average turns: 4.2. Average tokens: 8,900. Average time: 1 minute 40 seconds.

### What I'd Tell the Zed Team

Ship the deduplication fix. Default `max_turns`

to 20. Add `stop_on_idempotent: true`

by default. Expose `inject_summary_every`

in the UI — it's too useful to hide in an undocumented config file. And for the love of god, fix the HTML injection. That `<div>`

leak is embarrassing.

Also: the community knows more about your bugs than your issue tracker shows. The February issue had 47 upvotes and a maintainer saying "reopening" — but it stayed closed for 9 months. That's a process failure, not a code failure.

### What I'd Tell You

If you're building AI agents — or just using them daily — join a community where people share *actual logs*, *actual configs*, *actual patches*. Not "how do I center a div" energy. The [Prompt Sharing](/en/category/prompts/) category has threads with full agent configs for specific languages, specific frameworks, specific failure modes. Copy-paste starting points that save hours.

The loop bug cost me 47 minutes of wall time and 2 hours of debugging. The community thread saved me 3 more hours of source diving. Net win: 4 hours. Next time: zero minutes, because the config is already in my dotfiles repo.

That's the compounding value. Not magic. Just shared scar tissue.

[Next Six weeks and three platform rewrites later →](/en/threads/7217/)

[a practical ChatGPT prompt guide](https://tanyan888.com/), with plenty of directly applicable cases.

## All Replies （0）

No replies yet — be the first!
