You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[FEATURE]:Option to always start sessions in the configured default agent mode #27370
I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
Problem
When default_agent is set to "plan" in the config, new sessions correctly start in Plan mode. However, when reopening an old session that ended in Build mode, it restores the last-used mode (Build) instead of respecting the default_agent config.
This means I have to manually switch back to Plan mode every time I resume an old session, which defeats the purpose of having a default configured.
Proposed Solution
Add a config option (e.g., "always_use_default_agent": true) that forces all sessions — including resumed ones — to start in the configured default_agent mode, ignoring the persisted session state.
Alternatively, the existing default_agent setting could always take precedence over the session's saved mode when opening any session.
Use Case
I prefer to always start in Plan mode so I can review context before switching to Build. Having old sessions open in Build mode unexpectedly can lead to unintended changes if I start typing without noticing the mode.
I looked into the code and found the root cause: when restoring a session, restoreSessionStateFromMessages() reads the last user message's agent and writes it into session state. Then resolveModeState() sees a non-empty storedModeId and returns early, skipping default_agent entirely.
I think restoring the last-used agent is actually good idea — if you were mid-task in Build mode, coming back to Build makes sense. But it does ignore users who have explicitly configured default_agent and expect it to always be respected.
I'm thinking through the best way to handle this and will share a concrete proposal soon.
Root cause: restoreSessionStateFromMessages() writes the last-used agent into session state, then resolveModeState() sees a non-empty storedModeId and returns early — default_agent is never consulted.
Relevant code path in acp/agent.ts:
// restoreSessionStateFromMessages() — runs before resolveModeState()if(lastUser.agent){this.sessionManager.setMode(sessionId,lastUser.agent)// writes "build" into state}// resolveModeState() — sees storedModeId and exits earlyconststoredModeId=this.sessionManager.get(sessionId).modeIdif(storedModeId&&availableModes.some((mode)=>mode.id===storedModeId)){return{ availableModes,currentModeId: storedModeId}// default_agent never reached}
Reproduction steps:
Set "default_agent": "plan" in opencode.json
Open opencode — session correctly starts in Plan mode
Press Tab to switch to Build mode, send any message
Close opencode, then reopen and resume the same session
Session opens in Build mode instead of Plan — default_agent is ignored
---
Proposed fix
I looked at two approaches:
Option A — add always_use_default_agent: false opt-out field
Default behavior when default_agent is set becomes: always use default_agent when opening any session (new or resumed). The reasoning: anyone who takes the time to configure default_agent has a strong intent to use that agent — silently overriding it on resume is surprising. Users who prefer the old restore behavior can explicitly opt out:
{ "default_agent": "plan" } // always opens in Plan
{ "default_agent": "plan", "always_use_default_agent": false } // new sessions use Plan, resumed sessions restore last-used
acp/runtime.ts: expose the default-agent startup policy from directory-scoped config, since acp/agent.ts currently only receives ACP config and cannot directly tell whether this option is set
acp/agent.ts: in resolveModeState(), skip the storedModeId early-return when default_agent is set and always_use_default_agent !== false
customize-opencode.md: document the new field
Option B — change default_agent from string to object
More extensible for future per-default-agent options (e.g. { "name": "plan", "always": false, "model": "...", "tools": [...] }), but requires handling a union type (string | object) everywhere default_agent is read — agent.ts, acp/agent.ts, acp/runtime.ts, docs, and tests. Note that per-agent config is already covered by the existing agent field, so the extensibility gain is limited.
I prefer Option A: minimal API surface change, fully backward-compatible, and the semantics are clear — if you configure a default_agent, you almost certainly want it respected on every open. The opt-out exists for the rare case where you don't.
Happy to implement whichever direction you prefer.
Activity
21pounder commentedon May 18, 2026
I looked into the code and found the root cause: when restoring a session,
restoreSessionStateFromMessages()reads the last user message's agent and writes it into session state. ThenresolveModeState()sees a non-emptystoredModeIdand returns early, skippingdefault_agententirely.I think restoring the last-used agent is actually good idea — if you were mid-task in Build mode, coming back to Build makes sense. But it does ignore users who have explicitly configured
default_agentand expect it to always be respected.I'm thinking through the best way to handle this and will share a concrete proposal soon.
21pounder commentedon May 20, 2026
@kitlangton Hi, here's my concrete proposal.
Root cause:
restoreSessionStateFromMessages()writes the last-used agent into session state, thenresolveModeState()sees a non-emptystoredModeIdand returns early —default_agentis never consulted.Relevant code path in
acp/agent.ts:Reproduction steps:
"default_agent": "plan"inopencode.jsondefault_agentis ignoredProposed fix
I looked at two approaches:
Option A — add
always_use_default_agent: falseopt-out fieldDefault behavior when
default_agentis set becomes: always usedefault_agentwhen opening any session (new or resumed). The reasoning: anyone who takes the time to configuredefault_agenthas a strong intent to use that agent — silently overriding it on resume is surprising. Users who prefer the old restore behavior can explicitly opt out:{ "default_agent": "plan" } // always opens in Plan { "default_agent": "plan", "always_use_default_agent": false } // new sessions use Plan, resumed sessions restore last-usedChanges needed:
config.ts: addalways_use_default_agent: Schema.optional(Schema.Boolean)acp/runtime.ts: expose the default-agent startup policy from directory-scoped config, sinceacp/agent.tscurrently only receives ACP config and cannot directly tell whether this option is setacp/agent.ts: inresolveModeState(), skip thestoredModeIdearly-return whendefault_agentis set andalways_use_default_agent !== falsecustomize-opencode.md: document the new fieldOption B — change
default_agentfrom string to object{ "default_agent": { "name": "plan", "always": true } }More extensible for future per-default-agent options (e.g.
{ "name": "plan", "always": false, "model": "...", "tools": [...] }), but requires handling a union type (string | object) everywheredefault_agentis read —agent.ts,acp/agent.ts,acp/runtime.ts, docs, and tests. Note that per-agent config is already covered by the existingagentfield, so the extensibility gain is limited.I prefer Option A: minimal API surface change, fully backward-compatible, and the semantics are clear — if you configure a
default_agent, you almost certainly want it respected on every open. The opt-out exists for the rare case where you don't.Happy to implement whichever direction you prefer.
ezzems commentedon Jun 3, 2026
Hi @21pounder,
Is there anything I can help with regarding this task, or are we currently waiting for comments from @kitlangton?
Please let me know if there is anything I can do to move this forward.
Regards,
21pounder commentedon Jun 4, 2026
@ezzems still waiting, it's a big change u know.
github-actions commentedon Aug 4, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.