チュートリアル 1: CLI チャットボット
サブコマンド: tutorial chat-bot
ソース: src/go/cmd/tutorial/chatbot.go
学べること
copilot.Clientを作成して起動する方法- システムメッセージとパーミッションハンドラを備えたセッションを作成する方法
- 単一のプロンプトを送信してレスポンスを受信する方法
AssistantMessageDeltaDataによるストリーミングトークンの受信方法Ctrl+Cでクリーンに終了するインタラクティブなチャットループの実行方法
前提条件
ステップ 1 — クライアントの作成と起動
copilot.Client がメインのエントリポイントです。デフォルトでは copilot バイナリをサブプロセスとして起動し、stdio 経由で通信します。すでに TCP モードで稼働中の Copilot CLI がある場合のみ Connection を渡します。
import (
"context"
copilot "github.com/github/copilot-sdk/go"
)
// デフォルト: SDK が CLI を stdio 経由で起動
client := copilot.NewClient(nil)
// オプション: 稼働中の CLI サーバーに接続(TCP モード)
// client := copilot.NewClient(&copilot.ClientOptions{
// Connection: copilot.URIConnection{URL: "localhost:3000"},
// })
if err := client.Start(ctx); err != nil {
return fmt.Errorf("failed to start Copilot client: %w", err)
}
defer func() { _ = client.Stop() }()
注意:
client.Start(ctx)は JSON-RPC 接続を確立します。セッションを作成する前に呼び出し、client.Stop()(ここではdefer)と対にしてサブプロセスを解放します。
ステップ 2 — セッションの設定
CreateSession は、1 つの会話に関するすべてをまとめた *copilot.SessionConfig を受け取ります。
session, err := client.CreateSession(ctx, &copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
Streaming: copilot.Bool(true),
SystemMessage: &copilot.SystemMessageConfig{Content: "You are a helpful assistant."},
})
if err != nil {
return fmt.Errorf("failed to create session: %w", err)
}
主なフィールド:
| フィールド | 説明 |
|---|---|
OnPermissionRequest |
各ツール実行前に呼び出される。copilot.PermissionHandler.ApproveAll はすべての要求を承認する |
Streaming |
copilot.Bool(true) でトークンを逐次受信。省略(または false)で完全なレスポンスを待機する |
SystemMessage |
&copilot.SystemMessageConfig{Content: ...} でアシスタントのペルソナを設定する |
ステップ 3 — セッションイベントの処理
セッションイベントは session.On(handler) で配信されます。Go SDK は各イベントのペイロードを event.Data として渡し、型スイッチで判別します。ここでストリーミング出力とエラーを受け取ります。
session.On(func(event copilot.SessionEvent) {
switch data := event.Data.(type) {
case *copilot.AssistantMessageDeltaData:
fmt.Print(data.DeltaContent)
case *copilot.SessionErrorData:
fmt.Fprintf(os.Stderr, "\n[Error] %s\n", data.Message)
}
})
主なイベントペイロード型:
| 型 | 発火するタイミング |
|---|---|
*copilot.AssistantMessageDeltaData |
ストリーミングトークンが届いたとき |
*copilot.AssistantMessageData |
アシスタントメッセージ全体が揃ったとき |
*copilot.SessionErrorData |
エラーが発生したとき |
ステップ 4 — プロンプトの送信
reply, err := session.SendPromptAndWait(ctx, prompt)
if err != nil {
return err
}
var content string
if reply != nil {
if data, ok := reply.Data.(*copilot.AssistantMessageData); ok {
content = data.Content
}
}
SendPromptAndWait はセッションがアイドルになるまでブロックします。その間、ストリーミングデルタは session.On で登録したハンドラに配信されます。返却される reply はメッセージ全体を Data フィールドに保持します。
ステップ 5 — インタラクティブなチャットループ
複数ターンの会話では、セッションを生かしたまま SendPromptAndWait をループで呼び出します。Ctrl+C(コンテキストのキャンセル)でブロッキング読み取りを中断できるよう、標準入力は goroutine から読み取ります。
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
lines := make(chan string)
go func() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
lines <- scanner.Text()
}
close(lines)
}()
for {
fmt.Print("You: ")
select {
case <-ctx.Done():
return nil
case line, ok := <-lines:
if !ok {
return nil // 標準入力の EOF
}
userInput := strings.TrimSpace(line)
if userInput == "" {
continue
}
fmt.Print("Copilot: ")
if _, err := session.SendPromptAndWait(ctx, userInput); err != nil {
return err
}
fmt.Println()
}
}
サブコマンドの実行
まず CLI をビルドし、src/go ディレクトリから chat-bot サブコマンドを実行します。
cd src/go
make build
# 単一プロンプト
./dist/template-github-copilot-go tutorial chat-bot --prompt "Explain goroutines in Go"
# インタラクティブループ(Ctrl+C または EOF で終了)
./dist/template-github-copilot-go tutorial chat-bot --loop
# カスタム CLI サーバー URL(任意 — CLI サーバーが TCP モードで稼働中の場合のみ)
./dist/template-github-copilot-go tutorial chat-bot --cli-url localhost:3000 --loop
フラグ
| フラグ | 短縮形 | デフォルト | 説明 |
|---|---|---|---|
--prompt |
-p |
Hello, Copilot! What can you do? |
送信するプロンプト(単発モード) |
--cli-url |
-c |
(空) | 任意の Copilot CLI サーバー URL(例: localhost:3000) |
--loop |
-l |
false |
インタラクティブなチャットループモードで実行(Ctrl+C で終了) |
グローバルな
--verbose/-vフラグはログレベルをDEBUGに下げ、クライアントの接続モードとセッションのライフサイクルを表示します。
単独 CLI サーバー(TCP)への接続
デフォルトでは SDK は copilot CLI をサブプロセスとして起動し、stdio 経由で通信します。あるいは、CLI を長時間稼働する TCP サーバーとして実行し、--cli-url で接続することもできます。これは、認証済みの単一の CLI プロセスを複数の実行で共有したい場合に便利です。
ステップ 1 — CLI サーバーの起動
別のターミナルで、CLI をサーバーモードで起動します。
export COPILOT_GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"
copilot --server --port 3000 --log-level all \
--allow-all-tools --allow-all-paths --allow-all-urls
ステップ 2 — サブコマンドから接続
別のターミナルで、サブコマンドを稼働中のサーバーに向けます。
cd src/go
./dist/template-github-copilot-go tutorial chat-bot \
--cli-url localhost:3000 --prompt "Reply with exactly: connection ok"
成功するとアシスタントのレスポンス(例: connection ok)が返ります。
GitHub Actions で実行する(CI スモークテスト)
本リポジトリには、この chat-bot サブコマンドを手動のスモークテストとして実行する
ワークフロー
.github/workflows/go-run.yaml
が同梱されています。Go CLI をビルドし、Copilot CLI をインストールして、エージェントに
単一のプロンプトを送信します。
実行方法
- リポジトリの Actions タブ → go-run ワークフローを開きます。
- Run workflow をクリックします(手動トリガーの
workflow_dispatchワークフローです)。 - 必要に応じて prompt 入力(デフォルト:
Hello)を編集して実行します。
ジョブはローカルと同じコマンドを実行します。SDK が copilot CLI を stdio 経由で
起動するため、別途サーバーを起動する必要はありません。
./dist/template-github-copilot-go tutorial chat-bot --verbose --prompt "<あなたのプロンプト>"
COPILOT_GITHUB_TOKEN シークレットの設定
このワークフローは dev
環境(environment)
で実行され、COPILOT_GITHUB_TOKEN
シークレット
(有効な Copilot サブスクリプションを持つアカウントの GitHub Personal Access Token)を
読み取ります。次のいずれかの方法で設定してください。
- 手動(UI): リポジトリの Settings → Environments → New environment で
devという名前の環境を作成し、environment secret としてCOPILOT_GITHUB_TOKENを追加します。Creating secrets for an environment を参照してください。 - Terraform で: リポジトリの GitHub Secrets シナリオ を使うと、
dev環境とそのシークレットを再現可能な形でプロビジョニングできます。
トークンは GitHub → Settings → Developer settings → Personal access tokens から Copilot アクセス権付きで作成してください(Managing your personal access tokens を参照)。必ず暗号化シークレットとしてのみ保存し、リポジトリにコミットしないでください。
セキュリティ上の注意: このワークフローは
prompt入力をシェルコマンドへ直接展開せず、環境変数経由でステップに渡します。これにより信頼できない入力によるスクリプトインジェクションを緩和します。
参考情報・出典
| リソース | リンク |
|---|---|
| GitHub Copilot SDK for Go(API リファレンス) | pkg.go.dev |
| GitHub Copilot SDK(モノレポ) | github/copilot-sdk |
workflow_dispatch イベント |
docs.github.com |
| GitHub Actions でのシークレットの利用 | docs.github.com |
| デプロイ用環境の管理 | docs.github.com |
| Personal access token の管理 | docs.github.com |
次のステップ
- pkg.go.dev で Go API 全体を参照する