Skip to content

Instantly share code, notes, and snippets.

@devm33
Last active August 18, 2026 15:45
Show Gist options
  • Select an option

  • Save devm33/ed55b25ab5f39a651010a2e7c979f3dd to your computer and use it in GitHub Desktop.

Select an option

Save devm33/ed55b25ab5f39a651010a2e7c979f3dd to your computer and use it in GitHub Desktop.
GitHub Copilot user and token endpoint invocation report

GitHub Copilot user and token endpoint invocation report

Status: Source audit completed August 18, 2026. Intended for planning load on GitHub services.

Executive summary

The endpoint count is layered rather than a single constant. A cold desktop flow can involve shared VS Code account services before either harness, then harness-specific calls, each with an independent process-local cache.

Under the explicit assumptions below, the cold logical invocation counts are:

Situation /copilot_internal/user /copilot_internal/v2/token Runtime topology
Legacy local harness 3 2 Runtime loaded in the extension host; no CLI child
Agent host with github/copilot-sdk 4 3 One agent-host process and one shared CLI/runtime child

These totals assume one desktop VS Code instance, one valid GitHub OAuth session, empty process-local caches, no reusable persisted DefaultAccountService policy data (or a forced refresh), chat_enabled=true, the Copilot extension token manager is initialized, one successful HTTP attempt, and no quota, BYOK, or debug-only path. If the extension token manager is not initialized, subtract one /copilot_internal/user and one /copilot_internal/v2/token from either total. If chat_enabled=false, the workbench account layer does not request /copilot_internal/v2/token, so subtract another one token request.

The most important findings are:

  • github/copilot-sdk makes zero direct calls to either endpoint. It transports the token to the child runtime.
  • copilot-agent-runtime makes zero direct calls to /copilot_internal/v2/token.
  • The VS Code agent-host process initiates both calls. Its CopilotApiService fetches /copilot_internal/user directly and invokes RequestType.CopilotToken through the separate @vscode/copilot-api package, which maps that request to /copilot_internal/v2/token.
  • The normal agent-host CLI child makes zero authentication endpoint calls at process startup. VS Code starts it with useLoggedInUser: false and supplies the GitHub token per request.
  • The agent host creates one CopilotClient, and that client creates one CLI/runtime child. Sessions are multiplexed over that child; it is not one child per session.
  • /copilot_internal/user is independently requested and cached in VS Code, the agent host, and the runtime. Those caches are not shared.

For load planning, the architecture change has two effects:

  • Cold load: agent host + SDK adds a net one /copilot_internal/user and one /copilot_internal/v2/token over the legacy path under the stated assumptions.
  • Active steady-state load: the legacy and child-runtime 15-minute caches replace each other. The additional agent-host cache can add up to about 2.4 /copilot_internal/user calls per active token per hour when qualifying accesses continue, plus one response-lifetime-driven /copilot_internal/v2/token refresh stream. These are per-process caches, so restarts and additional agent-host processes reset or multiply them.

Scope and source revisions

This report compares:

  1. The legacy local harness in microsoft/vscode, which loads @github/copilot/sdk and a LocalSessionManager in the extension host.
  2. The agent-host architecture in microsoft/vscode, which uses the public github/copilot-sdk package and a spawned copilot-agent-runtime CLI child.

The audit used these revisions:

Counts in this report are logical request operations. HTTP retries, fallback hosts, rejected credentials, process restarts, and forced refreshes can produce more wire attempts.

Counts by source

This table shows exactly which source contributes each cold call.

Architecture Source and process Responsibility /copilot_internal/user /copilot_internal/v2/token
Shared VS Code Workbench DefaultAccountService Account entitlements 1 1 when chat_enabled=true
Shared VS Code Extension-host CopilotTokenManager Copilot authentication 1 1
Legacy @github/copilot/sdk in the extension host Explicit-token user resolution 1 0
Agent host VS Code agent-host CopilotApiService plus @vscode/copilot-api CAPI context and restricted-telemetry token 1 on a cold per-token cache 1 on a cold per-token cache after a changed non-empty GitHub token is applied
Agent host github/copilot-sdk library in the agent-host process Starts and transports RPC to the runtime child 0 0
Agent host copilot-agent-runtime CLI child Explicit-token user resolution 1 0

GitHub service load model

The cache lifetime, scope, and trigger determine sustained load. The rates below are the maximum cache-driven cadence under continuous qualifying access. They exclude retries, failures, explicit cache bypasses, and forced refreshes. Lazy caches generate no refresh traffic while unused.

Source and process Endpoint Cache scope and key Freshness or refresh threshold Load after the cold call
Workbench DefaultAccountService Both endpoints Workbench/account state with application-scoped persisted policy data One-hour staleness check and poll Up to 1 call/hour/endpoint/cache instance while active; fresh persisted data can suppress startup calls
Extension-host CopilotTokenManager Both endpoints, paired Extension-host token state Refreshes when absent, forced, or within five minutes of computed expiry; expiry is response-driven using refresh_in One paired user+token call per authentication refresh cycle; no fixed rate can be derived without the server response lifetime
Legacy in-process runtime /copilot_internal/user Process-global LRU, keyed by hash of host and token; maximum 1,000 entries 15-minute absolute TTL; stale-while-revalidate Up to about 4 calls/hour/distinct token/process under continuous access
VS Code agent-host CopilotApiService /copilot_internal/user Agent-host process, keyed by raw GitHub token 30-minute TTL with a five-minute early-refresh window; refresh is lazy Up to about 2.4 calls/hour/distinct token/agent host under continuous access
VS Code agent-host CopilotApiService /copilot_internal/v2/token Agent-host process, keyed by GitHub token Response-driven expiry, floored at 60 seconds; refresh on the next access with five minutes or less remaining One call per effective token lifetime minus the five-minute buffer; no fixed rate can be derived without refresh_in or expires_at
github/copilot-sdk library Both endpoints No endpoint cache because it makes no direct calls Not applicable 0
copilot-agent-runtime CLI child /copilot_internal/user Process-global LRU within each child, keyed by hash of host and token; maximum 1,000 entries 15-minute absolute TTL; stale-while-revalidate Up to about 4 calls/hour/distinct token/CLI child under continuous access

The source citations for these policies are:

Capacity-planning formulas

For continuously active caches over a one-hour window:

legacy_internal_user ≲ workbench_cache_instances
                     + extension_auth_refresh_cycles
                     + 4 × legacy_runtime_token_process_pairs

agent_host_internal_user ≲ workbench_cache_instances
                         + extension_auth_refresh_cycles
                         + 2.4 × agent_host_token_pairs
                         + 4 × cli_child_token_process_pairs

incremental_internal_user ≲ 2.4 × agent_host_token_pairs
    when each legacy runtime token/process pair is replaced by one CLI child token/process pair

The 2.4 and 4 terms are TTL ceilings under continuous access, not background timers. For /copilot_internal/v2/token, the incremental agent-host load is:

incremental_v2_token =
    applied_token_cold_mints
    + accesses_after_each_response_driven_refresh_threshold

Use the observed distribution of refresh_in or expires_at to turn that expression into requests per hour. A count based only on client source cannot produce a reliable fixed token-refresh rate.

The five-minute refresh buffer is larger than the 60-second expiry floor. If the service returns an effective token lifetime of five minutes or less, the cached token is already inside its refresh window, so every subsequent qualifying access can mint again. Capacity planning should verify the production lifetime distribution and treat short-lifetime responses as a potential high-load case.

Burst and multiplier risks

  • A fresh agent-host desktop path can issue four user calls and three token calls, spread across independent VS Code and runtime components.
  • The architecture-specific portion is two user calls and one token call: one user+token pair from the agent host, zero from the SDK library, and one user call from the runtime child.
  • Same-token sessions share one CLI child and normally do not multiply requests.
  • Each distinct token creates a separate cache entry and refresh stream.
  • Agent-host or CLI restarts lose their process-local caches and recreate cold load.
  • Separate application instances and remote hosts can create independent agent-host and CLI processes. Workspace folders and sessions alone do not.
  • Concurrent successful cold requests are deduplicated within the agent-host and runtime caches. Failed runtime validation is not cached, so invalid-token bursts can generate one upstream request per caller.

The shared VS Code calls before the harness are visible in two independent components:

Situation 1: Legacy local harness

The legacy harness dynamically loads the internal SDK and constructs one lazy LocalSessionManager inside the existing extension-host process. It does not construct a public CopilotClient, so it does not spawn a CLI child: copilotcliSessionService.ts#L155-L227.

The harness obtains the VS Code GitHub session token and calls resolveAuthInfoFromToken. On a cold token cache, that operation adds one /copilot_internal/user request: copilotCli.ts#L646-L684.

flowchart TD
    A[VS Code workbench] -->|1x user entitlement| U1["GET /copilot_internal/user"]
    A -->|1x token entitlement if chat enabled| T1["GET /copilot_internal/v2/token"]
    B[Copilot extension token manager] -->|1x user during auth| U2["GET /copilot_internal/user"]
    B -->|1x token during auth| T2["GET /copilot_internal/v2/token"]
    B --> C[Legacy local harness in extension host]
    C -->|resolveAuthInfoFromToken, cold cache| U3["GET /copilot_internal/user"]
    C --> D[LocalSessionManager]
    D --> E[Sessions run in process]
Loading

Legacy cold count

Source and process /copilot_internal/user /copilot_internal/v2/token
VS Code workbench DefaultAccountService 1 1
VS Code extension-host CopilotTokenManager 1 1
In-process @github/copilot/sdk runtime resolver 1 0
Total under stated assumptions 3 2

Multiple local sessions using the same token do not each create a network request. They share the runtime's process-global explicit-token cache.

Situation 2: Agent host with github/copilot-sdk

VS Code owns one memoized CopilotClient, configured for stdio with useLoggedInUser: false, and shares it across sessions: copilotAgent.ts#L1757-L1931. The SDK client starts one child process and keeps it as cliProcess: client.ts#L2405-L2624.

The process answer is therefore:

  • VS Code creates one agent-host process for this service.
  • The SDK library runs inside that agent host; it is not another process.
  • The one CopilotClient creates one CLI/runtime child.
  • Additional sessions reuse the same child.
  • A client restart, another VS Code application instance or remote host, or another CopilotClient can create another child.

VS Code passes the GitHub token at session level: copilotSessionLauncher.ts#L723-L869. Because the client is started without logged-in-user authentication, the child makes no auth endpoint call merely by starting. Its first token-bearing create, resume, or equivalent authentication operation resolves the explicit token and adds one cold /copilot_internal/user.

The agent host independently resolves its CAPI context. The executable chain is:

_applyGitHubToken(changed non-empty token)
  -> _updateRestrictedTelemetry
  -> _resolveRestrictedTelemetry
  -> resolveRestrictedTelemetryContext
  -> _getCopilotTokenEntry
  -> _buildCopilotToken
  -> _getClientForToken
     -> GET /copilot_internal/user
  -> RequestType.CopilotToken
     -> GET /copilot_internal/v2/token

_buildCopilotToken first calls _getClientForToken, so a fully cold token cache performs the user discovery before minting the token. Restricted-telemetry and SKU work then share the same cached user context, avoiding duplicate user requests. This is implemented in copilotAgent.ts#L1381-L1476 and copilotApiService.ts#L929-L1134. The audited VS Code lockfile resolves @vscode/copilot-api 0.5.2; that package's RequestType.CopilotToken mapping targets /copilot_internal/v2/token. This package is separate from github/copilot-sdk.

flowchart TD
    A[VS Code workbench] -->|1x user entitlement| U1["GET /copilot_internal/user"]
    A -->|1x token entitlement if chat enabled| T1["GET /copilot_internal/v2/token"]
    B[Copilot extension token manager] -->|1x user during auth| U2["GET /copilot_internal/user"]
    B -->|1x token during auth| T2["GET /copilot_internal/v2/token"]
    A --> H[One VS Code agent-host process]
    H -->|CAPI context, cold cache| U3["GET /copilot_internal/user"]
    H -->|automatic restricted-telemetry resolution, cold cache| T3["GET /copilot_internal/v2/token"]
    H --> S[One CopilotClient]
    S -->|spawns once| R[One CLI/runtime child]
    R -->|first token-bearing operation| U4["GET /copilot_internal/user"]
    H -->|many sessions| R
Loading

Agent-host cold count

Source and process /copilot_internal/user /copilot_internal/v2/token
VS Code workbench DefaultAccountService 1 1
VS Code extension-host CopilotTokenManager 1 1
VS Code agent-host CopilotApiService 1 1
github/copilot-sdk library 0 0
copilot-agent-runtime CLI child 1 0
Total under stated assumptions 4 3

An additional same-token SDK session adds zero endpoint calls while both relevant caches are fresh.

Cache implementation details

Component and endpoint Cache scope Refresh behavior
Workbench DefaultAccountService: user and v2 token VS Code workbench process plus application-scoped persisted policy data One-hour staleness check and poll; persisted fresh data can suppress a cold-window fetch, and forced refresh can bypass it
Extension CopilotTokenManager: paired user and v2 token Extension host Re-authenticates when the token is absent, forced, or within five minutes of expiry; response refresh_in contributes to computed expiry
Legacy/runtime explicit-token user lookup Process-global runtime LRU, keyed by SHA-256 of host and token, maximum 1,000 entries Fresh for 15 minutes; stale value is returned while one background refresh runs; valid cold misses are single-flighted
Agent-host user/CAPI context Agent-host process, keyed by GitHub token Nominal 30-minute TTL with a five-minute refresh buffer; the next access after about 25 minutes re-fetches, and concurrent callers share the same promise
Agent-host v2 token Agent-host process, keyed by GitHub token Expiry uses now + refresh_in when provided, otherwise expires_at, floored at now + 60 seconds; the next access with five minutes or less remaining refreshes it, and concurrent callers share one mint
CLI child explicit-token user lookup Process-global within that child; same runtime LRU as the legacy resolver Fresh for 15 minutes, stale-while-revalidate, and cold-miss single-flight

Runtime cache details are implemented in resolve_info.rs#L5-L54 and resolve_info.rs#L109-L283. ghs_ and OpenShell resolver tokens bypass both the cache and /copilot_internal/user, using synthetic user metadata instead.

The agent-host cache constants and behavior are implemented in copilotApiService.ts#L151-L159, copilotApiService.ts#L210-L214, and copilotApiService.ts#L929-L1134.

sequenceDiagram
    participant V as VS Code agent host
    participant H as Host user cache (30m)
    participant C as CLI child
    participant R as Runtime user cache (15m)
    participant G as GitHub API

    V->>H: Resolve CAPI context for token
    H->>G: GET /copilot_internal/user
    G-->>H: User and endpoint data
    V->>C: Token-bearing request
    C->>R: Resolve AuthInfo
    R->>G: GET /copilot_internal/user
    G-->>R: Copilot user data
    Note over H,R: Independent caches - neither suppresses the other
    V->>C: Additional same-token session
    C->>R: Cache hit
    R-->>C: No network request while fresh
Loading

Endpoint-specific call paths

/copilot_internal/user

It can be called by:

  1. VS Code DefaultAccountService for entitlement/account state.
  2. The Copilot extension token manager, paired with each Copilot-token authentication cycle.
  3. The legacy in-process runtime when resolveAuthInfoFromToken sees a cold or stale token entry.
  4. The agent-host CopilotApiService for CAPI endpoint, login, SKU, and restricted-telemetry context.
  5. The CLI child when a per-session GitHub token is first resolved.
  6. Explicit cache-bypassing quota reads: account.getQuota({ gitHubToken }) adds one request per invocation: sdkServerHost.ts#L1042-L1071.
  7. Explicit refreshCopilotUser operations or failed validations. Failed runtime validations are not cached.

For a time window W, distinct tokens T, and forced uncached quota/refresh calls Q, the runtime portion is approximately:

runtime_user_calls =
    cold_or_stale_resolutions(T, process, 15-minute TTL)
    + Q

It is not proportional to the number of sessions because successful same-token resolutions are single-flighted and cached.

/copilot_internal/v2/token

It can be called by:

  1. VS Code DefaultAccountService, when chat_enabled=true.
  2. The Copilot extension token manager during Copilot-token authentication.
  3. The agent-host CopilotApiService, which mints once when a non-empty GitHub token is applied for restricted-telemetry resolution; utility chat can reuse the cached mint.

It is not directly called by github/copilot-sdk or copilot-agent-runtime. The executable runtime builds /copilot_internal/user, but has no v2-token request builder: core.rs#L622-L633.

Practical conclusions

  1. For a cold, typical desktop comparison, use 3 user / 2 token for the legacy harness and 4 user / 3 token for agent host + SDK.
  2. For the architecture-specific increment only, exclude shared VS Code account and extension authentication:
    • Legacy harness: 1 user / 0 token, from the in-process runtime resolver.
    • Agent host + SDK: 2 user / 1 token: one user request and one token request in the VS Code agent host, zero requests in the SDK library, and one user request in the runtime child.
  3. A second same-token session normally adds 0 user / 0 token while caches are fresh.
  4. At about 15 minutes, another runtime token resolution can return stale data and trigger one background /copilot_internal/user refresh.
  5. The next relevant access after about 25 minutes can make the agent-host CAPI-context cache add another /copilot_internal/user.
  6. The runtime never adds /copilot_internal/v2/token; any such call is in a VS Code layer.
  7. Count processes per CopilotClient, not per session: the normal agent-host design has one shared CLI child.

Caveats

  • The extension token manager and workbench account service are separate. Their caches do not suppress each other.
  • Whether the classic extension token manager initializes in every agent-host product configuration is a runtime/product activation detail. The layered table allows that row to be removed when it is not active.
  • chat_enabled=false suppresses the workbench token-entitlement request.
  • Applying a changed, non-empty GitHub token currently starts restricted-telemetry resolution. It mints an agent-host v2 token only when that token's cache entry is absent or stale; utility-token consumers reuse the cache.
  • Multiple accounts, enterprise hosts, separate application instances, remote hosts, client restarts, and distinct CopilotClient objects multiply process-local cold calls.
  • Same-application windows can multiply workbench and extension-host rows, while they normally share the main-process agent host. Workspace folders and SDK sessions alone do not create more agent-host or CLI processes.
  • HTTP retry and fallback behavior can make packet captures show more attempts than the logical counts in this report.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment