# OpenTelemetry instrumentation for Copilot SDK
This guide shows how to add OpenTelemetry tracing to your Copilot SDK applications.
## Built-in telemetry support
The SDK has built-in support for configuring OpenTelemetry on the CLI process and propagating W3C Trace Context between the SDK and CLI. Provide a `TelemetryConfig` when creating the client to opt in:
Node.js / TypeScript
```typescript
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient({
telemetry: {
otlpEndpoint: "http://localhost:4318",
},
});
```
Python
```python
from copilot import CopilotClient
client = CopilotClient(
telemetry={
"otlp_endpoint": "http://localhost:4318",
},
)
```
Go
```go
client, err := copilot.NewClient(copilot.ClientOptions{
Telemetry: &copilot.TelemetryConfig{
OTLPEndpoint: "http://localhost:4318",
},
})
```
.NET
```csharp
var client = new CopilotClient(new CopilotClientOptions
{
Telemetry = new TelemetryConfig
{
OtlpEndpoint = "http://localhost:4318",
},
});
```
Java
```java
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.json.*;
var client = new CopilotClient(new CopilotClientOptions()
.setTelemetry(new TelemetryConfig()
.setOtlpEndpoint("http://localhost:4318"))
);
```
Rust
```rust
use github_copilot_sdk::{Client, ClientOptions, TelemetryConfig};
let client = Client::start(ClientOptions::new()
.with_telemetry(TelemetryConfig::new()
.with_otlp_endpoint("http://localhost:4318"))
).await?;
```
### TelemetryConfig options
| Option | Node.js | Python | Go | .NET | Java | Rust | Description |
|---|---|---|---|---|---|---|---|
| OTLP endpoint | `otlpEndpoint` | `otlp_endpoint` | `OTLPEndpoint` | `OtlpEndpoint` | `otlpEndpoint` | `otlp_endpoint` | OTLP HTTP endpoint URL |
| File path | `filePath` | `file_path` | `FilePath` | `FilePath` | `filePath` | `file_path` | File path for JSON-lines trace output |
| Exporter type | `exporterType` | `exporter_type` | `ExporterType` | `ExporterType` | `exporterType` | `exporter_type` | `"otlp-http"` or `"file"` |
| Source name | `sourceName` | `source_name` | `SourceName` | `SourceName` | `sourceName` | `source_name` | Instrumentation scope name |
| Capture content | `captureContent` | `capture_content` | `CaptureContent` | `CaptureContent` | `captureContent` | `capture_content` | Whether to capture message content |
### Trace context propagation
> **Most users don't need this.** The `TelemetryConfig` above is all you need to collect traces from the CLI. The trace context propagation described in this section is an **advanced feature** for applications that create their own OpenTelemetry spans and want them to appear in the **same distributed trace** as the CLI's spans.
The SDK can propagate W3C Trace Context (`traceparent`/`tracestate`) on JSON-RPC payloads so that your application's spans and the CLI's spans are linked in one distributed trace. This is useful when, for example, you want to see a "handle tool call" span in your app nested inside the CLI's "execute tool" span, or show the SDK call as a child of your request-handling span.
#### SDK → CLI (outbound)
For **Node.js**, provide an `onGetTraceContext` callback on the client options. This is only needed if your application already uses `@opentelemetry/api` and you want to link your spans with the CLI's spans. The SDK calls this callback before `session.create`, `session.resume`, and `session.send` RPCs:
```typescript
import { CopilotClient } from "@github/copilot-sdk";
import { propagation, context } from "@opentelemetry/api";
const client = new CopilotClient({
telemetry: { otlpEndpoint: "http://localhost:4318" },
onGetTraceContext: () => {
const carrier: Record = {};
propagation.inject(context.active(), carrier);
return carrier; // { traceparent: "00-...", tracestate: "..." }
},
});
```
For **Python**, **Go**, and **.NET**, trace context injection is automatic when the respective OpenTelemetry/Activity API is configured—no callback is needed.
#### CLI → SDK (inbound)
When the CLI invokes a tool handler, the `traceparent` and `tracestate` from the CLI's span are available in all languages:
* **Go**: The `ToolInvocation.TraceContext` field is a `context.Context` with the trace already restored—use it directly as the parent for your spans.
* **Python**: Trace context is automatically restored around the handler via `trace_context()`—child spans are parented to the CLI's span automatically.
* **.NET**: Trace context is automatically restored via `RestoreTraceContext()`—child `Activity` instances are parented to the CLI's span automatically.
* **Node.js**: Since the SDK has no OpenTelemetry dependency, `traceparent` and `tracestate` are passed as raw strings on the `ToolInvocation` object. Restore the context manually if needed:
```typescript
import { propagation, context, trace } from "@opentelemetry/api";
session.registerTool(myTool, async (args, invocation) => {
// Restore the CLI's trace context as the active context
const carrier = {
traceparent: invocation.traceparent,
tracestate: invocation.tracestate,
};
const parentCtx = propagation.extract(context.active(), carrier);
// Create a child span under the CLI's span
const tracer = trace.getTracer("my-app");
return context.with(parentCtx, () =>
tracer.startActiveSpan("my-tool", async (span) => {
try {
const result = await doWork(args);
return result;
} finally {
span.end();
}
})
);
});
```
### Per-language dependencies
| Language | Dependency | Notes |
|---|---|---|
| Node.js |—| No dependency; provide `onGetTraceContext` callback for outbound propagation |
| Python | `opentelemetry-api` | Install with `pip install copilot-sdk[telemetry]` |
| Go | `go.opentelemetry.io/otel` | Required dependency |
| .NET |—| Uses built-in `System.Diagnostics.Activity` |
| Java | `io.opentelemetry:opentelemetry-api` | Add this dependency for SDK-based setup; trace context injection is automatic when the OpenTelemetry Java agent or SDK is configured |
## References
* [OpenTelemetry GenAI Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/)
* [OpenTelemetry MCP Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/mcp/)
* [OpenTelemetry Python SDK](https://opentelemetry.io/docs/instrumentation/python/)
* [Copilot SDK Documentation](https://github.com/github/copilot-sdk)