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)
- In
copilotcliSession.ts, wrap the session's handleRequest() in otelService.startActiveSpan("copilotcli_session", ...).
- Subscribe to SDK events (
tool.execution_start, assistant.message, assistant.usage) and create child spans to mirror the foreground agent's span hierarchy.
- Wire subagent trace context storage (
storeTraceContext("subagent:...")) so background-agent-invoked subagents inherit the trace.
Layer B — SDK exposes request IDs (medium-term)
- 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.
- 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)
- 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.ts — CopilotCLISessionOptions.toSessionOptions(), where session config is built
src/extension/chatSessions/copilotcli/node/copilotcliSession.ts — handleRequest(), SDK event subscriptions
src/extension/chatSessions/copilotcli/node/copilotcliSessionService.ts — createSession()
src/platform/otel/common/otelService.ts — IOTelService 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:
Problem
The background agent (copilotcli) has zero OTel instrumentation from the VS Code extension side.
The
@github/copilotSDK (copilot-clipackage) manages its own HTTP client internally. The VS Code extension creates the SDK session viatoSessionOptions()incopilotCli.tsbut passes no trace context or request headers. The SDK bypasses the extension'snetworkRequest()pipeline entirely.Impact
X-Request-Idvalues sent by the SDK are internal and not exposed to the extensionCurrent foreground agent OTel (for comparison)
The foreground agent already has full OTel instrumentation:
invoke_agentspan wrapping the agent orchestrationchat {model}spans per LLM API call (span kind: CLIENT)execute_tool {name}spans per tool invocationThe background agent has none of this.
Proposed Fix (layered)
Layer A — Create extension-side OTel spans (short-term)
copilotcliSession.ts, wrap the session'shandleRequest()inotelService.startActiveSpan("copilotcli_session", ...).tool.execution_start,assistant.message,assistant.usage) and create child spans to mirror the foreground agent's span hierarchy.storeTraceContext("subagent:...")) so background-agent-invoked subagents inherit the trace.Layer B — SDK exposes request IDs (medium-term)
ClientOptionssupportsrequestHeaders?: Record<string, string>at the per-request level. Expose a session-leveldefaultHeadersconfig in the@github/copilotSDK.X-Request-IdandX-GitHub-Request-IDfrom CAPI responses via events, so the extension can log/correlate them.Layer C — SDK-native OTel (long-term)
@github/copilotSDK itself should accept an OTelTracerProviderand create spans internally for each LLM call and tool execution.Key Files
src/extension/chatSessions/copilotcli/node/copilotCli.ts—CopilotCLISessionOptions.toSessionOptions(), where session config is builtsrc/extension/chatSessions/copilotcli/node/copilotcliSession.ts—handleRequest(), SDK event subscriptionssrc/extension/chatSessions/copilotcli/node/copilotcliSessionService.ts—createSession()src/platform/otel/common/otelService.ts—IOTelServiceinterface (startActiveSpan,storeTraceContext)Context
The copilotcli SDK (
@github/copilot) uses its own internal HTTP client that bypasses the extension'snetworkRequest()pipeline. The SDK'sSessionOptionstype has norequestHeadersfield, though per-requestClientOptionsandGetCompletionWithToolsOptionsdo supportrequestHeaders. The SDK'sCAPIRequestContexttype supportsinteractionType,agentTaskId,parentAgentTaskId,clientSessionId, andinteractionId.For the foreground agent OTel implementation (as reference), see: