Skip to content

BYOK Support for Copilot Agent Host Harness #340335

Open

Description

EnvironmentsEnvironments
  1. Local (Same Machine)
  2. Remote
    • WSL
    • SSH
    • Dev Containers
    • Tunnels
    • Web Socket

Status

  • 🟢 Local
    • Local agent host supports BYOK models from in-built and extension contributed models using a proxy from the agent host
  • 🔴 Remote

Invariants

  1. Multi Surface must work (VS Code and any other Copilot SDK consumer)
  2. Multi device should work (Local and remote environments with multiple clients)

Note: Roaming is not required. if you set up BYOK on one machine, it is not expected to automatically propagate credentials to other machines

Problem

1. Dependence on the Extension Host

The existing BYOK support is dependent on the existence of the extension host with the support of

  1. In-built BYOK providers
  2. Extension contributed BYOK providers

Support in the Copilot Harness should enable users to use the same BYOK configuration across all Copilot SDK surfaces, and that can not happen with the dependence on the current extension host.

2. Continuity across Clients

Currently, the Client connecting to the Agent Host owns and manages the BYOK models.
To maintain continuity across clients (remotely) connecting to a single agent host, the models must be provided from and be owned by the Agent Host itself.
eg:

  1. Client A connects to Agent Host and starts a Session A using model BYOK Model A
  2. Client B connects to Agent Host
  3. Client A disconnects

Client B should be able to continue Session A with BYOK Model A

This is not possible today as the client's extension host runs the inference to model providers.

Proposed Solution

Support BYOK through Model Providers configured in GitHub Copilot Plugins.

This will enable:

  1. The Agent Host to own and manage Model Providers
    • enables continuity across clients
  2. Multiple SDK Surfaces to configure BYOK models the same way (eg: GitHub Copilot App, Copilot CLI, etc)

This will also make configuring models a 'Customization' concept, which conceptually makes sense.

Tasks

  • Add support for GitHub Copilot Plugins to provide Configurable Model Providers
    • Add support for plugins to run outside the scope of sessions
      • Model Providers should be able to provide models across all sessions and not need to be started per session
    • Add support for plugins to specify that it provides models in the manifest
  • Create popularly used Model Provider Plugins for users to migrate to
  • Create an experience in VS Code to configure Plugin-provided model providers Locally
  • Create an experience in VS Code to configure Plugin-provided model providers Remotely

