# How to Contribute to NVIDIA Switchyard: A Complete Step-by-Step Guide

> Learn how to contribute to NVIDIA Switchyard with this step-by-step guide. Fork the repo, create a branch, test your changes, and submit a pull request to enhance this powerful tool.

- Repository: [NVIDIA-NeMo/Switchyard](https://github.com/NVIDIA-NeMo/Switchyard)
- Tags: how-to-guide
- Published: 2026-08-23

---

**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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/CONTRIBUTING.md) and enforced by its CI pipeline (for example, in [`.github/workflows/ci.yml`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/.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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/crates/libsy/README.md) and the top-level [`README.md`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/CONTRIBUTING.md) guide.

### Step 1: Fork & Clone

Start by **forking the repository** on GitHub and cloning your fork locally. Then add upstream:

```bash
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:

```bash
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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/CONTRIBUTING.md) guide and the [`ci.yml`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/ci.yml) workflow:

**Running the Rust test suite** — you need `cargo fmt`, `cargo clippy`, and the test suite:

```bash
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`:

```bash
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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/.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:

```bash
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:

```bash
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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/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

```bash

# 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)

```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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/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

```python
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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/README.md) | High-level overview, quick-start commands, and the architecture diagram. |
| [`CONTRIBUTING.md`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/CONTRIBUTING.md) | The full contribution workflow, code standards, and DCO requirements. |
| [`docs/architecture.md`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/docs/architecture.md) | Detailed request lifecycle and component-interaction diagram. |
| [`crates/libsy/README.md`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/crates/libsy/README.md) | Description of the routing algorithms crate and how to embed it. |
| [`crates/switchyard-server/README.md`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/.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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/.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`](https://github.com/NVIDIA-NeMo/Switchyard/blob/main/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.