Skip to content

feat(delegation): add operator-controlled capability lanes - #73405

Closed
fgpaz wants to merge 1 commit into
NousResearch:mainfrom
fgpaz:feat/delegation-capability-lanes
Closed

feat(delegation): add operator-controlled capability lanes#73405
fgpaz wants to merge 1 commit into
NousResearch:mainfrom
fgpaz:feat/delegation-capability-lanes

Conversation

@fgpaz

@fgpaz fgpaz commented Jul 28, 2026

Copy link
Copy Markdown

Summary

Adds operator-controlled capability lanes to the existing delegate_task tool:

  • explore
  • engineer
  • review

The model may request a capability label, while the operator owns the provider/model/reasoning mapping in delegation.lanes.

delegation:
  lanes:
    explore:
      enabled: true
      provider: openai-codex
      model: <operator-selected-model>
      reasoning_effort: medium
delegate_task(goal="Inspect this codebase", lane="explore")

Motivation

Raw per-call model selection was intentionally rejected in #10996 because exposing model in the tool schema bypasses credential resolution, cost guardrails, and operator control. The tier/profile direction discussed in #9737 and #11155 is useful, but those proposals also accumulated heuristic routing, free-form tiers, reasoning floors, and unrelated complexity.

This PR keeps only the narrow safety boundary:

  • the model sees a fixed capability enum, never provider/model names;
  • the operator selects the actual route in config.yaml;
  • arbitrary model/provider/API key/base URL/request/command overrides remain absent from the model-facing schema;
  • invalid, disabled, unknown, or incomplete lane configuration fails closed;
  • no heuristic router, extra LLM call, config cache, credential-pool change, or new tool is introduced.

Behavior

Resolution precedence:

  1. per-item tasks[].lane;
  2. top-level lane;
  3. no lane: existing delegation behavior, unchanged.

Reasoning precedence for a configured lane:

  1. lane reasoning_effort;
  2. global delegation override;
  3. parent reasoning effort.

A configured lane resolves through Hermes' existing credential/provider pipeline before the child is created. A mixed batch may request different capabilities per item without receiving deployment-specific routing details.

Compatibility and footprint

  • Backward-compatible when lane is omitted.
  • Extends the existing delegate_task schema rather than adding a core tool.
  • Static schema; does not mutate toolsets or the system prompt mid-conversation.
  • No credentials or deployment-specific model IDs are versioned.
  • No changes to credential pools, providers, gateway, memory, plugins, or agent prompts.
  • Rebased as one commit on current main before push.

Changed production paths are limited to:

  • tools/delegate_tool.py — lane schema, validation, config resolution, and child routing;
  • run_agent.py — propagate the optional lane through the existing dispatcher;
  • hermes_cli/config.py — commented configuration example;
  • delegation documentation.

Validation

On current main (9e2f07e704d6433c118cdb4543e8519e1fa62762):

  • scripts/run_tests.sh tests/tools/test_delegate_lanes.py tests/tools/test_delegate.py tests/tools/test_async_delegation.py -q
    • 218 passed, 0 failed
  • scripts/run_tests.sh tests/run_agent/test_run_agent.py -k delegate -q
    • 1 passed, 0 failed
  • python -m py_compile ... — PASS
  • ruff check ... — PASS
  • git diff --check origin/main...HEAD — PASS

A live E2E exercised the full path with an OpenAI Codex parent using one configured engineer lane child on a different model:

  • exactly one child created;
  • child model and reasoning matched operator configuration;
  • parent and child completed successfully;
  • no duplicate children;
  • no child tool calls;
  • secret scan across runner output, usage, manifest, and transcript was clean.

Security notes

The model-facing contract intentionally does not accept arbitrary:

  • provider or model identifiers;
  • API keys, base URLs, or request overrides;
  • output-token overrides;
  • commands, arguments, or ACP transport overrides.

This keeps cost, credentials, and deployment routing operator-owned while still allowing the orchestrator to ask for the capability a subtask needs.

Related: #10996, #9737, #11155.

@alt-glitch alt-glitch added type/feature New feature or request comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard tool/delegate Subagent delegation area/config Config system, migrations, profiles P3 Low — cosmetic, nice to have needs-decision Awaiting maintainer decision before any implementation sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Jul 28, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the careful implementation and for keeping raw provider and credential values out of the model-facing schema.

Automated hermes-sweeper review found that this PR falls under the standing delegation-model-routing policy: Hermes does not support per-call or per-task model/provider routing through delegate_task, including fixed capability/tier labels that resolve to different configured routes. Current main keeps the sanctioned routing control at the global delegation.provider / delegation.model configuration level (tools/delegate_tool.py:3755).

  • This PR adds top-level and tasks[] lane choices that select provider/model/reasoning routes (tools/delegate_tool.py, PR commit 5c55438543c1).
  • The operator-controlled mapping and fail-closed validation are thoughtful, but they do not change the policy match: the model can still select a per-task route.
  • A focused re-scope using the existing global delegation configuration is the supported alternative.

Closed as not-planned per standing maintainer policy (delegation-model-routing). This is a design-direction decision, not a code-quality judgment — see the Contribution Rubric in AGENTS.md for what the project is looking for. If you believe this policy was misapplied to your change, comment here and a maintainer will take a look.

@teknium1 teknium1 closed this Jul 30, 2026
@teknium1 teknium1 added the sweeper:not-planned Sweeper: closed per standing maintainer policy (design direction) label Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have sweeper:not-planned Sweeper: closed per standing maintainer policy (design direction) sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades 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