feat(plugin)!: Add Switchyard Decision API routing plugin#369
feat(plugin)!: Add Switchyard Decision API routing plugin#369bbednarski9 wants to merge 7 commits into
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Enterprise Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
218718d to
a376278
Compare
|
reference arch: flowchart TD
S["Relay startup"] --> V["Validate configuration, URLs, bindings, and secret environment variables"]
V --> C["Build HTTP clients"]
C --> R["Relay becomes ready"]
R -. "No startup probe" .-> SY["Switchyard server"]
Q["LLM request"] --> D["POST Decision API"]
D -->|Valid decision| P["Dispatch selected provider"]
D -->|Unavailable, timeout, invalid response, or binding drift| F["Dispatch trusted same-protocol fallback"]
E["ATOF event"] --> A["Best-effort POST"]
A -->|Switchyard unavailable| L["Log failure; routing continues"]
|
| SPDX-License-Identifier: Apache-2.0 | ||
| --> | ||
|
|
||
| # NeMo Relay Switchyard plugin |
There was a problem hiding this comment.
The structure of this README should be in line with other READMEs.
|
|
||
| ## Configuration | ||
|
|
||
| Start from [`examples/switchyard/plugins.toml`](../../examples/switchyard/plugins.toml). Sensitive |
There was a problem hiding this comment.
Avoid relative links for READMEs which ultimately get published/viewed outside of GitHub
| `/v1/atof/events` URL, `field_name_policy = "preserve"`, and at least one environment-referenced | ||
| authentication header. | ||
|
|
||
| ## Verification |
There was a problem hiding this comment.
Should explicitly mention that all steps should be run from the repository root.
(Note: if this is still applicable/included)
There was a problem hiding this comment.
example/switchyard needs to have a comprehensive README. The crate's README is not the correct place.
| `nemo-relay-switchyard` is Relay's first-party remote Decision API integration. It has no Rust | ||
| dependency on Switchyard: the current `switchyard.routing_request.v1` and | ||
| `switchyard.routing_decision.v1` JSON contracts are represented by local compatibility types. |
There was a problem hiding this comment.
This is a bit confusing to me. Is this something that we want to expose to users, just to change it later on to the proper switchyard crate?
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
dec7a01 to
7cf4735
Compare
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Overview
This adds the Relay-side P0 integration between NeMo Relay and a Switchyard remote Decision API.
Summary
nemo-relay-switchyardfirst-party plugin with no Switchyard Rust dependency.switchyard.routing_request.v1contract.switchyard.routing_decision.v1responses against exact Relay-owned backend bindings.Details
The Decision API selects only a configured backend ID and exact model/protocol/endpoint tuple. Relay retains ownership of provider URLs, credentials, request/response translation, retries, and final trusted fallbacks. Decision failures, malformed responses, binding drift, unsupported provider extensions, and missing required identity all fail open to the same inbound protocol.
context_mode = "atof_required"requires Relay's existing ATOF HTTP exporter to target Switchyard's/v1/atof/eventsendpoint with preserved field names and environment-referenced authentication. The plugin emits best-effort canonicalswitchyard.routing.*marks but does not install a duplicate event subscriber or Relay-side feature accumulator.The Hermes smoke runs a fixed three-query session through local Ollama and verifies
llama3.2:latest→qwen3.6:35b→llama3.2:latest. Because the current Cascade Decision API classifies from accumulated Relay snapshots rather thancurrent_request.body, the smoke inserts clearly labeled canonical tool-result ATOF fixtures between queries: a critical failure drives the strong override and a clean-test result drives the final weak classifier decision. Each fixture and its ingestion report is preserved with the trajectory.The smoke writes:
Where should the reviewer start?
crates/switchyard/src/component.rs— lifecycle, validation, Decision API calls, retries, fallback, and marks.crates/switchyard/src/translation.rsandstream_translation.rs— the buffered and SSE 3×3 protocol matrices, including the standard OpenAIstream_options.include_usagetransport hint.crates/cli/src/gateway.rs— reserved routed-dispatch headers and structured retry-aware provider failures.crates/cli/tests/switchyard_process_e2e.rs— CI-safe process-boundary coverage for routing, streaming, fail-open, and reserved-header stripping.examples/switchyard/run-real-e2e.shandrun-hermes-ollama-smoke.sh— cumulative Switchyard compatibility and shareable local trajectories.The commits separate runtime/ATOF prerequisites, gateway retry infrastructure, plugin implementation, and E2E/trajectory work.
Review guidelines
atof_requiredcross-component validation together.Testing summary
cargo fmt --all -- --checkcargo clippy -p nemo-relay-switchyard -p nemo-relay-cli --all-targets -- -D warningscargo test --workspace(all workspace unit, integration, and doc tests passed)cargo test -p nemo-relay-switchyard(22 passed)cargo test -p nemo-relay-cli --test switchyard_process_e2e(buffered, SSE, Decision API fail-open, and reserved headers)examples/switchyard/run-real-e2e.sh(weak → strong → strong, including SSE)examples/switchyard/run-hermes-ollama-smoke.sh(weak → strong → weak across two Ollama models)Previous feedback addressed
Related Issues