Skip to content

[FEATURE]:Option to always start sessions in the configured default agent mode #27370

Description

@ezzems

Feature hasn't been suggested before.

  • 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.

Activity

21pounder commented on May 18, 2026

@21pounder
Contributor

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.

21pounder commented on May 20, 2026

@21pounder
Contributor

@kitlangton Hi, here's my concrete proposal.

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 early
const storedModeId = this.sessionManager.get(sessionId).modeId
if (storedModeId && availableModes.some((mode) => mode.id === storedModeId)) {
  return { availableModes, currentModeId: storedModeId }  // default_agent never reached
}

Reproduction steps:

  1. Set "default_agent": "plan" in opencode.json
Image
  1. Open opencode — session correctly starts in Plan mode
Image
  1. Press Tab to switch to Build mode, send any message
Image
  1. Close opencode, then reopen and resume the same session
  2. Session opens in Build mode instead of Plan — default_agent is ignored
Image ---

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

Changes needed:

  • config.ts: add always_use_default_agent: Schema.optional(Schema.Boolean)
  • 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

{ "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) 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.

ezzems commented on Jun 3, 2026

@ezzems
Author

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 commented on Jun 4, 2026

@21pounder
Contributor

@ezzems still waiting, it's a big change u know.

github-actions commented on Aug 4, 2026

@github-actions
Contributor

To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions