Skip to content

fix(delegate): honor per-call and per-task model overrides#23649

Open
qWaitCrypto wants to merge 1 commit into
NousResearch:mainfrom
qWaitCrypto:fix/delegate-model-overrides
Open

fix(delegate): honor per-call and per-task model overrides#23649
qWaitCrypto wants to merge 1 commit into
NousResearch:mainfrom
qWaitCrypto:fix/delegate-model-overrides

Conversation

@qWaitCrypto

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes a delegation wiring gap: delegate_task() could only route child models
through delegation.model config or by inheriting the parent model. A single
delegation call could not explicitly choose a child model, and batch mode could
not route different sub-tasks to different models.

This PR adds per-call and per-task model overrides for delegation without
expanding the provider/credential system.

Model selection precedence is now:

  • tasks[].model
  • delegate_task(model=...)
  • delegation.model
  • parent_agent.model

It also keeps explicit model overrides from silently inheriting the parent's
fallback model chain, so a child that was explicitly routed to another model
does not fail back onto the parent model behind the caller's back.

This PR intentionally does not add per-task provider overrides. Provider,
base URL, API mode, and credential resolution remain controlled by existing
delegation config and parent runtime state.

Related Issue

Fixes the delegate_task per-call / per-task model override gap described in
the delegation model routing discussion.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✅ Tests (adding or improving test coverage)

Changes Made

  • Added top-level model support to tools/delegate_tool.py
    delegate_task(...).
  • Added per-task tasks[].model support to the delegate tool schema.
  • Threaded model override precedence through child construction:
    • tasks[].model > delegate_task(model=...) > delegation.model > parent.model
  • Added _normalize_model_override(...) helper to keep override parsing narrow
    and explicit.
  • Prevented explicit model overrides from inheriting the parent's fallback chain.
  • Added regression coverage in tests/tools/test_delegate.py for:
    • schema exposure of model
    • top-level model override
    • per-task model override beating top-level
    • per-call override beating delegation.model
    • config model still applying without override
    • explicit model override clearing inherited fallback

How to Test

  1. Run the delegate tool test suite:
    python3 -m pytest -q -n 0 tests/tools/test_delegate.py
  2. Confirm the suite passes.
  3. Verify the new behaviors covered by tests:
    • schema exposes top-level model and tasks[].model
    • single-call override reaches child AIAgent(model=...)
    • tasks[].model beats top-level model
    • explicit override beats delegation.model
    • no override keeps current delegation.model behavior
    • explicit override does not inherit parent fallback chain

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: WSL / Linux python3 -m pytest

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

Focused verification passed locally:

132 passed in 15.34s

@ozdalva

ozdalva commented May 13, 2026

Copy link
Copy Markdown

Reviewed this alongside the other competing PRs (#20000, #23266, #23769, #25026) and this is the cleanest implementation by far. The guard that suppresses the parent's fallback chain is a critical detail every other PR misses — without it, an explicit model override could be silently subverted by a rate-limit or auth fail fallback. The model-only approach is also the right call: adding a separate provider param creates ambiguity (which wins when they conflict?) and model names already imply their provider through existing routing.

+1 from me, hope this gets merged soon 🙏

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

Labels

P3 Low — cosmetic, nice to have tool/delegate Subagent delegation type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants