# How to Use GitHub Copilot SDK with Python: Complete Implementation Guide

> Master the GitHub Copilot SDK with Python. This guide shows you how to programmatically interact with AI models using CopilotClient and CopilotSession for seamless integration.

- Repository: [GitHub/copilot-sdk](https://github.com/github/copilot-sdk)
- Tags: how-to-guide
- Published: 2026-06-06

---

**The GitHub Copilot SDK for Python provides an asynchronous wrapper around the Copilot CLI runtime, enabling you to programmatically interact with AI models through `CopilotClient` and `CopilotSession` objects using JSON-RPC communication.**

The `github/copilot-sdk` repository offers a thin, official Python interface that manages the Copilot CLI process lifecycle rather than embedding LLM logic directly. By using this SDK, developers can create AI-powered applications that leverage custom tool definitions, permission handling, and streaming responses. This article demonstrates how to use GitHub Copilot SDK with Python, covering everything from basic setup to advanced architectural patterns.

## Core Architecture

The SDK architecture rests on three fundamental abstractions that handle process management, protocol communication, and conversation state.

### CopilotClient: The Entry Point

Located in [`python/copilot/client.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/client.py), the `CopilotClient` class serves as the primary async context manager. It launches or connects to a Copilot CLI process and owns the JSON-RPC channel. The client handles connection setup, protocol version negotiation, and lifecycle management across different transport methods.

### CopilotSession: Conversation State

Each `CopilotSession` represents a single conversation thread with the model, created via `client.create_session()` in [`python/copilot/session.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/session.py). Sessions expose high-level methods including `send()` for prompts, `on()` for event handlers, and `ui.*` helpers for interactive dialogs. Internally, sessions map to RPC endpoints defined in [`python/copilot/generated/rpc.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/generated/rpc.py).

### RuntimeConnection: Transport Layer

The `RuntimeConnection` abstraction in [`python/copilot/client.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/client.py) (lines 98-119) supports three transport modes without requiring code changes elsewhere:

- **STDIO**: Spawns CLI as child process via stdin/stdout
- **TCP**: Connects via TCP sockets  
- **URI**: Attaches to an already-running server endpoint

### Data Flow

The SDK implements a strict request-response pipeline:

1. **CopilotClient** establishes the transport via `RuntimeConnection` factories (`for_stdio`, `for_tcp`, `for_uri`)
2. **JSON-RPC channel** ([`python/copilot/_jsonrpc.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/_jsonrpc.py)) handles non-blocking message serialization
3. **ServerRpc** ([`python/copilot/generated/rpc.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/generated/rpc.py)) maps to CLI protocol endpoints
4. **CopilotSession** dispatches events to user code through handlers

This architecture ensures the SDK remains thin—it forwards all requests to the CLI runtime without embedding model logic.

## Installation and Basic Setup

To begin using the GitHub Copilot SDK with Python, install the package from the repository and ensure the Copilot CLI is available in your environment.

```bash
pip install git+https://github.com/github/copilot-sdk.git#subdirectory=python

```

The SDK requires Python 3.8+ and an active GitHub Copilot CLI installation. All interactions are asynchronous, requiring `asyncio` for execution.

## Practical Implementation Patterns

### Pattern 1: Basic Async Usage

The most common pattern involves creating a client, spawning a session with auto-approved permissions, sending a prompt, and waiting for completion. This example uses `PermissionHandler.approve_all` to automatically authorize tool calls:

```python
import asyncio
from copilot import CopilotClient
from copilot.session import PermissionHandler

async def main():
    async with CopilotClient() as client:
        async with await client.create_session(
            on_permission_request=PermissionHandler.approve_all,
            model="gpt-4"
        ) as session:

            def on_event(ev):
                print(f"Event: {ev.type}")

            session.on(on_event)
            await session.send("What is the capital of France?")
            await session.wait_idle()

asyncio.run(main())

```

The `wait_idle()` helper blocks until the session receives `SessionIdleData`, indicating all processing—including tool execution—has completed.

### Pattern 2: Defining Custom Tools with Pydantic

Custom tools extend model capabilities by allowing the CLI to execute Python functions. Define tools using the `@define_tool` decorator from [`python/copilot/tools.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/tools.py), which automatically generates JSON schemas from Pydantic models:

```python
from pydantic import BaseModel, Field
from copilot import CopilotClient, define_tool
from copilot.session import PermissionHandler

class SearchParams(BaseModel):
    query: str = Field(description="Search query string")

@define_tool(description="Search documentation")
async def search_docs(params: SearchParams) -> str:
    # Implementation: query your documentation database

    return f"Results for: {params.query}"

async def main():
    async with CopilotClient() as client:
        async with await client.create_session(
            on_permission_request=PermissionHandler.approve_all,
            model="gpt-4",
            tools=[search_docs]
        ) as session:

            await session.send("Search for authentication methods")
            await session.wait_idle()

asyncio.run(main())

```

When the model requests a tool call, the SDK routes the `tool.call` RPC to your decorated function, handles schema validation via Pydantic, and returns results to the conversation.

### Pattern 3: Streaming Real-Time Responses

For interactive applications, enable streaming to receive token-by-token updates. Set `streaming=True` during session creation and handle `AssistantMessageDeltaData` events:

```python
import asyncio
from copilot import CopilotClient
from copilot.session import PermissionHandler
from copilot.session_events import (
    AssistantMessageDeltaData, AssistantMessageData, SessionIdleData
)

async def main():
    async with CopilotClient() as client:
        async with await client.create_session(
            on_permission_request=PermissionHandler.approve_all,
            model="gpt-4",
            streaming=True
        ) as session:

            complete = asyncio.Event()

            def handler(ev):
                match ev.data:
                    case AssistantMessageDeltaData() as d:
                        print(d.delta_content or "", end="", flush=True)
                    case AssistantMessageData() as m:
                        print("\n[Complete]")
                    case SessionIdleData():
                        complete.set()

            session.on(handler)
            await session.send("Explain quantum computing")
            await complete.wait()

asyncio.run(main())

```

The `streaming` flag instructs the CLI to emit `assistant.message_delta` events, which the SDK forwards as `AssistantMessageDeltaData` objects containing incremental content.

## Advanced Features and Configuration

### Permission Handling

The `PermissionHandler` class in [`python/copilot/session.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/session.py) controls tool execution authorization. Beyond `approve_all`, you can implement custom logic:

```python
def custom_permission_handler(request):
    if request.tool_name == "safe_tool":
        return True
    return False  # Denies by default

```

### UI Elicitation

Sessions expose `ui.confirm()`, `ui.select()`, and `ui.input()` methods that surface native Copilot-CLI dialogs when the runtime supports them, enabling interactive clarification without breaking the JSON-RPC flow.

### Telemetry and Tracing

The SDK supports OpenTelemetry via configuration in [`python/copilot/client.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/client.py) and [`python/copilot/_telemetry.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/_telemetry.py). Trace context propagates automatically across RPC boundaries when telemetry is enabled.

### Session Persistence

Configure `InfiniteSessionConfig` in [`python/copilot/session.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/session.py) for background token-window management and persistent workspace states, enabled by default for long-running applications.

## Key Source Files Reference

Understanding the SDK layout accelerates debugging and extension:

- **[`python/copilot/client.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/client.py)**: Main `CopilotClient` class, `RuntimeConnection` factories, telemetry initialization
- **[`python/copilot/session.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/session.py)**: `CopilotSession` implementation, permission handling, UI helpers, tool execution routing  
- **[`python/copilot/tools.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/tools.py)**: `@define_tool` decorator, low-level `Tool` class, schema generation
- **[`python/copilot/_jsonrpc.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/_jsonrpc.py)**: Async JSON-RPC client over stdin/stdout or TCP
- **[`python/copilot/generated/rpc.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/generated/rpc.py)**: Auto-generated RPC endpoint definitions matching CLI protocol
- **[`python/copilot/generated/session_events.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/generated/session_events.py)**: Event dataclasses (`AssistantMessageDeltaData`, `SessionIdleData`, etc.)

## Summary

- **The GitHub Copilot SDK for Python** wraps the Copilot CLI in an async interface using `CopilotClient` and JSON-RPC channels.
- **Sessions** manage conversation state through `CopilotSession` objects, supporting tools, permissions, and UI interactions.
- **Transport flexibility** allows STDIO, TCP, or URI connections without changing application code.
- **Custom tools** use the `@define_tool` decorator with Pydantic models for automatic schema generation.
- **Streaming responses** require `streaming=True` and handling `AssistantMessageDeltaData` events for real-time output.
- **All LLM logic** resides in the CLI runtime; the SDK acts as a thin, type-safe bridge.

## Frequently Asked Questions

### What Python version is required for the GitHub Copilot SDK?

The SDK requires Python 3.8 or higher due to its reliance on `async`/`await` syntax and modern type hints. All core functionality is implemented using asyncio patterns found in [`python/copilot/client.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/client.py).

### Can I use the SDK without installing the Copilot CLI separately?

No. The SDK in `github/copilot-sdk` is explicitly a thin wrapper that communicates via JSON-RPC with the Copilot CLI process. You must have the CLI binary installed and accessible in your system PATH, as the `CopilotClient` class spawns or connects to this runtime.

### How do I handle tool permissions programmatically?

Pass a handler function to `on_permission_request` when calling `client.create_session()` in [`python/copilot/session.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/session.py). Use `PermissionHandler.approve_all` for automation during development, or implement custom logic that inspects the request object to approve specific tools while rejecting others.

### Is streaming supported for all models?

Streaming support depends on the Copilot CLI runtime capabilities rather than the SDK itself. When `streaming=True` is passed to `create_session()`, the SDK forwards `assistant.message_delta` events from [`python/copilot/generated/session_events.py`](https://github.com/github/copilot-sdk/blob/main/python/copilot/generated/session_events.py) as they arrive, but the underlying model and CLI version must support streaming tokens.