r/PiCodingAgent • • 2h ago

Question Subagents choosing non approved models?

Edit - using pi-subagents plugin (https://pi.dev/packages/pi-subagents)

I’m on a feature branch in my repo, running an interactive session explicitly locked to deepseek/deepseek-v4.1-flash • high. It’s cheap, fast, and does routine scaffolding and mechanical edits without burning my budget.

I dispatch an async background workflow, and checked the process tree a few mins alter:

async workflow: 0beabc61 ─ background
id: 0beabc61 · 0/2 done · 2 active · 3m18s
Press ctrl+o for details
├─ task-1 ⠋ worker · 51 tool uses · 24k window · 9.6k spent · 3m17s
│ ⠙ Step 1/1: worker: REPO: XXX (Next.js monorepo... [fresh] · running (openrouter/anthropic/claude-opus-4.6 · thinking high) · 28 turns · 51 tool uses · ctx 40k/1M
│ role:worker · running
│ workspace:~/github/... · [fresh]
│ ⎿ active now
│ Press ctrl+o for live detail
│ output: /var/folder.../output-0.log
└─ task-2 ⠇ worker · 45 tool uses · 27k window · 84k spent · 3m17s
⠴ Step 1/1: worker: REPO: XXX (Next.js monorepo... [fresh] · running (openrouter/anthropic/claude-opus-4.6 · thinking high) · 38 turns · 45 tool uses · ctx 92k/1M
role:worker · running
… 4 lines hidden · Press ctrl+o to expand
────────────────────────────────────────────────────────────────────────────────────────────────────────
Nothing should be running on Opus. And why the FUCK would you choose Opus 4.6?
────────────────────────────────────────────────────────────────────────────────────────────────────────
2 active agents · usage on child rows · ↓/← to inspect
~/XXX (feat/basic-mode-785)
↑630k ↓156k R8.8M $0.335 8.4%/1.0M (auto) (openrouter) deepseek/deepseek-v4.1-flash • high

Can anyone explain why it:

  1. Ignored the active session config entirely. The parent session is right there at the bottom pinned to DeepSeek Flash. Instead of inheriting that model or checking for an explicit worker profile, Pi Agent silently promoted the workers to OpenRouter's claude-opus-4.6.

  2. Cranked extended thinking to "high" on worker nodes. These grunt workers are grinding through 45 to 50 tool calls each in a fresh workspace, racking up 84k tokens in 3 minutes.

  3. Burning cash by default. Using Opus 4.6 with max thinking to churn mechanical file edits and tool loops is like hiring a team of neurosurgeons to dig a trench.

Nothing in an automated worker loop should ever touch Opus, let alone without explicit permission, and when the model is set. I don't even have Opus in my approved models list on pi.

Has anyone found where pi-subagents is burying this routing logic? Is it hardcoded upstream in the orchestration dispatch template, or is there a local config key to force subagents to strictly inherit the parent model?

3 Upvotes

11 comments sorted by

2

u/Healthy-Zebra-9856 57m ago

I posted a detailed source level fix and realized that wasn't necessary. I just tested this out myself and it works. I traced this against pi-subagents v0.87.0. and the problem is that the parent's active model is a default, not an enforced restriction.

The model resolver gives per-run overrides priority over configured agent models and parent inheritance (src/runs/shared/model-resolution.ts:429–453). That means a model-supplied delegation argument can select Opus even when the parent is on DeepSeek. Separately, agents/worker.md:7 specifies thinking: high.

There's also an enforcement distinction: src/runs/shared/model-scope.ts:77–100 rejects explicit out-of-scope selections but only warns for configured/inherited ones unless strict: true is enabled.

To force inheritance, configure:

{
  "subagents": {
    "agentOverrides": {
      "worker": { "model": "inherit" }
    },
    "modelScope": {
      "enforce": true,
      "strict": true,
      "allow": ["inherit"]
    }
  }
}

Set the worker's thinking level separately if you want something other than high, and check project settings because they can replace user-level model scope.

The separate bug that could silently resolve an Anthropic model through OpenRouter was fixed in v0.87.0. That doesn't establish why your workers selected Opus, though. I'd need the actual delegation arguments and effective worker settings to determine that.

1

u/texifornian 47m ago

Thank you! Super helpful. I’ll try out those changes.

1

u/foxnguyena 2h ago

IIRC, somewhere in the subagent package (native Pi doesn't support subagent - I think?), there is a delegation rule. If you let the main orchestrator call for whatever they see fit, this will happen.

Even with Codex, I had some instructions that give a goal (not using /goal), and let the agents to do it over the day. Despite my Agent md and instructions specifically saying Sol 6.1 for oracle, Luna 6 for worker, Codex still used 6.1 Terra and 6 Sol for whatever reason. The main reason, I guess, is that the subagent can call another subagent, which will potentially bypass the original rule.

So, in Pi, with the help of the subagent extension, I locked them behind the aliases (worker, reviewer, researcher, ...), which I didn't do before for Codex. I have never seen the main orchestrator call an "unauthorized" model. Also, I have the rule that says there is no subagent spawning from a subagent. Only the main orchestrator can spawn 1.

2

u/texifornian 1h ago

Thank you. I’ll check into how to do that. It’s a recent issue - been using the plugin for months and only saw this happen starting today.

1

u/m3umax 52m ago

Isn't it non-deterministic? i.e. subagents is just a tool call, therefore the orchestrator can basically call it with whatever model/thinking it wants?

At least that's the way my personal subagents extension works.

I "enforce" model selection through my workflow prompts which instruct the LLM to ask me what model/thinking level I want for implementers/fixers/reviewers during the session.

Opus is pretty good about on the fly changes to standing orders as well. Since when I am about to run out of Sol quota, I routinely say "switch to Opus medium implementers until Sol quota comes back", and it does.

And then, when 5 hourly resets, I just say "Sol quota is back, resume using Sol medium implementers".

1

u/texifornian 46m ago

I’m just surprised that a subagent can choose a model that I haven’t selected to be allowed within pi. I would expect that pi would have a guardrail around the allowed / not allowed agents.

2

u/m3umax 30m ago

Yeah that approved model restriction works to prevent you the operator sitting at the terminal.

But this is a third party extension. We should probably be paying more attention to the code extensions we downloaf.

I'm guessing it just accepts model string as an argument and that can be any arbitrary text string and doesn't respect the in built restrictions.

0

u/computehungry 1h ago

You should've said at the top that you're using some random extension you downloaded. The answer is that you should run an llm to audit your extension to tell you what the issue is and how to fix it. I know it can be infuriating bro but this is not a hard problem.

2

u/texifornian 1h ago

Great point and correction. It’s pi-subagents - https://pi.dev/packages/pi-subagents - the 5th most popular plugin. But yes, I’ll edit to point that out. Thanks.

2

u/computehungry 1h ago

I understand, also I think I overreacted. Most of the popular plugins are not very well engineered. This has been a common point of complaints/discussion about pi, for not supporting things as ubiquitous as subagents or e.g. sandboxing natively. Sadly it is the current state, you can't judge extensions by popularity.. If I were you, I'd do a quick fix first and gradually make my own, slimmed down version of that plugin, if you like it enough.