Skip to main content

Создайте своё первое приложение на базе Copilot

В этом уроке вы будете использовать Copilot SDK для создания помощника командной строки. Вы начнёте с основ, добавляете потоковые ответы, затем добавляете пользовательские инструменты — давая Copilot возможность вызывать ваш код.

Что вы создадите:

You: What's the weather like in Seattle?
Copilot: Let me check the weather for Seattle...
         Currently 62°F and cloudy with a chance of rain.
         Typical Seattle weather!

You: How about Tokyo?
Copilot: In Tokyo it's 75°F and sunny. Great day to be outside!

Необходимые условия

Прежде чем начать, убедитесь, что у вас есть:

  • GitHub Copilot CLI установлен и аутентифицирован (Руководство по установке)
  • Ваш предпочтительный языковой режим выполнения:
    • Node.js 20+ или Python 3.11+ или Go 1.24+ или Rust 1.94+ или Java 17+ или .NET 8.0+

Убедитесь, что CLI работает:

copilot --version

Шаг 1: установка SDK

TypeScript

Сначала создайте новый каталог и инициализуйте проект:

mkdir copilot-demo && cd copilot-demo
npm init -y --init-type module

Затем установите SDK и TypeScript runner:

npm install @github/copilot-sdk tsx
Python
pip install github-copilot-sdk
Go

Во-первых, создайте новую директорию и инициализуйте модуль:

mkdir copilot-demo && cd copilot-demo
go mod init copilot-demo

Затем установите SDK:

go get github.com/github/copilot-sdk/go
Rust

Сначала создайте новый двоичный ящик:

cargo new copilot-demo && cd copilot-demo

Затем установите SDK и прямые зависимости, используемые в примерах:

cargo add github-copilot-sdk --features derive
# Used by #[tokio::main] and tokio::spawn
cargo add tokio --features rt-multi-thread,macros
# Used by custom-tool parameter derives later in this guide
cargo add serde --features derive
cargo add schemars
.NET

Во-первых, создайте новый консольный проект:

dotnet new console -n CopilotDemo && cd CopilotDemo

Затем добавьте SDK:

dotnet add package GitHub.Copilot.SDK
Java

Сначала создайте новый каталог и инициализуйте свой проект.

Maven — добавьте к вашему pom.xml:

<dependency>
    <groupId>com.github</groupId>
    <artifactId>copilot-sdk-java</artifactId>
    <version>${copilot.sdk.version}</version>
</dependency>

Gradle — добавьте к вашему build.gradle:

implementation 'com.github:copilot-sdk-java:${copilotSdkVersion}'

Шаг 2: отправьте первое сообщение

Создайте новый файл и добавьте следующий код. Это самый простой способ использовать SDK — около 5 строк кода.

TypeScript

Создайте index.ts:

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

const client = new CopilotClient();
const session = await client.createSession({ 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

Создайте main.py:

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

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

    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-4.1")
    response = await session.send_and_wait("What is 2 + 2?")
    print(response.data.content)

    await client.stop()

asyncio.run(main())

Запустите его:

python main.py
Go

Создайте main.go:

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    copilot "github.com/github/copilot-sdk/go"
)

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

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

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

    if d, ok := response.Data.(*copilot.AssistantMessageData); ok {
        fmt.Println(d.Content)
    }
    os.Exit(0)
}

Запустите его:

go run main.go
Rust

Создайте src/main.rs:

use std::sync::Arc;
use std::time::Duration;

use github_copilot_sdk::handler::ApproveAllHandler;
use github_copilot_sdk::{Client, ClientOptions, MessageOptions, SessionConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::start(ClientOptions::default()).await?;
    let session = client
        .create_session(SessionConfig::default().with_handler(Arc::new(ApproveAllHandler)))
        .await?;

    let response = session
        .send_and_wait(
            MessageOptions::new("What is 2 + 2?").with_wait_timeout(Duration::from_secs(120)),
        )
        .await?;

    if let Some(event) = response {
        if let Some(content) = event.data.get("content").and_then(|value| value.as_str()) {
            println!("{content}");
        }
    }

    session.disconnect().await?;
    client.stop().await?;
    Ok(())
}

Запустите его:

cargo run
.NET

Создайте новый консольный проект и добавьте его в Program.cs:

using GitHub.Copilot;

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

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

Запустите его:

dotnet run
Java

Создайте HelloCopilot.java:

import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;

public class HelloCopilot {
    public static void main(String[] args) throws Exception {
        try (var client = new CopilotClient()) {
            client.start().get();

            var session = client.createSession(
                new SessionConfig()
                    .setModel("gpt-4.1")
                    .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
            ).get();

            var response = session.sendAndWait(
                new MessageOptions().setPrompt("What is 2 + 2?")
            ).get();

            System.out.println(response.getData().content());

            client.stop().get();
        }
    }
}

Запустите его:

javac -cp copilot-sdk.jar HelloCopilot.java && java -cp .:copilot-sdk.jar HelloCopilot

Вам стоит увидеть:

4

