Skip to main content

Python SDK for GitHub Copilot CLI

Project description

Copilot Python SDK

Python SDK for programmatic control of GitHub Copilot CLI via JSON-RPC.

Note: This SDK is in technical preview and may change in breaking ways.

Installation

pip install -e ".[dev]"
# or
uv pip install -e ".[dev]"

Quick Start

import asyncio
from copilot import CopilotClient

async def main():
    # Create and start client
    client = CopilotClient()
    await client.start()

    # Create a session
    session = await client.create_session({"model": "gpt-5"})

    # Wait for response using session.idle event
    done = asyncio.Event()

    def on_event(event):
        if event.type.value == "assistant.message":
            print(event.data.content)
        elif event.type.value == "session.idle":
            done.set()

    session.on(on_event)

    # Send a message and wait for completion
    await session.send({"prompt": "What is 2+2?"})
    await done.wait()

    # Clean up
    await session.destroy()
    await client.stop()

asyncio.run(main())

Features

  • ✅ Full JSON-RPC protocol support
  • ✅ stdio and TCP transports
  • ✅ Real-time streaming events
  • ✅ Session history with get_messages()
  • ✅ Type hints throughout
  • ✅ Async/await native

API Reference

CopilotClient

client = CopilotClient({
    "cli_path": "copilot",  # Optional: path to CLI executable
    "cli_url": None,        # Optional: URL of existing server (e.g., "localhost:8080")
    "log_level": "info",    # Optional: log level (default: "info")
    "auto_start": True,     # Optional: auto-start server (default: True)
    "auto_restart": True,   # Optional: auto-restart on crash (default: True)
})
await client.start()

session = await client.create_session({"model": "gpt-5"})

def on_event(event):
    print(f"Event: {event['type']}")

session.on(on_event)
await session.send({"prompt": "Hello!"})

# ... wait for events ...

await session.destroy()
await client.stop()

CopilotClient Options:

  • cli_path (str): Path to CLI executable (default: "copilot" or COPILOT_CLI_PATH env var)
  • cli_url (str): URL of existing CLI server (e.g., "localhost:8080", "http://127.0.0.1:9000", or just "8080"). When provided, the client will not spawn a CLI process.
  • cwd (str): Working directory for CLI process
  • port (int): Server port for TCP mode (default: 0 for random)
  • use_stdio (bool): Use stdio transport instead of TCP (default: True)
  • log_level (str): Log level (default: "info")
  • auto_start (bool): Auto-start server on first use (default: True)
  • auto_restart (bool): Auto-restart on crash (default: True)

Tools

Define tools with automatic JSON schema generation using the @define_tool decorator and Pydantic models:

from pydantic import BaseModel, Field
from copilot import CopilotClient, define_tool

class LookupIssueParams(BaseModel):
    id: str = Field(description="Issue identifier")

@define_tool(description="Fetch issue details from our tracker")
async def lookup_issue(params: LookupIssueParams) -> str:
    issue = await fetch_issue(params.id)
    return issue.summary

session = await client.create_session({
    "model": "gpt-5",
    "tools": [lookup_issue],
})

Note: When using from __future__ import annotations, define Pydantic models at module level (not inside functions).

Low-level API (without Pydantic):

For users who prefer manual schema definition:

from copilot import CopilotClient, Tool

async def lookup_issue(invocation):
    issue_id = invocation["arguments"]["id"]
    issue = await fetch_issue(issue_id)
    return {
        "textResultForLlm": issue.summary,
        "resultType": "success",
        "sessionLog": f"Fetched issue {issue_id}",
    }

session = await client.create_session({
    "model": "gpt-5",
    "tools": [
        Tool(
            name="lookup_issue",
            description="Fetch issue details from our tracker",
            parameters={
                "type": "object",
                "properties": {
                    "id": {"type": "string", "description": "Issue identifier"},
                },
                "required": ["id"],
            },
            handler=lookup_issue,
        )
    ],
})

The SDK automatically handles tool.call, executes your handler (sync or async), and responds with the final result when the tool completes.

Image Support

The SDK supports image attachments via the attachments parameter. You can attach images by providing their file path:

await session.send({
    "prompt": "What's in this image?",
    "attachments": [
        {
            "type": "file",
            "path": "/path/to/image.jpg",
        }
    ]
})

Supported image formats include JPG, PNG, GIF, and other common image types. The agent's view tool can also read images directly from the filesystem, so you can also ask questions like:

await session.send({"prompt": "What does the most recent jpg in this directory portray?"})

Streaming

Enable streaming to receive assistant response chunks as they're generated:

import asyncio
from copilot import CopilotClient

async def main():
    client = CopilotClient()
    await client.start()

    session = await client.create_session({
        "model": "gpt-5",
        "streaming": True
    })

    # Use asyncio.Event to wait for completion
    done = asyncio.Event()

    def on_event(event):
        if event.type.value == "assistant.message_delta":
            # Streaming message chunk - print incrementally
            delta = event.data.delta_content or ""
            print(delta, end="", flush=True)
        elif event.type.value == "assistant.reasoning_delta":
            # Streaming reasoning chunk (if model supports reasoning)
            delta = event.data.delta_content or ""
            print(delta, end="", flush=True)
        elif event.type.value == "assistant.message":
            # Final message - complete content
            print("\n--- Final message ---")
            print(event.data.content)
        elif event.type.value == "assistant.reasoning":
            # Final reasoning content (if model supports reasoning)
            print("--- Reasoning ---")
            print(event.data.content)
        elif event.type.value == "session.idle":
            # Session finished processing
            done.set()

    session.on(on_event)
    await session.send({"prompt": "Tell me a short story"})
    await done.wait()  # Wait for streaming to complete

    await session.destroy()
    await client.stop()

asyncio.run(main())

When streaming=True:

  • assistant.message_delta events are sent with delta_content containing incremental text
  • assistant.reasoning_delta events are sent with delta_content for reasoning/chain-of-thought (model-dependent)
  • Accumulate delta_content values to build the full response progressively
  • The final assistant.message and assistant.reasoning events contain the complete content

Note: assistant.message and assistant.reasoning (final events) are always sent regardless of streaming setting.

Requirements

  • Python 3.9+
  • GitHub Copilot CLI installed and accessible

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

github_copilot_sdk-0.1.17.tar.gz (79.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

github_copilot_sdk-0.1.17-py3-none-any.whl (32.7 kB view details)

Uploaded Python 3

File details

Details for the file github_copilot_sdk-0.1.17.tar.gz.

File metadata

  • Download URL: github_copilot_sdk-0.1.17.tar.gz
  • Upload date:
  • Size: 79.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for github_copilot_sdk-0.1.17.tar.gz
Algorithm Hash digest
SHA256 f401ee4fc84d1da290a7db86a53e3a72b8e8c70d38e24fda61a58b195d3cea48
MD5 56f4275ea45dc2c2e5853571b5b5acd3
BLAKE2b-256 81c7b5c9c1e5d1c6c84889fad3548abe264d876fbc6940001044790d4b9e1d61

See more details on using hashes here.

Provenance

The following attestation bundles were made for github_copilot_sdk-0.1.17.tar.gz:

Publisher: publish.yml on github/copilot-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file github_copilot_sdk-0.1.17-py3-none-any.whl.

File metadata

File hashes

Hashes for github_copilot_sdk-0.1.17-py3-none-any.whl
Algorithm Hash digest
SHA256 a3412db49cf2dc7100f90b24d555c68ecf70d2d01270aa11799181c974a21a8f
MD5 958757bc7a81ec5b7dfa21bca519846d
BLAKE2b-256 d273588631163b7d202d84aed56b0f626739646023216bd7e9370c51ea9cc190

See more details on using hashes here.

Provenance

The following attestation bundles were made for github_copilot_sdk-0.1.17-py3-none-any.whl:

Publisher: publish.yml on github/copilot-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page