mcpField
C
copilot-sdk

copilot-sdk

github.com/githubエージェントワークフロー40.5k9.4k 回インストール今日更新
リポジトリ

copilot-sdk について

GitHub Copilot SDKは、Python、TypeScript、Go、.NETからCopilotのエージェントランタイムをアプリに組み込むためのSDKです。カスタムツールやエージェント、セッション管理、ストリーミング、MCPサーバー接続に対応します。

主な機能

  1. 014言語からCopilotを組み込み
  2. 02セッション応答とイベントのストリーミング
  3. 03カスタムツールとエージェントの定義
  4. 04セッションの保存・再開・管理
  5. 05システムメッセージとツール権限の設定

活用シーン

  1. 01アプリ内に対話型AIアシスタントを構築
  2. 02エージェントにアプリ固有のツールを追加
  3. 03MCPサーバーの既成ツールを接続
  4. 04アプリ再起動後に会話を再開

MCP 対応

セッションからMCPサーバーに接続し、その既成ツールをCopilotのワークフローで利用できます。別途起動したCopilot CLIサーバーへの接続にも対応します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/github/awesome-copilot --skill copilot-sdk

インストール後、Claude Code で/copilot-sdkを入力して読み込まれたか確認します。

詳細

GitHub Copilot SDK

Python、TypeScript、Go、または .NET を使用して、あらゆるアプリケーションに Copilot のエージェント型ワークフローを組み込みます。

概要

GitHub Copilot SDK は、Copilot CLI の背後にあるものと同じエンジンを公開します。これは実運用でテスト済みのエージェントランタイムであり、プログラムから呼び出すことができます。独自のオーケストレーションを構築する必要はありません。エージェントの動作を定義すれば、Copilot がプランニング、ツールの呼び出し、ファイル編集などを処理します。

前提条件

  1. GitHub Copilot へのアクセスと、認証済みの環境
  2. 言語ランタイム: Node.js ^20.19.0 または >=22.12.0、Python 3.11 以降、Go 1.24 以降、または .NET Standard 2.0 互換の実装
  3. Go: GitHub Copilot CLI がインストールされ、認証済みであること(インストールガイド)

TypeScript、Python、.NET の各パッケージは、デフォルトで同梱の Copilot ランタイムを使用するため、別途 CLI をインストールする必要はありません。

インストール

Node.js/TypeScript
mkdir copilot-demo && cd copilot-demo
npm init -y --init-type module
npm install @github/copilot-sdk tsx
Python
pip install github-copilot-sdk

# Optional: pre-download the bundled runtime instead of downloading it on first use
python -m copilot download-runtime

公開されている Python の wheel には、固定されたランタイムバージョンが含まれています。事前ダウンロードコマンドはそのランタイムをローカルにキャッシュします。省略した場合、SDK は初回使用時に自動的にダウンロードを試みます。

Go
mkdir copilot-demo && cd copilot-demo
go mod init copilot-demo
go get github.com/github/copilot-sdk/go
.NET
dotnet new console -n CopilotDemo && cd CopilotDemo
dotnet add package GitHub.Copilot.SDK

クイックスタート

TypeScript
import { CopilotClient, approveAll } from "@github/copilot-sdk";

const client = new CopilotClient();
const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4.1",
});

const response = await session.sendAndWait({ prompt: "What is 2 + 2?" });
console.log(response?.data.content);

await client.stop();
process.exit(0);

実行: npx tsx index.ts

Python
import asyncio
from copilot import CopilotClient, PermissionHandler

async def main():
    async with CopilotClient() as client:
        async with await client.create_session(
            on_permission_request=PermissionHandler.approve_all,
            model="gpt-4.1",
        ) as session:
            response = await session.send_and_wait("What is 2 + 2?")
            print(response.data.content)

asyncio.run(main())
Go
package main

import (
    "fmt"
    "log"
    "os"
    copilot "github.com/github/copilot-sdk/go"
)

