feat(plugin)!: Add Switchyard Decision API routing plugin#369
feat(plugin)!: Add Switchyard Decision API routing plugin#369bbednarski9 wants to merge 47 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds Switchyard routing, optimization contribution and summary plumbing, retry-aware gateway handling, environment-based ATOF headers, Hermes/session wiring, and example configs and scripts with expanded coverage. ChangesOptimization contracts and bindings
Switchyard and CLI wiring
Switchyard examples, smoke tests, and process e2e
Estimated code review effort: 5 (Critical) | ~120 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
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"]
|
dec7a01 to
7cf4735
Compare
83bb3c1 to
99bcb91
Compare
cb060b8 to
865e331
Compare
6633376 to
c32a5e2
Compare
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>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
f06899d to
0d73b57
Compare
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>
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>
willkill07
left a comment
There was a problem hiding this comment.
As written, this will only work through the sidecar and not through any native integrations (like Hermes or LC Deep Agents).
I appreciate the non-breaking API changes for FFI / Python / Node
Since it's experimental and likely subject to change, I'm approving with minor cleanliness nits.
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Warning
BREAKING CHANGE: [Rust source compatibility] This PR adds
FlowError::Upstreamand new fields to the publicAtofEndpointConfig,AtofEndpointSectionConfig, andEmitMarkEventParamstypes. Downstream exhaustiveFlowErrormatches must handle the new variant, and direct struct literals must initialize the new fields or migrate to the provided constructor/builder APIs. Builder-based mark emission and default Relay configurations remain compatible.Overview
This adds Relay's first-party integration with the Switchyard Decision API. The plugin routes buffered and streaming LLM requests through an external Switchyard service, executes the selected Relay-owned backend, and records causal model-routing optimization evidence.
Switchyard owns provider-protocol translation through its
switchyard-translationRust library. Relay consumes that library only when the native Switchyard plugin is enabled; default Relay builds do not include either the plugin or the translation dependency.Details
Plugin and execution behavior
nemo-relay-switchyardfirst-party plugin.switchyard.routing_request.v1requests.Translation ownership and optional dependency
Request, buffered-response, and SSE translation across OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages use Switchyard's public
switchyard-translationlibrary instead of a Relay-local translation engine.The dependency is pinned to the immutable topic-branch commit
8f9db9a6a47f848cdff1d262276ba25a8ae9cbc8, which includes the Decision API series, StageRouter baseline/freshness behavior, and Switchyard #46.The Relay CLI exposes this through
--features switchyard:nemo-relay-clicontains neithernemo-relay-switchyardnorswitchyard-translation.Runtime requirements
The current experimental deployment requires a separately running Switchyard service from the pinned topic commit. The plugin does not start or supervise that service.
Switchyard availability is not a Relay startup requirement. It is a request-time dependency: connection failures, timeouts, malformed decisions, selected-route drift, unsupported extensions, and missing required identity fail open to the configured same-protocol default. ATOF-backed profiles additionally require Relay's ATOF HTTP exporter to target Switchyard's
/v1/atof/eventsendpoint with preserved field names and environment-referenced authentication.The public examples document this service boundary, verify the exact Switchyard revision before startup, and intentionally remain manual compatibility workflows rather than production orchestration.
Optimization accounting and observability
This PR builds on the plugin-neutral accounting contract merged in NeMo Relay #389. Applied routing contributions carry the selected and baseline model transition, decision identity, backend and tier, attempt, rollout mode, reason, and router metadata. Observe-only decisions remain visible as non-applied evidence.
Relay core combines routing and other plugin contributions at LLM close while retaining explicit token evidence for downstream repricing. Existing requested, decision, retry, fallback, and error routing marks remain available alongside the canonical optimization contribution.
The generic ATIF change that attributes
step.model_nameto the effective response model is intentionally separated into NeMo Relay #399. This PR still ensures translated provider responses carry the actual selected model; #399 independently controls how ATIF presents it.Testing summary
cargo fmt --all -- --checkcargo clippy -p nemo-relay-switchyard --all-targets -- -D warningscargo clippy -p nemo-relay-cli --features switchyard --all-targets -- -D warningscargo check -p nemo-relay-cli— proves the default CLI builds without Switchyard.cargo check -p nemo-relay-cli --features switchyard— proves the opt-in dependency path.cargo test -p nemo-relay-switchyard— 31 passed.cargo test -p nemo-relay-cli gateway::tests— 33 passed without the feature.cargo test -p nemo-relay-cli --features switchyard gateway::tests— 33 passed with the feature.cargo test -p nemo-relay-cli --features switchyard --test switchyard_process_e2e— buffered, streaming, retry, and fail-open process boundary passed after the split.examples/switchyard/run-real-e2e.shagainst the exact pinned Switchyard service — passed with the expected StageRouter route sequenceprovider/weak,provider/strong,provider/strong.Previous feedback addressed
Where should the reviewer start?
crates/switchyard/src/component.rs— Decision API lifecycle, exact target and baseline validation, retries, fallback, and terminal route commitment.crates/switchyard/src/translation.rsandstream_translation.rs— thin policy adapters over the Switchyard-owned translation library.crates/cli/Cargo.tomland thecfg(feature = "switchyard")registration paths — compile-time optionality.crates/cli/src/gateway.rs— reserved dispatch headers and structured retry-aware upstream failures.crates/cli/tests/switchyard_process_e2e.rs— process-boundary buffered, streaming, and fail-open coverage.examples/switchyard/README.mdandrun-real-e2e.sh— pinned experimental service workflow.Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)