Поздравляем! Вы только что создали своё первое приложение на базе Copilot.

Шаг 3: добавляйте ответы на поток

Сейчас вы ждёте полного ответа, прежде чем что-либо увидеть. Давайте сделаем это интерактивным, транслируя ответы по мере их генерации.

TypeScript

Обновление index.ts:

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

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

// Listen for response chunks
session.on("assistant.message_delta", (event) => {
    process.stdout.write(event.data.deltaContent);
});
session.on("session.idle", () => {
    console.log(); // New line when done
});

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

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

Обновление main.py:

import asyncio
import sys
from copilot import CopilotClient
from copilot.session import PermissionHandler
from copilot.generated.session_events import SessionEventType

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

    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-4.1", streaming=True)

    # Listen for response chunks
    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()  # New line when done

    session.on(handle_event)

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

    await client.stop()

asyncio.run(main())
Go

Обновление main.go:

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    copilot "github.com/github/copilot-sdk/go"
)

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

    session, err := client.CreateSession(ctx, &copilot.SessionConfig{
        Model:     "gpt-4.1",
        Streaming: copilot.Bool(true),
    })
    if err != nil {
        log.Fatal(err)
    }

    // Listen for response chunks
    session.On(func(event copilot.SessionEvent) {
        switch d := event.Data.(type) {
        case *copilot.AssistantMessageDeltaData:
            fmt.Print(d.DeltaContent)
        case *copilot.SessionIdleData:
            _ = d
            fmt.Println()
        }
    })

    _, err = session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Tell me a short joke"})
    if err != nil {
        log.Fatal(err)
    }
    os.Exit(0)
}
Rust

Обновление src/main.rs:

use std::io::{self, Write};
use std::sync::Arc;
use std::time::Duration;

use github_copilot_sdk::handler::ApproveAllHandler;
use github_copilot_sdk::{Client, ClientOptions, MessageOptions, SessionConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::start(ClientOptions::default()).await?;

    let mut config = SessionConfig::default();
    config.streaming = Some(true);
    let session = client
        .create_session(config.with_handler(Arc::new(ApproveAllHandler)))
        .await?;

    // Listen for response chunks
    let mut events = session.subscribe();
    tokio::spawn(async move {
        while let Ok(event) = events.recv().await {
            match event.event_type.as_str() {
                "assistant.message_delta" => {
                    if let Some(text) =
                        event.data.get("deltaContent").and_then(|value| value.as_str())
                    {
                        print!("{text}");
                        io::stdout().flush().ok();
                    }
                }
                "assistant.message" => println!(),
                _ => {}
            }
        }
    });

    session
        .send_and_wait(
            MessageOptions::new("Tell me a short joke")
                .with_wait_timeout(Duration::from_secs(120)),
        )
        .await?;

    session.disconnect().await?;
    client.stop().await?;
    Ok(())
}
.NET

Обновление Program.cs:

using GitHub.Copilot;

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

// Listen for response chunks
session.On<SessionEvent>(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" });
Java

Обновление HelloCopilot.java:

import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;

public class HelloCopilot {
    public static void main(String[] args) throws Exception {
        try (var client = new CopilotClient()) {
            client.start().get();

            var session = client.createSession(
                new SessionConfig()
                    .setModel("gpt-4.1")
                    .setStreaming(true)
                    .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
            ).get();

            // Listen for response chunks
            session.on(AssistantMessageDeltaEvent.class, delta -> {
                System.out.print(delta.getData().deltaContent());
            });
            session.on(SessionIdleEvent.class, idle -> {
                System.out.println(); // New line when done
            });

            session.sendAndWait(
                new MessageOptions().setPrompt("Tell me a short joke")
            ).get();

            client.stop().get();
        }
    }
}

Запусти код ещё раз. Вы увидите, как ответ будет появляться слово за словом.

Методы подписки на события

SDK предоставляет методы подписки на события сессии:

МетодDescription
on(handler)Подписывайтесь на все события; Возвращает функцию отписки
on(eventType, handler)Оформите подписку на конкретный тип события (Node.js/TypeScript); Возвращает функцию отписки
subscribe()Подписывайтесь на все события (Rust); Фильтр по event_type
TypeScript
// Subscribe to all events
const unsubscribeAll = session.on((event) => {
    console.log("Event:", event.type);
});

// Subscribe to specific event type
const unsubscribeIdle = session.on("session.idle", (event) => {
    console.log("Session is idle");
});

// Later, to unsubscribe:
unsubscribeAll();
unsubscribeIdle();
Python
from copilot import CopilotClient, PermissionDecisionApproveOnce
from copilot.generated.session_events import SessionEvent, SessionEventType

client = CopilotClient()

session = await client.create_session(on_permission_request=lambda req, inv: PermissionDecisionApproveOnce())

# Subscribe to all events
unsubscribe = session.on(lambda event: print(f"Event: {event.type}"))

# Filter by event type in your handler
def handle_event(event: SessionEvent) -> None:
    if event.type == SessionEventType.SESSION_IDLE:
        print("Session is idle")
    elif event.type == SessionEventType.ASSISTANT_MESSAGE:
        print(f"Message: {event.data.content}")

unsubscribe = session.on(handle_event)

# Later, to unsubscribe:
unsubscribe()
# Subscribe to all events
unsubscribe = session.on(lambda event: print(f"Event: {event.type}"))

# Filter by event type in your handler
def handle_event(event):
    if event.type == SessionEventType.SESSION_IDLE:
        print("Session is idle")
    elif event.type == SessionEventType.ASSISTANT_MESSAGE:
        print(f"Message: {event.data.content}")

unsubscribe = session.on(handle_event)

# Later, to unsubscribe:
unsubscribe()
Go
package main

import (
    "fmt"

    copilot "github.com/github/copilot-sdk/go"
)

func main() {
    session := &copilot.Session{}

    // Subscribe to all events
    unsubscribe := session.On(func(event copilot.SessionEvent) {
        fmt.Println("Event:", event.Type)
    })

    // Filter by event type in your handler
    session.On(func(event copilot.SessionEvent) {
        switch d := event.Data.(type) {
        case *copilot.SessionIdleData:
            _ = d
            fmt.Println("Session is idle")
        case *copilot.AssistantMessageData:
            fmt.Println("Message:", d.Content)
        }
    })

    // Later, to unsubscribe:
    unsubscribe()
}
// Subscribe to all events
unsubscribe := session.On(func(event copilot.SessionEvent) {
    fmt.Println("Event:", event.Type)
})

// Filter by event type in your handler
session.On(func(event copilot.SessionEvent) {
    switch d := event.Data.(type) {
    case *copilot.SessionIdleData:
        _ = d
        fmt.Println("Session is idle")
    case *copilot.AssistantMessageData:
        fmt.Println("Message:", d.Content)
    }
})

// Later, to unsubscribe:
unsubscribe()
Rust
let mut events = session.subscribe();

tokio::spawn(async move {
    while let Ok(event) = events.recv().await {
        println!("Event: {}", event.event_type);

        match event.event_type.as_str() {
            "session.idle" => println!("Session is idle"),
            "assistant.message" => {
                if let Some(content) = event.data.get("content").and_then(|value| value.as_str()) {
                    println!("Message: {content}");
                }
            }
            _ => {}
        }
    }
});
.NET
using GitHub.Copilot;

public static class EventSubscriptionExample
{
    public static void Example(CopilotSession session)
    {
        // Subscribe to all events
        var unsubscribe = session.On<SessionEvent>(ev => Console.WriteLine($"Event: {ev.Type}"));

        // Filter by event type using pattern matching
        session.On<SessionEvent>(ev =>
        {
            switch (ev)
            {
                case SessionIdleEvent:
                    Console.WriteLine("Session is idle");
                    break;
                case AssistantMessageEvent msg:
                    Console.WriteLine($"Message: {msg.Data.Content}");
                    break;
            }
        });

        // Later, to unsubscribe:
        unsubscribe.Dispose();
    }
}
// Subscribe to all events
var unsubscribe = session.On<SessionEvent>(ev => Console.WriteLine($"Event: {ev.Type}"));

// Filter by event type using pattern matching
session.On<SessionEvent>(ev =>
{
    switch (ev)
    {
        case SessionIdleEvent:
            Console.WriteLine("Session is idle");
            break;
        case AssistantMessageEvent msg:
            Console.WriteLine($"Message: {msg.Data.Content}");
            break;
    }
});

// Later, to unsubscribe:
unsubscribe.Dispose();
Java
// Subscribe to all events
var unsubscribe = session.on(event -> {
    System.out.println("Event: " + event.getType());
});

// Subscribe to a specific event type
session.on(AssistantMessageEvent.class, msg -> {
    System.out.println("Message: " + msg.getData().content());
});

session.on(SessionIdleEvent.class, idle -> {
    System.out.println("Session is idle");
});

// Later, to unsubscribe:
unsubscribe.close();

Шаг 4: добавить кастомный инструмент

А теперь о сильной части. Давайте дадим Copilot возможность вызывать ваш код, определив кастомный инструмент. Мы создадим простой инструмент для поиска погоды.

TypeScript

Обновление index.ts:

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

// Define a tool that Copilot can call
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, you'd 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({
    model: "gpt-4.1",
    streaming: true,
    tools: [getWeather],
});

session.on("assistant.message_delta", (event) => {
    process.stdout.write(event.data.deltaContent);
});

session.on("session.idle", () => {
    console.log(); // New line when done
});

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

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

Обновление main.py:

import asyncio
import random
import sys
from copilot import CopilotClient
from copilot.session import PermissionHandler
from copilot.tools import define_tool
from copilot.generated.session_events import SessionEventType
from pydantic import BaseModel, Field

# Define the parameters for the tool using Pydantic
class GetWeatherParams(BaseModel):
    city: str = Field(description="The name of the city to get weather for")

# Define a tool that Copilot can call
@define_tool(description="Get the current weather for a city")
async def get_weather(params: GetWeatherParams) -> dict:
    city = params.city
    # In a real app, you'd call a weather API here
    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():
    client = CopilotClient()
    await client.start()

    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-4.1", streaming=True, tools=[get_weather])

    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("What's the weather like in Seattle and Tokyo?")

    await client.stop()

asyncio.run(main())
Go

Обновление main.go:

package main

import (
    "context"
    "fmt"
    "log"
    "math/rand"
    "os"

    copilot "github.com/github/copilot-sdk/go"
)

// Define the parameter type
type WeatherParams struct {
    City string `json:"city" jsonschema:"The city name"`
}

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

func main() {
    ctx := context.Background()

    // Define a tool that Copilot can call
    getWeather := copilot.DefineTool(
        "get_weather",
        "Get the current weather for a city",
        func(params WeatherParams, inv copilot.ToolInvocation) (WeatherResult, error) {
            // In a real app, you'd call a weather API here
            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
        },
    )

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

    session, err := client.CreateSession(ctx, &copilot.SessionConfig{
        Model:     "gpt-4.1",
        Streaming: copilot.Bool(true),
        Tools:     []copilot.Tool{getWeather},
    })
    if err != nil {
        log.Fatal(err)
    }

    session.On(func(event copilot.SessionEvent) {
        switch d := event.Data.(type) {
        case *copilot.AssistantMessageDeltaData:
            fmt.Print(d.DeltaContent)
        case *copilot.SessionIdleData:
            _ = d
            fmt.Println()
        }
    })

    _, err = session.SendAndWait(ctx, copilot.MessageOptions{
        Prompt: "What's the weather like in Seattle and Tokyo?",
    })
    if err != nil {
        log.Fatal(err)
    }
    os.Exit(0)
}
Rust

Обновление src/main.rs:

use std::io::{self, Write};
use std::sync::Arc;
use std::time::Duration;

use github_copilot_sdk::handler::ApproveAllHandler;
use github_copilot_sdk::tool::{JsonSchema, ToolHandlerRouter, define_tool};
use github_copilot_sdk::{Client, ClientOptions, MessageOptions, SessionConfig, ToolResult};
use serde::Deserialize;

#[derive(Deserialize, JsonSchema)]
struct GetWeatherParams {
    city: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Define a tool that Copilot can call
    let router = ToolHandlerRouter::new(
        vec![define_tool(
            "get_weather",
            "Get the current weather for a city",
            |_inv, params: GetWeatherParams| async move {
                Ok(ToolResult::Text(format!(
                    "{}: 62°F and sunny",
                    params.city
                )))
            },
        )],
        Arc::new(ApproveAllHandler),
    );
    let tools = router.tools();

    let client = Client::start(ClientOptions::default()).await?;

    let mut config = SessionConfig::default();
    config.streaming = Some(true);
    config.tools = Some(tools);
    let session = client.create_session(config.with_handler(Arc::new(router))).await?;

    let mut events = session.subscribe();
    tokio::spawn(async move {
        while let Ok(event) = events.recv().await {
            match event.event_type.as_str() {
                "assistant.message_delta" => {
                    if let Some(text) =
                        event.data.get("deltaContent").and_then(|value| value.as_str())
                    {
                        print!("{text}");
                        io::stdout().flush().ok();
                    }
                }
                "assistant.message" => println!(),
                _ => {}
            }
        }
    });

    session
        .send_and_wait(
            MessageOptions::new("What's the weather like in Seattle and Tokyo?")
                .with_wait_timeout(Duration::from_secs(120)),
        )
        .await?;

    session.disconnect().await?;
    client.stop().await?;
    Ok(())
}
.NET

Обновление Program.cs:

using GitHub.Copilot;
using Microsoft.Extensions.AI;
using System.ComponentModel;

await using var client = new CopilotClient();

// Define a tool that Copilot can call
var getWeather = CopilotTool.DefineTool(
    ([Description("The city name")] string city) =>
    {
        // In a real app, you'd call a weather API here
        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 };
    },
    factoryOptions: new AIFunctionFactoryOptions
    {
        Name = "get_weather",
        Description = "Get the current weather for a city",
    }
);

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

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

await session.SendAndWaitAsync(new MessageOptions
{
    Prompt = "What's the weather like in Seattle and Tokyo?",
});
Java

Обновление HelloCopilot.java:

import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;

public class HelloCopilot {
    public static void main(String[] args) throws Exception {
        var random = new Random();
        var conditions = List.of("sunny", "cloudy", "rainy", "partly cloudy");

        // Define a tool that Copilot can call
        var getWeather = ToolDefinition.create(
            "get_weather",
            "Get the current weather for a city",
            Map.of(
                "type", "object",
                "properties", Map.of(
                    "city", Map.of("type", "string", "description", "The city name")
                ),
                "required", List.of("city")
            ),
            invocation -> {
                var city = (String) invocation.getArguments().get("city");
                var temp = random.nextInt(30) + 50;
                var condition = conditions.get(random.nextInt(conditions.size()));
                return CompletableFuture.completedFuture(Map.of(
                    "city", city,
                    "temperature", temp + "°F",
                    "condition", condition
                ));
            }
        );

        try (var client = new CopilotClient()) {
            client.start().get();

            var session = client.createSession(
                new SessionConfig()
                    .setModel("gpt-4.1")
                    .setStreaming(true)
                    .setTools(List.of(getWeather))
                    .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
            ).get();

            session.on(AssistantMessageDeltaEvent.class, delta -> {
                System.out.print(delta.getData().deltaContent());
            });
            session.on(SessionIdleEvent.class, idle -> {
                System.out.println();
            });

            session.sendAndWait(
                new MessageOptions().setPrompt("What's the weather like in Seattle and Tokyo?")
            ).get();

            client.stop().get();
        }
    }
}

Запустите его, и вы увидите, как Copilot позвонит в ваш инструмент для получения погодных данных, а затем ответит с результатами!

Шаг 5: создайте интерактивного помощника

Давайте объединим всё это в полезного интерактивного помощника:

TypeScript
import { CopilotClient, defineTool } 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({
    model: "gpt-4.1",
    streaming: true,
    tools: [getWeather],
});

