Agent resets to Build after streaming error #8864

Open
opened 2026-02-16 18:11:03 -05:00 by yindo · 2 comments
Owner

Originally created by @Matroskin86 on GitHub (Feb 8, 2026).

Originally assigned to: @rekram1-node on GitHub.

Summary

When a streaming error occurs during a response, OpenCode resets the active agent to the default Build agent. The user's selected custom agent is silently lost until a fresh message is sent.

Steps to reproduce

  1. Create a custom agent (e.g. ~/.config/opencode/agents/lobster.md)
  2. Select the custom agent in OpenCode
  3. Send a message to a provider that occasionally returns streaming errors (e.g. an OpenAI-compatible proxy with intermittent failures)
  4. When a streaming error occurs, observe that the next retry/message uses the Build agent system prompt instead of the custom agent's prompt

Expected behavior

The custom agent should persist across streaming errors and retries. If the user selected "Lobster" agent, all subsequent messages (including retries after errors) should continue using the Lobster agent prompt.

Actual behavior

After a streaming error:

  • The active agent silently resets to Build
  • The Build agent system prompt (14586 chars, "You are OpenCode, the best coding agent...") replaces the custom agent prompt
  • The custom agent is restored only when the user sends a new message (not a retry)

How I discovered this

I added debug logging inside a plugin's experimental.chat.system.transform hook to track what arrives in output.system[0]:

[T1] system[0] length=7895, starts="🦞 Клешня" ← custom agent ✅
[T2] streaming error occurs
[T3] system[0] length=14586, starts="You are OpenCode" ← Build agent ❌
[T4] system[0] length=14586, starts="You are OpenCode" ← still Build ❌
[T5] new user message → system[0] length=7895, starts="🦞 Клешня" ← custom agent back ✅

Environment

  • OpenCode v1.1.53 (Homebrew, macOS)
  • Provider: OpenAI-compatible via @ai-sdk/openai-compatible
  • Plugin: @tarquinen/opencode-dcp v2.0.2 (used for debug logging, not the cause)

Additional context

This was initially misattributed to the DCP plugin (see opencode-dynamic-context-pruning#367). After isolating variables with debug logging, the root cause is in OpenCode's error recovery path, which resets the agent state.

Originally created by @Matroskin86 on GitHub (Feb 8, 2026). Originally assigned to: @rekram1-node on GitHub. ## Summary When a streaming error occurs during a response, OpenCode resets the active agent to the default **Build** agent. The user's selected custom agent is silently lost until a fresh message is sent. ## Steps to reproduce 1. Create a custom agent (e.g. `~/.config/opencode/agents/lobster.md`) 2. Select the custom agent in OpenCode 3. Send a message to a provider that occasionally returns streaming errors (e.g. an OpenAI-compatible proxy with intermittent failures) 4. When a streaming error occurs, observe that the next retry/message uses the **Build** agent system prompt instead of the custom agent's prompt ## Expected behavior The custom agent should persist across streaming errors and retries. If the user selected "Lobster" agent, all subsequent messages (including retries after errors) should continue using the Lobster agent prompt. ## Actual behavior After a streaming error: - The active agent silently resets to Build - The Build agent system prompt (14586 chars, "You are OpenCode, the best coding agent...") replaces the custom agent prompt - The custom agent is restored only when the user sends a **new** message (not a retry) ## How I discovered this I added debug logging inside a plugin's `experimental.chat.system.transform` hook to track what arrives in `output.system[0]`: ``` [T1] system[0] length=7895, starts="🦞 Клешня" ← custom agent ✅ [T2] streaming error occurs [T3] system[0] length=14586, starts="You are OpenCode" ← Build agent ❌ [T4] system[0] length=14586, starts="You are OpenCode" ← still Build ❌ [T5] new user message → system[0] length=7895, starts="🦞 Клешня" ← custom agent back ✅ ``` ## Environment - OpenCode v1.1.53 (Homebrew, macOS) - Provider: OpenAI-compatible via `@ai-sdk/openai-compatible` - Plugin: `@tarquinen/opencode-dcp` v2.0.2 (used for debug logging, not the cause) ## Additional context This was initially misattributed to the DCP plugin (see [opencode-dynamic-context-pruning#367](https://github.com/Opencode-DCP/opencode-dynamic-context-pruning/issues/367)). After isolating variables with debug logging, the root cause is in OpenCode's error recovery path, which resets the agent state.
Author
Owner

@github-actions[bot] commented on GitHub (Feb 8, 2026):

This issue might be a duplicate of existing issues. Please check:

  • #12234: Infinite retry loop when StreamIdleTimeoutError occurs during tool input generation

Both issues involve streaming errors causing state/agent resets and retry loops. Feel free to ignore if your issue addresses a different scenario.

@github-actions[bot] commented on GitHub (Feb 8, 2026): This issue might be a duplicate of existing issues. Please check: - #12234: Infinite retry loop when StreamIdleTimeoutError occurs during tool input generation Both issues involve streaming errors causing state/agent resets and retry loops. Feel free to ignore if your issue addresses a different scenario.
Author
Owner

@Matroskin86 commented on GitHub (Feb 8, 2026):

Not a duplicate of #12234

Thanks for flagging, but these are different bugs in the error recovery path:

#12234 This issue (#12750)
Trigger StreamIdleTimeoutError during tool input generation Generic streaming error from provider
Symptom Infinite retry loop, UI stuck on "Preparing write..." Custom agent silently replaced with Build agent
Root cause isRetryable: true + no max retry cap + doom loop detection misses empty {} inputs Error recovery resets agent state to default
User impact Must manually abort (Escape) Loses custom agent prompt, gets wrong persona
Retry behavior Exponential backoff retries forever Retry may succeed, but with wrong agent

#12234 is about retry loops that never terminate. This issue is about agent state not surviving error recovery — the retry might work fine, but it runs with the Build agent instead of the user's selected agent.

They could share code in the error recovery path in processor.ts, but the fixes are orthogonal:

  • #12234 needs a max retry cap / better doom loop detection
  • This issue needs agent state preservation across retries
@Matroskin86 commented on GitHub (Feb 8, 2026): ## Not a duplicate of #12234 Thanks for flagging, but these are different bugs in the error recovery path: | | #12234 | This issue (#12750) | |---|---|---| | **Trigger** | `StreamIdleTimeoutError` during tool input generation | Generic streaming error from provider | | **Symptom** | Infinite retry loop, UI stuck on "Preparing write..." | Custom agent silently replaced with Build agent | | **Root cause** | `isRetryable: true` + no max retry cap + doom loop detection misses empty `{}` inputs | Error recovery resets agent state to default | | **User impact** | Must manually abort (Escape) | Loses custom agent prompt, gets wrong persona | | **Retry behavior** | Exponential backoff retries forever | Retry may succeed, but with wrong agent | #12234 is about **retry loops that never terminate**. This issue is about **agent state not surviving error recovery** — the retry might work fine, but it runs with the Build agent instead of the user's selected agent. They could share code in the error recovery path in `processor.ts`, but the fixes are orthogonal: - #12234 needs a max retry cap / better doom loop detection - This issue needs agent state preservation across retries
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#8864