Skip to content

Support OTel instrumentation for Background Agent (Copilot CLI) #298832

Description

@zhichli

Problem

The background agent (copilotcli) has zero OTel instrumentation from the VS Code extension side.

The @github/copilot SDK (copilot-cli package) manages its own HTTP client internally. The VS Code extension creates the SDK session via toSessionOptions() in copilotCli.ts but passes no trace context or request headers. The SDK bypasses the extension's networkRequest() pipeline entirely.

Impact

  • Background agent runs are completely invisible to distributed tracing
  • No OTel spans for LLM calls or tool executions
  • No correlation with foreground agent traces or eval runs
  • The X-Request-Id values sent by the SDK are internal and not exposed to the extension

Current foreground agent OTel (for comparison)

The foreground agent already has full OTel instrumentation:

  • invoke_agent span wrapping the agent orchestration
  • chat {model} spans per LLM API call (span kind: CLIENT)
  • execute_tool {name} spans per tool invocation
  • Metrics: token usage, operation duration, tool call count/duration, TTFT
  • Events: inference details, session start, tool call, agent turn

The background agent has none of this.

Proposed Fix (layered)

Layer A — Create extension-side OTel spans (short-term)

  1. In copilotcliSession.ts, wrap the session's handleRequest() in otelService.startActiveSpan("copilotcli_session", ...).
  2. Subscribe to SDK events (tool.execution_start, assistant.message, assistant.usage) and create child spans to mirror the foreground agent's span hierarchy.
  3. Wire subagent trace context storage (storeTraceContext("subagent:...")) so background-agent-invoked subagents inherit the trace.

Layer B — SDK exposes request IDs (medium-term)

  1. The SDK's ClientOptions supports requestHeaders?: Record<string, string> at the per-request level. Expose a session-level defaultHeaders config in the @github/copilot SDK.
  2. The SDK should also expose X-Request-Id and X-GitHub-Request-ID from CAPI responses via events, so the extension can log/correlate them.

Layer C — SDK-native OTel (long-term)

  1. The @github/copilot SDK itself should accept an OTel TracerProvider and create spans internally for each LLM call and tool execution.

Key Files

  • src/extension/chatSessions/copilotcli/node/copilotCli.tsCopilotCLISessionOptions.toSessionOptions(), where session config is built
  • src/extension/chatSessions/copilotcli/node/copilotcliSession.tshandleRequest(), SDK event subscriptions
  • src/extension/chatSessions/copilotcli/node/copilotcliSessionService.tscreateSession()
  • src/platform/otel/common/otelService.tsIOTelService interface (startActiveSpan, storeTraceContext)

Context

The copilotcli SDK (@github/copilot) uses its own internal HTTP client that bypasses the extension's networkRequest() pipeline. The SDK's SessionOptions type has no requestHeaders field, though per-request ClientOptions and GetCompletionWithToolsOptions do support requestHeaders. The SDK's CAPIRequestContext type supports interactionType, agentTaskId, parentAgentTaskId, clientSessionId, and interactionId.

For the foreground agent OTel implementation (as reference), see:

Metadata

Metadata

Labels

copilot-cli-agentBackground Agent related features/bugsfeature-requestRequest for new features or functionality

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions