Replies: 2 comments
|
We hit this on
Representative child {"type":"request/header","data":{"header":{"config":{"provider":"opencode-go","model":"deepseek-v4-flash","maxTokens":384000}}}}Two small observations that may matter for the fix:
The proposed direction (delegation follows the parent's live route — the folded Happy to share sanitized session excerpts or help test the patch against the pi-ai multi-provider adapter. |
|
This stale-seed case now has a verified alternative path through the Pi plugin ecosystem. It does not patch DSH native subagents; dsh plugin --profile <你的-profile> add pi2dsh
dsh plugin --profile <你的-profile> add @tintinweb/pi-subagentsFor an unpinned child, route precedence is: explicit Pi child model → the caller session's last durable real The acceptance test uses stock dsh-TUI and real model calls: the parent first runs on Reproduction and evidence: |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Summary
When the configured default model is changed (e.g. from Auto Router (
openrouter/auto) to a concrete model likestealth/ox-alpha), sessions that were created — or merely resumed — under the old default keep spawning subagents that still route on the old model. The main chat visibly runs the new model, while every delegated child silently answers via the router, which fans out to arbitrary upstream models.The cause looks like a split-brain between two per-session "model" values: the request route (what the chat actually sends on) and the agent seed options (stamped at create/resume time). Subagent delegation reads the latter.
Environment
@deepseek-ai/dsh0.1.1-rc.2 (dsh-subagent,dsh-host-apiproxy,dsh-agent-default-modelall 0.1.1-rc.2)127.0.0.1:3081openrouter; default model was at some point set toopenrouter/auto("Auto Router"), later switched tostealth/ox-alphaEvidence
From session logs (
.dsh/sessions/...):Parent session — requests actually running Ox Alpha:
{"type":"request/header","data":{"header":{"config":{"provider":"openrouter","model":"stealth/ox-alpha"}}}}…yet every child it spawned around that time carried the stale seed:
{"type":"subagent/descriptor","data":{"version":2,"mode":"continuable","provider":"spawn","label":"Add serverbound play interaction packets","agentProvider":"openrouter","agentModel":"openrouter/auto"}}and the children's own
request/headerevents confirm they really calledopenrouter/auto.Root cause walkthrough
Web layer seeds options once per create/resume. In
dsh-host-apiproxy/src/api-proxy.ts:"Never goes stale" only holds across create/resume calls. A session left open across a default change keeps the old seed.
Per-session selection is separate and doesn't touch options.
selectionFor()resolves the request route as: in-process UI pick → latest loggedrequest/header→ liveagent-default-model. Switching models in the UI (or changing the default) updates what the chat sends on — but never rewritesagent.options.Delegation reads the raw seed. In
packages/subagent/subagent/src/child-agent.ts:The continuable descriptor snapshot in
SubagentRuntime.startContinuableduplicates the same read:So a session seeded while the default was
openrouter/autokeeps delegating children onopenrouter/autoindefinitely, even while the parent itself runs a concrete model. The same applies to any long-lived session after any default change — the drift is just most visible (and most costly) with a router model, where you don't control which upstream model answers.Proposed fix
Make delegation follow the parent's live route, falling back to the seed only before the first request exists. The folded request header is already the exact source
selectionFor()uses for sessions without an in-process pick:…and use the same helper for the descriptor snapshot in
startContinuable(both the bundled copy andtypes/child-agent.ts).I've been running exactly this patch locally (verified: stale-seed parent with live Ox Alpha route → child gets
stealth/ox-alpha; blank parent → falls back to seed; per-child override → respected). Happy to open a PR if you tell me which repo/branch to target and whether you'd prefer this shape or a different one.Alternative directions
agent.optionswhen a session's effective selection changes (keeps inheritance semantics but makes the web layer own the sync), orWorkarounds (until fixed)
One caveat users should know: since
selectionFor()prefers the latest logged request over the live default, resuming does not reset what an existing session sends on — only what future subagents inherit. Both surfaces have to be checked when chasing "why is my subagent on a different model".All reactions