Enterprise OTel managed-settings policy for Copilot (extension + agent host)#323227
Merged
Conversation
High-level plan for VS Code enterprise control of Copilot agent-host OTel export via the cross-client telemetry managed-settings schema (matches CLI ManagedTelemetrySettings, copilot-agent-runtime #10735). Covers schema, ownership, precedence, security, delivery channels, suppressions, and touch points.
The managed-settings policy (AccountPolicyService) is applied only in the renderer's MultiplexPolicyService, so the main-process config service that ElectronAgentHostStarter reads returns policyValue===undefined for the chat.agentHost.otel.* keys. The agent host was therefore spawned without the managed OTel env (endpoint/protocol/enabled) and never exported telemetry. Thread the renderer-resolved policy to the starter over the existing renderer->main connection seam (the renderer is already the gate for policy-resolved agent-host decisions main cannot observe): - agentService: AgentHostOTelPolicyIpcChannel + readAgentHostOTelPolicySettings() + sanitizeAgentHostOTelPolicySettings(). - localAgentHostService: forward the resolved policy before acquirePort (FIFO ordering lands it before the lazy spawn). - electronAgentHostStarter: cache the renderer policy and use it as buildAgentHostOTelEnv policySettings, falling back to main-process policy. Additive/optional: no managed policy -> unchanged behavior. Verified e2e (agent host env got endpoint 4318 + http/protobuf; Aspire service.name github-copilot).
…tributes/serviceName Records the runtime spike: the headless agent host resolves OTel from env only and doesn't self-fetch managed telemetry, but build_resource reads OTEL_SERVICE_NAME / OTEL_RESOURCE_ATTRIBUTES env. Revised plan delivers serviceName + resourceAttributes to both surfaces (env for the host, programmatic for the extension) and headers to the extension only; agent-host headers stay deferred (env would leak the token to tool subprocesses).
Contributor
There was a problem hiding this comment.
Pull request overview
Adds enterprise-managed OpenTelemetry (OTel) configuration for Copilot via managed settings/policies, wiring the resolved policy into both the Copilot extension’s OTLP exporter configuration and the agent-host process spawn environment so enterprises can centrally mandate endpoint/protocol/content-capture/service identity.
Changes:
- Extends managed-settings schema and normalizer to support a
telemetryblock (including structured map fields encoded as JSON). - Registers new/updated policies + policyReferences to allow enterprise management of Copilot OTel settings, including desktop forwarding of renderer-resolved managed settings to the main-process agent-host starter.
- Updates Copilot extension OTel config resolution and exporters to support
http/protobuf, merged resource attributes/headers, and policy > env > setting precedence (with new/updated unit tests).
Show a summary per file
| File | Description |
|---|---|
| src/vs/workbench/services/accounts/test/browser/managedSettings.test.ts | Adds coverage for telemetry flattening + JSON-encoded map keys in managed settings. |
| src/vs/workbench/services/accounts/browser/managedSettings.ts | Extends managed-settings response typing to include telemetry block. |
| src/vs/platform/policy/common/copilotManagedSettings.ts | Adds telemetry managed-settings keys + nested structured-key handling in normalizer. |
| src/vs/platform/agentHost/test/common/agentService.test.ts | Adds tests for agent-host OTel env building and policy snapshot/sanitization. |
| src/vs/platform/agentHost/node/nodeAgentHostStarter.ts | Applies enterprise policy values when building agent-host OTel env (node starter). |
| src/vs/platform/agentHost/electron-main/electronAgentHostStarter.ts | Adds renderer→main IPC forwarding for managed OTel policy + uses it when spawning host. |
| src/vs/platform/agentHost/electron-browser/localAgentHostService.ts | Sends resolved policy snapshot to main process before requesting agent-host connection. |
| src/vs/platform/agentHost/common/agentService.ts | Adds policy plumbing, IPC channel, sanitization, and new OTel env vars (service/resource attrs, per-signal protocol). |
| src/vs/platform/agentHost/common/agentHostStarter.config.contribution.ts | Registers new enterprise policies and hidden “policy-only” delivery slots for agent-host OTel. |
| extensions/copilot/src/platform/otel/node/otelServiceImpl.ts | Adds headers support and http/protobuf OTLP exporters for extension-side OTLP export. |
| extensions/copilot/src/platform/otel/common/test/otelConfig.spec.ts | Adds tests for policy precedence + resource/header merging + protocol behavior. |
| extensions/copilot/src/platform/otel/common/otelConfig.ts | Implements policy > env > setting precedence, adds headers/resourceAttrs/serviceName, and splits transport vs wire protocol. |
| extensions/copilot/src/platform/otel/common/agentOTelEnv.ts | Threads resolved otlpProtocol through to Claude env derivation. |
| extensions/copilot/src/extension/extension/vscode-node/services.ts | Wires policyValue reads into resolveOTelConfig inputs. |
| extensions/copilot/package.json | Adds new OTel settings + policyReferences for enterprise management; updates deps for proto exporters. |
| extensions/copilot/package-lock.json | Locks new @opentelemetry/*-otlp-proto dependencies. |
| build/lib/policies/policyData.jsonc | Updates generated policy catalog to include new Copilot OTel policies/references. |
Review details
Files not reviewed (1)
- extensions/copilot/package-lock.json: Generated file
- Files reviewed: 16/17 changed files
- Comments generated: 12
- Review effort level: Low
8ec16e8 to
7c94b4d
Compare
…inference, prototype-pollution hardening
…nce and new settings
…nfig keys to match package.json
d558564 to
e5ec5ab
Compare
The checked-in policyData.jsonc was generated with the Copilot extension loaded, which injected referencedSettings linking the OTel extension settings to the core CopilotOtel* policies. The PolicyExport integration test regenerates using the test fixture distro with no user extensions, so those referencedSettings are absent. Regenerate in an isolated environment to match the fixture-based export.
… env A plain 'npm run export-policy-data' loads dev-profile extensions, injecting referencedSettings the fixture-based PolicyExport integration test won't produce — failing CI in a way that is not reproducible locally. Document the isolated regeneration command.
lszomoru
approved these changes
Jun 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
What
Lets enterprises mandate OpenTelemetry configuration for Copilot through managed settings instead of relying on per-user
OTEL_*/COPILOT_OTEL_*environment variables. Adds atelemetryblock to the managed-settings schema coveringenabled,endpoint,protocol,captureContent,lockCaptureContent,serviceName,resourceAttributes, andheaders, surfaced as VS Code policies and applied across both Copilot OTel surfaces:otelConfig.ts/otelServiceImpl.ts).agentService.ts+ starters).Precedence is uniform: policy > env > setting > default, with managed values winning per field.
Key behaviors and safety guarantees:
http/protobuf): the managed wire protocol is threaded through a dedicated slot so both surfaces emit protobuf (not just JSON) when the enterprise mandates it.serviceName/resourceAttributes: delivered to the agent host via standardOTEL_SERVICE_NAME/OTEL_RESOURCE_ATTRIBUTESenv, and merged per-key into the extension's resource (policy wins).headersare extension-only and out-of-env: managed OTLP headers (which may carry an auth token) are applied directly to the extension's OTLP exporter, never via environment variables — so the secret can't leak into the tool subprocesses the agent host spawns.Structured map fields (
resourceAttributes,headers) are carried through the managed-settings normalizer as JSON-encoded objects under nested keys; scalar fields flatten automatically.Why
Enterprises need to control where Copilot telemetry flows (endpoint, auth headers, content-capture policy, service identity) without depending on each user setting env vars. This brings VS Code in line with the same OTel managed-settings policy being rolled out in the Copilot CLI.
Known limitations (flagged for review)
Agent-host
headersare deferred. Unlike the extension, the agent host can only receive config via env vars, and anOTEL_EXPORTER_OTLP_HEADERSvalue would be inherited by every tool subprocess the host spawns — leaking the secret. Secure delivery requires the CLI runtime's out-of-env header stamping, so agent-host headers are intentionally not delivered here. Extension headers (the secure path) ship in this PR.Agent-host OTel env is fixed at spawn. The host computes its OTel env once when it starts; a managed-policy change (or first sync) that lands after the host has spawned isn't re-applied until the host respawns — the same "reload to apply" class as the extension. Re-spawning the host on a managed-OTel-policy change is a follow-up.
Tests
agentService.test.ts), managed-settings normalization incl. nested map flattening (managedSettings.test.ts).otelConfig.spec.ts).service.name, resource attributes, andhttp/protobuf; agent host correctly excludes the header.