Skip to main content

カスタム スキル

スキルは、Copilotの機能を拡張する再利用可能なプロンプト モジュールです。 ディレクトリからスキルを読み込み、特定の分野やワークフロー向けの特殊な機能を Copilot に提供します。

Overview

スキルは、SKILL.md ファイルを含む名前の付いたディレクトリです。これは、Copilot に指示を提供する Markdown ドキュメントです。 読み込まれると、スキルのコンテンツがセッション コンテキストに挿入されます。

スキルを使用すると、次のことができるようになります。

  • 再利用可能なモジュールにドメインの専門知識をパッケージ化する
  • プロジェクト間で特殊な動作を共有する
  • 複雑なエージェント構成を整理する
  • セッションごとの機能の有効化/無効化

スキルの読み込み

セッションの作成時にスキルを含むディレクトリを指定します。

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

const client = new CopilotClient();
const session = await client.createSession({
    model: "gpt-4.1",
    skillDirectories: [
        "./skills/code-review",
        "./skills/documentation",
    ],
    onPermissionRequest: async () => ({ kind: "approve-once" }),
});

// Copilot now has access to skills in those directories
await session.sendAndWait({ prompt: "Review this code for security issues" });
Python
from copilot import CopilotClient, PermissionDecisionApproveOnce

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

    session = await client.create_session(
        on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
        model="gpt-4.1",
        skill_directories=[
            "./skills/code-review",
            "./skills/documentation",
        ],
    )

    # Copilot now has access to skills in those directories
    await session.send_and_wait("Review this code for security issues")

    await client.stop()
Go
package main

import (
    "context"
    "log"
    copilot "github.com/github/copilot-sdk/go"
    "github.com/github/copilot-sdk/go/rpc"
)

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",
        SkillDirectories: []string{
            "./skills/code-review",
            "./skills/documentation",
        },
        OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
            return &rpc.PermissionDecisionApproveOnce{}, nil
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    // Copilot now has access to skills in those directories
    _, err = session.SendAndWait(ctx, copilot.MessageOptions{
        Prompt: "Review this code for security issues",
    })
    if err != nil {
        log.Fatal(err)
    }
}
.NET
using GitHub.Copilot;
using GitHub.Copilot.Rpc;

await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
    Model = "gpt-4.1",
    SkillDirectories = new List<string>
    {
        "./skills/code-review",
        "./skills/documentation",
    },
    OnPermissionRequest = (req, inv) =>
        Task.FromResult(PermissionDecision.ApproveOnce()),
});

// Copilot now has access to skills in those directories
await session.SendAndWaitAsync(new MessageOptions
{
    Prompt = "Review this code for security issues"
});
Java
import com.github.copilot.sdk.CopilotClient;
import com.github.copilot.sdk.events.*;
import com.github.copilot.sdk.json.*;
import java.util.List;

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

    var session = client.createSession(
        new SessionConfig()
            .setModel("gpt-4.1")
            .setSkillDirectories(List.of(
                "./skills/code-review",
                "./skills/documentation"
            ))
            .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
    ).get();

    // Copilot now has access to skills in those directories
    session.sendAndWait(new MessageOptions()
        .setPrompt("Review this code for security issues")
    ).get();
}

スキルの無効化

他のユーザーをアクティブにしたまま、特定のスキルを無効にします。

TypeScript
const session = await client.createSession({
    skillDirectories: ["./skills"],
    disabledSkills: ["experimental-feature", "deprecated-tool"],
});
Python
from copilot.session import PermissionHandler

session = await client.create_session(
    on_permission_request=PermissionHandler.approve_all,
    skill_directories=["./skills"],
    disabled_skills=["experimental-feature", "deprecated-tool"],
)
Go
package main

import (
    "context"
    copilot "github.com/github/copilot-sdk/go"
    "github.com/github/copilot-sdk/go/rpc"
)

func main() {
    ctx := context.Background()
    client := copilot.NewClient(nil)

    session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
        SkillDirectories: []string{"./skills"},
        DisabledSkills:   []string{"experimental-feature", "deprecated-tool"},
        OnPermissionRequest: func(req copilot.PermissionRequest, inv copilot.PermissionInvocation) (rpc.PermissionDecision, error) {
            return &rpc.PermissionDecisionApproveOnce{}, nil
        },
    })
    _ = session
}
session, _ := client.CreateSession(context.Background(), &copilot.SessionConfig{
    SkillDirectories: []string{"./skills"},
    DisabledSkills:   []string{"experimental-feature", "deprecated-tool"},
})
.NET
using GitHub.Copilot;
using GitHub.Copilot.Rpc;

public static class SkillsExample
{
    public static async Task Main()
    {
        await using var client = new CopilotClient();

        var session = await client.CreateSessionAsync(new SessionConfig
        {
            SkillDirectories = new List<string> { "./skills" },
            DisabledSkills = new List<string> { "experimental-feature", "deprecated-tool" },
            OnPermissionRequest = (req, inv) =>
                Task.FromResult(PermissionDecision.ApproveOnce()),
        });
    }
}
var session = await client.CreateSessionAsync(new SessionConfig
{
    SkillDirectories = new List<string> { "./skills" },
    DisabledSkills = new List<string> { "experimental-feature", "deprecated-tool" },
});
Java
import com.github.copilot.sdk.json.*;
import java.util.List;

var session = client.createSession(
    new SessionConfig()
        .setSkillDirectories(List.of("./skills"))
        .setDisabledSkills(List.of("experimental-feature", "deprecated-tool"))
        .setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();

スキル ディレクトリ構造

各スキルは、 SKILL.md ファイルを含む名前付きサブディレクトリです。

skills/
├── code-review/
│   └── SKILL.md
└── documentation/
    └── SKILL.md

skillDirectories オプションは、親ディレクトリ (例: ./skills) を指します。 CLI は、即時サブディレクトリ内のすべての SKILL.md ファイルを検出します。

SKILL.md 形式

SKILL.md ファイルは、オプションの YAML frontmatter を含むマークダウン ドキュメントです。

---
name: code-review
description: Specialized code review capabilities
---

# Code Review Guidelines

When reviewing code, always check for:

1. **Security vulnerabilities** - SQL injection, XSS, etc.
2. **Performance issues** - N+1 queries, memory leaks
3. **Code style** - Consistent formatting, naming conventions
4. **Test coverage** - Are critical paths tested?

Provide specific line-number references and suggested fixes.

フロントマターのフィールド:

  • name: スキルの識別子 (選択的に無効にするために disabledSkills で使用されます)。 省略すると、ディレクトリ名が使用されます。
  • description: スキルが実行する内容の簡単な説明。

マークダウン本文には、スキルの読み込み時にセッション コンテキストに挿入される命令が含まれます。

構成オプション

SessionConfig スキル フィールド

LanguageフィールドタイプDescription
Node.jsskillDirectoriesstring[]スキルを読み込むためのディレクトリ
Node.jsdisabledSkillsstring[]無効にするスキル
Pythonskill_directorieslist[str]スキルを読み込むためのディレクトリ
Pythondisabled_skillslist[str]無効にするスキル
GoSkillDirectories[]stringスキルを読み込むためのディレクトリ
GoDisabledSkills[]string無効にするスキル
.NETSkillDirectoriesList<string>スキルを読み込むためのディレクトリ
.NETDisabledSkillsList<string>無効にするスキル

ベスト プラクティス

  1. ドメイン別に整理 する - 関連するスキルをグループ化する ( skills/security/skills/testing/など)

  2. フロントマッターを使用する - わかりやすくするために YAML フロントマッターに namedescription を含める

  3. ドキュメントの依存関係 - スキルに必要なツールまたは MCP サーバーに注意してください

  4. 分離してスキルをテスト する - 組み合わせる前にスキルの動作を確認する

  5. 相対パスを使用 する - 環境間でスキルを移植可能にする

他の機能との組み合わせ

スキル + カスタム エージェント

エージェントの skills フィールドにリストされているスキルは 、一括で事前に読み込まれます。その完全なコンテンツは起動時にエージェントのコンテキストに挿入されるため、エージェントはスキル ツールを呼び出すことなく、すぐにスキル命令にアクセスできます。 スキル名は、セッション レベルの skillDirectoriesから解決されます。

const session = await client.createSession({
    skillDirectories: ["./skills/security"],
    customAgents: [{
        name: "security-auditor",
        description: "Security-focused code reviewer",
        prompt: "Focus on OWASP Top 10 vulnerabilities",
        skills: ["security-scan", "dependency-check"],
    }],
    onPermissionRequest: async () => ({ kind: "approve-once" }),
});

メモ

スキルはオプトインされます。 skills を省略すると、スキル コンテンツは挿入されません。 サブエージェントは親からスキルを継承しません。エージェントごとに明示的に一覧表示する必要があります。

スキル + MCP サーバー

スキルは MCP サーバーの機能を補完できます。

const session = await client.createSession({
    skillDirectories: ["./skills/database"],
    mcpServers: {
        postgres: {
            type: "local",
            command: "npx",
            args: ["-y", "@modelcontextprotocol/server-postgres"],
            tools: ["*"],
        },
    },
    onPermissionRequest: async () => ({ kind: "approve-once" }),
});

Troubleshooting

スキルが読み込まれていない

  1. パスの確認 - スキル ディレクトリのパスが正しく、 SKILL.md ファイルを含むサブディレクトリが含まれていることを確認します
  2. アクセス許可を確認 する - SDK がディレクトリを読み取ることができることを確認する
  3. SKILL.md の形式を確認 - Markdown が正しい形式になっており、YAML フロントマターで有効な構文が使用されていることを確認する
  4. デバッグ ログを有効にする - スキルの読み込みログを表示するように logLevel: "debug" を設定する

スキルの競合

複数のスキルが競合する手順を提供する場合:

  • disabledSkillsを使用して競合するスキルを除外する
  • スキル ディレクトリを再構成して重複を回避する

こちらも参照ください