func main() {
    client := copilot.NewClient(nil)
    if err := client.Start(); err != nil {
        log.Fatal(err)
    }
    defer client.Stop()

    session, err := client.CreateSession(&copilot.SessionConfig{
        OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
        Model:               "gpt-4.1",
    })
    if err != nil {
        log.Fatal(err)
    }

    response, err := session.SendAndWait(copilot.MessageOptions{Prompt: "What is 2 + 2?"}, 0)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(*response.Data.Content)
    os.Exit(0)
}
.NET (C#)
using GitHub.Copilot.SDK;

await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
    OnPermissionRequest = PermissionHandler.ApproveAll,
    Model = "gpt-4.1",
});

var response = await session.SendAndWaitAsync(new MessageOptions { Prompt = "What is 2 + 2?" });
Console.WriteLine(response?.Data.Content);

実行: dotnet run

ストリーミングレスポンス

より良い UX のためにリアルタイム出力を有効にします:

TypeScript
import { CopilotClient, approveAll, SessionEvent } from "@github/copilot-sdk";

const client = new CopilotClient();
const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4.1",
    streaming: true,
});

session.on((event: SessionEvent) => {
    if (event.type === "assistant.message_delta") {
        process.stdout.write(event.data.deltaContent);
    }
    if (event.type === "session.idle") {
        console.log(); // New line when done
    }
});

await session.sendAndWait({ prompt: "Tell me a short joke" });

await client.stop();
process.exit(0);
Python
import asyncio
import sys
from copilot import CopilotClient, PermissionHandler
from copilot.generated.session_events import SessionEventType

async def main():
    async with CopilotClient() as client:
        async with await client.create_session(
            on_permission_request=PermissionHandler.approve_all,
            model="gpt-4.1",
            streaming=True,
        ) as session:
            def handle_event(event):
                if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
                    sys.stdout.write(event.data.delta_content)
                    sys.stdout.flush()
                if event.type == SessionEventType.SESSION_IDLE:
                    print()

            session.on(handle_event)
            await session.send_and_wait("Tell me a short joke")

asyncio.run(main())
Go
session, err := client.CreateSession(&copilot.SessionConfig{
	OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
    Model:     "gpt-4.1",
    Streaming: true,
})

session.On(func(event copilot.SessionEvent) {
    if event.Type == "assistant.message_delta" {
        fmt.Print(*event.Data.DeltaContent)
    }
    if event.Type == "session.idle" {
        fmt.Println()
    }
})

_, err = session.SendAndWait(copilot.MessageOptions{Prompt: "Tell me a short joke"}, 0)
.NET
await using var session = await client.CreateSessionAsync(new SessionConfig
{
    OnPermissionRequest = PermissionHandler.ApproveAll,
    Model = "gpt-4.1",
    Streaming = true,
});

session.On(ev =>
{
    if (ev is AssistantMessageDeltaEvent deltaEvent)
        Console.Write(deltaEvent.Data.DeltaContent);
    if (ev is SessionIdleEvent)
        Console.WriteLine();
});

await session.SendAndWaitAsync(new MessageOptions { Prompt = "Tell me a short joke" });

カスタムツール

Copilot が推論中に呼び出せるツールを定義します。ツールを定義すると、Copilot に次のことを伝えます:

  1. ツールが何をするか(説明)
  2. 必要なパラメータは何か(スキーマ)
  3. 実行するコードは何か(ハンドラー)
TypeScript (JSON Schema)
import { CopilotClient, approveAll, defineTool, SessionEvent } from "@github/copilot-sdk";

const getWeather = defineTool("get_weather", {
    description: "Get the current weather for a city",
    parameters: {
        type: "object",
        properties: {
            city: { type: "string", description: "The city name" },
        },
        required: ["city"],
    },
    handler: async (args: { city: string }) => {
        const { city } = args;
        // In a real app, call a weather API here
        const conditions = ["sunny", "cloudy", "rainy", "partly cloudy"];
        const temp = Math.floor(Math.random() * 30) + 50;
        const condition = conditions[Math.floor(Math.random() * conditions.length)];
        return { city, temperature: `${temp}°F`, condition };
    },
});

const client = new CopilotClient();
const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4.1",
    streaming: true,
    tools: [getWeather],
});

session.on((event: SessionEvent) => {
    if (event.type === "assistant.message_delta") {
        process.stdout.write(event.data.deltaContent);
    }
});

await session.sendAndWait({
    prompt: "What's the weather like in Seattle and Tokyo?",
});

await client.stop();
process.exit(0);
Python (Pydantic)
import asyncio
import random
import sys
from copilot import CopilotClient, PermissionHandler
from copilot.tools import define_tool
from copilot.generated.session_events import SessionEventType
from pydantic import BaseModel, Field

class GetWeatherParams(BaseModel):
    city: str = Field(description="The name of the city to get weather for")

@define_tool(description="Get the current weather for a city")
async def get_weather(params: GetWeatherParams) -> dict:
    city = params.city
    conditions = ["sunny", "cloudy", "rainy", "partly cloudy"]
    temp = random.randint(50, 80)
    condition = random.choice(conditions)
    return {"city": city, "temperature": f"{temp}°F", "condition": condition}

async def main():
    async with CopilotClient() as client:
        async with await client.create_session(
            on_permission_request=PermissionHandler.approve_all,
            model="gpt-4.1",
            streaming=True,
            tools=[get_weather],
        ) as session:
            def handle_event(event):
                if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
                    sys.stdout.write(event.data.delta_content)
                    sys.stdout.flush()

            session.on(handle_event)
            await session.send_and_wait(
                "What's the weather like in Seattle and Tokyo?"
            )

asyncio.run(main())
Go
type WeatherParams struct {
    City string `json:"city" jsonschema:"The city name"`
}

type WeatherResult struct {
    City        string `json:"city"`
    Temperature string `json:"temperature"`
    Condition   string `json:"condition"`
}

getWeather := copilot.DefineTool(
    "get_weather",
    "Get the current weather for a city",
    func(params WeatherParams, inv copilot.ToolInvocation) (WeatherResult, error) {
        conditions := []string{"sunny", "cloudy", "rainy", "partly cloudy"}
        temp := rand.Intn(30) + 50
        condition := conditions[rand.Intn(len(conditions))]
        return WeatherResult{
            City:        params.City,
            Temperature: fmt.Sprintf("%d°F", temp),
            Condition:   condition,
        }, nil
    },
)

session, _ := client.CreateSession(&copilot.SessionConfig{
	OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
    Model:     "gpt-4.1",
    Streaming: true,
    Tools:     []copilot.Tool{getWeather},
})
.NET (Microsoft.Extensions.AI)
using GitHub.Copilot.SDK;
using Microsoft.Extensions.AI;
using System.ComponentModel;

var getWeather = AIFunctionFactory.Create(
    ([Description("The city name")] string city) =>
    {
        var conditions = new[] { "sunny", "cloudy", "rainy", "partly cloudy" };
        var temp = Random.Shared.Next(50, 80);
        var condition = conditions[Random.Shared.Next(conditions.Length)];
        return new { city, temperature = $"{temp}°F", condition };
    },
    "get_weather",
    "Get the current weather for a city"
);

await using var session = await client.CreateSessionAsync(new SessionConfig
{
    OnPermissionRequest = PermissionHandler.ApproveAll,
    Model = "gpt-4.1",
    Streaming = true,
    Tools = [getWeather],
});

ツールの仕組み

Copilot があなたのツールを呼び出すと判断した場合:

  1. Copilot がパラメータを含むツール呼び出しリクエストを送信します
  2. SDK があなたのハンドラー関数を実行します
  3. 結果が Copilot に返送されます
  4. Copilot がその結果を自身のレスポンスに組み込みます

Copilot は、ユーザーの質問とあなたのツールの説明に基づいて、いつツールを呼び出すかを判断します。

インタラクティブ CLI アシスタント

完全なインタラクティブアシスタントを構築します:

TypeScript
import { CopilotClient, approveAll, defineTool, SessionEvent } from "@github/copilot-sdk";
import * as readline from "readline";

const getWeather = defineTool("get_weather", {
    description: "Get the current weather for a city",
    parameters: {
        type: "object",
        properties: {
            city: { type: "string", description: "The city name" },
        },
        required: ["city"],
    },
    handler: async ({ city }) => {
        const conditions = ["sunny", "cloudy", "rainy", "partly cloudy"];
        const temp = Math.floor(Math.random() * 30) + 50;
        const condition = conditions[Math.floor(Math.random() * conditions.length)];
        return { city, temperature: `${temp}°F`, condition };
    },
});

const client = new CopilotClient();
const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4.1",
    streaming: true,
    tools: [getWeather],
});

session.on((event: SessionEvent) => {
    if (event.type === "assistant.message_delta") {
        process.stdout.write(event.data.deltaContent);
    }
});

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});

console.log("Weather Assistant (type 'exit' to quit)");
console.log("Try: 'What's the weather in Paris?'\n");

const prompt = () => {
    rl.question("You: ", async (input) => {
        if (input.toLowerCase() === "exit") {
            await client.stop();
            rl.close();
            return;
        }

        process.stdout.write("Assistant: ");
        await session.sendAndWait({ prompt: input });
        console.log("\n");
        prompt();
    });
};

prompt();
Python
import asyncio
import random
import sys
from copilot import CopilotClient, PermissionHandler
from copilot.tools import define_tool
from copilot.generated.session_events import SessionEventType
from pydantic import BaseModel, Field

class GetWeatherParams(BaseModel):
    city: str = Field(description="The name of the city to get weather for")

@define_tool(description="Get the current weather for a city")
async def get_weather(params: GetWeatherParams) -> dict:
    conditions = ["sunny", "cloudy", "rainy", "partly cloudy"]
    temp = random.randint(50, 80)
    condition = random.choice(conditions)
    return {"city": params.city, "temperature": f"{temp}°F", "condition": condition}

async def main():
    async with CopilotClient() as client:
        async with await client.create_session(
            on_permission_request=PermissionHandler.approve_all,
            model="gpt-4.1",
            streaming=True,
            tools=[get_weather],
        ) as session:
            def handle_event(event):
                if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
                    sys.stdout.write(event.data.delta_content)
                    sys.stdout.flush()

            session.on(handle_event)

            print("Weather Assistant (type 'exit' to quit)")
            print("Try: 'What's the weather in Paris?'\n")

            while True:
                try:
                    user_input = input("You: ")
                except EOFError:
                    break

                if user_input.lower() == "exit":
                    break

                sys.stdout.write("Assistant: ")
                await session.send_and_wait(user_input)
                print("\n")

asyncio.run(main())

MCP サーバー統合

事前構築済みのツールのために MCP(Model Context Protocol)サーバーに接続します。リポジトリ、Issue、PR へのアクセスのために GitHub の MCP サーバーに接続します:

TypeScript
const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4.1",
    mcpServers: {
        github: {
            type: "http",
            url: "https://api.githubcopilot.com/mcp/",
        },
    },
});
Python
async with await client.create_session(
    on_permission_request=PermissionHandler.approve_all,
    model="gpt-4.1",
    mcp_servers={
        "github": {
            "type": "http",
            "url": "https://api.githubcopilot.com/mcp/",
        },
    },
) as session:
    ...
Go
session, _ := client.CreateSession(&copilot.SessionConfig{
	OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
    Model: "gpt-4.1",
    MCPServers: map[string]copilot.MCPServerConfig{
        "github": {
            "type": "http",
            "url": "https://api.githubcopilot.com/mcp/",
        },
    },
})
.NET
await using var session = await client.CreateSessionAsync(new SessionConfig
{
    OnPermissionRequest = PermissionHandler.ApproveAll,
    Model = "gpt-4.1",
    McpServers = new Dictionary<string, McpServerConfig>
    {
        ["github"] = new McpServerConfig
        {
            Type = "http",
            Url = "https://api.githubcopilot.com/mcp/",
        },
    },
});

カスタムエージェント

特定のタスク向けに特化した AI ペルソナを定義します:

TypeScript
const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4.1",
    customAgents: [{
        name: "pr-reviewer",
        displayName: "PR Reviewer",
        description: "Reviews pull requests for best practices",
        prompt: "You are an expert code reviewer. Focus on security, performance, and maintainability.",
    }],
});
Python
async with await client.create_session(
    on_permission_request=PermissionHandler.approve_all,
    model="gpt-4.1",
    custom_agents=[{
        "name": "pr-reviewer",
        "display_name": "PR Reviewer",
        "description": "Reviews pull requests for best practices",
        "prompt": "You are an expert code reviewer. Focus on security, performance, and maintainability.",
    }],
) as session:
    ...

システムメッセージ

AI の動作と個性をカスタマイズします:

TypeScript
const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4.1",
    systemMessage: {
        content: "You are a helpful assistant for our engineering team. Always be concise.",
    },
});
Python
async with await client.create_session(
    on_permission_request=PermissionHandler.approve_all,
    model="gpt-4.1",
    system_message={
        "content": "You are a helpful assistant for our engineering team. Always be concise.",
    },
) as session:
    ...

外部 CLI サーバー

CLI をサーバーモードで別途実行し、SDK をそれに接続します。デバッグ、リソースの共有、カスタム環境などに役立ちます。

CLI をサーバーモードで起動
copilot --server --port 4321
SDK を外部サーバーに接続
TypeScript
const client = new CopilotClient({
    cliUrl: "localhost:4321"
});

const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4.1",
});
Python
from copilot import CopilotClient, PermissionHandler, RuntimeConnection

async with CopilotClient(
    connection=RuntimeConnection.for_uri("localhost:4321")
) as client:
    async with await client.create_session(
        on_permission_request=PermissionHandler.approve_all,
        model="gpt-4.1",
    ) as session:
        ...
Go
client := copilot.NewClient(&copilot.ClientOptions{
    CLIUrl: "localhost:4321",
})

if err := client.Start(); err != nil {
    log.Fatal(err)
}

session, _ := client.CreateSession(&copilot.SessionConfig{
	OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
	Model:               "gpt-4.1",
})
.NET
using var client = new CopilotClient(new CopilotClientOptions
{
    CliUrl = "localhost:4321"
});

await using var session = await client.CreateSessionAsync(new SessionConfig
{
    OnPermissionRequest = PermissionHandler.ApproveAll,
    Model = "gpt-4.1",
});

注: 外部サーバーを使用するように構成した場合、SDK は自身の接続のみを管理し、外部プロセスは管理しません。

イベントタイプ

イベント説明
user.messageユーザー入力が追加されました
assistant.message完全なモデルレスポンス
assistant.message_deltaストリーミングレスポンスのチャンク
assistant.reasoningモデルの推論(モデル依存)
assistant.reasoning_deltaストリーミング推論のチャンク
tool.execution_startツールの呼び出しが開始されました
tool.execution_completeツールの実行が完了しました
session.idleアクティブな処理がありません
session.errorエラーが発生しました

クライアント設定

オプション説明デフォルト
cliPathCopilot CLI 実行ファイルへのパスシステム PATH
cliUrl既存のサーバーに接続 (例: "localhost:4321")なし
portサーバー通信ポートランダム
useStdioTCP の代わりに stdio トランスポートを使用true
logLevelログの詳細度"info"
autoStartサーバーを自動的に起動true
autoRestartクラッシュ時に再起動true
cwdCLI プロセスの作業ディレクトリ継承

セッション設定

オプション説明
model使用する LLM ("gpt-4.1"、"claude-sonnet-4.5" など)
sessionIdカスタムセッション識別子
toolsカスタムツール定義
mcpServersMCP サーバー接続
customAgentsカスタムエージェントペルソナ
systemMessageデフォルトのシステムプロンプトを上書き
streaming増分応答チャンクを有効化
availableTools許可されたツールのホワイトリスト
excludedTools無効化されたツールのブラックリスト

セッションの永続化

再起動をまたいで会話を保存および再開します:

カスタム ID で作成
const session = await client.createSession({
    onPermissionRequest: approveAll,
    sessionId: "user-123-conversation",
    model: "gpt-4.1"
});
セッションを再開
const session = await client.resumeSession("user-123-conversation", { onPermissionRequest: approveAll });
await session.send({ prompt: "What did we discuss earlier?" });
セッションの一覧表示と削除
const sessions = await client.listSessions();
await client.deleteSession("old-session-id");

エラー処理

try {
    const client = new CopilotClient();
    const session = await client.createSession({
        onPermissionRequest: approveAll,
        model: "gpt-4.1",
    });
    const response = await session.sendAndWait(
        { prompt: "Hello!" },
        30000 // timeout in ms
    );
} catch (error) {
    if (error.code === "ENOENT") {
        console.error("Copilot CLI not installed");
    } else if (error.code === "ECONNREFUSED") {
        console.error("Cannot connect to Copilot server");
    } else {
        console.error("Error:", error.message);
    }
} finally {
    await client.stop();
}

グレースフルシャットダウン

process.on("SIGINT", async () => {
    console.log("Shutting down...");
    await client.stop();
    process.exit(0);
});

一般的なパターン

マルチターン会話
const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4.1",
});

await session.sendAndWait({ prompt: "My name is Alice" });
await session.sendAndWait({ prompt: "What's my name?" });
// Response: "Your name is Alice"
ファイル添付
await session.send({
    prompt: "Analyze this file",
    attachments: [{
        type: "file",
        path: "./data.csv",
        displayName: "Sales Data"
    }]
});
長時間操作の中止
const timeoutId = setTimeout(() => {
    session.abort();
}, 60000);

session.on((event) => {
    if (event.type === "session.idle") {
        clearTimeout(timeoutId);
    }
});

利用可能なモデル

実行時に利用可能なモデルを照会します:

const models = await client.getModels();
// Returns: ["gpt-4.1", "gpt-4o", "claude-sonnet-4.5", ...]

ベストプラクティス

  1. 常にクリーンアップする: 言語ネイティブのコンテキストマネージャーやディスポーザルを使用するか、セッションを明示的に切断してクライアントを停止します
  2. タイムアウトを設定する: 長時間操作にはタイムアウト付きの sendAndWait を使用します
  3. イベントを処理する: 堅牢なエラー処理のためにエラーイベントを購読します
  4. ストリーミングを使用する: 長い応答での UX 向上のためにストリーミングを有効にします
  5. セッションを永続化する: マルチターン会話にはカスタムセッション ID を使用します
  6. 明確なツールを定義する: 説明的なツール名と説明を記述します

アーキテクチャ

Your Application
       |
  SDK Client
       | JSON-RPC
  Copilot CLI (server mode)
       |
  GitHub (models, auth)

SDK は CLI プロセスのライフサイクルを自動的に管理します。すべての通信は stdio または TCP を介した JSON-RPC で行われます。

リソース

ステータス

この SDK は テクニカルプレビュー であり、破壊的な変更が含まれる可能性があります。本番環境での使用はまだ推奨されません。

コメント