Skip to content

(MOT-3925) fix(harness): inherit parent provider only when the spawn model is inherited too - #461

Merged
andersonleal merged 1 commit into
mainfrom
fix/harness-spawn-provider-inheritance
Jul 9, 2026
Merged

(MOT-3925) fix(harness): inherit parent provider only when the spawn model is inherited too#461
andersonleal merged 1 commit into
mainfrom
fix/harness-spawn-provider-inheritance

Conversation

@andersonleal

@andersonleal andersonleal commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Problem

harness::spawn with an explicit model but no provider silently attached the parent turn's provider to the child. A parent running zai::glm-5.2 spawning model=claude-sonnet-4-6 produced the incoherent pair zai::claude-sonnet-4-6. The router honors an explicit provider without catalog membership checks (documented intent — decide() step 1 is cold-catalog tolerant), so provider-zai sent the claude model to Z.AI, which rejected it upstream:

{"error":{"code":"1211","message":"Unknown Model, please check the model code."}}

The child session died with the raw error as its result, and the parent could not recover by picking another Anthropic model — the retry inherited zai again.

Observed in a live multi-agent run: children spawned in-turn (fact-extractor-b4k9, summarizer-b4k9) inherited provider=zai and failed, while children spawned through the parentless reactive path got provider=None and ran the same model successfully via catalog routing to anthropic. Reproducible with iii trigger router::complete model=claude-sonnet-4-6 provider=zai messages=[…].

Fix

seed_child now resolves the provider through child_provider(): an explicit request wins; otherwise the parent's provider is inherited only when the model is inherited too — model and provider stay a coherent pair. A spawn that names its own model gets no provider and the router routes it by catalog.

spawn model spawn provider before after
explicit explicit both used unchanged
inherited inherited parent pair unchanged
inherited explicit explicit provider unchanged
explicit absent parent's provider none → router decides

harness::send's inject path already reuses the last turn's options as one bundle, so spawn was the only place the pair could split.

Test

provider_is_inherited_only_together_with_the_model in subagent.rs covers the failing case, coherent-pair inheritance, explicit-provider-wins, and parentless spawns. Full harness lib suite: 194 passed.

https://claude.ai/code/session_0155foth69LSS75ebk2gjZ8U

Summary by CodeRabbit

  • Bug Fixes
    • Improved provider selection for newly spawned sessions to keep model and provider choices consistent.
    • Explicit provider selections now take priority, while model-only requests no longer inherit an incompatible provider.
    • Sessions without a parent now start without inherited settings.
    • Updated validation coverage for the supported model/provider combinations.

…herited too

seed_child resolved the child's model and provider from different sources:
an explicit spawn model still picked up the parent turn's provider. A parent
running zai::glm-5.2 spawning a child with model=claude-sonnet-4-6 produced
the incoherent pair zai::claude-sonnet-4-6; the router honors an explicit
provider without catalog checks (by design), so Z.AI answered
{"error":{"code":"1211","message":"Unknown Model, please check the model
code."}} and the child session died with it.

The child's provider now stays a coherent pair with the model: an explicit
request wins; otherwise the parent's provider is inherited only when the
model is inherited too. A spawn that names its own model gets no provider,
letting the router route the model by catalog.

Claude-Session: https://claude.ai/code/session_0155foth69LSS75ebk2gjZ8U
@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workers Ready Ready Preview, Comment Jul 9, 2026 2:52pm
workers-tech-spec Ready Ready Preview, Comment Jul 9, 2026 2:52pm

Request Review

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

skill-check — worker

0 verified, 41 skipped (no docs/).

Layer Result
structure
vale
ai
render

Four for four. Nicely done.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The provider derivation logic in seed_child was refactored into a new child_provider helper that enforces coherent model+provider pairing rules: explicit provider always wins, explicit model without provider prevents inheritance, and unset model/provider inherits the parent's provider. Tests were added to validate this matrix.

Changes

Provider Inheritance Rule

Layer / File(s) Summary
Provider inheritance helper and wiring
harness/src/subagent.rs
Adds child_provider helper enforcing model+provider coherence rules and updates seed_child to delegate provider resolution to it.
Inheritance matrix tests
harness/src/subagent.rs
Adds spawn_request test helper and a new test validating provider inheritance behavior across explicit/unset model and provider combinations, including parentless spawns.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant SeedChild
    participant ChildProvider
    participant ParentRecord

    Caller->>SeedChild: spawn request (model?, provider?)
    SeedChild->>ChildProvider: child_provider(req, parent_record)
    ChildProvider->>ParentRecord: read parent provider
    alt provider explicitly set
        ChildProvider-->>SeedChild: use request provider
    else model set, provider unset
        ChildProvider-->>SeedChild: return None (router resolves)
    else model and provider unset
        ChildProvider-->>SeedChild: inherit parent provider
    end
    SeedChild-->>Caller: child session with resolved provider
Loading

Poem

A hop, a nibble, a coherent pair,
model and provider matched with care,
no borrowed provider when model's declared,
but silence inherits what parent shared.
🐰 tests all green, my carrot's spared!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main fix: provider inheritance only when the spawn model is inherited too.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/harness-spawn-provider-inheritance

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@andersonleal andersonleal added the no-ticket PR deliberately has no Linear ticket (bump/typo/CI-only) label Jul 9, 2026
@andersonleal andersonleal changed the title fix(harness): inherit parent provider only when the spawn model is inherited too (MOT-3925) fix(harness): inherit parent provider only when the spawn model is inherited too Jul 9, 2026
@andersonleal andersonleal removed the no-ticket PR deliberately has no Linear ticket (bump/typo/CI-only) label Jul 9, 2026
@andersonleal
andersonleal merged commit 06f7c46 into main Jul 9, 2026
71 of 74 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant