Skip to content

[feature] Go bindings for model selection, modeled on switchyard-node #1030

Open

Description

@bricke

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-runner through a C ABI (staticlib), and a Go package wraps it through cgo. The wrapper code would be about the size of switchyard-node, which is 114 lines.
  • messages uses the same RoutingMessage shape as the Node binding, passed as JSON.
  • Cancelling the ctx cancels the Rust routing future, as AbortSignal does 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/amd64 and linux/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

Scope notes

  • Owning surface: a new binding crate (e.g. crates/switchyard-go) plus a Go package (e.g. bindings/go), on top of switchyard-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

  1. bricke commented on Oct 27, 2026

    @bricke
    Author

    Any input on this topic?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions