Skip to content

Add experimental multi-provider BYOK registry config across all six SDKs#1718

Open
stephentoub wants to merge 2 commits into
mainfrom
stephentoub/multi-provider-byok-config
Open

Add experimental multi-provider BYOK registry config across all six SDKs#1718
stephentoub wants to merge 2 commits into
mainfrom
stephentoub/multi-provider-byok-config

Conversation

@stephentoub

Copy link
Copy Markdown
Collaborator

Why

The CLI protocol recently gained a named-provider / provider-model registry (copilot-agent-runtime#9864): providers and models on session create/resume. This lets an app register several BYOK providers, declare multiple models per provider, and bind custom agents to provider-qualified model ids. None of the SDKs surfaced it yet, so SDK consumers couldn't use multi-provider configurations. This PR closes that gap in all six SDKs (.NET, Node, Python, Go, Rust, Java).

What

  • New config surface in every SDK: NamedProviderConfig (name, type, wireApi, baseUrl, apiKey/bearerToken, headers, azure) and ProviderModelConfig (id, provider, wireModel, token limits, capabilities), wired onto the session config used for create and resume. Custom agents can reference provider-qualified model ids (e.g. alpha/sonnet).
  • Marked experimental using each language's existing convention ([Experimental] / @CopilotExperimental / Experimental: doc markers / etc.). The whole feature should be treated as experimental for now.
  • Java AgentInfo parity: added model to the hand-written com.github.copilot.rpc.AgentInfo so it matches the agent-info type already exposed by the other five SDKs (the field deserializes from the existing session.agent.list payload, so no protocol change).
  • End-to-end tests in all six SDKs validating that multiple providers, multiple models per provider, and custom agents bound to those models coexist in one session, launch, and route a turn to the correct provider with the configured wire model, X-Provider header, and credential.

Notes for reviewers

  • Snapshots are shared across all six SDKs. Each language's harness derives the snapshot folder/file from the test file and test names, so all six suites replay the same four YAML fixtures under test/snapshots/multi_provider_registry/. There are no per-language snapshots.
  • Routing tests use openai/completions providers pointed at the replay proxy (only /chat/completions is captured); providers are distinguished on the wire by a per-provider X-Provider header. The agent-binding test additionally includes an anthropic provider purely to prove heterogeneous providers coexist (no dispatch).
  • All six E2E suites pass locally (4 tests each), and the Java AgentInfoTest was extended for the new model field (7/7).

Test plan

  • .NET: dotnet test E2E MultiProviderRegistryE2ETests - 4/4
  • Node: npm run test -- multi_provider_registry - 4/4
  • Python: pytest e2e/test_multi_provider_registry_e2e.py - 4/4
  • Go: go test -run TestMultiProviderRegistryE2E ./internal/e2e - 4/4
  • Rust: cargo test --test e2e multi_provider_registry - 4/4
  • Java: mvn test -Dtest=MultiProviderRegistryE2ETest - 4/4, plus AgentInfoTest 7/7; spotless clean

Surfaces the new named-provider / provider-model registry from
copilot-agent-runtime#9864 (providers + models on session create/resume)
in the .NET, Node, Python, Go, Rust, and Java SDKs. The whole feature is
marked experimental in each language using that SDK's existing convention.

Custom agents can now bind to provider-qualified BYOK model ids (e.g.
"alpha/sonnet"), letting multiple providers, multiple models per provider,
and agents/subagents coexist in one session and route inference to the
right provider with the configured wire model and headers.

Also adds end-to-end coverage for the surface in every SDK (shared replay
snapshots under test/snapshots/multi_provider_registry), and exposes
"model" on the Java hand-written rpc.AgentInfo so it matches the agent-info
type in the other five SDKs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 18, 2026 13:46
@stephentoub stephentoub requested a review from a team as a code owner June 18, 2026 13:46
Comment thread rust/tests/e2e/multi_provider_registry.rs
Comment thread rust/tests/e2e/multi_provider_registry.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an experimental multi-provider BYOK registry surface (providers + models) to each SDK’s session create/resume configuration, enabling apps to register multiple named providers, define multiple models per provider, and bind custom agents to provider-qualified model IDs (e.g. alpha/sonnet). It also adds Java parity for AgentInfo.model and introduces cross-SDK E2E coverage using shared replay snapshots.

Changes:

  • Added new provider/model registry config types and plumbed providers/models through session create + resume wire payloads across Rust, Go, Python, Node, Java, and .NET.
  • Added/updated E2E tests in each language plus shared replay fixtures under test/snapshots/multi_provider_registry/.
  • Extended Java AgentInfo with a model field and updated tests accordingly.
Show a summary per file
File Description
test/snapshots/multi_provider_registry/should_route_delta_turbo_turn_to_its_provider_and_wire_model.yaml Adds replay fixture for routing the delta/turbo selection to its wire model.
test/snapshots/multi_provider_registry/should_route_alpha_sonnet_turn_to_its_provider_and_wire_model.yaml Adds replay fixture for routing the alpha/sonnet selection to its wire model.
test/snapshots/multi_provider_registry/should_route_alpha_haiku_turn_to_its_provider_and_wire_model.yaml Adds replay fixture for routing the alpha/haiku selection to its wire model.
test/snapshots/multi_provider_registry/should_register_multiple_providers_with_custom_agents_bound_to_their_models.yaml Adds replay fixture used by the registry + agent-binding test case.
rust/tests/e2e/multi_provider_registry.rs Adds Rust E2E coverage for registry creation, agent bindings, and per-provider routing assertions.
rust/tests/e2e.rs Registers the new Rust E2E module.
rust/src/wire.rs Extends Rust wire DTOs for session create/resume with providers and models.
rust/src/types.rs Introduces NamedProviderConfig + ProviderModelConfig and wires them into SessionConfig / ResumeSessionConfig plus serialization tests.
python/e2e/test_multi_provider_registry_e2e.py Adds Python E2E coverage for registry creation, agent bindings, and per-provider routing assertions.
python/copilot/session.py Adds Python TypedDict definitions for NamedProviderConfig and ProviderModelConfig.
python/copilot/client.py Plumbs providers and models through create_session / resume_session and adds snake_case→wire conversion helpers.
python/copilot/init.py Exports NamedProviderConfig and ProviderModelConfig from the public Python package surface.
nodejs/test/e2e/multi_provider_registry.e2e.test.ts Adds Node E2E coverage for registry creation, agent bindings, and per-provider routing assertions.
nodejs/src/types.ts Adds NamedProviderConfig + ProviderModelConfig and exposes them on SessionConfigBase.
nodejs/src/index.ts Re-exports the new Node types from the SDK entry point.
nodejs/src/client.ts Includes providers and models in Node session create/resume RPC payloads.
java/src/test/java/com/github/copilot/MultiProviderRegistryE2ETest.java Adds Java E2E coverage for registry creation, agent bindings, and per-provider routing assertions.
java/src/test/java/com/github/copilot/MultiProviderConfigTest.java Adds Java unit tests for JSON serialization and cloning behavior of the new config types + SessionConfig/ResumeSessionConfig integration.
java/src/test/java/com/github/copilot/AgentInfoTest.java Extends Java tests for the new AgentInfo.model field.
java/src/main/java/com/github/copilot/SessionRequestBuilder.java Plumbs providers and models from config objects into create/resume request DTOs.
java/src/main/java/com/github/copilot/rpc/SessionConfig.java Adds experimental providers/models fields + getters/setters + cloning support.
java/src/main/java/com/github/copilot/rpc/ResumeSessionRequest.java Adds experimental providers/models fields to the internal resume request DTO.
java/src/main/java/com/github/copilot/rpc/ResumeSessionConfig.java Adds experimental providers/models fields + getters/setters + cloning support.
java/src/main/java/com/github/copilot/rpc/ProviderModelConfig.java Introduces Java ProviderModelConfig (experimental) with fluent setters and JSON mapping.
java/src/main/java/com/github/copilot/rpc/NamedProviderConfig.java Introduces Java NamedProviderConfig (experimental) with fluent setters and JSON mapping.
java/src/main/java/com/github/copilot/rpc/CreateSessionRequest.java Adds experimental providers/models fields to the internal create request DTO.
java/src/main/java/com/github/copilot/rpc/AgentInfo.java Adds model to Java AgentInfo for parity with other SDKs.
go/types.go Adds Go NamedProviderConfig + ProviderModelConfig plus SessionConfig/ResumeSessionConfig fields and request struct plumbing.
go/internal/e2e/multi_provider_registry_e2e_test.go Adds Go E2E coverage for registry creation, agent bindings, and per-provider routing assertions.
go/client.go Plumbs Providers and Models into Go create/resume session RPC requests.
dotnet/test/E2E/MultiProviderRegistryE2ETests.cs Adds .NET E2E coverage for registry creation, agent bindings, and per-provider routing assertions.
dotnet/src/Types.cs Adds .NET NamedProviderConfig + ProviderModelConfig and exposes them on SessionConfigBase.
dotnet/src/Client.cs Plumbs Providers/Models into .NET create/resume session requests and registers types for JSON source-gen.

Copilot's findings

  • Files reviewed: 33/33 changed files
  • Comments generated: 0

@github-actions

This comment has been minimized.

Apply prettier (Node) and ruff format (Python) to the new multi-provider
registry E2E test files so the format-check CI steps pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Cross-SDK Consistency Review ✅

This PR adds the multi-provider BYOK registry config (NamedProviderConfig + ProviderModelConfig) and the AgentInfo.model parity fix across all six SDKs. Here's what the consistency review found:

NamedProviderConfig — fully consistent

All six SDKs expose identical wire-level fields (name, type, wireApi, baseUrl, apiKey, bearerToken, azure, headers). Each language applies its own naming convention correctly:

Field (wire) TypeScript Python Go .NET Java Rust
name name name Name Name name name
type type type Type Type type provider_type (reserved kw → #[serde(rename="type")])
wireApi wireApi wire_api WireAPI WireApi wireApi wire_api
baseUrl baseUrl base_url BaseURL BaseUrl baseUrl base_url
apiKey apiKey api_key APIKey ApiKey apiKey api_key
bearerToken bearerToken bearer_token BearerToken BearerToken bearerToken bearer_token
azure azure azure Azure Azure azure azure
headers headers headers Headers Headers headers headers

ProviderModelConfig — fully consistent

All nine fields (id, provider, wireModel, modelId, name, maxPromptTokens, maxContextWindowTokens, maxOutputTokens, capabilities) are present in every SDK with correct language-idiomatic naming.

providers / models on SessionConfig and ResumeSessionConfig — fully consistent

All SDKs wire both fields for both create and resume paths.

✅ Experimental markers — language-idiomatic and consistently applied

SDK Convention used
.NET [Experimental(Diagnostics.Experimental)] on type and members
Node.js @experimental JSDoc tag
Go // Experimental: ... doc comments on fields and types
Rust **Experimental.** leading paragraph in doc comments
Python **Experimental.** in docstrings
Java @CopilotExperimental annotation on class and methods

AgentInfo.model parity fix

Java's hand-written AgentInfo was the only SDK that lacked the model field. The other five SDKs expose it through their generated types (e.g., AgentInfo.model in Go's rpc.go, Model in .NET's Rpc.cs, model in Node.js's rpc.ts, Rust's generated/api_types.rs). Adding it to Java correctly closes the parity gap without any protocol change.

✅ Rust builder pattern

NamedProviderConfig::new(name, base_url) and ProviderModelConfig::new(id, provider) are Rust-idiomatic; no equivalent is needed in other SDKs, which use object/struct literals or fluent setters.

Summary

No cross-SDK inconsistencies found. The feature is implemented in all six languages with consistent wire semantics, correct language idioms, and appropriate experimental markers.

Generated by SDK Consistency Review Agent for issue #1718 · sonnet46 3.9M ·

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants