Switchyard Configuration
Experimental NeMo Relay 0.6.0 integration: This release calls a separately running Switchyard Decision API.
Start with the Switchyard 0.6.0 setup and validation guide before using this page as the complete configuration reference.
The Switchyard component connects Relay’s CLI gateway to a separately running
Switchyard Decision API. Relay
owns provider credentials, backend endpoints, dispatch, retries, and trusted
fallbacks. The Switchyard service selects a backend. Relay validates the
decision, translates requests and responses in process through the
switchyard-translation library, and dispatches directly to the selected
Relay-owned target.
How the Configuration Fits Together
Configure the integration in four core steps. Profiles that use ATOF history add the fifth requirement:
- Set
decision_api_urland authentication so Relay can call the Switchyard Decision API. - Select the Switchyard routing profile with
decision_profile_id. - Add a Relay-owned
targetsbinding for every Switchyardbackend_idthat the profile can return. Relay validates the returned backend ID, model, protocol, and endpoint exactly before dispatch. - Choose a trusted same-protocol target for each inbound protocol under
default_targets. Relay uses these defaults for observe-only traffic and fail-open dispatch. - Configure profiles that depend on ATOF history, including StageRouter, with
context_mode = "atof_required"andatof_endpoint_name, then configure the matching observability stream sink. Relay fails startup validation if the named sink is missing or invalid.
The following is a complete component configuration. The referenced environment variables must be set before Relay starts.
Decision API and Rollout Options
The following table describes the Decision API and rollout settings:
Do not define the same header, including case variants, in both a static header map and its environment map. Keep bearer tokens, API keys, cookies, and other secrets in environment variables rather than tracked configuration.
Request Materialization
Every Decision API request contains routing identity, inbound protocol, a
request summary, and the attempt number. request_materialization controls how
much additional request content is included.
Choose the least materialization needed by the selected profile. In particular,
none and summary_only intentionally share the same current wire behavior but
express different configuration intent.
Context, Retries, and Inbound Protocols
The following table describes context, retry, and inbound protocol settings:
payload_only supports request-aware routing without an ATOF dependency.
Relay can create request-scoped synthetic identity when stable identity is not
available.
atof_required is for profiles that classify from accumulated ATOF context. It
requires stable session and request identity plus an enabled, authenticated
Relay HTTP ATOF stream sink whose name matches atof_endpoint_name. The sink
specifies the Switchyard ingestion URL, must use transport = "http_post", and
must set field_name_policy = "preserve". Relay rejects missing or duplicate
named sinks during startup validation. A local ATOF file sink
does not satisfy this delivery requirement by itself.
Target Bindings and Trusted Defaults
The following table describes target bindings and trusted defaults:
Do not define the same target header, including case variants, in both
headers and header_env.
Protocol and endpoint pairs are fixed:
Each protocol in enabled_inbound_profiles requires a corresponding
default_targets entry. Defaults for disabled protocols can be omitted. Each
configured default must refer to a target with the matching protocol. Duplicate
exact bindings for model, protocol, endpoint, and base URL are rejected.
Recommended Recipes
Observe-Only Rollout
Use observe-only mode to verify decisions and routing marks without sending traffic to the selected target:
Relay calls the Decision API and records the hypothetical selection, but sends the request to the inbound protocol’s trusted default once. Routing retries are not applied.
Payload-Only Request-Aware Routing
Use recent request content for routing without operating the ATOF accumulator:
ATOF-Backed StageRouter Routing
Use ATOF context when StageRouter should classify from accumulated session signals:
Configure the matching observability component with a named stream sink:
Runtime and Fail-Open Behavior
The integration handles routing and failures as follows:
- Relay validates the decision’s backend ID, model, protocol, and endpoint against its target binding before dispatch. Unknown backends, malformed decisions, and target drift fail open.
- Decision API errors are not recursively retried. Relay immediately dispatches the trusted same-protocol default.
- Retryable provider connection, timeout, status, context-window, and
model-unavailable failures can obtain a new decision, bounded by
max_retries. - Non-retryable provider failures use the trusted fallback immediately. After retry exhaustion, Relay dispatches that fallback once.
- A streaming request can retry only before receiving its first upstream item. After the stream commits, Relay propagates later failures without another dispatch.
- Relay forwards provider-specific extensions unchanged when every configured target uses the inbound protocol. If any target uses another protocol, nonportable extensions fail open to the trusted same-protocol default before the Decision API call. Request translation failures before provider dispatch and buffered response translation failures also fail open. After a streaming response emits its first item, later provider or translation failures propagate without another dispatch.
- Routing-mark delivery is best-effort and does not change provider results.
Experimental Limitations
Consider the following experimental limitations before adopting the plugin:
- The plugin is published as
nemo-relay-switchyardbut is excluded from default Relay CLI builds. Build the CLI withcargo build -p nemo-relay-cli --features switchyard. - The routing boundary is currently service-based. Relay calls Switchyard’s
HTTP Decision API but does not start or supervise the service. Relay derives
/healthfromdecision_api_urland fails plugin activation unless the service returns{"status":"ok"}. Decision API failures after activation fail open to the trusted same-protocol default. - ATOF-backed profiles additionally depend on Switchyard’s HTTP ingestion and accumulator runtime, stable request and session identity, and one named, authenticated Relay ATOF HTTP stream sink. A local file sink does not populate the Switchyard accumulator.
- Provider-protocol translation runs in Relay’s process through the
switchyard-translationRust library. Routing decisions and ATOF accumulation remain out of process. - The Rust Switchyard component is currently registered only by Relay’s CLI gateway. Hermes native plugins and the LangChain, LangGraph, and Deep Agents integrations do not load it in process. They receive Switchyard routing only when their provider traffic is explicitly sent through the Relay gateway.
- The Switchyard examples are manual compatibility and trajectory workflows, not production deployment orchestration.
- Compatibility is pinned to Switchyard commit
8f9db9a6ontopic/nemo-relay-integration. Testing another revision is deliberate and can expose contract drift. - The Decision API and service/library boundary are experimental.
- Nonportable provider extensions in configurations that can translate across protocols, malformed decisions, service failures, pre-dispatch translation failures, buffered-response translation failures, and target drift fail open to Relay’s trusted same-protocol default. Failures after a streaming response commits propagate without another dispatch.
- Secrets must remain environment-referenced. The examples generate ephemeral local credentials and are not credential-management guidance.
Run nemo-relay doctor to validate component configuration before startup. For
the pinned local service and manual compatibility workflow, refer to the
Switchyard integration examples.