Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,119 @@ await using var session = await client.CreateSessionAsync(new()

---

## Telemetry & Observability

The Copilot SDK supports [OpenTelemetry](https://opentelemetry.io/) for distributed tracing. Provide a `telemetry` configuration to the client to enable trace export from the CLI process and automatic [W3C Trace Context](https://www.w3.org/TR/trace-context/) propagation between the SDK and CLI.

### Enabling Telemetry

Pass a `telemetry` (or `Telemetry`) config when creating the client. This is the opt-in — no separate "enabled" flag is needed.

<details open>
<summary><strong>Node.js / TypeScript</strong></summary>

<!-- docs-validate: skip -->
```typescript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient({
telemetry: {
otlpEndpoint: "http://localhost:4318",
},
});
```

Optional peer dependency: `@opentelemetry/api`

</details>

<details>
<summary><strong>Python</strong></summary>

<!-- docs-validate: skip -->
```python
from copilot import CopilotClient, SubprocessConfig

client = CopilotClient(SubprocessConfig(
telemetry={
"otlp_endpoint": "http://localhost:4318",
},
))
```

Install with telemetry extras: `pip install copilot-sdk[telemetry]` (provides `opentelemetry-api`)

</details>

<details>
<summary><strong>Go</strong></summary>

<!-- docs-validate: skip -->
```go
client, err := copilot.NewClient(copilot.ClientOptions{
Telemetry: &copilot.TelemetryConfig{
OTLPEndpoint: "http://localhost:4318",
},
})
```

Dependency: `go.opentelemetry.io/otel`

</details>

<details>
<summary><strong>.NET</strong></summary>

<!-- docs-validate: skip -->
```csharp
var client = new CopilotClient(new CopilotClientOptions
{
Telemetry = new TelemetryConfig
{
OtlpEndpoint = "http://localhost:4318",
},
});
```

No extra dependencies — uses built-in `System.Diagnostics.Activity`.

</details>

### TelemetryConfig Options

| Option | Node.js | Python | Go | .NET | Description |
|---|---|---|---|---|---|
| OTLP endpoint | `otlpEndpoint` | `otlp_endpoint` | `OTLPEndpoint` | `OtlpEndpoint` | OTLP HTTP endpoint URL |
| File path | `filePath` | `file_path` | `FilePath` | `FilePath` | File path for JSON-lines trace output |
| Exporter type | `exporterType` | `exporter_type` | `ExporterType` | `ExporterType` | `"otlp-http"` or `"file"` |
| Source name | `sourceName` | `source_name` | `SourceName` | `SourceName` | Instrumentation scope name |
| Capture content | `captureContent` | `capture_content` | `CaptureContent` | `CaptureContent` | Whether to capture message content |

### File Export

To write traces to a local file instead of an OTLP endpoint:

<!-- docs-validate: skip -->
```typescript
const client = new CopilotClient({
telemetry: {
filePath: "./traces.jsonl",
exporterType: "file",
},
});
```

### Trace Context Propagation

Trace context is propagated automatically — no manual instrumentation is needed:

- **SDK → CLI**: `traceparent` and `tracestate` headers from the current span/activity are included in `session.create`, `session.resume`, and `session.send` RPC calls.
- **CLI → SDK**: When the CLI invokes tool handlers, the trace context from the CLI's span is propagated so your tool code runs under the correct parent span.

📖 **[OpenTelemetry Instrumentation Guide →](./observability/opentelemetry.md)** — detailed GenAI semantic conventions, event-to-attribute mapping, and complete examples.

---

## Learn More

- [Authentication Guide](./auth/index.md) - GitHub OAuth, environment variables, and BYOK
Expand All @@ -1406,6 +1519,7 @@ await using var session = await client.CreateSessionAsync(new()
- [Using MCP Servers](./features/mcp.md) - Integrate external tools via Model Context Protocol
- [GitHub MCP Server Documentation](https://github.com/github/github-mcp-server)
- [MCP Servers Directory](https://github.com/modelcontextprotocol/servers) - Explore more MCP servers
- [OpenTelemetry Instrumentation](./observability/opentelemetry.md) - Add tracing to your SDK usage

---

Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Detailed API reference for each session hook.

### [Observability](./observability/opentelemetry.md)

- [OpenTelemetry Instrumentation](./observability/opentelemetry.md)add tracing to your SDK usage
- [OpenTelemetry Instrumentation](./observability/opentelemetry.md)built-in TelemetryConfig, trace context propagation, and application-level tracing

### [Integrations](./integrations/microsoft-agent-framework.md)

Expand Down
154 changes: 153 additions & 1 deletion docs/observability/opentelemetry.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,158 @@
# OpenTelemetry Instrumentation for Copilot SDK

This guide shows how to add OpenTelemetry tracing to your Copilot SDK applications using GenAI semantic conventions.
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:

<details open>
<summary><strong>Node.js / TypeScript</strong></summary>

<!-- docs-validate: skip -->
```typescript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient({
telemetry: {
otlpEndpoint: "http://localhost:4318",
},
});
```

</details>

<details>
<summary><strong>Python</strong></summary>

<!-- docs-validate: skip -->
```python
from copilot import CopilotClient, SubprocessConfig

client = CopilotClient(SubprocessConfig(
telemetry={
"otlp_endpoint": "http://localhost:4318",
},
))
```

</details>

<details>
<summary><strong>Go</strong></summary>

<!-- docs-validate: skip -->
```go
client, err := copilot.NewClient(copilot.ClientOptions{
Telemetry: &copilot.TelemetryConfig{
OTLPEndpoint: "http://localhost:4318",
},
})
```

</details>

<details>
<summary><strong>.NET</strong></summary>

<!-- docs-validate: skip -->
```csharp
var client = new CopilotClient(new CopilotClientOptions
{
Telemetry = new TelemetryConfig
{
OtlpEndpoint = "http://localhost:4318",
},
});
```

</details>

### TelemetryConfig Options

| Option | Node.js | Python | Go | .NET | Description |
|---|---|---|---|---|---|
| OTLP endpoint | `otlpEndpoint` | `otlp_endpoint` | `OTLPEndpoint` | `OtlpEndpoint` | OTLP HTTP endpoint URL |
| File path | `filePath` | `file_path` | `FilePath` | `FilePath` | File path for JSON-lines trace output |
| Exporter type | `exporterType` | `exporter_type` | `ExporterType` | `ExporterType` | `"otlp-http"` or `"file"` |
| Source name | `sourceName` | `source_name` | `SourceName` | `SourceName` | Instrumentation scope name |
| Capture content | `captureContent` | `capture_content` | `CaptureContent` | `CaptureContent` | 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:

<!-- docs-validate: skip -->
```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<string, string> = {};
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:

<!-- docs-validate: skip -->
```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` |

## Application-Level Instrumentation

The rest of this guide shows how to add your own OpenTelemetry spans around SDK operations using GenAI semantic conventions. This is complementary to the built-in `TelemetryConfig` above — you can use both together.

## Overview

Expand Down
27 changes: 27 additions & 0 deletions dotnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ new CopilotClient(CopilotClientOptions? options = null)
- `Logger` - `ILogger` instance for SDK logging
- `GitHubToken` - GitHub token for authentication. When provided, takes priority over other auth methods.
- `UseLoggedInUser` - Whether to use logged-in user for authentication (default: true, but false when `GitHubToken` is provided). Cannot be used with `CliUrl`.
- `Telemetry` - OpenTelemetry configuration for the CLI process. Providing this enables telemetry — no separate flag needed. See [Telemetry](#telemetry) below.

#### Methods

Expand Down Expand Up @@ -546,6 +547,32 @@ var session = await client.CreateSessionAsync(new SessionConfig
});
```

## Telemetry

The SDK supports OpenTelemetry for distributed tracing. Provide a `Telemetry` config to enable trace export and automatic W3C Trace Context propagation.

```csharp
var client = new CopilotClient(new CopilotClientOptions
{
Telemetry = new TelemetryConfig
{
OtlpEndpoint = "http://localhost:4318",
},
});
```

**TelemetryConfig properties:**

- `OtlpEndpoint` - OTLP HTTP endpoint URL
- `FilePath` - File path for JSON-lines trace output
- `ExporterType` - `"otlp-http"` or `"file"`
- `SourceName` - Instrumentation scope name
- `CaptureContent` - Whether to capture message content

Trace context (`traceparent`/`tracestate`) is automatically propagated between the SDK and CLI on `CreateSessionAsync`, `ResumeSessionAsync`, and `SendAsync` calls, and inbound when the CLI invokes tool handlers.

No extra dependencies — uses built-in `System.Diagnostics.Activity`.

## User Input Requests

Enable the agent to ask questions to the user using the `ask_user` tool by providing an `OnUserInputRequest` handler:
Expand Down
Loading
Loading