Repository navigation
Description
Problem
Go services can't use Switchyard without running switchyard-server next to them, and the README rates switchyard-server as a demo component that is not meant for production. Python and Node hosts can embed routing through switchyard-py and switchyard-node. Go has no equivalent, so a Go gateway has to either run the demo server or reimplement the routing algorithms, and reimplemented algorithms drift from Switchyard's.
I hit this with YardMaster, a self-hosted Go gateway that currently supervises switchyard-server. In #989, @afourniernv advised moving off the server and onto the SDKs. This issue is that move.
Proposed solution
Go bindings that follow switchyard-node's model-selection API: the caller owns the completion request, and Switchyard picks the model.
runner, err := switchyard.NewRunner(tomlSource) // Runner::from_toml_for_model_selection
defer runner.Close()
decision, err := runner.Decide(ctx, "switchyard/auto", messages)
// decision.Target == "luna", decision.Model == "gpt-5.6-luna"- A small Rust crate exposes
switchyard-runnerthrough a C ABI (staticlib), and a Go package wraps it through cgo. The wrapper code would be about the size ofswitchyard-node, which is 114 lines. messagesuses the sameRoutingMessageshape as the Node binding, passed as JSON.- Cancelling the
ctxcancels the Rust routing future, asAbortSignaldoes in Node. - Errors carry the same codes:
ERR_CONFIG,ERR_UNKNOWN_ROUTE,ERR_INVALID_REQUEST,ERR_ROUTING,ERR_UNSUPPORTED_OUTCOME,ABORT_ERR. - Builds for
linux/amd64andlinux/arm64. Tests mirror the Node loopback tests.
A later step could add a managed path over Route::execute, so translation stays inside the Runner, consistent with the direction in #985 and #986. I'd only propose that once the decide-only binding has landed and has users.
Alternatives considered
- Keep running
switchyard-server. It isn't meant for production, per the README and docs: add YardMaster integration guide #989. - Reimplement the routing in Go. It would drift from Switchyard's algorithms, the same concern raised in [feature] Add a decision-only API for routing integrations #196.
- Call the Python bindings from a sidecar. That adds a second runtime and an extra network hop to every request.
Scope notes
- Owning surface: a new binding crate (e.g.
crates/switchyard-go) plus a Go package (e.g.bindings/go), on top ofswitchyard-runner. No changes to routing, protocol, translation or server code. - Public interfaces: adds a Go API and a C ABI used only by that package. No changes to existing Rust, PyO3, Python, CLI or TOML interfaces.
- Backward compatibility: none affected. The Go API would follow the Runner's alpha status.
Additional context
I'd be glad to write and maintain this. It could live in this repo next to the Node binding, or in a separate Apache-2.0 repository if you'd rather not take on another language. Let me know which you prefer before I open a PR. YardMaster would be its first user.
Activity
bricke commentedon Oct 27, 2026
Any input on this topic?