[BUG]: Primary-agent switches silently keep the previous agent's model in V2 · Issue #43179 · anomalyco/opencode · GitHub
Skip to content

[BUG]: Primary-agent switches silently keep the previous agent's model in V2 #43179

Open

Description

@nulluserid

Description

In the OpenCode 2 beta, switching primary agents changes the prompt and permissions but silently keeps the existing session model and variant.

For example, with Plan configured for provider/model-a#high and Build configured for provider/model-b#max, a Plan session remains on model A after Shift-Tab selects Build. The next request runs the Build agent on model A. Delegated children do use their own configured models, so the behavior is inconsistent between primary-agent switching and delegation.

This recreates the UX reported in #3550 and previously fixed by #3572. V2 now documents the separate session model, but the result is still surprising: an agent profile combines a prompt, permissions, and a model preference, and the UI presents the agent and model together.

This can silently run a role on a weaker, more expensive, or incompatible model and reasoning variant. It can also defeat an intended local-model boundary when a sensitive role is selected after a hosted-model role.

There is a legitimate opposite requirement in #41221: a model chosen manually should not be discarded on every agent switch. An unconditional "always switch" or "always preserve" rule makes one workflow fail.

Suggested behavior:

  • Track whether the session model is following the agent default or pinned by the user.
  • A new session initialized from an agent's configured model starts in follow-agent mode.
  • In follow-agent mode, switching primary agents applies the new agent's configured model and variant.
  • Selecting /models or /variants explicitly pins the session choice, so it survives later agent switches.
  • Show when a session override is pinned and provide a simple "Use agent default" action to return to follow-agent mode.
  • Update the selected agent and effective model atomically so plugins do not need timing-sensitive synchronization hooks.

That preserves explicit user choices while making configured role defaults behave like defaults. It prevents silent model/role mismatches without forcing plugin authors to build parallel preference stores or race the TUI.

Plugins

None required. The behavior reproduces with native V2 agents.<role>.model configuration.

OpenCode version

opencode2 v0.0.0-beta-17577

Steps to reproduce

  1. Configure two selectable primary agents with different native model values and variants.
  2. Start a new session with the first agent and confirm its configured model is active.
  3. Shift-Tab to the second agent.
  4. Send a prompt.
  5. Observe that the second agent's prompt/permissions run with the first agent's session model instead of its configured model.
  6. As a control, delegate to a child with its own configured model and observe that the child uses its configured model.

Screenshot and/or share link

No public share link; the session contains private repository context.

Operating System

Fedora Linux 44

Terminal

OpenCode TUI on Linux

Activity

  1. github-actions commented on Aug 18, 2026

    @github-actions
    Contributor

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

  2. nulluserid commented on Aug 18, 2026

    @nulluserid
    Author

    Thanks — I checked these before responding.

    The closest implementation work is #40604. It tags a manual model selection with the agent under which it was made, so an untouched agent can use its configured default without destroying a deliberate override. That is the same ambiguity this issue is trying to resolve rather than choosing “always switch” or “always preserve.”

    The remaining distinction is client/runtime scope: #40604 currently changes the app composer (packages/app/...), while this report reproduces in the OpenCode 2 beta TUI. The useful V2 behavior would be:

    1. An agent with no explicit session override uses its configured model and variant when selected.
    2. A deliberate model/variant selection remains an explicit override instead of being silently discarded.
    3. The UI indicates the override and offers a direct way to clear it and return to the agent default.

    I'm happy for maintainers to consolidate this under an existing issue if the equivalent V2 TUI path is tracked there. The main point is that the state needs to distinguish an inherited agent default from an explicit user selection; a single unlabelled session model cannot satisfy both sets of reports.

  3. nulluserid commented on Aug 21, 2026

    @nulluserid
    Author

    Additional concrete evidence from a real V2 primary session:

    Event Agent default Effective model
    Initial Build turn zai-coding-plan/glm-5.3#max zai-coding-plan/glm-5.3#max
    Shift-Tab to Plan deepseek/deepseek-v4-flash#high zai-coding-plan/glm-5.3#max

    This was the same primary session, not a delegated child. The agent changed, but the subsequent Plan turns retained the Build model and variant.

    The current V2 implementation appears to model this as two independent operations:

    Suggested regression coverage:

    1. An unpinned session switching A -> B atomically adopts the configured model and variant for B.
    2. An explicitly pinned user model follows the chosen pinning policy across agent switches.
    3. Use agent default clears the pin and adopts the current agent default.
    4. No provider turn can observe new agent instructions and permissions with the previous agent model.

    This also seems distinct from the app-composer persistence work in #40604 unless that work is extended to the V2 session/TUI path.

  4. lenucksi commented on Sep 27, 2026

    @lenucksi

    The pinned-vs-follow-agent split proposed here would also settle the precedence problem in #49713.

    Concretely: the per-agent override is an in-memory record keyed by agent name and is never written to disk — save() in packages/tui/src/context/local.tsx:169-180 persists only recent, favorite, and variant. So "pinned" state does not currently survive a restart at all, and there is no way to represent "following the agent default" vs "pinned" without adding that persistence.

    Happy to provide a repro that isolates the missing persistence from the agent-switch question, if that helps narrow the scope.

  5. r4zor4x commented on Sep 30, 2026

    @r4zor4x

    Still reproduces on v2.0.16 (stable) in the TUI, across providers:

    "agents": {
      "plan":  { "model": "claude-gateway/claude-opus-5-5" },
      "build": { "model": "github-copilot/claude-sonnet-5.5" }
    }

    In an existing session, Shift+Tab from Plan to Build keeps claude-opus-5-5 in the footer and on the next request. New sessions pick the agent's model correctly, so it only affects switching inside a session.

    From reading packages/tui/src/context/local.tsx, the carry-over looks deliberate: on agent change the current selection is re-set for the new agent (agent.set, "Retain both selections while agent and model commits arrive separately"), and the per-session draft takes precedence over the durable session model. So neither a server plugin reacting to session.agent.selected nor a TUI plugin can fix it cleanly: the TUI plugin API has no way to set the model, and no built-in command accepts a model id as input.

    👍 for the follow-agent / pinned split proposed above. It would cover this without breaking the manual-selection case in #41221.

    Maintainers: would you take a PR along those lines, given #40604 was closed? Happy to help if there is a preferred direction.

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions