Skip to content

refactor(profiles): nuke components-v2 and its mixed Python serving stack#119

Merged
nachiketb-nvidia merged 2 commits into
mainfrom
nachiketb/switch-1042-remove-the-mixed-components-v2-python-serving-stack
Jul 23, 2026
Merged

refactor(profiles): nuke components-v2 and its mixed Python serving stack#119
nachiketb-nvidia merged 2 commits into
mainfrom
nachiketb/switch-1042-remove-the-mixed-components-v2-python-serving-stack

Conversation

@nachiketb-nvidia

@nachiketb-nvidia nachiketb-nvidia commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

What

This PR nukes the abandoned components-v2 stack and the mixed Rust/Python serving path built around it.

  • delete switchyard-components-v2 and switchyard-components-v2-macros
  • delete their PyO3 profile bindings, config loader, tests, examples, and design document
  • remove Python switchyard serve --config
  • make ProfileInput and ProfileRequestMetadata small Python-owned values
  • remove all components-v2 workspace, lockfile, package, documentation, and skill references
  • keep Python YAML route bundles and launchers working
  • keep the independent Rust switchyard-server TOML configuration path working

This includes the components-v2 sub-agent override that landed on main during the rebase. Its protocol metadata, libsy SubagentOverride, libsy PyO3 binding, and libsy tests remain intact.

The result is 14.5k deleted lines and no remaining dependency from the Python extension or Rust workspace on components-v2.

Why

The repository had two unrelated configuration and execution paths:

  1. the Python CLI and profile runtime, including the transitional components-v2 bridge
  2. the libsy-based Rust server with its own explicit TOML configuration

Components-v2 was no longer the direction of the server architecture, but Python still linked it through PyO3 solely to load profile configs and expose request wrapper types. That kept a large, duplicated implementation alive without providing a migration path toward libsy.

Removing it now makes the ownership boundary explicit: the current Python runtime remains Python-owned, while new Rust orchestration belongs in libsy and switchyard-server.

How

  • replace the Rust-bound profile request wrappers with frozen, slotted Python dataclasses
  • remove native profile config exports from switchyard_rust
  • remove the Python profile config loader and the serve --config CLI branch
  • unlink and delete both components-v2 crates and their PyO3 bindings
  • update tests to cover the retained Python request metadata and route-bundle behavior
  • rewrite affected docs so Python users see YAML route bundles and Rust-server users see TOML
  • retain an explicit regression assertion that serve --config is no longer documented

What remains in Python

This PR intentionally preserves the currently supported Python behavior:

  • ProfileInput and ProfileRequestMetadata
  • the programmatic Profile, ProfileConfig, and profile runner protocols
  • registered concrete Python profiles and their behavior
  • YAML --routing-profiles parsing and route-table construction
  • Claude, Codex, and OpenClaw launcher integration
  • the Python FastAPI server, endpoints, processors, backends, and translation compatibility surfaces

These remain because the public Python CLI and launchers still depend on them today. Removing components-v2 does not silently remove those user-facing workflows.

Next steps

Follow-up work can now remove the remaining Python orchestration incrementally, without another compatibility bridge:

  1. construct libsy algorithms and targets directly from the supported server configuration
  2. move launcher-created routes onto libsy algorithms and clients
  3. replace profile-backed Python route-table construction with libsy-backed serving
  4. migrate any Python-only processors or endpoint behavior that the supported CLI still needs
  5. remove the Python profile protocols, concrete profiles, and profile metadata only after their callers are gone
  6. retire the Python server path once the Rust server has the required CLI, endpoint, and launcher parity

What to review

Please focus on these boundaries:

  • Deletion completeness: no components-v2 crate, binding, loader, dependency, or stale documentation remains
  • Rebase boundary: the new protocol/libsy sub-agent behavior remains while its components-v2 and loader-specific implementation is removed
  • Python compatibility: YAML route bundles, saved launcher configuration, and programmatic Python profiles still work
  • Request metadata: the Python-owned ProfileInput and ProfileRequestMetadata preserve the behavior callers rely on
  • CLI contract: serve --config is intentionally removed, while global --routing-profiles remains supported
  • Server separation: Python documentation points to YAML route bundles; switchyard-server retains its separate TOML workflow
  • Scope: this PR removes the dead bridge but does not prematurely rewrite the remaining Python runtime

Validation

  • uv run ruff check .
  • uv run mypy switchyard
  • focused Python suite: 139 passed, including the retained libsy sub-agent override binding
  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace
  • uv run --only-group docs mkdocs build --strict
  • isolated default and [cli,server] package smoke tests

Closes SWITCH-1042

@nachiketb-nvidia
nachiketb-nvidia requested a review from a team as a code owner July 23, 2026 01:33
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

🚀 View preview at
https://NVIDIA-NeMo.github.io/Switchyard/pr-preview/pr-119/

Built to branch gh-pages at 2026-07-23 16:46 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

Route Bundle Migration and Profile API Retirement

Layer / File(s) Summary
Retire v2 profile configuration and bindings
Cargo.toml, crates/switchyard-components-v2/..., crates/switchyard-py/..., switchyard_rust/..., switchyard/lib/profiles/...
Removes the v2 profile-config crates, bindings, loader exports, and native protocol declarations while retaining Python-owned request metadata and input types.
Serve through route bundles
switchyard/cli/..., tests/test_route_bundle.py, tests/test_rl_logging.py
Updates serve to load explicit or saved YAML route bundles, removes serve --config, and adjusts CLI validation and warning tests.
Document the route-bundle model
README.md, AGENTS.md, docs/..., .agents/...
Replaces profile-config examples and terminology with defaults, routes, and --routing-profiles, while documenting the separate Rust TOML schema.
Validate route-bundle documentation
tests/readme/test_readme.py, tests/test_cli_reference_docs.py, tests/test_python_profile_abstractions.py
Adds route-block schema validation and updates documentation and Python metadata behavior tests.

Estimated code review effort: 5 (Critical) | ~120 minutes

Poem

I’m a rabbit with routes in my hat,
YAML paths where old profiles sat.
V2 hops away,
New model IDs play,
And clean docs tell us where we’re at.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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 change: removing components-v2 and the mixed Python serving stack.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/readme/test_readme.py (1)

71-95: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Validate the bundle-level schema too.

This helper ignores top-level fields such as defaults: and only validates individual routes. A malformed global default or invalid routes shape can therefore pass despite the test claiming route-bundle schema validation. Validate the root bundle/defaults through the same validation layer before iterating routes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/readme/test_readme.py` around lines 71 - 95, The _validate_route_blocks
helper currently validates only individual routes, leaving malformed
bundle-level fields and routes shapes unchecked. Before iterating
payload["routes"], pass the full parsed bundle, including defaults and routes,
through the existing route-bundle validation layer, while preserving the
per-route validation and error context.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/cli_reference.md`:
- Around line 63-69: Update the route-type overviews to document the supported
escalation_router strategy: in docs/cli_reference.md lines 63-69, add
escalation_router to the public route-type list or explicitly mark the list
non-exhaustive; in docs/core_concepts.md lines 49-53, include escalation routing
in the strategy overview or mark that list non-exhaustive.

In `@docs/routing_algorithms/llm_classifier_routing.md`:
- Around line 81-83: Clarify in the configuration table that
classifier.min_confidence, classifier.fail_open, and
classifier.recent_turn_window are dotted paths to nested YAML keys, not literal
option names. Update the surrounding table heading or descriptions while
preserving the existing nested-key examples and setting meanings.

In `@switchyard/cli/switchyard_cli.py`:
- Around line 362-365: Update the remediation command in the bundle-only flow
near the routing-profile handling to place the global --routing-profiles PATH
option before the configure subcommand. Ensure the displayed command is
switchyard --routing-profiles PATH configure so argparse accepts the recovery
path.

---

Outside diff comments:
In `@tests/readme/test_readme.py`:
- Around line 71-95: The _validate_route_blocks helper currently validates only
individual routes, leaving malformed bundle-level fields and routes shapes
unchecked. Before iterating payload["routes"], pass the full parsed bundle,
including defaults and routes, through the existing route-bundle validation
layer, while preserving the per-route validation and error context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a0b7339e-ad1d-4c8b-a417-ca5b5e03652e

📥 Commits

Reviewing files that changed from the base of the PR and between 832547f and 2e160d9.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !Cargo.lock
📒 Files selected for processing (80)
  • .agents/skills/switchyard-codebase-exploration/SKILL.md
  • AGENTS.md
  • Cargo.toml
  • README.md
  • crates/switchyard-components-v2-macros/Cargo.toml
  • crates/switchyard-components-v2-macros/src/lib.rs
  • crates/switchyard-components-v2/Cargo.toml
  • crates/switchyard-components-v2/DESIGN.md
  • crates/switchyard-components-v2/src/backend.rs
  • crates/switchyard-components-v2/src/config.rs
  • crates/switchyard-components-v2/src/config/loading.rs
  • crates/switchyard-components-v2/src/config/parsing.rs
  • crates/switchyard-components-v2/src/config/resolving.rs
  • crates/switchyard-components-v2/src/lib.rs
  • crates/switchyard-components-v2/src/profile.rs
  • crates/switchyard-components-v2/src/profiles/latency_service/health.rs
  • crates/switchyard-components-v2/src/profiles/latency_service/mod.rs
  • crates/switchyard-components-v2/src/profiles/latency_service/polling.rs
  • crates/switchyard-components-v2/src/profiles/latency_service/selection.rs
  • crates/switchyard-components-v2/src/profiles/latency_service/tests.rs
  • crates/switchyard-components-v2/src/profiles/llm_routing.rs
  • crates/switchyard-components-v2/src/profiles/llm_routing/prompts/coding_agent.md
  • crates/switchyard-components-v2/src/profiles/llm_routing/prompts/general.md
  • crates/switchyard-components-v2/src/profiles/llm_routing/prompts/openclaw.md
  • crates/switchyard-components-v2/src/profiles/macros.rs
  • crates/switchyard-components-v2/src/profiles/mod.rs
  • crates/switchyard-components-v2/src/profiles/noop.rs
  • crates/switchyard-components-v2/src/profiles/passthrough.rs
  • crates/switchyard-components-v2/src/profiles/profile_types.rs
  • crates/switchyard-components-v2/src/profiles/random_routing.rs
  • crates/switchyard-components-v2/src/profiles/stage_router.rs
  • crates/switchyard-components-v2/src/profiles/stage_router/prompts/classifier.md
  • crates/switchyard-components-v2/src/stats.rs
  • crates/switchyard-components-v2/src/stats_recording.rs
  • crates/switchyard-components-v2/tests/config.rs
  • crates/switchyard-components-v2/tests/latency_service_profile.rs
  • crates/switchyard-components-v2/tests/llm_routing_profile.rs
  • crates/switchyard-components-v2/tests/passthrough_profile.rs
  • crates/switchyard-components-v2/tests/random_routing_profile.rs
  • crates/switchyard-components-v2/tests/stage_router_profile.rs
  • crates/switchyard-components/src/lib.rs
  • crates/switchyard-py/Cargo.toml
  • crates/switchyard-py/src/lib.rs
  • crates/switchyard-py/src/profile_bindings/mod.rs
  • crates/switchyard-py/src/profile_bindings/typed.rs
  • docs/cli_reference.md
  • docs/core_concepts.md
  • docs/guides/agent_launchers.md
  • docs/index.md
  • docs/internal/latency_service_routing.md
  • docs/internal/metrics_reference.md
  • docs/routing_algorithms/escalation_router_routing.md
  • docs/routing_algorithms/llm_classifier_routing.md
  • docs/routing_algorithms/overview.md
  • docs/routing_algorithms/random_routing.md
  • docs/routing_algorithms/stage_router_routing.md
  • docs/routing_algorithms/sticky_routing.md
  • examples/profiles.yaml
  • examples/python_profile.yaml
  • switchyard/__init__.py
  • switchyard/cli/route_bundle.py
  • switchyard/cli/switchyard_cli.py
  • switchyard/lib/__init__.py
  • switchyard/lib/profiles/__init__.py
  • switchyard/lib/profiles/header_routing.py
  • switchyard/lib/profiles/loader.py
  • switchyard/lib/profiles/protocols.py
  • switchyard/lib/profiles/stage_router_config.py
  • switchyard_rust/core.py
  • switchyard_rust/profiles.py
  • switchyard_rust/profiles.pyi
  • tests/readme/test_readme.py
  • tests/test_cli_reference_docs.py
  • tests/test_profile_migration.py
  • tests/test_python_profile_abstractions.py
  • tests/test_python_profile_loader.py
  • tests/test_rl_logging.py
  • tests/test_route_bundle.py
  • tests/test_serve_profile_config.py
  • tests/test_switchyard_rust_profile_bindings.py
💤 Files with no reviewable changes (51)
  • crates/switchyard-components-v2/src/profiles/llm_routing/prompts/coding_agent.md
  • crates/switchyard-components-v2-macros/Cargo.toml
  • crates/switchyard-components-v2/src/profiles/stage_router/prompts/classifier.md
  • crates/switchyard-components-v2/DESIGN.md
  • crates/switchyard-components-v2/src/profiles/llm_routing/prompts/general.md
  • crates/switchyard-components-v2/tests/stage_router_profile.rs
  • crates/switchyard-components-v2/src/stats.rs
  • crates/switchyard-components-v2/tests/latency_service_profile.rs
  • crates/switchyard-components-v2/src/profiles/profile_types.rs
  • examples/python_profile.yaml
  • examples/profiles.yaml
  • crates/switchyard-components-v2/src/profiles/llm_routing/prompts/openclaw.md
  • crates/switchyard-components-v2/tests/random_routing_profile.rs
  • crates/switchyard-components-v2/tests/passthrough_profile.rs
  • crates/switchyard-components-v2/Cargo.toml
  • crates/switchyard-components-v2-macros/src/lib.rs
  • switchyard/lib/profiles/loader.py
  • crates/switchyard-components-v2/tests/llm_routing_profile.rs
  • Cargo.toml
  • crates/switchyard-components-v2/src/profiles/macros.rs
  • crates/switchyard-components-v2/src/profiles/latency_service/tests.rs
  • crates/switchyard-components-v2/src/profiles/random_routing.rs
  • crates/switchyard-components-v2/src/profiles/noop.rs
  • crates/switchyard-components-v2/src/config/loading.rs
  • crates/switchyard-py/src/profile_bindings/typed.rs
  • crates/switchyard-components-v2/src/profiles/passthrough.rs
  • crates/switchyard-components-v2/src/profiles/latency_service/health.rs
  • tests/test_serve_profile_config.py
  • crates/switchyard-components-v2/src/profiles/latency_service/polling.rs
  • docs/internal/latency_service_routing.md
  • crates/switchyard-components-v2/tests/config.rs
  • crates/switchyard-components-v2/src/backend.rs
  • crates/switchyard-components-v2/src/config.rs
  • crates/switchyard-components-v2/src/profiles/llm_routing.rs
  • crates/switchyard-py/Cargo.toml
  • crates/switchyard-components-v2/src/lib.rs
  • crates/switchyard-components-v2/src/profiles/mod.rs
  • crates/switchyard-components-v2/src/stats_recording.rs
  • crates/switchyard-components-v2/src/profile.rs
  • tests/test_python_profile_loader.py
  • tests/test_profile_migration.py
  • crates/switchyard-components-v2/src/profiles/stage_router.rs
  • tests/test_switchyard_rust_profile_bindings.py
  • crates/switchyard-components-v2/src/profiles/latency_service/mod.rs
  • crates/switchyard-components-v2/src/config/parsing.rs
  • switchyard/init.py
  • crates/switchyard-py/src/lib.rs
  • crates/switchyard-py/src/profile_bindings/mod.rs
  • crates/switchyard-components-v2/src/profiles/latency_service/selection.rs
  • crates/switchyard-components-v2/src/config/resolving.rs
  • switchyard_rust/core.py

Comment thread docs/cli_reference.md Outdated
Comment thread docs/routing_algorithms/llm_classifier_routing.md
Comment thread switchyard/cli/switchyard_cli.py
@nachiketb-nvidia nachiketb-nvidia changed the title refactor(profiles): remove the components-v2 serving stack refactor(profiles): nuke components-v2 and its mixed Python serving stack Jul 23, 2026
@ryan-lempka

Copy link
Copy Markdown
Collaborator

@nachiketb-nvidia can you check code rabbit comments?

Signed-off-by: nachiketb <nachiketb@nvidia.com>
@nachiketb-nvidia
nachiketb-nvidia force-pushed the nachiketb/switch-1042-remove-the-mixed-components-v2-python-serving-stack branch from 2e160d9 to 1a3f472 Compare July 23, 2026 16:33
Signed-off-by: nachiketb <nachiketb@nvidia.com>
@nachiketb-nvidia

Copy link
Copy Markdown
Contributor Author

addressed! Added bundle-level schema validation.

@nachiketb-nvidia
nachiketb-nvidia enabled auto-merge (squash) July 23, 2026 16:47
@nachiketb-nvidia
nachiketb-nvidia merged commit 4ccec5d into main Jul 23, 2026
19 checks passed
@nachiketb-nvidia
nachiketb-nvidia deleted the nachiketb/switch-1042-remove-the-mixed-components-v2-python-serving-stack branch July 23, 2026 16:51
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.

3 participants