How to Contribute to NVIDIA Switchyard: A Complete Step-by-Step Guide
TLDR: Fork the NVIDIA-NeMo/Switchyard repository, choose a focused change, create a conventional-commit branch, run the Rust and Python lint/test suites, commit with a DCO sign-off, and open a PR against main — maintainers are auto-assigned via CODEOWNERS and the PR gets squash-merged after review.
NVIDIA Switchyard is an open-source Rust-based proxy and library for routing LLM traffic, built to provide provider-neutral request/response types, protocol translation, routing algorithms, and metrics collection. Whether you want to fix a typo, add a new routing algorithm, or extend Python bindings, this guide walks through the exact contribution workflow as documented in the repository's CONTRIBUTING.md and enforced by its CI pipeline (for example, in .github/workflows/ci.yml). By following these steps, you'll be contributing to one of the more active projects in the LLM infrastructure space.
Understanding the Repository Structure
Before contributing, it helps to know how the codebase is organized. Switchyard is split into several crates under the crates/ directory, each with a clear responsibility, as described in crates/libsy/README.md and the top-level README.md.
| Crate | Responsibility |
|---|---|
crates/switchyard-server |
HTTP serving, config parsing, and exposing OpenAI/Anthropic-compatible endpoints |
Bold — the switchyard-server crate is what you run when you want a standalone proxy.
| crates/switchyard-translation | Wire-format codecs that translate between provider-native formats and Switchyard’s internal protocol |
| crates/protocol | Provider-neutral request/response and streaming types (the public API surface) |
| crates/libsy | Core routing algorithms (e.g., random, LLM-classifier, stage-router, escalation) |
| crates/libsy-llm-client | Helper client that makes HTTP calls to upstream models on behalf of a routing algorithm |
| crates/switchyard-py | Python bindings (PyO3) that expose the Rust crates to Python (switchyard.libsy) |
| switchyard/ (Python package) | Thin wrapper that re-exports the Rust symbols for Python consumers |
The lifecycle of a request is simple yet powerful: clients using the native OpenAI or Anthropic API format send requests to Switchyard, which selects a backend based on its routing rules, translates the request into that backend’s native format, forwards the call, and translates the response back to the client shape. This architecture lets you embed routing logic in your own app (the Library Path) or run a stand-alone proxy (the Server Path) — see docs/architecture.md for the full diagram.
The Contribution Workflow
Here is the exact process contributors follow when submitting code to the NVIDIA-NeMo/Switchyard repository, based on the CONTRIBUTING.md guide.
Step 1: Fork & Clone
Start by forking the repository on GitHub and cloning your fork locally. Then add upstream:
git clone https://github.com/YOUR-USERNAME/Switchyard.git
cd Switchyard
git remote add upstream https://github.com/NVIDIA-NeMo/Switchyard.git
This gives you two remotes: origin (your copy) and upstream (the official project). You can pull from upstream to stay current.
Step 2: Size Your Change
Switchyard uses a simple threshold to decide whether you need to open an issue first:
- Small changes — typos, docs fixes, ≤ 100 lines of code — can go straight to a pull request.
- Large changes — new features, refactorings, > 100 lines — require opening an issue first so maintainers can confirm the direction before you invest time.
Step 3: Create a Focused Branch with a Prefix Convention
Use a branch name that clearly describes the scope and intent. The repository convention uses prefixes like feature/…, fix/…, docs/…, test/…. Example:
git checkout -b feature/add-new-router-backend
This keeps the history clear and makes code review easier.
Step 4: Develop and Test Locally
The repo has two development stacks that must both satisfy the CI checks. According to the CONTRIBUTING.md guide and the ci.yml workflow:
Running the Rust test suite — you need cargo fmt, cargo clippy, and the test suite:
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
Zero lint errors, strict clippy (with -D warnings), and all tests must pass.
Running the Python test suite — after installing dependencies with uv sync:
uv run ruff check .
uv run mypy switchyard
uv run pytest tests/ -v
Ruff enforces Python lint style, Mypy enforces strict type-checking, and pytest ensures behavioral correctness, just like the CI in .github/workflows/ci.yml.
Step 5: Commit with DCO Sign-Off
Switchyard requires a Developer Certificate of Origin (DCO) on every single commit, meaning every commit needs a “Signed-off-by” line. Git makes adding this trivial: use the -s flag along with Conventional Commits syntax. Example:
git commit -s -m "feat: add my-new-router-backend"
Conventional Commits uses prefixes like feat:, fix:, docs:, test:. But the repository also uses a Conventional Commits requirement for the PR title, so keep the same style for your PR message.
Step 6: Open a Pull Request
Push the branch to your fork:
git push origin feature/add-new-router-backend
Then open a pull request targeting the main branch. The PR title follows the Conventional Commit style; if the change is associated with a GitHub issue, link it (for example, with “Closes #42”). The CI pipeline and the AI summarizers handle linting and code smell automatically. Crucially, you do not need to manually assign reviewers — the repository’s CODEOWNERS file automatically requests review from the core NVIDIA team.
Step 7: Iterate on Review
After maintainers review your PR, they’ll likely ask for tweaks. Address feedback with additional commits — avoid rewriting history with git rebase or force-push unless explicitly requested. Once approved, the PR will be squash-merged so the history stays clean and linear, with your commits folded into one combined commit.
Step 8: Documentation and Tests for New APIs
New public APIs must come with:
- Docstrings (Python) or
///comments (Rust), e.g., theResponsetype incrates/protocol. - Unit tests that cover the new behavior (placed in
crates/libsy/tests/ortests/for Python). - Updates to relevant docs — for example, adding an entry to
docs/routing_algorithms/…or updatingdocs/architecture.md.
Practical Code Examples
Here are three quick examples to get you started, straight from the repository’s setup.
Running the Server Locally
# Install the server binary (requires Rust)
cargo install --locked switchyard-server
# Create a minimal routes.toml (see Getting Started)
export OPENROUTER_API_KEY="your-openrouter-key"
switchyard-server --config routes.toml --dry-run
switchyard-server --config routes.toml --host 127.0.0.1 --port 4000
Adding a New Routing Algorithm (Rust)
// crates/libsy/src/my_algorithm.rs
use switchyard_protocol::{Request, Response};
pub struct MyAlgorithm;
impl MyAlgorithm {
pub async fn branch(&self, req: Request) -> Result<Response, SwitchyardError> {
// custom routing logic here
Ok(Response::default())
}
}
Then register the new algorithm in crates/libsy/src/lib.rs, write unit tests in crates/libsy/tests/, and update the router documentation in docs/routing_algorithms/.
Using the Python Library
import switchyard.libsy as libsy
router = libsy.RandomRouter(targets=["model-a", "model-b"])
# router now makes the decision for each incoming request
Key Files to Know Before Diving In
| File | Why it matters |
|---|---|
README.md |
High-level overview, quick-start commands, and the architecture diagram. |
CONTRIBUTING.md |
The full contribution workflow, code standards, and DCO requirements. |
docs/architecture.md |
Detailed request lifecycle and component-interaction diagram. |
crates/libsy/README.md |
Description of the routing algorithms crate and how to embed it. |
crates/switchyard-server/README.md |
Server-side configuration, CLI flags, and routing-algorithm selection. |
tests/ |
Unit-test suite for both Python and Rust; the reference for test style. |
.github/workflows/ci.yml |
The CI pipeline that enforces linting, type-checking, and test passes on every push. |
Summary
Here’s a quick recap of contributing to NVIDIA Switchyard:
- Fork and clone the NVIDIA-NiMo/Switchyard repo while assigning an
upstreamremote. - For large changes (>100 lines), open an issue first; for small fixes, PR directly to
main. - Keep branches focused with prefixes (
feature/,fix/,docs/,test/). - Pass the full CI locally:
cargo fmt,cargo clippy -D warnings,cargo test,uv-basedruff,mypy,pytest. - Commit with Conventional Commits and the
-sDCO signoff, and write a Conventional-style PR title. - Let
CODEOWNERShandle the review assignment; don’t manually add reviewers. - Expect squash-merge after the review; iterate with additional commits, never force-push away feedback.
- Make sure new public APIs come with docstrings/
///comments, unit tests, and docs updates.
Following these steps will let you contribute to a quality Rust/Python LLM-routing project, help keep the codebase well-linted and well-tested, and evolve Switchyard’s routing capabilities. Happy hacking.
Frequently Asked Questions
Do I need to sign a CLA before contributing to Switchyard?
Yes, there’s a Developer Certificate of Origin (DCO) requirement, not a separate CLA. Every commit must include a “Build,” “Signed-off-by” line, which you can add with git commit -s. The GitHub action won’t pass without it.
What test commands does the CI run on each PR?
The CI in .github/workflows/ci.yml runs cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo test --workspace for Rust. For Python, it runs uv run ruff check ., uv run mypy switchyard, and uv run pytest tests/ -v.
Can I contribute new routing algorithms in Python only?
No. The routing algorithms live in Rust under crates/libsy (see crates/libsy/src/lib.rs), and the Python bindings in crates/switchyard-py only expose those Rust routers. To add a new routing algorithm, you must write it in Rust, then optionally expose it via the PyO3 bindings.
Is there a style guide for commit messages?
Yes — the repository requires Conventional Commits (for example: feat:, fix:, docs:, test:). Both the commit message and the pull request title need to follow that style, and every commit requires a DCO sign-off.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →