Status: Source audit completed August 18, 2026. Intended for planning load on GitHub services.
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-sdkmakes zero direct calls to either endpoint. It transports the token to the child runtime.copilot-agent-runtimemakes zero direct calls to/copilot_internal/v2/token.- The VS Code agent-host process initiates both calls. Its
CopilotApiServicefetches/copilot_internal/userdirectly and invokesRequestType.CopilotTokenthrough the separate@vscode/copilot-apipackage, 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: falseand 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/useris 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/userand one/copilot_internal/v2/tokenover 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/usercalls per active token per hour when qualifying accesses continue, plus one response-lifetime-driven/copilot_internal/v2/tokenrefresh stream. These are per-process caches, so restarts and additional agent-host processes reset or multiply them.
This report compares:
- The legacy local harness in
microsoft/vscode, which loads@github/copilot/sdkand aLocalSessionManagerin the extension host. - The agent-host architecture in
microsoft/vscode, which uses the publicgithub/copilot-sdkpackage and a spawnedcopilot-agent-runtimeCLI child.
The audit used these revisions:
microsoft/vscodeatcf9be8472b3df50d9628481027c3724409e2ca05github/copilot-sdkat4472fcb9ad342b02aae14ccc3cf1c8083603863egithub/copilot-agent-runtimeatfc3dbdee641222adde630c1c10d9db5f99dd7624
Counts in this report are logical request operations. HTTP retries, fallback hosts, rejected credentials, process restarts, and forced refreshes can produce more wire attempts.
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 |
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:
- Workbench one-hour policy:
defaultAccount.ts#L652-L869. - Extension token refresh:
copilotTokenManager.ts#L156-L271. - Runtime 15-minute LRU and stale-while-revalidate behavior:
resolve_info.rs#L5-L54andresolve_info.rs#L109-L283. - Agent-host user and token cache constants and behavior:
copilotApiService.ts#L151-L159,copilotApiService.ts#L210-L214, andcopilotApiService.ts#L929-L1134.
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.
- 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:
DefaultAccountServicefetches/copilot_internal/user, then fetches/copilot_internal/v2/tokenonly when the returned account has chat enabled. Both are guarded by one-hour freshness checks:defaultAccount.ts#L652-L869.CopilotTokenManagerconcurrently fetches the Copilot token and Copilot user during authentication:copilotTokenManager.ts#L156-L271andcopilotTokenManager.ts#L344-L357.
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]
| 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.
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
CopilotClientcreates one CLI/runtime child. - Additional sessions reuse the same child.
- A client restart, another VS Code application instance or remote host, or another
CopilotClientcan 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
| 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.
| 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
It can be called by:
- VS Code
DefaultAccountServicefor entitlement/account state. - The Copilot extension token manager, paired with each Copilot-token authentication cycle.
- The legacy in-process runtime when
resolveAuthInfoFromTokensees a cold or stale token entry. - The agent-host
CopilotApiServicefor CAPI endpoint, login, SKU, and restricted-telemetry context. - The CLI child when a per-session GitHub token is first resolved.
- Explicit cache-bypassing quota reads:
account.getQuota({ gitHubToken })adds one request per invocation:sdkServerHost.ts#L1042-L1071. - Explicit
refreshCopilotUseroperations 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.
It can be called by:
- VS Code
DefaultAccountService, whenchat_enabled=true. - The Copilot extension token manager during Copilot-token authentication.
- 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.
- For a cold, typical desktop comparison, use 3 user / 2 token for the legacy harness and 4 user / 3 token for agent host + SDK.
- 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.
- A second same-token session normally adds 0 user / 0 token while caches are fresh.
- At about 15 minutes, another runtime token resolution can return stale data and trigger one background
/copilot_internal/userrefresh. - The next relevant access after about 25 minutes can make the agent-host CAPI-context cache add another
/copilot_internal/user. - The runtime never adds
/copilot_internal/v2/token; any such call is in a VS Code layer. - Count processes per
CopilotClient, not per session: the normal agent-host design has one shared CLI child.
- 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=falsesuppresses 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
CopilotClientobjects 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.