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., the Response type in crates/protocol.
  • Unit tests that cover the new behavior (placed in crates/libsy/tests/ or tests/ for Python).
  • Updates to relevant docs — for example, adding an entry to docs/routing_algorithms/… or updating docs/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 upstream remote.
  • 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-based ruff, mypy, pytest.
  • Commit with Conventional Commits and the -s DCO signoff, and write a Conventional-style PR title.
  • Let CODEOWNERS handle 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →