Switchyard translates three APIs and chooses the backend
Switchyard accepts OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages. A configured route selects an upstream, sends the request in that provider's format, then translates the response back into the client's expected shape. This is especially useful for coding agents: Claude Code can keep speaking the Anthropic protocol while a request goes to an OpenAI-compatible local server. Codex can use the same proxy without forcing every backend to implement the Responses API.
Routing is more than a round-robin switch. The built-in options include a fixed random split, an LLM classifier, signal-based stage routing, escalation after a judge examines a weaker model's answer, and a composite route. The switchyard-libsy crate separates those decisions from HTTP and provider SDKs. An existing gateway can ask libsy what to call, execute the model request itself, and return the result to the algorithm. That boundary is Switchyard's best reason to exist.
The server is explicitly a demo before version 1.0
The README gives unusually direct maturity labels. Libsy is beta and ready for trial integration. The LLM client and runner are alpha. The standalone server is a demo and is not recommended for production. Switchyard as a whole is pre-alpha, with significant API and algorithm changes expected before 1.0. Buyers should take those labels more seriously than the NVIDIA name or the 2,491 GitHub stars.
Release v0.2.0, published August 10, 2026, was a large redesign around a native Rust server and separated crates. It also deprecated the older Python server, YAML route bundles, profile APIs, and several previous routing components. That clean break may improve the architecture, but it proves the compatibility warning is active. Pin the release and its TOML schema during an evaluation; tracking main would invite unnecessary churn.
What happened when we ran it
Our sandbox installed 34 Python packages in 296 seconds and occupied 36 MB. The build passed in 10 seconds. Pytest then exited with code 1 after 23 seconds, reporting 86 passed, 10 failed, 1 warning, and 2 errors across 98 tests. Pip-audit found 0 known vulnerabilities in the installed packages. We tested commit 053a61e with Python 3.12 on 3 CPUs and 8 GB of RAM.
The log tail names one concrete failure: an async test in test_libsy_minimal_bindings.py could not run because async functions are not natively supported, and pytest printed a list of suitable framework plugins. It also recorded collection or setup errors for tests/e2e/test_closed_book_proxy_integration.py and tests/test_prepare_harbor_dataset.py. The tail does not show the other failure details, so it would be wrong to assign them one shared cause.
The checkout had 304 files, about 63,644 source lines, and measured 5 MB before dependencies. It included 8 CI workflow files, a Dockerfile, and a tests directory. Those signals and 86 passing tests show real engineering work. The failed full run still matters because a new contributor following the available environment did not reach green without additional investigation.
Routing can add model calls as well as save them
A random route adds little decision overhead and is useful for controlled comparisons. Classifier routing asks a model to choose a tier before the main request. Escalation first runs the weaker target, then has a judge decide whether the same prompt should go to the stronger one. Stage routing instead reads conversation signals such as tool results and errors, which can avoid a classifier call when those signals are dependable. Each policy changes cost, delay, and failure behavior differently.
Pull request 560 exposes a sharp current example. It says stage routing could not de-escalate Codex sessions because Responses arguments arrived as encoded JSON, exec_command was unknown, and its cmd field was not read. The proposed change was measured against 39 recorded calls, where none classified as an edit or write beforehand. Until that fix is in the version you deploy, verify routing with your agent's actual wire traffic rather than a synthetic chat request.
Observability has known gaps in version 0.2.0
The native server exposes Prometheus metrics, OpenTelemetry spans, aggregate statistics, optional session statistics, and durable JSONL routing logs. Metrics cover requests, errors, latency, tokens, and routing overhead. These are the right surfaces for determining whether a router saves money or only moves it between providers. A /health endpoint and config dry run also make the basic server path easy to inspect.
Version 0.2.0 documents limits that affect those numbers. Some fallback and escalation decisions lack target attribution in metrics and stats. The retry recovery counter can stay at zero after a successful retry, and session IDs are absent from native session statistics. Buffered upstream work may continue after a client disconnect and incur provider cost. Issue 480 also says upstream response headers are discarded before they can reach the downstream client.
Use libsy before betting on the whole proxy
Teams with an existing Rust gateway should start with switchyard-libsy. Its algorithm contract lets the host retain transport, authentication, retries, and provider clients. That limits exposure to the youngest server code while preserving the typed routing model. A standalone trial can use cargo install --locked switchyard-server, a small routes file, and one low-risk upstream.
Run a replay of real Claude Code or Codex sessions and record which target served every turn. Include tool calls, context-window errors, streaming, client cancellation, and a provider failure. Our 10 failed tests make that exercise mandatory, not ceremonial. Switchyard is interesting because the routing layer is composable. It is not yet the sensible default for an organization that only needs one dependable model proxy.