Activity

  1. khanhkit commented on Oct 9, 2026

    @khanhkit

    I hit the same remote-continuity problem while running Copilot Agent Host through code-server/web and have a working implementation/proof-of-concept that may be useful as reference for this issue.

    The failure mode matches the issue exactly: a BYOK turn routed through the renderer/extension-host bridge is tied to the client lifecycle, so a hard reload or full tab/browser disconnect can kill active inference even though the server-side Agent Host remains alive.

    What I validated:

    • On VS Code 1.140, moving direct-capable BYOK providers into the server Agent Host let an active turn survive hard reload and full browser/tab detach without sending a new message.
    • I ported the same implementation to VS Code 1.141 (2a59476c9bfcb90b3ddc372c36762471b7dfad1c) and reran the targeted contracts:
      • Agent Host launcher: 109/109
      • BYOK bridge registry: 11/11
      • protocol handler: 175/175
      • AHP JSONL redaction: 14/14
      • browser BYOK handler: 22/22
      • browser Agent Host session/Changes behavior: 22/22
      • full build:vscode / core-ci, code-server build, and release all pass; exact release verification is 5897/5897 files.

    The proof-of-concept takes a conservative approach:

    1. Only BYOK providers whose semantics can be represented faithfully are registered directly in Agent Host.
    2. Credential-bearing provider descriptors are bounded, ephemeral/in-memory only, validated at the protocol boundary, and redacted from AHP JSONL/state/telemetry.
    3. Providers with semantics that are not safely representable stay on the existing renderer bridge rather than being silently normalized.
    4. Vision/tool-calling/reasoning capability metadata is preserved.
    5. Native Copilot authentication semantics are not bypassed; the direct path is for BYOK.

    Reference implementation and motivation are currently visible in coder/code-server#8047. The code-server maintainer suggested upstreaming this directly because the problem should apply equally to Codespaces / VS Code Web.

    I see this issue proposes Plugin-provided configurable model providers, which is a broader and cleaner long-term ownership model than my direct-descriptor bridge. I do not want to open a competing PR blindly. If useful, I can split out the validated pieces/tests from the proof-of-concept, or adapt them to the plugin-provider direction here.

  2. khanhkit commented on Oct 9, 2026

    @khanhkit

    One additional finding while aligning the PoC with the Option B / plugin-provider direction here: the Copilot SDK/runtime substrate is already much closer to this design than the current VS Code integration suggests.

    In the SDK bundled with the validated VS Code 1.141 candidate, the experimental session API already exposes:

    • session.providers.getCatalog / discover / getStatus / models.list / models.prepareConfiguration
    • provider-adapter provenance builtIn | configured | extension | custom, with stable opaque adapterId / owner attribution
    • automatic-discovery policy including automatic | configuredOnly | explicit, network scope, input requirements, and trust requirements
    • session.provider.add / sync / withdraw for the per-session selectable provider/model registry
    • providerToken.getToken for on-demand bearer/OAuth tokens; the token callback stays SDK-side rather than being serialized

    The generated contract for provider.withdraw even explicitly notes that unrelated registry entries may have been added by “a plugin calling provider.add at runtime”.

    VS Code already supplies a connection-level extensionLaunchProvider before sessions are created. Its Agent Host resolver can launch trusted extension.mjs entrypoints from user/plugin sources through the bundled SDK bootstrap, so the process-lifecycle substrate also appears to exist.

    What I do not see in current VS Code main is the product integration for this provider surface: there are no callers of session.providers.*, and PluginComponent still covers commands/skills/agents/rules/hooks/MCP/automations but no model-provider component. An isolated tokenless 1.141 runtime session also returns an empty provider catalog with no provider plugin/config present.

    So I would no longer upstream the PoC's credential-bearing syncEphemeralByokModels transport as the target architecture. A cleaner split appears to be: provider plugin/runtime owns the adapter and discovery/configuration, VS Code consumes the catalog/configuration plan, and the prepared NamedProviderConfig + ProviderModelConfig is applied through session.provider.add.

    The reusable pieces from the PoC are mainly the renderer-detach continuity contract, capability/fallback regressions, and credential redaction/no-persistence tests. I’ll keep the code-server implementation as reference evidence and wait for owner guidance on which VS Code-side slice is useful before opening a competing PR.

  3. khanhkit commented on Oct 10, 2026

    @khanhkit

    Follow-up from current main / @github/copilot-sdk 1.0.19-preview.0: I was able to close one uncertainty from my previous comment with an isolated runtime probe using the same extension bootstrap contract VS Code installs.

    The extension process successfully executed:

    extension.mjs -> joinSession() -> session.rpc.provider.add({ providers, models }) -> session.rpc.model.list()

    and model.list returned the newly registered plugin-proof/proof-model. The probe used a loopback-unused endpoint, no real credentials, and performed no inference, so this proves the plugin-to-session provider registration/control-plane path only (not provider inference).

    That makes the smaller architecture clearer: VS Code does not need to reproduce the earlier renderer credential/direct-provider bridge just to register plugin-owned BYOK models. The remaining gap for #340335 is provider-specific discovery/configuration/lifecycle outside an already-created session, plus a safe way to request provider plugin extensions without implicitly broadening arbitrary project/user extension execution. Today the public SDK still has global extensions.*, while provider catalog/configuration remains under session.providers.*; VS Code's session config also currently ties requestExtensions to the canvas runtime gate.

    I would therefore avoid a broad requestExtensions = true workaround and keep provider/model/credential semantics in the runtime/plugin owner. Once a provider-specific/global lifecycle contract exists, the VS Code-side delta should be much smaller than the reference code-server PoC.

    Additional isolation finding (2026-10-10): I tested the coarse extension gate directly. With the same Agent Plugin under com.github.copilot/extensions/, requestExtensions: false produced no launch; requestExtensions: true launched it and provider.add succeeded. When user + project + plugin extensions were all discoverable, the connection-global launch provider could deny user/project and launch only the plugin.

    The remaining problem is concurrency/session ownership: the released ExtensionLaunchProviderResolveRequest contains id/name/modulePath/source but no sessionId. Since the resolver is connection-global, a process-wide “canvas enabled” flag/count cannot safely distinguish a plugin-only BYOK session from another concurrent canvas-enabled session. This is not hypothetical: github/copilot-sdk#2637 previously prototyped exactly the stronger contract (sessionId, defaultLaunch, explicit deny), and microsoft/vscode#335951 used exact-session launch authorization. That SDK PR was closed and current SDK main (snapshot for CLI 1.0.96-2) is back to the simpler request shape; npm 1.0.20-preview.2 is the same in this respect.

    So the minimal safe VS Code change appears dependency-blocked on restoring an equivalent session-scoped launch-admission primitive (or a session-level extension-source allowlist). Without that, simply enabling requestExtensions for provider plugins risks broadening project/user extension execution across concurrent sessions. I am intentionally not proposing that workaround.
    Clarification against this issue's stated target: the sessionId launch contract above would only make a session-extension workaround isolatable. The issue explicitly calls for model-provider plugins to run outside the scope of sessions and provide models across all sessions. I therefore do not think restoring session-scoped launch admission is the target solution for #340335; the probe is useful mainly because it rules out requestExtensions: true as a safe/minimal substitute. The actual dependency remains the runtime/plugin-level global provider lifecycle + manifest declaration described in the task list, after which VS Code should only need the configuration UX/integration slice.

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

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions