ビルドする内容:
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!
Prerequisites
開始する前に、以下の項目があることを確認します:
- 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 をインストールする
まず、新しいディレクトリを作成し、プロジェクトを初期化します。
mkdir copilot-demo && cd copilot-demo
npm init -y --init-type module
次に、SDK と TypeScript ランナーをインストールします。
npm install @github/copilot-sdk tsx
pip install github-copilot-sdk
まず、新しいディレクトリを作成し、モジュールを初期化します。
mkdir copilot-demo && cd copilot-demo
go mod init copilot-demo
次に、SDK をインストールします。
go get github.com/github/copilot-sdk/go
まず、新しいバイナリ クレートを作成します。
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
まず、新しいコンソール プロジェクトを作成します。
dotnet new console -n CopilotDemo && cd CopilotDemo
次に、SDK を追加します。
dotnet add package GitHub.Copilot.SDK
まず、新しいディレクトリを作成し、プロジェクトを初期化します。
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 行のコード) を使用する最も簡単な方法です。
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
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
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
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
新しいコンソール プロジェクトを作成し、これを 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
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: ストリーミング応答を追加する
現時点では、何かを表示する前に、完全な応答を待ちます。 生成された応答をストリーミングして対話型にしましょう。
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);
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())
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)
}
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(())
}
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" });
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 には、セッション イベントをサブスクライブするためのメソッドが用意されています。
| Method | Description |
|---|---|
on(handler) | すべてのイベントをサブスクライブする。unsubscribe 関数を返します |
on(eventType, handler) | 特定のイベントの種類 (Node.js/TypeScript のみ) をサブスクライブします。unsubscribe 関数を返します |
subscribe() | すべてのイベントを購読する (Rust); event_type で絞り込む |
// 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();
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()
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()
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}");
}
}
_ => {}
}
}
});
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();
// 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カスタム ツールを定義してコードを呼び出す機能を提供しましょう。 簡単な気象検索ツールを作成します。
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);
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())
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)
}
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(())
}
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?",
});
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: 対話型アシスタントを構築する
すべてを便利な対話型アシスタントにまとめてみましょう。
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
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
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
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
新しいコンソール プロジェクトを作成し、 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
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 に次のことを伝えていることになります:
- ツールの機能 (説明)
- 必要なパラメーター (スキーマ)
- 実行するコード (ハンドラー)
Copilotは、ユーザーの質問に基づいてツールを呼び出すタイミングを決定します。 その場合:
- Copilot はパラメーターを使用してツール呼び出し要求を送信します
- SDK によってハンドラー関数が実行されます
- 結果はCopilotに送り返されます
- Copilotは結果を応答に組み込みます
次は何ですか?
基本を理解したところで、さらに便利な機能をご紹介します:
MCP サーバーに接続する
MCP (モデル コンテキスト プロトコル) サーバーには、事前構築済みのツールが用意されています。 GitHubの MCP サーバーに接続して、リポジトリ、問題、プル要求にCopilotアクセスできるようにします。
const session = await client.createSession({
mcpServers: {
github: {
type: "http",
url: "https://api.githubcopilot.com/mcp/",
},
},
});
📖 ** Using MCP servers with the GitHub Copilot SDK** - ローカル サーバーとリモート サーバー、すべての構成オプション、トラブルシューティングについて説明します。
カスタム エージェントを作成する
特定のタスクに特化した AI ペルソナを定義します。
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" を設定して、最初からこのエージェントを事前に選択することもできます。 詳細については、 カスタム エージェントとサブエージェント オーケストレーション を参照してください。
システム メッセージをカスタマイズする
指示を追加することで、AI の動作と個性を制御します。
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.",
},
});
使用可能なセクション ID: identity、 tone、 tool_efficiency、 environment_context、 code_change_rules、 guidelines、 safety、 tool_instructions、 custom_instructions、 runtime_instructions、 last_instructions。
各オーバーライドでは、 replace、 remove、 append、 prependの 4 つのアクションがサポートされます。 不明なセクション ID は適切に処理されます。コンテンツは追加の命令に追加され、警告が出力されます。不明なセクションの remove は無視されます。
外部 CLI サーバーへの接続
既定では、COPILOT CLI プロセス ライフサイクルが SDK によって自動的に管理され、必要に応じて CLI が開始および停止されます。 ただし、サーバー モードで CLI を個別に実行し、SDK に接続することもできます。 これは、次の場合に役立ちます。
- デバッグ: SDK の再起動の間に CLI を実行したままにしてログを検査する
- リソース共有: 複数の SDK クライアントが同じ CLI サーバーに接続できる
- 開発: カスタム設定または別の環境で CLI を実行する
サーバー モードでの CLI の実行
--headless フラグを使用してサーバー モードで CLI を起動し、必要に応じてポートを指定します。
copilot --headless --port 4321
ポートを指定しない場合、CLI はランダムに使用可能なポートを選択します。
既定では、ヘッドレス サーバーはループバック (127.0.0.1) からの接続のみを受け入れるため、SDK は同じコンピューター上で実行する必要があります。 他のホスト (コンテナーまたは別のサーバーで CLI を実行する場合など) からの接続を受け入れるには、 --hostを使用して非ループバック アドレスにバインドします。
# Listen on all interfaces
copilot --headless --host 0.0.0.0 --port 4321
警告
非ループバック アドレスでヘッドレス サーバーを公開すると、そのアドレスにルーティングできるすべてのユーザーがヘッドレス サーバーに到達できるようになります。 ネットワーク制御 (ファイアウォール、プライベート ネットワーク、リバース プロキシ) と、環境に適した認証と組み合わせてください。
外部サーバーへの SDK の接続
CLI がサーバー モードで実行されたら、"cli url" オプションを使用してそれに接続するように SDK クライアントを構成します。
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 });
// ...
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)
# ...
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,
})
// ...
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?;
// ...
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
});
// ...
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/Go のUriConnectionが提供されている場合、または Rust がTransport::Externalを使用している場合、SDK は CLI プロセスを生成または管理しません。指定された URL にある既存のサーバーにのみ接続されます。
テレメトリと可観測性
Copilot SDK では、分散トレースの OpenTelemetry がサポートされています。 CLI プロセスからのトレース エクスポートと、SDK と CLI 間の telemetryの自動伝達を有効にする構成をクライアントに提供します。
テレメトリの有効化
クライアントの作成時に telemetry (または Telemetry) 構成を渡します。 これはオプトインです。個別の "有効" フラグは必要ありません。
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient({
telemetry: {
otlpEndpoint: "http://localhost:4318",
},
});
オプションのピア依存関係: @opentelemetry/api
from copilot import CopilotClient, CopilotClientOptions
client = CopilotClient(CopilotClientOptions(
telemetry={
"otlp_endpoint": "http://localhost:4318",
},
))
テレメトリの追加機能を使用してインストールする: pip install copilot-sdk[telemetry] ( opentelemetry-apiを提供)
client, err := copilot.NewClient(copilot.ClientOptions{
Telemetry: &copilot.TelemetryConfig{
OTLPEndpoint: "http://localhost:4318",
},
})
依存 関係: go.opentelemetry.io/otel
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 プロセス用のテレメトリ環境変数を挿入します。
var client = new CopilotClient(new CopilotClientOptions
{
Telemetry = new TelemetryConfig
{
OtlpEndpoint = "http://localhost:4318",
},
});
追加の依存関係はありません。組み込みの System.Diagnostics.Activityを使用します。
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.js | Python | Go | Rust | Java | .NET | Description |
|---|---|---|---|---|---|---|---|
| OTLP エンドポイント | otlpEndpoint | otlp_endpoint | OTLPEndpoint | otlp_endpoint | otlpEndpoint | OtlpEndpoint | OTLP HTTP エンドポイント URL |
| ファイルパス | filePath | file_path | FilePath | file_path | filePath | FilePath | JSON 行トレース出力のファイル パス |
| エクスポーターの種類 | exporterType | exporter_type | ExporterType | exporter_type | exporterType | ExporterType | |
"otlp-http" または "file" | |||||||
| 求人者名 | sourceName | source_name | SourceName | source_name | sourceName | SourceName | 計装範囲名 |
| コンテンツをキャプチャする | captureContent | capture_content | CaptureContent | capture_content | captureContent | CaptureContent | メッセージの内容をキャプチャするかどうか |
ファイルのエクスポート
OTLP エンドポイントの代わりにローカル ファイルにトレースを書き込むには、
const client = new CopilotClient({
telemetry: {
filePath: "./traces.jsonl",
exporterType: "file",
},
});
トレース コンテキストの伝達
トレース コンテキストは自動的に伝達されます。手動によるインストルメンテーションは必要ありません。
- SDK → CLI: 現在のスパン/アクティビティの
traceparentヘッダーとtracestateヘッダーは、session.create、session.resume、およびsession.sendRPC 呼び出しに含まれます。 - CLI → SDK: CLI がツール ハンドラーを呼び出すと、CLI のスパンからのトレース コンテキストが伝達され、ツール コードが正しい親スパンで実行されます。
📖 ** Copilot SDK 用の OpenTelemetry インストルメンテーション** - TelemetryConfig オプション、トレース コンテキスト伝達、および言語ごとの依存関係。
詳細情報
- 認証 - GitHub OAuth、環境変数、BYOK
- BYOK (bring your own key) - Azure AI Foundry、OpenAI などの独自の API キーを使用します。
- Node.js SDK リファレンス
- Python SDK リファレンス
- Go SDK リファレンス
- Rust SDK リファレンス
- .NET SDK リファレンス
- Java SDK リファレンス
- Using MCP servers with the GitHub Copilot SDK - モデル コンテキスト プロトコルを使用して外部ツールを統合する
- GitHub MCP サーバーのドキュメント
- MCP サーバー ディレクトリ - MCP サーバーの詳細を確認する
- Copilot SDK 用の OpenTelemetry インストルメンテーション - TelemetryConfig、トレース コンテキストの伝達、言語ごとの依存関係
それをやりました! GitHub Copilot SDK の主要な概念を学習しました。
- ✅ クライアントとセッションの作成
- ✅ メッセージの送信と応答の受信
- ✅ リアルタイム出力のためのストリーミング
- ✅ Copilot が呼び出せるカスタム ツールを定義する
今、素晴らしい何かを構築に行く! 🚀