Conversation
…lt OFF) - Add agent/model_router.py: deterministic, stdlib-only provider/model router (default OFF) - Replace fixed-name delegation.task_routing with delegation.model_router config - Precedence: explicit tasks[].model/provider > forced delegation.provider/base_url > router > inherit - Add tasks[].provider to delegate schema; explicit overrides bypass the router - Wire per-task fallback chain into _build_child_agent (override_fallback_chain) - Tests: 15 integration incl. REAL end-to-end router test (unmocked select_delegation_model) - No live API calls; no fixed model brand names in production path
…an-out caps Two reliability fixes in delegate_tool: 1) 401 fix: an explicit tasks[].provider/model that fails to resolve no longer merges the model onto the PARENT's credentials (which ran a foreign model against the wrong provider's auth -> 401). It now raises ValueError -> tool_error. Legitimate model-only override still inherits parent auth. 2) Safe caps: delegation.enforce_safe_caps (default true) clamps max_concurrent_children (hard cap 16) and max_spawn_depth (hard cap 3), one-shot warnings, byte-stable for normal config (3-10 / depth 1-3). enforce_safe_caps:false restores unbounded legacy. Regression tests in tests/tools/test_delegate.py + test_delegate_model_router_integration.py.
Related to the closed #66613 resubmission and the earlier delegation-routing cluster. This is the active branch, not a duplicate of closed predecessors; its routing policy and default cap changes need a maintainer decision. |
|
Thanks for the careful opt-in implementation and the focused test coverage. This automated hermes-sweeper review is closing this under the standing
For globally pinning subagent routing, please use Closed as not-planned per standing maintainer policy ( Closed as not-planned per standing maintainer policy ( |
Summary
Adds an optional, provider-aware dynamic model router for subagent delegation (default OFF), plus two reliability fixes on the same path:
tasks[].provider/modelno longer falls back to parent auth with a mismatched model (401),max_concurrent_children/max_spawn_depth(default ON, byte-stable for normal configs).Root cause
delegate_taskcould only inherit the parent model or honor an explicit override — no availability/capability-aware choice and no per-task fallback chain. Separately, a failed explicit override merged the model onto parent credentials (wrong provider auth → 401), and concurrency/depth knobs had no hard ceiling against exponential fan-out.Fix
agent/model_router.py: deterministic, stdlib-only router;enableddefault false; scores from injected inventory/catalog/pricing/credential gates — no network at import, no fixed model brand names.tools/delegate_tool.py:(creds, fallback_chain)with precedence explicit → forced delegation.provider/base_url → router → inherit; schema exposestasks[].model+tasks[].provider;override_fallback_chaininto_build_child_agent.ValueError→tool_error(model-only override still inherits parent auth).delegation.enforce_safe_caps(default true) clamps concurrent children (hard cap 16) and spawn depth (hard cap 3); opt-out viafalseor higher*_hard_cap.hermes_cli/config.py:delegation.model_routerblock default OFF + cap knobs documented incli-config.yaml.example.Footprint
Focused on delegation routing/reliability. Feature off by default for the router; caps only clamp absurd values under default config.
Validation
Tests
Unit router suite + integration (schema, override, forced provider, fallback chain, E2E unmocked select) + full
test_delegate*.pyregression.