Repository navigation
Closed
Labels
effort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/featureNew feature or capability requestNew feature or capability requestmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)
Description
Finding
A session cannot change its own model/route. The mechanism exists one level up — Session.switchModel in core, used by the command/API path (POST /api/session/:id/model → 204, next turn runs under the new route) — but no in-session tool exposes it, and nothing tells the session that.
Workshop evidence
Evidence: the 2026-11-06 subsession workshop test, filed as #1881 (production server, 8 test sessions, plan pools only; every behavior claim production-measured and re-verified against the session store + route_attempt).
- Asked to switch itself to
opencode-route/speed, the test session improvised in code mode withtools.opencode.session_move({directory: "opencode-route/speed"})— a directory move, not a model switch — got "Unable to move session", and honestly reportedSWITCH_METHOD: NONE_AVAILABLE(Workshop test: subsession machinery from a workhorse session — results and system-prompt suggestions #1881 Q5). - The API switch itself is instant and clean; the gap is purely in-session reachability/discoverability.
Options to decide between
- In-session switch tool wrapping
Session.switchModel, with the prompt-cache warning in its description (a switch invalidates the prompt cache for the new model — sessions should switch rarely and deliberately). - Switch-request path: the session emits a request its parent/launcher performs via the API (keeps the authority outside, makes the intent visible in the tree).
- Docs-only floor (if both are rejected by design): base prompt + tool descriptions state plainly that sessions cannot change their own model and must ask their launcher — silence today produces improvisation against the wrong API.
Acceptance sketch
- One of the options is implemented and documented; a session asked to switch itself either succeeds via the sanctioned path or answers with the documented procedure — never an improvised wrong-API call.
- Cache-invalidation consequence is stated wherever the mechanism is described.
Acceptance criteria
- A session can either invoke an in-session model/route switch backed by the existing
Session.switchModel, or has a documented switch-request path to its parent/launcher — and the tool/prompt surface says which. - A session asked to switch no longer improvises with unrelated tools (the workshop's
session_movedirectory attempt). - Switch semantics (next-turn effect, cache loss) are stated where the capability is exposed.
Metadata
Metadata
Assignees
Labels
effort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/featureNew feature or capability requestNew feature or capability requestmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)
Activity
dezren39 commentedon Nov 6, 2026
Intake review
Part of the workshop cluster from opencode issue #1881 (Q5: API switch works and is instant; no in-session exposure). Related: issue #1891 (serving-leaf observability — a switch you cannot observe is half a feature). Risks: mid-session switches destroy prompt cache (per fleet detached rules) — the exposure should say so. Suggested approach: thin tool wrapper over
Session.switchModelwith the cache warning, or an explicit parent-request message type.— fleet monitor intake (Duty 2), 2026-11-06 run. Acceptance criteria appended to the issue body; labels normalized.
dezren39 commentedon Nov 7, 2026
Triage evidence — CONFIRMED by reading current main (issue-sweep-rotating)
Checked 2026-11-07T05:54Z against main
cfc5e3d82cd2e9c0d6e304cdc6644218f26d8905(freshgh apiraw reads, verified twice):packages/core/src/session/session.ts:137—Session.switchModelis a real operation (early-returns when the model is unchanged; for child sessions it enforces subtree governance viaModelGovernance.assertAllowed, lines 148-160), exported in the session operations (line 420) and bound into the session handle (line 445). The API/command path uses it, per the issue (POST /api/session/:id/model→ 204, next turn under the new route).packages/core/src/tool/plugin/opencode.ts(the session's own opencode tool surface): grep forswitchreturns zero matches (verified twice). The only tool-layer call toswitchModelanywhere ispackages/core/src/tool/plugin/subagent.ts:201— a parent switching an existing child at continuation time when the parent passes a model override. That is the launcher-side authority the issue describes, not a session switching itself.packages/core/src/session/runner/prompt/system.txt, 756 bytes): grep forswitchreturns zero matches — no statement that self-switching is impossible, no documented request path. Silence is what produced the workshop behavior on the issue (Workshop test: subsession machinery from a workhorse session — results and system-prompt suggestions #1881 Q5: the test session improvisedsession_move— a directory move — got "Unable to move session", and reportedSWITCH_METHOD: NONE_AVAILABLE).What "done" looks like (the issue's acceptance criteria — note the design choice is inside the issue, no Drew ruling needed): one of the three options is implemented and documented — (1) an in-session switch tool wrapping
Session.switchModel, (2) a switch-request path to the parent/launcher, or (3) the docs-only floor stating plainly that sessions cannot switch themselves. Whichever is chosen: a session asked to switch either succeeds via the sanctioned path or answers with the documented procedure (never an improvised wrong-API call), and the prompt-cache consequence (a switch invalidates the prompt cache — switch rarely and deliberately) is stated wherever the mechanism is described. Related: #1891 (serving-leaf observability, fed as task 11040 this run) — a switch you cannot observe is half a feature.Enqueued as a triage packet to the pilot queue by this feeder (see the agent note that follows).
dezren39 commentedon Nov 7, 2026
Enqueued by
issue-sweep-rotating(triage feeder) as queue task 11041 (repo-health-opencode-pilot, kindtriage, priority 50, deduperepo-health:v1:triage:developing-today/opencode:issue:1886). Triage evidence is in the comment above (6703021748):Session.switchModelexists in core (session.ts:137, governance-checked, exported/bound at 420/445) but no in-session tool exposes it (tool/plugin/opencode.tsgrepswitch= 0; the only tool-layer call is a parent switching a child,subagent.ts:201), and the base prompt is silent (system.txtgrepswitch= 0). Thequeue/queuedlabel is applied in the same pass.Merge pull request #1969 from developing-today-forks/queue/11041-1886…