NVIDIA-NeMo / NVIDIA-NeMo/Switchyard

[feature] Support sub-agent-aware model routing

Open
#493 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Rust
Stars
3.2k
Forks
291
Avg merge
1d 8h
Merged PRs (30d)
182

Description

Problem

Coding-agent harnesses can delegate work to child agents. Each child receives a specific task from its parent, but the model best suited for that work may differ from the model serving the parent or other children.

Switchyard needs to route delegated sub-agent work independently while preserving the parent's routing behavior. This must be a server-side routing capability so it works across supported and custom clients.

The core composition is:

Parent routing policy + Sub-agent routing policy

The parent and sub-agent policies must be configurable independently.

Requirements

Sub-agent-aware routing should:

  • Distinguish parent-agent requests from delegated sub-agent requests.
  • Identify each child using a stable session_id + agent_id.
  • Support a fixed target for all delegated work without making a classifier call.
  • Support classification across any number of sub-agent targets.
  • Give the classifier only its configured system prompt and the delegated task prompt produced by the parent.
  • Retain a child's selected target when configured to classify once per child.
  • Keep sibling sub-agent assignments independent.
  • Leave parent-agent routing unchanged.
  • Exclude harness-maintenance requests from sub-agent routing.
  • Use a configured default child target when classification fails or abstains.
  • Log the child identity, whether classification ran, and the selected target.

Proposed configuration

A route may define an optional sub-agent routing policy independently of its parent routing policy.

Fixed sub-agent target

All delegated work goes to one target:

[routes.agent]
id = "agent"
type = "passthrough"
target = "parent"

[routes.agent.subagent]
type = "passthrough"
target = "worker"

The same sub-agent policy should compose with other parent algorithms:

[routes.agent]
id = "agent"
type = "stage_router"
# Parent Stage Router configuration

[routes.agent.subagent]
type = "passthrough"
target = "worker"
Classified sub-agent target

Delegated work is classified across multiple targets:

[routes.agent]
id = "agent"
type = "passthrough"
target = "parent"

[routes.agent.subagent]
type = "llm_classifier"
classifier_target = "classifier"
targets = ["worker", "reviewer"]
default_target = "worker"
classify_trigger = "new_session"
prompt = "Select the appropriate target for the delegated task."
response_schema = '''
{
  "type": "object",
  "properties": {
    "target": {
      "type": "string",
      "enum": ["worker", "reviewer"]
    }
  },
  "required": ["target"],
  "additionalProperties": false
}
'''
policy = { type = "target_selector", selector = "/target" }

The same sub-agent classifier should compose with parent-level passthrough, task-level classification, turn-based classification, Stage Router, and escalation routing.

Expected behavior

Parent request
    -> Parent routing policy
        -> Parent target

Delegated request
    -> Sub-agent routing policy
        -> Fixed target
        or
        -> Classifier-selected target

For classify_trigger = "new_session":

  1. The first delegated request for a child is classified.
  2. The selection is stored under that child's session_id + agent_id.
  3. Later requests from the same child reuse the selection.
  4. A different child is classified independently.

For classify_trigger = "every_request", each delegated request is classified again.

Success criteria

  • Parent and sub-agent routing policies can be configured independently.
  • A fixed target can serve all delegated work without a classifier call.
  • More than two classifier-selected sub-agent targets are supported.
  • Any supported parent algorithm can compose with either initial sub-agent policy.
  • Sub-agent decisions are isolated by child identity.
  • Requests without delegated-work metadata retain existing routing behavior.
  • Harness-maintenance traffic does not invoke or reuse sub-agent routing.
  • Omitting the sub-agent policy preserves the parent algorithm's existing behavior.
  • Claude Code, Codex, and explicit Switchyard metadata are covered by focused tests.

Alternatives considered

  • Client-side routing: Every launcher or custom client would need to implement the same policy.
  • Only supporting a fixed sub-agent target: Cannot select a model based on the delegated task.
  • Only supporting classifier-based routing: Adds an unnecessary model call when every child should use one known target.
  • Implementing sub-agent behavior inside one parent algorithm: Prevents independent composition with other parent routing strategies.

Scope notes

  • Primary surfaces: protocol metadata, routing composition, server TOML configuration, observability, tests, and documentation.
  • No new HTTP endpoint is required.
  • Any public Rust API changes need an explicit compatibility decision.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names no specific files, tests, or entry points. Start by tracing the protocol metadata, routing composition, server TOML configuration, observability, and existing routing tests described in the scope. Done means independent fixed or classified sub-agent policies compose with parent algorithms, preserve existing parent behavior, isolate child decisions, and cover Claude Code, Codex, and explicit Switchyard metadata.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend, testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.