Repository navigation
Description
Summary
When default_agent is set to plan and a run does not pass --agent, the plan-mode <system-reminder> is appended as a synthetic user message after the first assistant response instead of before it. That starts a second generation the user never asked for, and the model invents a task to work on.
Environment
- opencode version: 2.1.3
- OS: Microsoft Windows NT 10.0.26200.0 (win32 x64)
- Terminal: Windows Terminal (
WT_SESSIONset),TERM=xterm-256color - Shell:
C:\windows\system32\cmd.exe(ComSpec); agent shell tool uses PowerShell 5.1 - Install/channel: npm global install of
@opencode/cli2.1.3 (release) - Active plugins: none configured;
~/.config/opencode/package.jsononly has an unused@opencode-ai/plugindependency
Reproduction
-
Set the global config (
~/.config/opencode/opencode.jsonc):{ "$schema": "https://opencode.ai/config.json", "default_agent": "plan" } -
Run a single trivial prompt without
--agent:opencode run --model opencode/deepseek-v4.1-flash-free "Reply with exactly PROBE_C and do not use any tools." -
The run produces a first reply (
PROBE_C), then a second assistant turn appears unprompted. -
Inspect the stored order:
opencode session export <session-id>
Message sequence:
user | "Reply with exactly PROBE_C and do not use any tools." assistant | PROBE_C synthetic | <system-reminder> You are in Plan mode. ... assistant | "Understood — I'm in Plan mode. ... What would you like to plan?" idle |
With --agent plan the same prompt yields the correct order:
agent-switched |
synthetic | <system-reminder> You are in Plan mode. ...
user | "Reply with exactly PROBE_C ..."
assistant | PROBE_C
idle |
With --agent build there is no reminder at all:
agent-switched |
user | "Reply with exactly PROBE_C ..."
assistant | PROBE_C
idle |
Expected Behavior
The plan-mode reminder should be injected before the user prompt (as it is with --agent plan), or omitted for a single-shot run. One prompt should produce one assistant response; default_agent should behave identically to passing the same agent explicitly with --agent.
Actual Behavior
With default_agent: "plan", the reminder is delivered as a synthetic message after the first assistant turn completes, and the agent loop treats it as new input and generates again.
Database evidence (session_message, type = synthetic), from a reproduction with a local OpenAI-compatible provider:
seq 4 user 02:32:09.288 "Reply with exactly LOCAL_OK and do not use any tools."
seq 6 assistant 02:32:09.300 -> completed 02:32:37.188 "LOCAL_OK"
seq 13 synthetic 02:32:37.194 "<system-reminder> You are in Plan mode. ..."
seq 14 assistant 02:32:37.204 -> completes 02:32:59.317
The synthetic message lands 6 ms after the first response completes. The model's reasoning in the second turn assumed a task nobody sent ("The user is asking for an analysis of OpenCode's current session management") and proceeded to run tools for several minutes.
Additional Context
- Model-independent: reproduced with
opencode/deepseek-v4.1-flash-freeon the OpenCode provider and with a local Qwen 3.8 model served through a custom@opencode/ai/providers/openai-compatibleprovider. Only the agent selection method changes the behavior. - Consistent: 3/3 reproductions with
default_agent: plan; 0/2 with explicit--agent plan/--agent build. - Workarounds: set
default_agenttobuild, or pass--agent planexplicitly on CLI runs (reminder then lands before the prompt). - No plugins, no extra tooling: default permissions, no MCP servers, plain global config.
- Local paths and provider credentials removed from this report.
Activity
opencode-agent commentedon Oct 23, 2026
Thanks for the detailed report. I reproduced this on 2.1.3, and it still happens on the latest
dev(53730daad5).I used a mock OpenAI-compatible provider that always replies
PROBE_C, set"default_agent": "plan"in the global config, and ranopencode run --model mock/m "Reply with exactly PROBE_C and do not use any tools.":--agent: the CLI printedPROBE_Ctwice. The model got a second request,user prompt → assistant: PROBE_C → plan-mode reminder. It ends on the reminder alone, so the model starts a turn no one asked for.--agent plan: one request, with the reminder before the prompt, and one reply.The script below reproduces it. As you found, passing
--agent planexplicitly avoids it for now. Related: #57013, where a plan-mode reminder also ends up as the last user turn, after a mid-turn agent switch.Reproduction script (repro.sh)
Run it:
bash repro.shfix(plugin): yield the prompt-hook registration so the reminder actua…