session.on("assistant.message_delta", (event) => {
    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();

Проведите с:

npx tsx weather-assistant.ts
Python

Создайте weather_assistant.py:

import asyncio
import random
import sys
from copilot import CopilotClient
from copilot.session import 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():
    client = CopilotClient()
    await client.start()

    session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-4.1", streaming=True, tools=[get_weather])

    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?' or 'Compare weather in NYC and LA'\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")

    await client.stop()

asyncio.run(main())

Проведите с:

python weather_assistant.py
Go

Создайте weather-assistant.go:

package main

import (
    "bufio"
    "context"
    "fmt"
    "log"
    "math/rand"
    "os"
    "strings"

    copilot "github.com/github/copilot-sdk/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"`
}

func main() {
    ctx := context.Background()

    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
        },
    )

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

    session, err := client.CreateSession(ctx, &copilot.SessionConfig{
        Model:     "gpt-4.1",
        Streaming: copilot.Bool(true),
        Tools:     []copilot.Tool{getWeather},
    })
    if err != nil {
        log.Fatal(err)
    }

    session.On(func(event copilot.SessionEvent) {
        switch d := event.Data.(type) {
        case *copilot.AssistantMessageDeltaData:
            fmt.Print(d.DeltaContent)
        case *copilot.SessionIdleData:
            _ = d
            fmt.Println()
        }
    })

    fmt.Println("🌤️  Weather Assistant (type 'exit' to quit)")
    fmt.Println("   Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\n")

    scanner := bufio.NewScanner(os.Stdin)
    for {
        fmt.Print("You: ")
        if !scanner.Scan() {
            break
        }
        input := scanner.Text()
        if strings.ToLower(input) == "exit" {
            break
        }

        fmt.Print("Assistant: ")
        _, err = session.SendAndWait(ctx, copilot.MessageOptions{Prompt: input})
        if err != nil {
            fmt.Fprintf(os.Stderr, "Error: %v\n", err)
            break
        }
        fmt.Println()
    }
    if err := scanner.Err(); err != nil {
        fmt.Fprintf(os.Stderr, "Input error: %v\n", err)
    }
}

Проведите с:

go run weather-assistant.go
Rust

Создайте src/main.rs:

use std::io::{self, BufRead, Write};
use std::sync::Arc;
use std::time::Duration;

use github_copilot_sdk::handler::ApproveAllHandler;
use github_copilot_sdk::tool::{JsonSchema, ToolHandlerRouter, define_tool};
use github_copilot_sdk::{Client, ClientOptions, MessageOptions, SessionConfig, ToolResult};
use serde::Deserialize;

#[derive(Deserialize, JsonSchema)]
struct GetWeatherParams {
    city: String,
}

fn read_line() -> Option<String> {
    let stdin = io::stdin();
    let mut line = String::new();
    stdin.lock().read_line(&mut line).ok()?;
    if line.is_empty() {
        return None;
    }
    Some(line.trim_end_matches(&['\n', '\r'][..]).to_string())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let router = ToolHandlerRouter::new(
        vec![define_tool(
            "get_weather",
            "Get the current weather for a city",
            |_inv, params: GetWeatherParams| async move {
                Ok(ToolResult::Text(format!(
                    "{}: 62°F and sunny",
                    params.city
                )))
            },
        )],
        Arc::new(ApproveAllHandler),
    );
    let tools = router.tools();

    let client = Client::start(ClientOptions::default()).await?;

    let mut config = SessionConfig::default();
    config.streaming = Some(true);
    config.tools = Some(tools);
    let session = client.create_session(config.with_handler(Arc::new(router))).await?;

    let mut events = session.subscribe();
    tokio::spawn(async move {
        while let Ok(event) = events.recv().await {
            match event.event_type.as_str() {
                "assistant.message_delta" => {
                    if let Some(text) =
                        event.data.get("deltaContent").and_then(|value| value.as_str())
                    {
                        print!("{text}");
                        io::stdout().flush().ok();
                    }
                }
                "assistant.message" => println!(),
                _ => {}
            }
        }
    });

    println!("Weather Assistant (type 'exit' to quit)");
    println!("Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\n");

    loop {
        print!("You: ");
        io::stdout().flush().ok();

        let Some(input) = read_line() else { break };
        if input.eq_ignore_ascii_case("exit") {
            break;
        }

        print!("Assistant: ");
        io::stdout().flush().ok();
        session
            .send_and_wait(MessageOptions::new(input).with_wait_timeout(Duration::from_secs(120)))
            .await?;
        println!();
    }

    session.disconnect().await?;
    client.stop().await?;
    Ok(())
}

Проведите с:

cargo run
.NET

Создайте новый консольный проект и обновите Program.csего:

using GitHub.Copilot;
using Microsoft.Extensions.AI;
using System.ComponentModel;

// Define the weather tool
var getWeather = CopilotTool.DefineTool(
    ([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 };
    },
    factoryOptions: new AIFunctionFactoryOptions
    {
        Name = "get_weather",
        Description = "Get the current weather for a city",
    });

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

// Listen for response chunks
session.On<SessionEvent>(ev =>
{
    if (ev is AssistantMessageDeltaEvent deltaEvent)
    {
        Console.Write(deltaEvent.Data.DeltaContent);
    }
    if (ev is SessionIdleEvent)
    {
        Console.WriteLine();
    }
});

Console.WriteLine("🌤️  Weather Assistant (type 'exit' to quit)");
Console.WriteLine("   Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\n");

while (true)
{
    Console.Write("You: ");
    var input = Console.ReadLine();

    if (string.IsNullOrEmpty(input) || input.Equals("exit", StringComparison.OrdinalIgnoreCase))
    {
        break;
    }

    Console.Write("Assistant: ");
    await session.SendAndWaitAsync(new MessageOptions { Prompt = input });
    Console.WriteLine("\n");
}

Проведите с:

dotnet run
Java

Создайте WeatherAssistant.java:

import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;

public class WeatherAssistant {
    public static void main(String[] args) throws Exception {
        var random = new Random();
        var conditions = List.of("sunny", "cloudy", "rainy", "partly cloudy");

        var getWeather = ToolDefinition.create(
            "get_weather",
            "Get the current weather for a city",
            Map.of(
                "type", "object",
                "properties", Map.of(
                    "city", Map.of("type", "string", "description", "The city name")
                ),
                "required", List.of("city")
            ),
            invocation -> {
                var city = (String) invocation.getArguments().get("city");
                var temp = random.nextInt(30) + 50;
                var condition = conditions.get(random.nextInt(conditions.size()));
                return CompletableFuture.completedFuture(Map.of(
                    "city", city,
                    "temperature", temp + "°F",
                    "condition", condition
                ));
            }
        );

        try (var client = new CopilotClient()) {
            client.start().get();

            var session = client.createSession(
                new SessionConfig()
                    .setModel("gpt-4.1")
                    .setStreaming(true)
                    .setOnPermissionRequest(request ->
                        CompletableFuture.completedFuture(PermissionDecision.allow())
                    )
                    .setTools(List.of(getWeather))
            ).get();

            session.on(AssistantMessageDeltaEvent.class, delta -> {
                System.out.print(delta.getData().deltaContent());
            });
            session.on(SessionIdleEvent.class, idle -> {
                System.out.println();
            });

            System.out.println("🌤️  Weather Assistant (type 'exit' to quit)");
            System.out.println("   Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'\n");

            var scanner = new Scanner(System.in);
            while (true) {
                System.out.print("You: ");
                if (!scanner.hasNextLine()) break;
                var input = scanner.nextLine();
                if (input.equalsIgnoreCase("exit")) break;

                System.out.print("Assistant: ");
                session.sendAndWait(
                    new MessageOptions().setPrompt(input)
                ).get();
                System.out.println("\n");
            }

            client.stop().get();
        }
    }
}

Проведите с:

javac -cp copilot-sdk.jar WeatherAssistant.java && java -cp .:copilot-sdk.jar WeatherAssistant

Пример сеанса:

🌤️  Weather Assistant (type 'exit' to quit)
   Try: 'What's the weather in Paris?' or 'Compare weather in NYC and LA'

You: What's the weather in Seattle?
Assistant: Let me check the weather for Seattle...
It's currently 62°F and cloudy in Seattle.

You: How about Tokyo and London?
Assistant: I'll check both cities for you:
- Tokyo: 75°F and sunny
- London: 58°F and rainy

You: exit

Вы создали ассистента с помощью кастомного инструмента, который Copilot может вызвать!

Как работают средства

Когда вы определяете инструмент, вы говорите Copilot:

  1. Что делает инструмент (описание)
  2. Какие параметры нужны (схема)
  3. Какой код запускать (обработчик)

Copilot решает, когда вызвать ваш инструмент, исходя из вопроса пользователя. Когда это происходит:

  1. Copilot отправляет запрос на вызов инструмента с параметрами
  2. SDK запускает функцию обработчика
  3. Результат отправляется обратно в Copilot
  4. Copilot включает результат в свой ответ

Что дальше?

Теперь, когда у вас есть основы, вот более мощные возможности для изучения:

Подключение к серверам MCP

Серверы MCP (Model Context Protocol) предоставляют готовые инструменты. Подключитесь к MCP-серверу GitHub, чтобы дать Copilot доступ к репозиториям, проблемам и pull requests:

const session = await client.createSession({
    mcpServers: {
        github: {
            type: "http",
            url: "https://api.githubcopilot.com/mcp/",
        },
    },
});

📖 ** Using MCP servers with the GitHub Copilot SDK** — Узнайте о локальных и удалённых серверах, всех настройках и решении неполадок.

Создание настраиваемых агентов

Определите специализированные ИИ-персоны для конкретных задач:

const session = await client.createSession({
    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.",
    }],
});

Совет

Вы также можете настроить agent: "pr-reviewer" в конфигурации сессии предвыбор этого агента с самого начала. Подробности смотрите в АВТОЗАГОЛОВКЕ .

Настройка системного сообщения

Контролируйте поведение и личность ИИ, добавляя инструкции:

const session = await client.createSession({
    systemMessage: {
        content: "You are a helpful assistant for our engineering team. Always be concise.",
    },
});

Для более тонкого управления используйте mode: "customize" переобозначение отдельных разделов системного запроса, сохраняя остальные:

const session = await client.createSession({
    systemMessage: {
        mode: "customize",
        sections: {
            tone: { action: "replace", content: "Respond in a warm, professional tone. Be thorough in explanations." },
            code_change_rules: { action: "remove" },
            guidelines: { action: "append", content: "\n* Always cite data sources" },
        },
        content: "Focus on financial analysis and reporting.",
    },
});

Доступные идентификаторы разделов: identity, tone, tool_efficiency, environment_context, code_change_rules, , guidelines, tool_instructions``last_instructions``safety``custom_instructions``runtime_instructions.

Каждое переопределение поддерживает четыре действия: replace, remove, appendи prepend. Неизвестные идентификаторы разделов обрабатываются изящно — к дополнительным инструкциям добавляется содержимое и появляется предупреждение; remove на неизвестных участках молча игнорируется.

См. языковые READMEs SDK для примеров в TypeScript, Python, Go, Rust, Java и C#.

Подключение к внешнему CLI-серверу

По умолчанию SDK автоматически управляет жизненным циклом процесса Copilot CLI, запуская и останавливая CLI по мере необходимости. Однако можно отдельно запустить CLI в серверном режиме и подключить к нему SDK. Это может быть полезно для:

  • Отладка: Оставляйте CLI включённым между перезагрузками SDK для проверки логов
  • Совместное использование ресурсов: несколько SDK-клиентов могут подключаться к одному и тому же CLI-серверу
  • Разработка: запускайте CLI с пользовательскими настройками или в другой среде

Запуск CLI в серверном режиме

Запустите CLI в серверном режиме с помощью --headless флага и, по желанию, укажите порт:

copilot --headless --port 4321

Если вы не указываете порт, CLI выберет случайный доступный порт.

По умолчанию безголовый сервер принимает соединения только через loopback (127.0.0.1), поэтому SDK должен работать на той же машине. Чтобы принять соединения от других хостов (например, при запуске CLI в контейнере или на отдельном сервере), привяжьте к адресу без обратной связи с --host:

# Listen on all interfaces
copilot --headless --host 0.0.0.0 --port 4321

Предупреждение

Открытие безголового сервера на не-лупбэк-адресе делает его доступным для любого, кто может маршрутизироваться по этому адресу. Сочетайте его с сетевыми контролями (файрвол, частная сеть, обратный прокси) и аутентификацией, подходящей для вашей среды.

Подключение SDK к внешнему серверу

Когда CLI заработает в серверном режиме, настройте SDK-клиент для подключения к нему через опцию «cli url»:

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

const client = new CopilotClient({
    cliUrl: "localhost:4321"
});

// Use the client normally
const session = await client.createSession({ onPermissionRequest: approveAll });
// ...
Python
from copilot import CopilotClient, RuntimeConnection
from copilot.session import PermissionHandler

client = CopilotClient(connection=RuntimeConnection.for_uri("localhost:4321"))
await client.start()

# Use the client normally
session = await client.create_session(on_permission_request=PermissionHandler.approve_all)
# ...
Go
package main

import (
    "context"
    "log"

    copilot "github.com/github/copilot-sdk/go"
)

func main() {
    ctx := context.Background()

    client := copilot.NewClient(&copilot.ClientOptions{
        Connection: copilot.UriConnection{URL: "localhost:4321"},
    })

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

    // Use the client normally
    _, _ = client.CreateSession(ctx, &copilot.SessionConfig{
        OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
    })
}
import copilot "github.com/github/copilot-sdk/go"

client := copilot.NewClient(&copilot.ClientOptions{
    Connection: copilot.UriConnection{URL: "localhost:4321"},
})

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

// Use the client normally
session, err := client.CreateSession(ctx, &copilot.SessionConfig{
    OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
})
// ...
Rust
use std::sync::Arc;

use github_copilot_sdk::handler::ApproveAllHandler;
use github_copilot_sdk::{Client, ClientOptions, SessionConfig, Transport};

let mut options = ClientOptions::default();
options.transport = Transport::External {
    host: "localhost".to_string(),
    port: 4321,
};
let client = Client::start(options).await?;

// Use the client normally
let session = client
    .create_session(SessionConfig::default().with_handler(Arc::new(ApproveAllHandler)))
    .await?;
// ...
.NET
using GitHub.Copilot;

using var client = new CopilotClient(new CopilotClientOptions
{
    Connection = RuntimeConnection.ForUri("localhost:4321"),
});

// Use the client normally
await using var session = await client.CreateSessionAsync(new()
{
    OnPermissionRequest = PermissionHandler.ApproveAll
});
// ...
Java
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.json.*;

var client = new CopilotClient(
    new CopilotClientOptions().setCliUrl("localhost:4321")
);
client.start().get();

// Use the client normally
var session = client.createSession(
    new SessionConfig().setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();
// ...

Примечание: Когда cli_url / cliUrl предоставляется UriConnection / Go, или использует Rust Transport::External, SDK не создаёт и не управляет CLI-процессом — он подключается только к существующему серверу по указанному URL.

Телеметрия и наблюдаемость

SDK Copilot поддерживает OpenTelemetry для распределённого трассировки. Предоставить клиенту telemetry конфигурацию для включения экспорта трасс из процесса CLI и автоматического распространения контекста W3C Trace между SDK и CLI.

Включение телеметрии

Передайте конфигурацию telemetry (или Telemetry) при создании клиента. Это опция для включения — отдельный флаг «включено» не требуется.

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

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

Опциональная зависимость от пиров: @opentelemetry/api

Python
from copilot import CopilotClient, CopilotClientOptions

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

Установка с дополнительными элементами телеметрии: pip install copilot-sdk[telemetry] (предоставляет opentelemetry-api)

Go
client, err := copilot.NewClient(copilot.ClientOptions{
    Telemetry: &copilot.TelemetryConfig{
        OTLPEndpoint: "http://localhost:4318",
    },
})

Зависимость: go.opentelemetry.io/otel

Rust
use github_copilot_sdk::{Client, ClientOptions, OtelExporterType, TelemetryConfig};

let mut options = ClientOptions::default();
options.telemetry = Some(
    TelemetryConfig::new()
        .with_exporter_type(OtelExporterType::OtlpHttp)
        .with_otlp_endpoint("http://localhost:4318"),
);
let client = Client::start(options).await?;

Никаких дополнительных зависимостей — SDK вводит переменные среды телеметрии для сгенерированного CLI-процесса.

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

Нет дополнительных зависимостей — использует встроенные System.Diagnostics.Activity.

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")));

Зависимость: io.opentelemetry:opentelemetry-api

Опции TelemetryConfig

ОпцияNode.jsPythonGoRustJava.NETDescription
Конечная точка OTLPotlpEndpointotlp_endpointOTLPEndpointotlp_endpointotlpEndpointOtlpEndpointURL конечной точки OTLP HTTP
Путь к файлуfilePathfile_pathFilePathfile_pathfilePathFilePathПуть файла для вывода JSON-lines trace
Тип экспортераexporterTypeexporter_typeExporterTypeexporter_typeexporterTypeExporterType
"otlp-http" или "file"
Имя источникаsourceNamesource_nameSourceNamesource_namesourceNameSourceNameНазвание области приборов
Захват контентаcaptureContentcapture_contentCaptureContentcapture_contentcaptureContentCaptureContentНужно ли фиксировать содержимое сообщений

Экспорт файлов

Чтобы записать трассы в локальный файл вместо конечной точки OTLP:

const client = new CopilotClient({
  telemetry: {
    filePath: "./traces.jsonl",
    exporterType: "file",
  },
});

Распространение контекста следов

Trace context распространяется автоматически — не требуется ручное инструментирование:

  • SDK → CLI: traceparent и tracestate заголовки текущего диапазона/активности включены в session.create, session.resumeи session.send RPC-вызовы.
  • CLI → SDK: Когда CLI вызывает обработчики инструментов, контекст трассировки из span-а CLI распространяется, чтобы ваш инструмент работал под правильным родительским span.

📖 ** Инструментация OpenTelemetry для Copilot SDK**—Опции TelemetryConfig, распространение контекста трассировки и зависимости по языкам.

Узнать больше

Ты сделал это! Вы изучили основные концепции SDK GitHub Copilot:

  • ✅ Создание клиента и сессии
  • ✅ Отправка сообщений и получение ответов
  • ✅ Стриминг для выхода в реальном времени
  • ✅ Определение пользовательских инструментов, которые Copilot может вызывать

А теперь иди и построй что-то потрясающее! 🚀