Skip to content

Enterprise OTel managed-settings policy for Copilot (extension + agent host)#323227

Merged
zhichli merged 27 commits into
mainfrom
zhichli/otelpolicy2
Jun 27, 2026
Merged

Enterprise OTel managed-settings policy for Copilot (extension + agent host)#323227
zhichli merged 27 commits into
mainfrom
zhichli/otelpolicy2

Conversation

@zhichli

@zhichli zhichli commented Jun 27, 2026

Copy link
Copy Markdown
Member

Overview

What

Lets enterprises mandate OpenTelemetry configuration for Copilot through managed settings instead of relying on per-user OTEL_* / COPILOT_OTEL_* environment variables. Adds a telemetry block to the managed-settings schema covering enabled, endpoint, protocol, captureContent, lockCaptureContent, serviceName, resourceAttributes, and headers, surfaced as VS Code policies and applied across both Copilot OTel surfaces:

  • Copilot Chat extension — managed values are resolved into its OTLP exporter config (otelConfig.ts / otelServiceImpl.ts).
  • Agent host process — managed values are translated into the spawned process's OTel env vars (agentService.ts + starters).

Precedence is uniform: policy > env > setting > default, with managed values winning per field.

Key behaviors and safety guarantees:

  • Protocol parity (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 standard OTEL_SERVICE_NAME / OTEL_RESOURCE_ATTRIBUTES env, and merged per-key into the extension's resource (policy wins).
  • headers are 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.
  • Desktop agent-host delivery fix: the managed-settings policy layer lives only in the renderer; the agent-host starter runs in the main process and previously saw no managed OTel policy. The renderer now forwards the resolved policy to the starter over the existing connection seam, so the host spawns with the managed OTel env.

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)

  1. Agent-host headers are deferred. Unlike the extension, the agent host can only receive config via env vars, and an OTEL_EXPORTER_OTLP_HEADERS value 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.

  2. 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

  • Unit: agent-host env builder + policy read/sanitize (agentService.test.ts), managed-settings normalization incl. nested map flattening (managedSettings.test.ts).
  • Extension: OTel config precedence for protocol / serviceName / resourceAttributes / headers (otelConfig.spec.ts).
  • Verified end-to-end against a local OTLP collector: both surfaces emit with the managed service.name, resource attributes, and http/protobuf; agent host correctly excludes the header.

zhichli added 20 commits June 26, 2026 11:07
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).
Copilot AI review requested due to automatic review settings June 27, 2026 00:01

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

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 telemetry block (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

Comment thread extensions/copilot/src/platform/otel/common/otelConfig.ts
Comment thread extensions/copilot/src/platform/otel/common/otelConfig.ts Outdated
Comment thread extensions/copilot/package.json Outdated
Comment thread extensions/copilot/package.json Outdated
Comment thread extensions/copilot/package.json Outdated
Comment thread extensions/copilot/package.json Outdated
Comment thread src/vs/platform/policy/common/copilotManagedSettings.ts
Comment thread src/vs/platform/agentHost/common/agentService.ts
Comment thread extensions/copilot/src/platform/otel/common/otelConfig.ts
Comment thread src/vs/workbench/services/accounts/test/browser/managedSettings.test.ts Outdated
@zhichli zhichli force-pushed the zhichli/otelpolicy2 branch from d558564 to e5ec5ab Compare June 27, 2026 04:38
zhichli added 2 commits June 26, 2026 22:15
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.
@zhichli zhichli merged commit 1b43d57 into main Jun 27, 2026
30 checks passed
@zhichli zhichli deleted the zhichli/otelpolicy2 branch June 27, 2026 09:50
@vs-code-engineering vs-code-engineering Bot added this to the 1.127.0 milestone Jun 27, 2026
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