[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M718B6A0NT5XVZ9NR8FP7QF6":3,"skill-same:01M718B6A0NT5XVZ9NR8FP7QF6":73},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":47,"linkOnly":48,"markdownContent":49,"markdownBody":50,"frontMatter":51,"refName":53,"commitSha":54,"skillDirectory":55,"forksCount":14,"repositoryHtmlUrl":56,"repositoryHomepageUrl":6,"ownerHtmlUrl":57,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":58,"install":59,"resources":72},"01M718B6A0NT5XVZ9NR8FP7QF6","copilot-sdk",null,"Build applications that programmatically interact with GitHub Copilot. The SDK wraps the Copilot CLI via JSON-RPC, providing session management, custom tools, hooks, MCP server integration, and streaming across Node.js, Python, Go, and .NET.","sapsapshen\u002Fai-memory-router","sapsapshen","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F20347959?v=4","01M6XDQEF1DP50DKF37H81J3J5","shenmian","01M6XDQEJPE41Y3DT2763X8ZJN",0,"MIT","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fglobal\u002Fcopilot-sdk\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],"sdk","copilot","copilot sdk","Tools","2026","unknown","session management","across","community","hooks","session","node","applications","MCP","server","streaming","github copilot","mcp server","go","cli","2026-11-10 10:12:30",false,"---\nname: copilot-sdk\ndescription: \"Build applications that programmatically interact with GitHub Copilot. The SDK wraps the Copilot CLI via JSON-RPC, providing session management, custom tools, hooks, MCP server integration, and streaming across Node.js, Python, Go, and .NET.\"\nrisk: unknown\nsource: community\ndate_added: \"2026-02-27\"\n---\n\n# GitHub Copilot SDK\n\nBuild applications that programmatically interact with GitHub Copilot. The SDK wraps the Copilot CLI via JSON-RPC, providing session management, custom tools, hooks, MCP server integration, and streaming across Node.js, Python, Go, and .NET.\n\n## Prerequisites\n\n- **GitHub Copilot CLI** installed and authenticated (`copilot --version` to verify)\n- **GitHub Copilot subscription** (Individual, Business, or Enterprise) — not required for BYOK\n- **Runtime:** Node.js 18+ \u002F Python 3.8+ \u002F Go 1.21+ \u002F .NET 8.0+\n\n## Installation\n\n| Language | Package | Install |\n|----------|---------|---------|\n| Node.js | `@github\u002Fcopilot-sdk` | `npm install @github\u002Fcopilot-sdk` |\n| Python | `github-copilot-sdk` | `pip install github-copilot-sdk` |\n| Go | `github.com\u002Fgithub\u002Fcopilot-sdk\u002Fgo` | `go get github.com\u002Fgithub\u002Fcopilot-sdk\u002Fgo` |\n| .NET | `GitHub.Copilot.SDK` | `dotnet add package GitHub.Copilot.SDK` |\n\n---\n\n## Core Pattern: Client → Session → Message\n\nAll SDK usage follows this pattern: create a client, create a session, send messages.\n\n### Node.js \u002F TypeScript\n\n```typescript\nimport { CopilotClient } from \"@github\u002Fcopilot-sdk\";\n\nconst client = new CopilotClient();\nconst session = await client.createSession({ model: \"gpt-4.1\" });\n\nconst response = await session.sendAndWait({ prompt: \"What is 2 + 2?\" });\nconsole.log(response?.data.content);\n\nawait client.stop();\n```\n\n### Python\n\n```python\nimport asyncio\nfrom copilot import CopilotClient\n\nasync def main():\n    client = CopilotClient()\n    await client.start()\n    session = await client.create_session({\"model\": \"gpt-4.1\"})\n    response = await session.send_and_wait({\"prompt\": \"What is 2 + 2?\"})\n    print(response.data.content)\n    await client.stop()\n\nasyncio.run(main())\n```\n\n### Go\n\n```go\nclient := copilot.NewClient(nil)\nif err := client.Start(ctx); err != nil { log.Fatal(err) }\ndefer client.Stop()\n\nsession, _ := client.CreateSession(ctx, &copilot.SessionConfig{Model: \"gpt-4.1\"})\nresponse, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: \"What is 2 + 2?\"})\nfmt.Println(*response.Data.Content)\n```\n\n### .NET\n\n```csharp\nawait using var client = new CopilotClient();\nawait using var session = await client.CreateSessionAsync(new SessionConfig { Model = \"gpt-4.1\" });\nvar response = await session.SendAndWaitAsync(new MessageOptions { Prompt = \"What is 2 + 2?\" });\nConsole.WriteLine(response?.Data.Content);\n```\n\n---\n\n## Streaming Responses\n\nEnable real-time output by setting `streaming: true` and subscribing to delta events.\n\n```typescript\nconst session = await client.createSession({ model: \"gpt-4.1\", streaming: true });\n\nsession.on(\"assistant.message_delta\", (event) => {\n    process.stdout.write(event.data.deltaContent);\n});\nsession.on(\"session.idle\", () => console.log());\n\nawait session.sendAndWait({ prompt: \"Tell me a joke\" });\n```\n\n**Python equivalent:**\n\n```python\nfrom copilot.generated.session_events import SessionEventType\n\nsession = await client.create_session({\"model\": \"gpt-4.1\", \"streaming\": True})\n\ndef handle_event(event):\n    if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:\n        sys.stdout.write(event.data.delta_content)\n        sys.stdout.flush()\n\nsession.on(handle_event)\nawait session.send_and_wait({\"prompt\": \"Tell me a joke\"})\n```\n\n### Event Subscription\n\n| Method | Description |\n|--------|-------------|\n| `on(handler)` | Subscribe to all events; returns unsubscribe function |\n| `on(eventType, handler)` | Subscribe to specific event type (Node.js only) |\n\n---\n\n## Custom Tools\n\nDefine tools that Copilot can call to extend its capabilities.\n\n### Node.js\n\n```typescript\nimport { CopilotClient, defineTool } from \"@github\u002Fcopilot-sdk\";\n\nconst getWeather = defineTool(\"get_weather\", {\n    description: \"Get the current weather for a city\",\n    parameters: {\n        type: \"object\",\n        properties: { city: { type: \"string\", description: \"The city name\" } },\n        required: [\"city\"],\n    },\n    handler: async ({ city }) => ({ city, temperature: \"72°F\", condition: \"sunny\" }),\n});\n\nconst session = await client.createSession({\n    model: \"gpt-4.1\",\n    tools: [getWeather],\n});\n```\n\n### Python\n\n```python\nfrom copilot.tools import define_tool\nfrom pydantic import BaseModel, Field\n\nclass GetWeatherParams(BaseModel):\n    city: str = Field(description=\"The city name\")\n\n@define_tool(description=\"Get the current weather for a city\")\nasync def get_weather(params: GetWeatherParams) -> dict:\n    return {\"city\": params.city, \"temperature\": \"72°F\", \"condition\": \"sunny\"}\n\nsession = await client.create_session({\"model\": \"gpt-4.1\", \"tools\": [get_weather]})\n```\n\n### Go\n\n```go\ntype WeatherParams struct {\n    City string `json:\"city\" jsonschema:\"The city name\"`\n}\n\ngetWeather := copilot.DefineTool(\"get_weather\", \"Get weather for a city\",\n    func(params WeatherParams, inv copilot.ToolInvocation) (WeatherResult, error) {\n        return WeatherResult{City: params.City, Temperature: \"72°F\"}, nil\n    },\n)\n\nsession, _ := client.CreateSession(ctx, &copilot.SessionConfig{\n    Model: \"gpt-4.1\",\n    Tools: []copilot.Tool{getWeather},\n})\n```\n\n### .NET\n\n```csharp\nvar getWeather = AIFunctionFactory.Create(\n    ([Description(\"The city name\")] string city) => new { city, temperature = \"72°F\" },\n    \"get_weather\", \"Get the current weather for a city\");\n\nawait using var session = await client.CreateSessionAsync(new SessionConfig {\n    Model = \"gpt-4.1\", Tools = [getWeather],\n});\n```\n\n---\n\n## Hooks\n\nIntercept and customize session behavior at key lifecycle points.\n\n| Hook | Trigger | Use Case |\n|------|---------|----------|\n| `onPreToolUse` | Before tool executes | Permission control, argument modification |\n| `onPostToolUse` | After tool executes | Result transformation, logging |\n| `onUserPromptSubmitted` | User sends message | Prompt modification, filtering |\n| `onSessionStart` | Session begins | Add context, configure session |\n| `onSessionEnd` | Session ends | Cleanup, analytics |\n| `onErrorOccurred` | Error happens | Custom error handling, retry logic |\n\n### Example: Tool Permission Control\n\n```typescript\nconst session = await client.createSession({\n    hooks: {\n        onPreToolUse: async (input) => {\n            if ([\"shell\", \"bash\"].includes(input.toolName)) {\n                return { permissionDecision: \"deny\", permissionDecisionReason: \"Shell access not permitted\" };\n            }\n            return { permissionDecision: \"allow\" };\n        },\n    },\n});\n```\n\n### Pre-Tool Use Output\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `permissionDecision` | `\"allow\"` \\| `\"deny\"` \\| `\"ask\"` | Whether to allow the tool call |\n| `permissionDecisionReason` | string | Explanation for deny\u002Fask |\n| `modifiedArgs` | object | Modified arguments to pass |\n| `additionalContext` | string | Extra context for conversation |\n| `suppressOutput` | boolean | Hide tool output from conversation |\n\n---\n\n## MCP Server Integration\n\nConnect to MCP servers for pre-built tool capabilities.\n\n### Remote HTTP Server\n\n```typescript\nconst session = await client.createSession({\n    mcpServers: {\n        github: { type: \"http\", url: \"https:\u002F\u002Fapi.githubcopilot.com\u002Fmcp\u002F\" },\n    },\n});\n```\n\n### Local Stdio Server\n\n```typescript\nconst session = await client.createSession({\n    mcpServers: {\n        filesystem: {\n            type: \"local\",\n            command: \"npx\",\n            args: [\"-y\", \"@modelcontextprotocol\u002Fserver-filesystem\", \"\u002Fallowed\u002Fpath\"],\n            tools: [\"*\"],\n        },\n    },\n});\n```\n\n### MCP Config Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `type` | `\"local\"` \\| `\"http\"` | Server transport type |\n| `command` | string | Executable path (local) |\n| `args` | string[] | Command arguments (local) |\n| `url` | string | Server URL (http) |\n| `tools` | string[] | `[\"*\"]` or specific tool names |\n| `env` | object | Environment variables |\n| `cwd` | string | Working directory (local) |\n| `timeout` | number | Timeout in milliseconds |\n\n---\n\n## Authentication\n\n### Methods (Priority Order)\n\n1. **Explicit token** — `githubToken` in constructor\n2. **Environment variables** — `COPILOT_GITHUB_TOKEN` → `GH_TOKEN` → `GITHUB_TOKEN`\n3. **Stored OAuth** — From `copilot auth login`\n4. **GitHub CLI** — `gh auth` credentials\n\n### Programmatic Token\n\n```typescript\nconst client = new CopilotClient({ githubToken: process.env.GITHUB_TOKEN });\n```\n\n### BYOK (Bring Your Own Key)\n\nUse your own API keys — no Copilot subscription required.\n\n```typescript\nconst session = await client.createSession({\n    model: \"gpt-5.2-codex\",\n    provider: {\n        type: \"openai\",\n        baseUrl: \"https:\u002F\u002Fyour-resource.openai.azure.com\u002Fopenai\u002Fv1\u002F\",\n        wireApi: \"responses\",\n        apiKey: process.env.FOUNDRY_API_KEY,\n    },\n});\n```\n\n| Provider | Type | Notes |\n|----------|------|-------|\n| OpenAI | `\"openai\"` | OpenAI API and compatible endpoints |\n| Azure OpenAI | `\"azure\"` | Native Azure endpoints (don't include `\u002Fopenai\u002Fv1`) |\n| Azure AI Foundry | `\"openai\"` | OpenAI-compatible Foundry endpoints |\n| Anthropic | `\"anthropic\"` | Claude models |\n| Ollama | `\"openai\"` | Local models, no API key needed |\n\n**Wire API:** Use `\"responses\"` for GPT-5 series, `\"completions\"` (default) for others.\n\n---\n\n## Session Persistence\n\nResume sessions across restarts by providing your own session ID.\n\n```typescript\n\u002F\u002F Create with explicit ID\nconst session = await client.createSession({\n    sessionId: \"user-123-task-456\",\n    model: \"gpt-4.1\",\n});\n\n\u002F\u002F Resume later\nconst resumed = await client.resumeSession(\"user-123-task-456\");\nawait resumed.sendAndWait({ prompt: \"What did we discuss?\" });\n```\n\n**Session management:**\n\n```typescript\nconst sessions = await client.listSessions();          \u002F\u002F List all\nawait client.deleteSession(\"user-123-task-456\");       \u002F\u002F Delete\nawait session.destroy();                                \u002F\u002F Destroy active\n```\n\n**BYOK sessions:** Must re-provide `provider` config on resume (keys are not persisted).\n\n### Infinite Sessions\n\nFor long-running workflows that may exceed context limits:\n\n```typescript\nconst session = await client.createSession({\n    infiniteSessions: {\n        enabled: true,\n        backgroundCompactionThreshold: 0.80,\n        bufferExhaustionThreshold: 0.95,\n    },\n});\n```\n\n---\n\n## Custom Agents\n\nDefine specialized AI personas:\n\n```typescript\nconst session = await client.createSession({\n    customAgents: [{\n        name: \"pr-reviewer\",\n        displayName: \"PR Reviewer\",\n        description: \"Reviews pull requests for best practices\",\n        prompt: \"You are an expert code reviewer. Focus on security, performance, and maintainability.\",\n    }],\n});\n```\n\n---\n\n## System Message\n\nControl AI behavior and personality:\n\n```typescript\nconst session = await client.createSession({\n    systemMessage: { content: \"You are a helpful assistant. Always be concise.\" },\n});\n```\n\n---\n\n## Skills Integration\n\nLoad skill directories to extend Copilot's capabilities:\n\n```typescript\nconst session = await client.createSession({\n    skillDirectories: [\".\u002Fskills\u002Fcode-review\", \".\u002Fskills\u002Fdocumentation\"],\n    disabledSkills: [\"experimental-feature\"],\n});\n```\n\n---\n\n## Permission & Input Handlers\n\nHandle tool permissions and user input requests programmatically:\n\n```typescript\nconst session = await client.createSession({\n    onPermissionRequest: async (request) => {\n        \u002F\u002F Auto-approve git commands only\n        if (request.kind === \"shell\") {\n            return { approved: request.command.startsWith(\"git\") };\n        }\n        return { approved: true };\n    },\n    onUserInputRequest: async (request) => {\n        \u002F\u002F Handle ask_user tool calls\n        return { response: \"yes\" };\n    },\n});\n```\n\n---\n\n## External CLI Server\n\nConnect to a separately running CLI instead of auto-managing the process:\n\n```bash\ncopilot --headless --port 4321\n```\n\n```typescript\nconst client = new CopilotClient({ cliUrl: \"localhost:4321\" });\n```\n\n---\n\n## Client Configuration\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `cliPath` | string | Path to Copilot CLI executable |\n| `cliUrl` | string | URL of external CLI server |\n| `githubToken` | string | GitHub token for auth |\n| `useLoggedInUser` | boolean | Use stored CLI credentials (default: true) |\n| `logLevel` | string | `\"none\"` \\| `\"error\"` \\| `\"warning\"` \\| `\"info\"` \\| `\"debug\"` |\n| `autoRestart` | boolean | Auto-restart CLI on crash (default: true) |\n| `useStdio` | boolean | Use stdio transport (default: true) |\n\n## Session Configuration\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `model` | string | Model to use (e.g., `\"gpt-4.1\"`) |\n| `sessionId` | string | Custom ID for resumable sessions |\n| `streaming` | boolean | Enable streaming responses |\n| `tools` | Tool[] | Custom tools |\n| `mcpServers` | object | MCP server configurations |\n| `hooks` | object | Session hooks |\n| `provider` | object | BYOK provider config |\n| `customAgents` | object[] | Custom agent definitions |\n| `systemMessage` | object | System message override |\n| `skillDirectories` | string[] | Directories to load skills from |\n| `disabledSkills` | string[] | Skills to disable |\n| `reasoningEffort` | string | Reasoning effort level |\n| `availableTools` | string[] | Restrict available tools |\n| `excludedTools` | string[] | Exclude specific tools |\n| `infiniteSessions` | object | Auto-compaction config |\n| `workingDirectory` | string | Working directory |\n\n---\n\n## Debugging\n\nEnable debug logging to troubleshoot issues:\n\n```typescript\nconst client = new CopilotClient({ logLevel: \"debug\" });\n```\n\n**Common issues:**\n- `CLI not found` → Install CLI or set `cliPath`\n- `Not authenticated` → Run `copilot auth login` or provide `githubToken`\n- `Session not found` → Don't use session after `destroy()`\n- `Connection refused` → Check CLI process, enable `autoRestart`\n\n---\n\n## Key API Summary\n\n| Language | Client | Session Create | Send | Stop |\n|----------|--------|---------------|------|------|\n| Node.js | `new CopilotClient()` | `client.createSession()` | `session.sendAndWait()` | `client.stop()` |\n| Python | `CopilotClient()` | `client.create_session()` | `session.send_and_wait()` | `client.stop()` |\n| Go | `copilot.NewClient(nil)` | `client.CreateSession()` | `session.SendAndWait()` | `client.Stop()` |\n| .NET | `new CopilotClient()` | `client.CreateSessionAsync()` | `session.SendAndWaitAsync()` | `client.DisposeAsync()` |\n\n## References\n\n- [GitHub Copilot SDK](https:\u002F\u002Fgithub.com\u002Fgithub\u002Fcopilot-sdk)\n- [Copilot CLI Installation](https:\u002F\u002Fdocs.github.com\u002Fen\u002Fcopilot\u002Fhow-tos\u002Fset-up\u002Finstall-copilot-cli)\n- [MCP Protocol Specification](https:\u002F\u002Fmodelcontextprotocol.io)\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.\n","# GitHub Copilot SDK\n\nBuild applications that programmatically interact with GitHub Copilot. The SDK wraps the Copilot CLI via JSON-RPC, providing session management, custom tools, hooks, MCP server integration, and streaming across Node.js, Python, Go, and .NET.\n\n## Prerequisites\n\n- **GitHub Copilot CLI** installed and authenticated (`copilot --version` to verify)\n- **GitHub Copilot subscription** (Individual, Business, or Enterprise) — not required for BYOK\n- **Runtime:** Node.js 18+ \u002F Python 3.8+ \u002F Go 1.21+ \u002F .NET 8.0+\n\n## Installation\n\n| Language | Package | Install |\n|----------|---------|---------|\n| Node.js | `@github\u002Fcopilot-sdk` | `npm install @github\u002Fcopilot-sdk` |\n| Python | `github-copilot-sdk` | `pip install github-copilot-sdk` |\n| Go | `github.com\u002Fgithub\u002Fcopilot-sdk\u002Fgo` | `go get github.com\u002Fgithub\u002Fcopilot-sdk\u002Fgo` |\n| .NET | `GitHub.Copilot.SDK` | `dotnet add package GitHub.Copilot.SDK` |\n\n---\n\n## Core Pattern: Client → Session → Message\n\nAll SDK usage follows this pattern: create a client, create a session, send messages.\n\n### Node.js \u002F TypeScript\n\n```typescript\nimport { CopilotClient } from \"@github\u002Fcopilot-sdk\";\n\nconst client = new CopilotClient();\nconst session = await client.createSession({ model: \"gpt-4.1\" });\n\nconst response = await session.sendAndWait({ prompt: \"What is 2 + 2?\" });\nconsole.log(response?.data.content);\n\nawait client.stop();\n```\n\n### Python\n\n```python\nimport asyncio\nfrom copilot import CopilotClient\n\nasync def main():\n    client = CopilotClient()\n    await client.start()\n    session = await client.create_session({\"model\": \"gpt-4.1\"})\n    response = await session.send_and_wait({\"prompt\": \"What is 2 + 2?\"})\n    print(response.data.content)\n    await client.stop()\n\nasyncio.run(main())\n```\n\n### Go\n\n```go\nclient := copilot.NewClient(nil)\nif err := client.Start(ctx); err != nil { log.Fatal(err) }\ndefer client.Stop()\n\nsession, _ := client.CreateSession(ctx, &copilot.SessionConfig{Model: \"gpt-4.1\"})\nresponse, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: \"What is 2 + 2?\"})\nfmt.Println(*response.Data.Content)\n```\n\n### .NET\n\n```csharp\nawait using var client = new CopilotClient();\nawait using var session = await client.CreateSessionAsync(new SessionConfig { Model = \"gpt-4.1\" });\nvar response = await session.SendAndWaitAsync(new MessageOptions { Prompt = \"What is 2 + 2?\" });\nConsole.WriteLine(response?.Data.Content);\n```\n\n---\n\n## Streaming Responses\n\nEnable real-time output by setting `streaming: true` and subscribing to delta events.\n\n```typescript\nconst session = await client.createSession({ model: \"gpt-4.1\", streaming: true });\n\nsession.on(\"assistant.message_delta\", (event) => {\n    process.stdout.write(event.data.deltaContent);\n});\nsession.on(\"session.idle\", () => console.log());\n\nawait session.sendAndWait({ prompt: \"Tell me a joke\" });\n```\n\n**Python equivalent:**\n\n```python\nfrom copilot.generated.session_events import SessionEventType\n\nsession = await client.create_session({\"model\": \"gpt-4.1\", \"streaming\": True})\n\ndef handle_event(event):\n    if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:\n        sys.stdout.write(event.data.delta_content)\n        sys.stdout.flush()\n\nsession.on(handle_event)\nawait session.send_and_wait({\"prompt\": \"Tell me a joke\"})\n```\n\n### Event Subscription\n\n| Method | Description |\n|--------|-------------|\n| `on(handler)` | Subscribe to all events; returns unsubscribe function |\n| `on(eventType, handler)` | Subscribe to specific event type (Node.js only) |\n\n---\n\n## Custom Tools\n\nDefine tools that Copilot can call to extend its capabilities.\n\n### Node.js\n\n```typescript\nimport { CopilotClient, defineTool } from \"@github\u002Fcopilot-sdk\";\n\nconst getWeather = defineTool(\"get_weather\", {\n    description: \"Get the current weather for a city\",\n    parameters: {\n        type: \"object\",\n        properties: { city: { type: \"string\", description: \"The city name\" } },\n        required: [\"city\"],\n    },\n    handler: async ({ city }) => ({ city, temperature: \"72°F\", condition: \"sunny\" }),\n});\n\nconst session = await client.createSession({\n    model: \"gpt-4.1\",\n    tools: [getWeather],\n});\n```\n\n### Python\n\n```python\nfrom copilot.tools import define_tool\nfrom pydantic import BaseModel, Field\n\nclass GetWeatherParams(BaseModel):\n    city: str = Field(description=\"The city name\")\n\n@define_tool(description=\"Get the current weather for a city\")\nasync def get_weather(params: GetWeatherParams) -> dict:\n    return {\"city\": params.city, \"temperature\": \"72°F\", \"condition\": \"sunny\"}\n\nsession = await client.create_session({\"model\": \"gpt-4.1\", \"tools\": [get_weather]})\n```\n\n### Go\n\n```go\ntype WeatherParams struct {\n    City string `json:\"city\" jsonschema:\"The city name\"`\n}\n\ngetWeather := copilot.DefineTool(\"get_weather\", \"Get weather for a city\",\n    func(params WeatherParams, inv copilot.ToolInvocation) (WeatherResult, error) {\n        return WeatherResult{City: params.City, Temperature: \"72°F\"}, nil\n    },\n)\n\nsession, _ := client.CreateSession(ctx, &copilot.SessionConfig{\n    Model: \"gpt-4.1\",\n    Tools: []copilot.Tool{getWeather},\n})\n```\n\n### .NET\n\n```csharp\nvar getWeather = AIFunctionFactory.Create(\n    ([Description(\"The city name\")] string city) => new { city, temperature = \"72°F\" },\n    \"get_weather\", \"Get the current weather for a city\");\n\nawait using var session = await client.CreateSessionAsync(new SessionConfig {\n    Model = \"gpt-4.1\", Tools = [getWeather],\n});\n```\n\n---\n\n## Hooks\n\nIntercept and customize session behavior at key lifecycle points.\n\n| Hook | Trigger | Use Case |\n|------|---------|----------|\n| `onPreToolUse` | Before tool executes | Permission control, argument modification |\n| `onPostToolUse` | After tool executes | Result transformation, logging |\n| `onUserPromptSubmitted` | User sends message | Prompt modification, filtering |\n| `onSessionStart` | Session begins | Add context, configure session |\n| `onSessionEnd` | Session ends | Cleanup, analytics |\n| `onErrorOccurred` | Error happens | Custom error handling, retry logic |\n\n### Example: Tool Permission Control\n\n```typescript\nconst session = await client.createSession({\n    hooks: {\n        onPreToolUse: async (input) => {\n            if ([\"shell\", \"bash\"].includes(input.toolName)) {\n                return { permissionDecision: \"deny\", permissionDecisionReason: \"Shell access not permitted\" };\n            }\n            return { permissionDecision: \"allow\" };\n        },\n    },\n});\n```\n\n### Pre-Tool Use Output\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `permissionDecision` | `\"allow\"` \\| `\"deny\"` \\| `\"ask\"` | Whether to allow the tool call |\n| `permissionDecisionReason` | string | Explanation for deny\u002Fask |\n| `modifiedArgs` | object | Modified arguments to pass |\n| `additionalContext` | string | Extra context for conversation |\n| `suppressOutput` | boolean | Hide tool output from conversation |\n\n---\n\n## MCP Server Integration\n\nConnect to MCP servers for pre-built tool capabilities.\n\n### Remote HTTP Server\n\n```typescript\nconst session = await client.createSession({\n    mcpServers: {\n        github: { type: \"http\", url: \"https:\u002F\u002Fapi.githubcopilot.com\u002Fmcp\u002F\" },\n    },\n});\n```\n\n### Local Stdio Server\n\n```typescript\nconst session = await client.createSession({\n    mcpServers: {\n        filesystem: {\n            type: \"local\",\n            command: \"npx\",\n            args: [\"-y\", \"@modelcontextprotocol\u002Fserver-filesystem\", \"\u002Fallowed\u002Fpath\"],\n            tools: [\"*\"],\n        },\n    },\n});\n```\n\n### MCP Config Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `type` | `\"local\"` \\| `\"http\"` | Server transport type |\n| `command` | string | Executable path (local) |\n| `args` | string[] | Command arguments (local) |\n| `url` | string | Server URL (http) |\n| `tools` | string[] | `[\"*\"]` or specific tool names |\n| `env` | object | Environment variables |\n| `cwd` | string | Working directory (local) |\n| `timeout` | number | Timeout in milliseconds |\n\n---\n\n## Authentication\n\n### Methods (Priority Order)\n\n1. **Explicit token** — `githubToken` in constructor\n2. **Environment variables** — `COPILOT_GITHUB_TOKEN` → `GH_TOKEN` → `GITHUB_TOKEN`\n3. **Stored OAuth** — From `copilot auth login`\n4. **GitHub CLI** — `gh auth` credentials\n\n### Programmatic Token\n\n```typescript\nconst client = new CopilotClient({ githubToken: process.env.GITHUB_TOKEN });\n```\n\n### BYOK (Bring Your Own Key)\n\nUse your own API keys — no Copilot subscription required.\n\n```typescript\nconst session = await client.createSession({\n    model: \"gpt-5.2-codex\",\n    provider: {\n        type: \"openai\",\n        baseUrl: \"https:\u002F\u002Fyour-resource.openai.azure.com\u002Fopenai\u002Fv1\u002F\",\n        wireApi: \"responses\",\n        apiKey: process.env.FOUNDRY_API_KEY,\n    },\n});\n```\n\n| Provider | Type | Notes |\n|----------|------|-------|\n| OpenAI | `\"openai\"` | OpenAI API and compatible endpoints |\n| Azure OpenAI | `\"azure\"` | Native Azure endpoints (don't include `\u002Fopenai\u002Fv1`) |\n| Azure AI Foundry | `\"openai\"` | OpenAI-compatible Foundry endpoints |\n| Anthropic | `\"anthropic\"` | Claude models |\n| Ollama | `\"openai\"` | Local models, no API key needed |\n\n**Wire API:** Use `\"responses\"` for GPT-5 series, `\"completions\"` (default) for others.\n\n---\n\n## Session Persistence\n\nResume sessions across restarts by providing your own session ID.\n\n```typescript\n\u002F\u002F Create with explicit ID\nconst session = await client.createSession({\n    sessionId: \"user-123-task-456\",\n    model: \"gpt-4.1\",\n});\n\n\u002F\u002F Resume later\nconst resumed = await client.resumeSession(\"user-123-task-456\");\nawait resumed.sendAndWait({ prompt: \"What did we discuss?\" });\n```\n\n**Session management:**\n\n```typescript\nconst sessions = await client.listSessions();          \u002F\u002F List all\nawait client.deleteSession(\"user-123-task-456\");       \u002F\u002F Delete\nawait session.destroy();                                \u002F\u002F Destroy active\n```\n\n**BYOK sessions:** Must re-provide `provider` config on resume (keys are not persisted).\n\n### Infinite Sessions\n\nFor long-running workflows that may exceed context limits:\n\n```typescript\nconst session = await client.createSession({\n    infiniteSessions: {\n        enabled: true,\n        backgroundCompactionThreshold: 0.80,\n        bufferExhaustionThreshold: 0.95,\n    },\n});\n```\n\n---\n\n## Custom Agents\n\nDefine specialized AI personas:\n\n```typescript\nconst session = await client.createSession({\n    customAgents: [{\n        name: \"pr-reviewer\",\n        displayName: \"PR Reviewer\",\n        description: \"Reviews pull requests for best practices\",\n        prompt: \"You are an expert code reviewer. Focus on security, performance, and maintainability.\",\n    }],\n});\n```\n\n---\n\n## System Message\n\nControl AI behavior and personality:\n\n```typescript\nconst session = await client.createSession({\n    systemMessage: { content: \"You are a helpful assistant. Always be concise.\" },\n});\n```\n\n---\n\n## Skills Integration\n\nLoad skill directories to extend Copilot's capabilities:\n\n```typescript\nconst session = await client.createSession({\n    skillDirectories: [\".\u002Fskills\u002Fcode-review\", \".\u002Fskills\u002Fdocumentation\"],\n    disabledSkills: [\"experimental-feature\"],\n});\n```\n\n---\n\n## Permission & Input Handlers\n\nHandle tool permissions and user input requests programmatically:\n\n```typescript\nconst session = await client.createSession({\n    onPermissionRequest: async (request) => {\n        \u002F\u002F Auto-approve git commands only\n        if (request.kind === \"shell\") {\n            return { approved: request.command.startsWith(\"git\") };\n        }\n        return { approved: true };\n    },\n    onUserInputRequest: async (request) => {\n        \u002F\u002F Handle ask_user tool calls\n        return { response: \"yes\" };\n    },\n});\n```\n\n---\n\n## External CLI Server\n\nConnect to a separately running CLI instead of auto-managing the process:\n\n```bash\ncopilot --headless --port 4321\n```\n\n```typescript\nconst client = new CopilotClient({ cliUrl: \"localhost:4321\" });\n```\n\n---\n\n## Client Configuration\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `cliPath` | string | Path to Copilot CLI executable |\n| `cliUrl` | string | URL of external CLI server |\n| `githubToken` | string | GitHub token for auth |\n| `useLoggedInUser` | boolean | Use stored CLI credentials (default: true) |\n| `logLevel` | string | `\"none\"` \\| `\"error\"` \\| `\"warning\"` \\| `\"info\"` \\| `\"debug\"` |\n| `autoRestart` | boolean | Auto-restart CLI on crash (default: true) |\n| `useStdio` | boolean | Use stdio transport (default: true) |\n\n## Session Configuration\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `model` | string | Model to use (e.g., `\"gpt-4.1\"`) |\n| `sessionId` | string | Custom ID for resumable sessions |\n| `streaming` | boolean | Enable streaming responses |\n| `tools` | Tool[] | Custom tools |\n| `mcpServers` | object | MCP server configurations |\n| `hooks` | object | Session hooks |\n| `provider` | object | BYOK provider config |\n| `customAgents` | object[] | Custom agent definitions |\n| `systemMessage` | object | System message override |\n| `skillDirectories` | string[] | Directories to load skills from |\n| `disabledSkills` | string[] | Skills to disable |\n| `reasoningEffort` | string | Reasoning effort level |\n| `availableTools` | string[] | Restrict available tools |\n| `excludedTools` | string[] | Exclude specific tools |\n| `infiniteSessions` | object | Auto-compaction config |\n| `workingDirectory` | string | Working directory |\n\n---\n\n## Debugging\n\nEnable debug logging to troubleshoot issues:\n\n```typescript\nconst client = new CopilotClient({ logLevel: \"debug\" });\n```\n\n**Common issues:**\n- `CLI not found` → Install CLI or set `cliPath`\n- `Not authenticated` → Run `copilot auth login` or provide `githubToken`\n- `Session not found` → Don't use session after `destroy()`\n- `Connection refused` → Check CLI process, enable `autoRestart`\n\n---\n\n## Key API Summary\n\n| Language | Client | Session Create | Send | Stop |\n|----------|--------|---------------|------|------|\n| Node.js | `new CopilotClient()` | `client.createSession()` | `session.sendAndWait()` | `client.stop()` |\n| Python | `CopilotClient()` | `client.create_session()` | `session.send_and_wait()` | `client.stop()` |\n| Go | `copilot.NewClient(nil)` | `client.CreateSession()` | `session.SendAndWait()` | `client.Stop()` |\n| .NET | `new CopilotClient()` | `client.CreateSessionAsync()` | `session.SendAndWaitAsync()` | `client.DisposeAsync()` |\n\n## References\n\n- [GitHub Copilot SDK](https:\u002F\u002Fgithub.com\u002Fgithub\u002Fcopilot-sdk)\n- [Copilot CLI Installation](https:\u002F\u002Fdocs.github.com\u002Fen\u002Fcopilot\u002Fhow-tos\u002Fset-up\u002Finstall-copilot-cli)\n- [MCP Protocol Specification](https:\u002F\u002Fmodelcontextprotocol.io)\n\n## When to Use\nThis skill is applicable to execute the workflow or actions described in the overview.\n",{"name":5,"risk":32,"source":35,"date_added":52,"description":7},"2026-02-27","main","7a38d8e7073e61c16eda85681cb32fb68a8657a5","skills-store\u002Fglobal\u002Fcopilot-sdk","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router","https:\u002F\u002Fgithub.com\u002Fsapsapshen","2026-04-14 21:12:12",{"source":8,"skillName":5,"commands":60,"prompt":70,"zipAvailable":71},[61,64,67],{"tool":62,"command":63},"npx","npx skills add sapsapshen\u002Fai-memory-router --skill copilot-sdk",{"tool":65,"command":66},"bunx","bunx skills add sapsapshen\u002Fai-memory-router --skill copilot-sdk",{"tool":68,"command":69},"pnpm","pnpm dlx skills add sapsapshen\u002Fai-memory-router --skill copilot-sdk","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fglobal\u002Fcopilot-sdk\u002FSKILL.md",true,[],[74,98,123,133,146,162],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":85,"publishedAt":47},"01M71ATQRKG48SH06FQ697T5G9","wechat-search","Search WeChat Official Account articles using OpenClaw's web search and fetch capabilities with compliance-focused design.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fwechat-search-release\u002FSKILL.md",[80],{"categoryNo":81,"categoryName":82,"taxonomyType":83,"taxonomyTypeDesc":84},"01JBSEEDCAT000000000000037","律师与法务","PROFESSION","适用职业",[86,87,88,89,90,91,92,93,94,95,96,97],"wechat search","wechat","search","capabilities","openclaw","design","web search","compliance","web","official","fetch","with",{"skillNo":99,"name":100,"nameZh":6,"description":101,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":102,"categories":103,"keywords":104,"publishedAt":47},"01M71ATNAVGZB35PFYM2GC5N00","trend-tap","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend tap', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-tap\u002FSKILL.md",[],[105,106,107,108,109,110,88,111,112,113,114,115,116,117,118,119,120,121,34,122],"trend","trend tap","tap","api keys","Bash","time","trending","hacker","aggregator","do","when","brew","live","data","google","install","read","api",{"skillNo":124,"name":125,"nameZh":6,"description":126,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":127,"categories":128,"keywords":129,"publishedAt":47},"01M71ATJ9AM5KM15AA8PS302EB","trend-radar","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend pulse', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-radar\u002FSKILL.md",[],[130,131,105,116,117,118,119,109,88,121,132,34,122,115,113,112,111,120,110,108],"trend radar","radar","pulse",{"skillNo":134,"name":135,"nameZh":6,"description":136,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":137,"categories":138,"keywords":139,"publishedAt":47},"01M71ATGF095N3EJM9G8SD0BB5","tech-news-daily","每日科技新闻汇——从全球多个 RSS 源抓取最新科技新闻，翻译（英→中）、去重、排版成每日简报。当用户询问科技新闻、科技新鲜事、每日科技、技术动态、Daily Tech News 或类似表达时触发此技能。","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftech-news-daily\u002FSKILL.md",[],[140,141,142,143,144,145],"news","tech","tech news daily","daily","rss","翻译",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":155,"publishedAt":47},"01M71ATFAEAMQ17M70NQNY7SR8","summarize","Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsummarize\u002FSKILL.md",[152],{"categoryNo":153,"categoryName":154,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000021","资料检索与研究",[148,94,156,46,157,97,116,158,159,160,107,161,120],"Audio","youtube","images","https","files","pdfs",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":168,"publishedAt":47},"01M71ATDNS3R0M4H936PACQAWZ","sonoscli","Control Sonos speakers (discover\u002Fstatus\u002Fplay\u002Fvolume\u002Fgroup).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsonoscli\u002FSKILL.md",[],[164,169,170,45,120,171,159,172,173,174,175,176],"status","play","latest","github","discover","control","cmd","volume"]