docs(kyberforge): add GitHub Copilot plugins and sub-agents research
## Why Parallel research track to the Claude Code plugins research already committed. Needed to understand GitHub Copilot's extensibility model before designing cross-tool plugin compatibility for the kyberforge plugin system. ## Implementation Notes Three distinct Copilot extension tracks are covered: CLI plugins (plugin.json + marketplaces), cloud/IDE custom agents (frontmatter .md files committed to repos), and the SDK programmatic API. The SDK track got its own topic file (sdk.md) because the content doesn't fit neatly into the default topic list. Sources include Context7 (/websites/github_en_copilot), both user-provided reference URLs, and four additional deepened pages. ## Impact Provides a reference baseline for evaluating .claude-plugin/ / plugin.json compatibility between Claude Code and Copilot CLI — the two formats share a manifest discovery path and the strict:false field enables cross-tool plugin distribution. --- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
---
|
||||
topic: agent-definition
|
||||
source_keys:
|
||||
- context7-github-en-copilot
|
||||
- github-custom-agents-configuration
|
||||
- github-plugins-creating
|
||||
- github-cli-plugin-reference
|
||||
- github-sdk-custom-agents
|
||||
---
|
||||
|
||||
# Agent Definition Format
|
||||
|
||||
There are two file-based agent formats (CLI and cloud/IDE) and one programmatic format (SDK). They share vocabulary but differ in supported fields and runtime behavior.
|
||||
|
||||
## CLI Agents (`.agent.md` files)
|
||||
|
||||
Stored in `agents/` within a plugin directory, or directly in `.github/agents/`, `.claude/agents/`, or `~/.copilot/agents/`. File extension must be `.agent.md`.
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: my-agent
|
||||
description: Helps with specific tasks
|
||||
tools: ["bash", "edit", "view"]
|
||||
---
|
||||
|
||||
You are a specialized assistant that...
|
||||
```
|
||||
|
||||
| Field | Required | Notes |
|
||||
|---|---|---|
|
||||
| `name` | Yes | Identifier; home-directory version wins over repo-level on collision |
|
||||
| `description` | Yes | Used by the runtime for automatic agent selection — quality matters |
|
||||
| `tools` | No | Array of tool names; omit = all available tools |
|
||||
|
||||
Agents can be invoked with `/AGENT-NAME` in interactive sessions or `--agent AGENT-NAME` on the CLI.
|
||||
|
||||
## Cloud / IDE Custom Agents
|
||||
|
||||
Committed to `.github/copilot/agents/` (repo), org-level, or enterprise-level paths as plain `.md` files. Scoping hierarchy: enterprise overrides are lowest priority; repo-level overrides are highest. Currently in public preview for JetBrains, Eclipse, and Xcode.
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: implementation-planner
|
||||
description: Creates detailed implementation plans without executing code
|
||||
target: github-copilot
|
||||
tools: ["read", "search", "edit"]
|
||||
model: claude-sonnet-4-5
|
||||
---
|
||||
|
||||
You are a technical planning specialist...
|
||||
```
|
||||
|
||||
| Field | Required | Default | Notes |
|
||||
|---|---|---|---|
|
||||
| `name` | No | — | Display name |
|
||||
| `description` | Yes | — | Purpose and capabilities; drives auto-selection |
|
||||
| `target` | No | `both` | `vscode` or `github-copilot`; scopes which runtime loads this file |
|
||||
| `tools` | No | all tools | Omit = all; `[]` = none; list = restrict to named tools |
|
||||
| `model` | No | default model | Model to run this agent on |
|
||||
| `disable-model-invocation` | No | `false` | Prevents runtime from auto-selecting this agent |
|
||||
| `user-invocable` | No | `true` | Whether users can manually invoke this agent |
|
||||
| `mcp-servers` | No | — | Extra MCP servers (cloud agent only; ignored in VS Code and most IDEs) |
|
||||
| `metadata` | No | — | Key-value annotation pairs (ignored in VS Code) |
|
||||
|
||||
The `infer` field is retired — use `disable-model-invocation` + `user-invocable` instead.
|
||||
|
||||
Prompt body limit is 30,000 characters; content beyond this is truncated.
|
||||
|
||||
### Tool Aliases
|
||||
|
||||
The following aliases are interchangeable in the `tools` field:
|
||||
|
||||
| Canonical Name | Accepted Aliases | Purpose |
|
||||
|---|---|---|
|
||||
| `execute` | `shell`, `Bash`, `powershell` | Run shell commands |
|
||||
| `read` | `Read`, `NotebookRead` | Read file contents |
|
||||
| `edit` | `Edit`, `MultiEdit`, `Write`, `NotebookEdit` | Modify files |
|
||||
| `search` | `Grep`, `Glob` | Search files and text |
|
||||
| `agent` | `custom-agent`, `Task` | Invoke sub-agents |
|
||||
| `web` | `WebSearch`, `WebFetch` | Fetch URLs and web search |
|
||||
| `todo` | `TodoWrite` | Task lists (VS Code only) |
|
||||
|
||||
For MCP server tools, use `server-name/tool-name` syntax or `server-name/*` for all tools from a server.
|
||||
|
||||
### MCP Server Declaration (cloud agent frontmatter)
|
||||
|
||||
```yaml
|
||||
mcp-servers:
|
||||
custom-mcp:
|
||||
type: 'local'
|
||||
command: 'some-command'
|
||||
args: ['--arg1', '--arg2']
|
||||
tools: ["*"]
|
||||
env:
|
||||
ENV_VAR_NAME: ${{ secrets.COPILOT_MCP_ENV_VAR_VALUE }}
|
||||
```
|
||||
|
||||
Use `type: 'local'` (not `stdio`) in agent files. Secrets support five interpolation syntaxes including `$VAR`, `${VAR}`, `${VAR:-default}`, `${{ secrets.VAR }}`, and `${{ vars.VAR }}`.
|
||||
|
||||
## SDK Agents (Programmatic)
|
||||
|
||||
Defined as `CustomAgentConfig` objects passed to `client.createSession()`. See `sdk.md` for the full API and language-specific examples.
|
||||
|
||||
| Field | Required | Notes |
|
||||
|---|---|---|
|
||||
| `name` | Yes | Unique identifier; used in lifecycle events and for pre-selection |
|
||||
| `displayName` | No | Human-readable label in events |
|
||||
| `description` | No | Agent expertise; the runtime uses this for intent matching |
|
||||
| `tools` | No | `null` or omitted = all session tools; explicit list restricts |
|
||||
| `prompt` | Yes | System prompt for this agent's context |
|
||||
| `mcpServers` | No | Agent-scoped MCP config; not inherited from session level |
|
||||
| `infer` | No | Default `true`; set `false` to require explicit invocation |
|
||||
| `skills` | No | Skill names resolved from session `skillDirectories` |
|
||||
@@ -0,0 +1,147 @@
|
||||
---
|
||||
topic: api-reference
|
||||
source_keys:
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-finding-installing
|
||||
- github-custom-agents-configuration
|
||||
- github-sdk-custom-agents
|
||||
- context7-github-en-copilot
|
||||
---
|
||||
|
||||
# API Reference
|
||||
|
||||
## CLI Commands
|
||||
|
||||
### `copilot plugin`
|
||||
|
||||
| Command | Description |
|
||||
|---|---|
|
||||
| `copilot plugin install SPEC` | Install a plugin |
|
||||
| `copilot plugin uninstall NAME` | Remove a plugin |
|
||||
| `copilot plugin list` | List installed plugins |
|
||||
| `copilot plugin update NAME` | Update to latest version |
|
||||
| `copilot plugin enable NAME` | Re-enable a disabled plugin |
|
||||
| `copilot plugin disable NAME` | Disable without removing |
|
||||
| `copilot plugin marketplace add SPEC` | Register a marketplace |
|
||||
| `copilot plugin marketplace list` | List registered marketplaces |
|
||||
| `copilot plugin marketplace browse NAME` | Browse a marketplace |
|
||||
| `copilot plugin marketplace remove NAME` | Unregister a marketplace |
|
||||
|
||||
Flags:
|
||||
- `--force` on `marketplace remove` — removes even if plugins from it are installed
|
||||
- `--help` on any subcommand — full flag reference
|
||||
|
||||
### Plugin Install Specification Formats
|
||||
|
||||
| Format | Example |
|
||||
|---|---|
|
||||
| `PLUGIN@MARKETPLACE` | `database-tools@awesome-copilot` |
|
||||
| `OWNER/REPO` | `myorg/my-copilot-plugin` |
|
||||
| `OWNER/REPO:PATH` | `myorg/monorepo:plugins/dev` |
|
||||
| Git URL | `https://gitlab.com/org/repo.git` |
|
||||
| Local path | `./my-plugin` or `/abs/path` |
|
||||
|
||||
### In-Session Slash Commands
|
||||
|
||||
All `copilot plugin` subcommands have equivalent `/plugin` interactive counterparts:
|
||||
- `/plugin install`, `/plugin list`, `/plugin uninstall`, `/plugin update`
|
||||
- `/plugin marketplace list`, `/plugin marketplace browse NAME`
|
||||
- `/agent` — list available agents
|
||||
- `/skills list`, `/skills reload`, `/skills remove`
|
||||
|
||||
## `plugin.json` Field Reference
|
||||
|
||||
| Field | Type | Required | Constraints |
|
||||
|---|---|---|---|
|
||||
| `name` | string | Yes | Kebab-case, max 64 chars |
|
||||
| `description` | string | No | Max 1024 chars |
|
||||
| `version` | string | No | SemVer |
|
||||
| `author` | object | No | `{ name, email?, url? }` |
|
||||
| `homepage` | string | No | |
|
||||
| `repository` | string | No | |
|
||||
| `license` | string | No | SPDX identifier |
|
||||
| `keywords` | string[] | No | |
|
||||
| `category` | string | No | |
|
||||
| `tags` | string[] | No | |
|
||||
| `agents` | string or string[] | No | Default: `agents/` |
|
||||
| `skills` | string or string[] | No | Default: `skills/` |
|
||||
| `commands` | string or string[] | No | |
|
||||
| `hooks` | string or object | No | |
|
||||
| `extensions` | string, string[], or object | No | Use `{ paths, exclusive: true }` to disable built-ins |
|
||||
| `mcpServers` | string or object | No | |
|
||||
| `lspServers` | string or object | No | |
|
||||
|
||||
Manifest lookup order: `.plugin/plugin.json` → `plugin.json` → `.github/plugin/plugin.json` → `.claude-plugin/plugin.json`.
|
||||
|
||||
## CLI Agent Frontmatter Fields
|
||||
|
||||
Agent files are `.agent.md` files. Frontmatter fields:
|
||||
|
||||
| Field | Required | Notes |
|
||||
|---|---|---|
|
||||
| `name` | Yes | Agent identifier |
|
||||
| `description` | Yes | Used for automatic selection by runtime |
|
||||
| `tools` | No | Array; omit = all tools |
|
||||
|
||||
## Cloud / IDE Agent Frontmatter Fields
|
||||
|
||||
| Field | Required | Default | Notes |
|
||||
|---|---|---|---|
|
||||
| `name` | No | — | Display name |
|
||||
| `description` | Yes | — | Drives auto-selection |
|
||||
| `target` | No | `both` | `vscode` or `github-copilot` |
|
||||
| `tools` | No | all | Omit = all; `[]` = none |
|
||||
| `model` | No | default | Model identifier |
|
||||
| `disable-model-invocation` | No | `false` | Prevent runtime auto-selection |
|
||||
| `user-invocable` | No | `true` | Allow manual invocation |
|
||||
| `mcp-servers` | No | — | Cloud agent only; ignored in most IDEs |
|
||||
| `metadata` | No | — | Annotation map; ignored in VS Code |
|
||||
|
||||
Prompt body max: 30,000 characters.
|
||||
|
||||
## SDK `CustomAgentConfig` Fields
|
||||
|
||||
| Field | Type | Required | Notes |
|
||||
|---|---|---|---|
|
||||
| `name` | string | Yes | Unique identifier |
|
||||
| `displayName` | string | No | Label in lifecycle events |
|
||||
| `description` | string | No | Used for intent-based routing |
|
||||
| `tools` | string[] or null | No | `null`/omit = all session tools |
|
||||
| `prompt` | string | Yes | System prompt |
|
||||
| `mcpServers` | object | No | Agent-scoped; not inherited from session |
|
||||
| `infer` | boolean | No | Default `true`; `false` = explicit invocation only |
|
||||
| `skills` | string[] | No | Skill names from `skillDirectories` |
|
||||
|
||||
## SDK Session-Level Fields (Custom Agent Relevant)
|
||||
|
||||
| Field | Type | Notes |
|
||||
|---|---|---|
|
||||
| `customAgents` | array | The agent definitions |
|
||||
| `agent` | string | Pre-activate a named agent at session start |
|
||||
| `skillDirectories` | string[] | Directories for skill name resolution |
|
||||
| `defaultAgent.excludedTools` | string[] | Hide tools from main agent; sub-agents still see them |
|
||||
| `model` | string | Default model for all agents unless overridden |
|
||||
| `onPermissionRequest` | function | Session-wide; no per-agent override |
|
||||
|
||||
## Sub-Agent Lifecycle Events (SDK)
|
||||
|
||||
| Event | Key Fields |
|
||||
|---|---|
|
||||
| `subagent.selected` | `agentName`, `agentDisplayName`, `tools` |
|
||||
| `subagent.started` | `toolCallId`, `agentName`, `agentDisplayName`, `agentDescription` |
|
||||
| `subagent.completed` | `toolCallId`, `agentName`, `agentDisplayName` |
|
||||
| `subagent.failed` | `toolCallId`, `agentName`, `agentDisplayName`, `error` |
|
||||
| `subagent.deselected` | (no data) |
|
||||
|
||||
`toolCallId` is stable across `started`/`completed`/`failed` for a single invocation.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Purpose |
|
||||
|---|---|
|
||||
| `COPILOT_HOME` | Override config dir (default: `~/.copilot/`) |
|
||||
| `COPILOT_CACHE_HOME` | Override marketplace cache dir |
|
||||
| `COPILOT_SKILLS_DIRS` | Additional skill search paths |
|
||||
| `COPILOT_PLUGIN_DATA` | Persistent per-plugin data dir |
|
||||
| `CLAUDE_PLUGIN_DATA` | Alias for `COPILOT_PLUGIN_DATA` |
|
||||
| `PLUGIN_ROOT` | Installed plugin directory (LSP scripts / hook cwd) |
|
||||
@@ -0,0 +1,155 @@
|
||||
---
|
||||
topic: configuration
|
||||
source_keys:
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-creating
|
||||
- github-custom-agents-configuration
|
||||
- context7-github-en-copilot
|
||||
---
|
||||
|
||||
# Configuration
|
||||
|
||||
## `plugin.json` — Plugin Manifest
|
||||
|
||||
Located at one of these paths (checked in order, first found wins):
|
||||
- `.plugin/plugin.json`
|
||||
- `plugin.json`
|
||||
- `.github/plugin/plugin.json`
|
||||
- `.claude-plugin/plugin.json`
|
||||
|
||||
### Required field
|
||||
|
||||
| Field | Type | Notes |
|
||||
|---|---|---|
|
||||
| `name` | string | Kebab-case; letters, numbers, hyphens only; max 64 chars |
|
||||
|
||||
### Optional metadata fields
|
||||
|
||||
| Field | Type | Notes |
|
||||
|---|---|---|
|
||||
| `description` | string | Max 1024 chars |
|
||||
| `version` | string | SemVer |
|
||||
| `author` | object | `{ name (required), email?, url? }` |
|
||||
| `homepage` | string | |
|
||||
| `repository` | string | |
|
||||
| `license` | string | SPDX identifier |
|
||||
| `keywords` | string[] | Discoverability tags |
|
||||
| `category` | string | |
|
||||
| `tags` | string[] | |
|
||||
|
||||
### Component path fields
|
||||
|
||||
| Field | Type | Default | Purpose |
|
||||
|---|---|---|---|
|
||||
| `agents` | string or string[] | `agents/` | Agent file directories |
|
||||
| `skills` | string or string[] | `skills/` | Skill directories |
|
||||
| `commands` | string or string[] | — | Command directories |
|
||||
| `hooks` | string or object | — | Hooks config file path or inline object |
|
||||
| `extensions` | string, string[], or object | — | Extension dirs; `{ paths: [...], exclusive: true }` disables all built-ins |
|
||||
| `mcpServers` | string or object | — | MCP server config path or inline definitions |
|
||||
| `lspServers` | string or object | — | LSP server config path or inline definitions |
|
||||
|
||||
## `hooks.json` — Lifecycle Hooks
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"hooks": {
|
||||
"sessionStart": [
|
||||
{
|
||||
"type": "command",
|
||||
"bash": "echo 'started'",
|
||||
"powershell": "Write-Output 'started'",
|
||||
"cwd": ".",
|
||||
"timeoutSec": 30,
|
||||
"env": { "MY_VAR": "value" }
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`version: 1` is required. Available lifecycle hook points:
|
||||
|
||||
- `sessionStart`
|
||||
- `sessionEnd`
|
||||
- `userPromptSubmitted`
|
||||
- `preToolUse`
|
||||
- `postToolUse`
|
||||
- `errorOccurred`
|
||||
- `agentStop`
|
||||
|
||||
Each entry must have `type: "command"`. Provide `bash` for Linux/macOS and `powershell` for Windows — the correct script is selected automatically at runtime.
|
||||
|
||||
Hook files outside plugins live in `.github/hooks/NAME.json` (repo) or `~/.copilot/hooks/` (user).
|
||||
|
||||
## `.mcp.json` — MCP Server Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"serverName": {
|
||||
"type": "local",
|
||||
"command": "string",
|
||||
"args": ["array"],
|
||||
"env": {},
|
||||
"tools": ["*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Supported `type` values:
|
||||
- `local` / `stdio` — launches a local process
|
||||
- `http` — remote server, Streamable transport (preferred for new remote servers)
|
||||
- `sse` — remote server, deprecated
|
||||
|
||||
The `tools` field accepts `["*"]` for all tools or an explicit list. For `http` type, use `url` and `headers` fields instead of `command`.
|
||||
|
||||
## Skill Configuration
|
||||
|
||||
Skills live in named subdirectories within a `skills/` directory:
|
||||
|
||||
```
|
||||
skills/
|
||||
└── deploy/
|
||||
└── SKILL.md
|
||||
```
|
||||
|
||||
`SKILL.md` frontmatter:
|
||||
|
||||
| Field | Required | Notes |
|
||||
|---|---|---|
|
||||
| `name` | Yes | Lowercase, hyphens for spaces |
|
||||
| `description` | Yes | Drives automatic skill selection |
|
||||
| `allowed-tools` | No | Pre-approves tools (e.g. `shell`) to skip per-use permission prompts |
|
||||
| `license` | No | |
|
||||
|
||||
Only set `allowed-tools` if you have fully reviewed the skill and trust its source — it bypasses interactive confirmation for the listed tools.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Purpose |
|
||||
|---|---|
|
||||
| `COPILOT_HOME` | Override the Copilot CLI config directory (default: `~/.copilot/`) |
|
||||
| `COPILOT_CACHE_HOME` | Override the marketplace cache directory |
|
||||
| `COPILOT_SKILLS_DIRS` | Additional skill search paths (colon-separated) |
|
||||
| `COPILOT_PLUGIN_DATA` | Persistent writable data directory for a plugin (unique per plugin, survives updates) |
|
||||
| `CLAUDE_PLUGIN_DATA` | Alias for `COPILOT_PLUGIN_DATA` |
|
||||
| `PLUGIN_ROOT` | Available in LSP `cwd` and script paths; resolves to the installed plugin directory |
|
||||
|
||||
## LSP Server Configuration
|
||||
|
||||
Can be declared inline in `plugin.json` or in a separate `lsp-config/servers.json` file. Supports platform-specific launch scripts via `bash` and `powershell` keys.
|
||||
|
||||
| Field | Required | Description |
|
||||
|---|---|---|
|
||||
| `command` | One of these three | Executable path |
|
||||
| `bash` | ^ | Bash script, run via `bash -c SCRIPT` |
|
||||
| `powershell` | ^ | PowerShell script, run via `pwsh -c SCRIPT` |
|
||||
| `fileExtensions` | Yes | Map of `.ext` → language ID |
|
||||
| `cwd` | No | Working dir; supports `${PLUGIN_ROOT}` |
|
||||
| `args` | No | Arguments to `command` |
|
||||
| `env` | No | Environment variables |
|
||||
| `rootUri` | No | Project root relative to git root (default: `.`) |
|
||||
| `initializationOptions` | No | LSP init options |
|
||||
@@ -0,0 +1,263 @@
|
||||
---
|
||||
topic: examples
|
||||
source_keys:
|
||||
- context7-github-en-copilot
|
||||
- github-plugins-creating
|
||||
- github-custom-agents-configuration
|
||||
- github-sdk-custom-agents
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-marketplace
|
||||
---
|
||||
|
||||
# Examples
|
||||
|
||||
## Plugin Directory Structure
|
||||
|
||||
```
|
||||
my-plugin/
|
||||
├── plugin.json
|
||||
├── agents/
|
||||
│ └── helper.agent.md
|
||||
├── skills/
|
||||
│ └── deploy/
|
||||
│ └── SKILL.md
|
||||
├── hooks.json
|
||||
└── .mcp.json
|
||||
```
|
||||
|
||||
## Minimal `plugin.json`
|
||||
|
||||
```json
|
||||
{ "name": "my-plugin" }
|
||||
```
|
||||
|
||||
## Full `plugin.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-dev-tools",
|
||||
"description": "React development utilities",
|
||||
"version": "1.2.0",
|
||||
"author": {
|
||||
"name": "Jane Doe",
|
||||
"email": "jane@example.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": ["react", "frontend"],
|
||||
"agents": "agents/",
|
||||
"skills": ["skills/", "extra-skills/"],
|
||||
"hooks": "hooks.json",
|
||||
"mcpServers": ".mcp.json"
|
||||
}
|
||||
```
|
||||
|
||||
## CLI Agent Examples
|
||||
|
||||
### Read-Only Research Agent
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: researcher
|
||||
description: Explores codebases and answers questions; never modifies files
|
||||
tools: ["search", "read"]
|
||||
---
|
||||
|
||||
You are a research assistant. Analyze code and answer questions clearly.
|
||||
Do not modify any files under any circumstances.
|
||||
```
|
||||
|
||||
### Write-Capable Implementation Agent
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: implementer
|
||||
description: Makes targeted code changes based on provided specifications
|
||||
tools: ["read", "edit", "bash"]
|
||||
---
|
||||
|
||||
You are a code editor. Make minimal, surgical changes to files as instructed.
|
||||
Always read the relevant file before editing.
|
||||
```
|
||||
|
||||
## Cloud / IDE Agent Examples
|
||||
|
||||
### Testing Specialist (tool-unrestricted, behavioral constraint)
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: test-specialist
|
||||
description: Focuses on test coverage and quality without modifying production code
|
||||
---
|
||||
|
||||
You are a testing specialist. Write tests, identify coverage gaps, and improve
|
||||
test quality. Never modify source files outside of test directories.
|
||||
```
|
||||
|
||||
### Implementation Planner (tool-restricted)
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: implementation-planner
|
||||
description: Creates detailed implementation plans and technical specifications in markdown
|
||||
tools: ["read", "search", "edit"]
|
||||
---
|
||||
|
||||
You are a technical planning specialist. Produce comprehensive implementation plans
|
||||
as structured markdown. Do not execute code or run shell commands.
|
||||
```
|
||||
|
||||
### Agent with Custom MCP Server
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: db-analyst
|
||||
description: Analyzes database schema and queries using a Postgres MCP server
|
||||
tools: ["read", "search", "custom-db/query"]
|
||||
mcp-servers:
|
||||
custom-db:
|
||||
type: 'local'
|
||||
command: 'pg-mcp-server'
|
||||
args: ['--port', '5432']
|
||||
tools: ["*"]
|
||||
env:
|
||||
DB_PASSWORD: ${{ secrets.COPILOT_DB_PASSWORD }}
|
||||
---
|
||||
|
||||
You are a database analyst. Use the Postgres MCP server to run read-only queries
|
||||
and explain schema structure.
|
||||
```
|
||||
|
||||
## SDK Examples
|
||||
|
||||
### TypeScript — Researcher + Editor Pattern
|
||||
|
||||
```typescript
|
||||
import { CopilotClient } from "@github/copilot-sdk";
|
||||
|
||||
const client = new CopilotClient();
|
||||
await client.start();
|
||||
|
||||
const session = await client.createSession({
|
||||
model: "gpt-4.1",
|
||||
customAgents: [
|
||||
{
|
||||
name: "researcher",
|
||||
displayName: "Research Agent",
|
||||
description: "Explores codebases and answers questions using read-only tools",
|
||||
tools: ["grep", "glob", "view"],
|
||||
prompt: "You are a research assistant. Analyze code and answer questions. Do not modify any files.",
|
||||
},
|
||||
{
|
||||
name: "editor",
|
||||
displayName: "Editor Agent",
|
||||
description: "Makes targeted code changes",
|
||||
tools: ["view", "edit", "bash"],
|
||||
prompt: "You are a code editor. Make minimal, surgical changes to files as requested.",
|
||||
},
|
||||
],
|
||||
onPermissionRequest: async () => ({ kind: "approve-once" }),
|
||||
});
|
||||
```
|
||||
|
||||
### Python — Equivalent
|
||||
|
||||
```python
|
||||
from copilot import CopilotClient, PermissionDecisionApproveOnce
|
||||
|
||||
client = CopilotClient()
|
||||
await client.start()
|
||||
|
||||
session = await client.create_session(
|
||||
model="gpt-4.1",
|
||||
custom_agents=[
|
||||
{
|
||||
"name": "researcher",
|
||||
"display_name": "Research Agent",
|
||||
"description": "Explores codebases and answers questions using read-only tools",
|
||||
"tools": ["grep", "glob", "view"],
|
||||
"prompt": "You are a research assistant. Analyze code. Do not modify files.",
|
||||
},
|
||||
{
|
||||
"name": "editor",
|
||||
"display_name": "Editor Agent",
|
||||
"description": "Makes targeted code changes",
|
||||
"tools": ["view", "edit", "bash"],
|
||||
"prompt": "You are a code editor. Make minimal changes.",
|
||||
},
|
||||
],
|
||||
on_permission_request=lambda req, inv: PermissionDecisionApproveOnce(),
|
||||
)
|
||||
```
|
||||
|
||||
### Pre-Selecting an Agent at Session Start
|
||||
|
||||
```typescript
|
||||
const session = await client.createSession({
|
||||
model: "gpt-4.1",
|
||||
customAgents: [{ name: "researcher", ... }],
|
||||
agent: "researcher", // pre-activates without inference roundtrip
|
||||
onPermissionRequest: async () => ({ kind: "approve-once" }),
|
||||
});
|
||||
```
|
||||
|
||||
### Listening to Sub-Agent Lifecycle Events
|
||||
|
||||
```typescript
|
||||
session.on((event) => {
|
||||
if (event.type === "subagent.started") {
|
||||
console.log(`Sub-agent started: ${event.agentName} (${event.toolCallId})`);
|
||||
}
|
||||
if (event.type === "subagent.failed") {
|
||||
console.error(`Sub-agent failed: ${event.agentName}`, event.error);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Hooks Example
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"hooks": {
|
||||
"sessionStart": [
|
||||
{
|
||||
"type": "command",
|
||||
"bash": "echo 'Copilot session started'",
|
||||
"powershell": "Write-Output 'Copilot session started'",
|
||||
"cwd": ".",
|
||||
"timeoutSec": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Marketplace Manifest Example
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-team-marketplace",
|
||||
"owner": { "name": "My Team", "email": "team@example.com" },
|
||||
"metadata": { "description": "Internal tools", "version": "1.0.0" },
|
||||
"plugins": [
|
||||
{ "name": "backend-tools", "source": "./plugins/backend", "version": "1.0.0" },
|
||||
{ "name": "frontend-tools", "source": "./plugins/frontend", "version": "2.1.0" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Register it: `copilot plugin marketplace add myorg/my-team-plugins`
|
||||
|
||||
## Cross-Platform LSP Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"lspServers": {
|
||||
"my-lsp": {
|
||||
"bash": "${PLUGIN_ROOT}/scripts/start-lsp.sh",
|
||||
"powershell": "${PLUGIN_ROOT}/scripts/start-lsp.ps1",
|
||||
"fileExtensions": { ".myext": "mylang" }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
topic: installation
|
||||
source_keys:
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-finding-installing
|
||||
- github-plugins-creating
|
||||
- context7-github-en-copilot
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
## Plugin Install Specification Formats
|
||||
|
||||
The `copilot plugin install` command accepts multiple specification formats:
|
||||
|
||||
| Format | Example | When to use |
|
||||
|---|---|---|
|
||||
| `PLUGIN-NAME@MARKETPLACE` | `plugin install db-tools@awesome-copilot` | Installing from a registered marketplace |
|
||||
| `OWNER/REPO` | `plugin install myorg/my-plugin` | GitHub repo at root |
|
||||
| `OWNER/REPO:PATH` | `plugin install myorg/monorepo:plugins/dev-tools` | Plugin in a subdirectory |
|
||||
| `https://...` | `plugin install https://gitlab.com/org/repo.git` | Arbitrary Git URL |
|
||||
| `./path` or `/abs/path` | `plugin install ./my-plugin` | Local filesystem (development) |
|
||||
|
||||
## Core CLI Commands
|
||||
|
||||
```shell
|
||||
# Install
|
||||
copilot plugin install SPECIFICATION
|
||||
|
||||
# List installed plugins
|
||||
copilot plugin list
|
||||
|
||||
# Update a plugin to latest version
|
||||
copilot plugin update PLUGIN-NAME
|
||||
|
||||
# Remove a plugin
|
||||
copilot plugin uninstall PLUGIN-NAME
|
||||
|
||||
# Disable without removing (preserves config)
|
||||
copilot plugin disable PLUGIN-NAME
|
||||
|
||||
# Re-enable a disabled plugin
|
||||
copilot plugin enable PLUGIN-NAME
|
||||
```
|
||||
|
||||
All `copilot plugin` subcommands have equivalent `/plugin` slash-command forms for interactive sessions.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
For local development, install from a local path:
|
||||
|
||||
```shell
|
||||
copilot plugin install ./my-plugin
|
||||
```
|
||||
|
||||
Plugins are **cached on install** — changes to the plugin files on disk are not picked up automatically. Re-run the install command to update the cache:
|
||||
|
||||
```shell
|
||||
copilot plugin install ./my-plugin # picks up latest changes
|
||||
```
|
||||
|
||||
Verify loaded components after install:
|
||||
- `/agent` — lists available agents (confirm yours is listed)
|
||||
- `/skills list` — lists loaded skills
|
||||
|
||||
## Install Locations
|
||||
|
||||
Installed plugins are stored at:
|
||||
- Marketplace installs: `~/.copilot/installed-plugins/MARKETPLACE/PLUGIN-NAME/`
|
||||
- Direct (non-marketplace) installs: `~/.copilot/installed-plugins/_direct/SOURCE-ID/`
|
||||
|
||||
The `COPILOT_HOME` env var overrides the `~/.copilot/` base directory.
|
||||
|
||||
## Marketplace Cache
|
||||
|
||||
The marketplace index is cached locally at:
|
||||
- Linux: `~/.cache/copilot/marketplaces/`
|
||||
- macOS: `~/Library/Caches/copilot/marketplaces/`
|
||||
|
||||
Override with `COPILOT_CACHE_HOME`. Relevant in CI and containerized environments.
|
||||
|
||||
## Cloud / IDE Custom Agents — Setup
|
||||
|
||||
For cloud and IDE custom agents (the non-CLI track), installation is through Git: commit the `.md` agent files to the appropriate path in your repository (`.github/copilot/agents/` or org/enterprise equivalent). No CLI install step is needed — the Copilot service picks up files from the repository automatically. Scoping resolution (enterprise > org > repo) happens at request time.
|
||||
|
||||
## SDK Installation
|
||||
|
||||
The Copilot SDK is a standard package install per language:
|
||||
|
||||
```shell
|
||||
npm install @github/copilot-sdk # TypeScript / JavaScript
|
||||
pip install copilot-sdk # Python
|
||||
go get github.com/github/copilot-sdk/go # Go
|
||||
```
|
||||
|
||||
Java and .NET packages follow standard Maven/NuGet distribution. SDK agents are not installed — they are defined in code passed to `client.createSession()` at runtime.
|
||||
@@ -0,0 +1,133 @@
|
||||
---
|
||||
topic: marketplace
|
||||
source_keys:
|
||||
- github-plugins-marketplace
|
||||
- github-plugins-finding-installing
|
||||
- github-cli-plugin-reference
|
||||
- context7-github-en-copilot
|
||||
---
|
||||
|
||||
# Marketplace
|
||||
|
||||
A plugin marketplace is a Git repository (or local directory) containing a `marketplace.json` manifest and the plugin directories it references. Two marketplaces are registered by default: `copilot-plugins` and `awesome-copilot` (both hosted under the `github/` org on GitHub.com).
|
||||
|
||||
## Browsing and Installing from Marketplaces
|
||||
|
||||
```shell
|
||||
# List registered marketplaces
|
||||
copilot plugin marketplace list
|
||||
|
||||
# Browse plugins in a marketplace
|
||||
copilot plugin marketplace browse MARKETPLACE-NAME
|
||||
# example:
|
||||
copilot plugin marketplace browse awesome-copilot
|
||||
|
||||
# Install a plugin from a marketplace
|
||||
copilot plugin install PLUGIN-NAME@MARKETPLACE-NAME
|
||||
# example:
|
||||
copilot plugin install database-data-management@awesome-copilot
|
||||
```
|
||||
|
||||
## Managing Marketplaces
|
||||
|
||||
```shell
|
||||
# Register a GitHub.com repository as a marketplace
|
||||
copilot plugin marketplace add OWNER/REPO
|
||||
|
||||
# Register a non-GitHub Git host
|
||||
copilot plugin marketplace add https://gitlab.com/OWNER/REPO.git
|
||||
|
||||
# Register a local filesystem directory
|
||||
copilot plugin marketplace add /path/to/local/marketplace-dir
|
||||
|
||||
# Remove a registered marketplace
|
||||
copilot plugin marketplace remove MARKETPLACE-NAME
|
||||
|
||||
# Force-remove even when plugins from it are installed
|
||||
copilot plugin marketplace remove MARKETPLACE-NAME --force
|
||||
```
|
||||
|
||||
When adding, reference by `OWNER/REPO`. When removing, reference by the name shown in `marketplace list` (which comes from the `name` field in `marketplace.json`).
|
||||
|
||||
Removing a marketplace with installed plugins fails unless `--force` is passed. `--force` simultaneously unregisters the marketplace and uninstalls all its plugins.
|
||||
|
||||
## Creating a Marketplace
|
||||
|
||||
### Step 1: Create `marketplace.json`
|
||||
|
||||
Place the file at `.github/plugin/marketplace.json` in a Git repository. The CLI also recognizes `.claude-plugin/marketplace.json` as an alternative path.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-marketplace",
|
||||
"owner": {
|
||||
"name": "Your Organization",
|
||||
"email": "plugins@example.com"
|
||||
},
|
||||
"metadata": {
|
||||
"description": "Curated plugins for our team",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "frontend-design",
|
||||
"description": "Create professional GUIs",
|
||||
"version": "2.1.0",
|
||||
"source": "./plugins/frontend-design"
|
||||
},
|
||||
{
|
||||
"name": "security-checks",
|
||||
"description": "Check for common vulnerabilities",
|
||||
"version": "1.3.0",
|
||||
"source": "./plugins/security-checks"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### `marketplace.json` Top-Level Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|---|---|---|
|
||||
| `name` | Yes | Kebab-case; max 64 chars |
|
||||
| `owner` | Yes | `{ name: string, email?: string }` |
|
||||
| `plugins` | Yes | Array of plugin entry objects |
|
||||
| `metadata` | No | `{ description?, version?, pluginRoot? }` |
|
||||
|
||||
### Plugin Entry Fields (inside `plugins[]`)
|
||||
|
||||
| Field | Required | Notes |
|
||||
|---|---|---|
|
||||
| `name` | Yes | Kebab-case; max 64 chars |
|
||||
| `source` | Yes | Relative path from repo root to plugin directory |
|
||||
| `description` | No | Max 1024 chars |
|
||||
| `version` | No | |
|
||||
| `author` | No | `{ name, email?, url? }` |
|
||||
| `homepage`, `repository`, `license`, `keywords`, `category`, `tags` | No | Standard metadata |
|
||||
| `agents`, `skills`, `commands`, `hooks`, `mcpServers`, `lspServers` | No | Component overrides |
|
||||
| `strict` | No | Default `true`; set `false` for relaxed schema validation |
|
||||
|
||||
### Step 2: Add Plugin Directories
|
||||
|
||||
For each entry in `plugins[]`, add the plugin directory at the `source` path relative to the repo root. For example, `source: "./plugins/frontend-design"` means the plugin lives at `plugins/frontend-design/` in the repo.
|
||||
|
||||
### Step 3: Share
|
||||
|
||||
Users register your marketplace with:
|
||||
|
||||
```shell
|
||||
# GitHub-hosted
|
||||
copilot plugin marketplace add OWNER/REPO
|
||||
|
||||
# Non-GitHub Git host
|
||||
copilot plugin marketplace add https://git.example.com/org/repo
|
||||
|
||||
# Local shared filesystem
|
||||
copilot plugin marketplace add /path/to/local/dir
|
||||
```
|
||||
|
||||
Reference implementations: `github/copilot-plugins` and `github/awesome-copilot` — both have `marketplace.json` at `.github/plugin/marketplace.json`.
|
||||
|
||||
## The `strict` Field
|
||||
|
||||
When `strict: false` is set on a plugin entry, the CLI performs relaxed schema validation for that plugin. This is useful for plugins distributed as `.claude-plugin/` directories that also need to serve Claude Code — it allows extra or non-standard fields without failing validation.
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
topic: overview
|
||||
source_keys:
|
||||
- context7-github-en-copilot
|
||||
- github-plugins-creating
|
||||
- github-cli-plugin-reference
|
||||
- github-custom-agents-configuration
|
||||
- github-sdk-custom-agents
|
||||
---
|
||||
|
||||
# GitHub Copilot Agents and Plugins — Overview
|
||||
|
||||
GitHub Copilot exposes three distinct extension tracks. They share some vocabulary but differ in distribution model, runtime context, and target audience.
|
||||
|
||||
## Three Extension Tracks
|
||||
|
||||
### 1. CLI Plugin System
|
||||
|
||||
Plugins are installable packages for the Copilot CLI (`gh copilot` / `copilot` binary). A plugin bundles agents, skills, hooks, MCP servers, and LSP servers into a single directory with a `plugin.json` manifest. Plugins are discovered through **marketplaces** — Git repositories containing a `marketplace.json` registry — and installed via `copilot plugin install`.
|
||||
|
||||
This is the primary extensibility model for the CLI. It mirrors what you can configure locally (`.agent.md` files, `SKILL.md` files, `hooks.json`, `.mcp.json`) but makes those artifacts versionable and distributable.
|
||||
|
||||
### 2. Cloud / IDE Custom Agents
|
||||
|
||||
Custom agents for the GitHub Copilot cloud agent and supported IDEs are `.md` files committed to a repository under `.github/copilot/agents/` (or equivalent organization/enterprise paths). They carry YAML frontmatter specifying tool restrictions, model selection, and MCP server bindings, with the prompt body following.
|
||||
|
||||
These agents are scoped at three levels — **enterprise > organization > repository** — with lower levels overriding higher ones on name collision. The feature is in public preview for JetBrains IDEs, Eclipse, and Xcode as of the time of research.
|
||||
|
||||
### 3. SDK Custom Agents (Programmatic)
|
||||
|
||||
The Copilot SDK (`@github/copilot-sdk` for TypeScript, plus Go, Python, Java, .NET packages) lets application developers attach named `CustomAgentConfig` objects to a session at creation time. The runtime can auto-select sub-agents based on task context (`infer: true`, the default) or require explicit invocation. This track is for building Copilot-powered applications rather than personalizing the CLI.
|
||||
|
||||
## Component Primitives
|
||||
|
||||
All three tracks build on the same underlying primitives:
|
||||
|
||||
| Primitive | CLI | Cloud Agent | SDK |
|
||||
|---|---|---|---|
|
||||
| Agents | `.agent.md` files | `.md` files with frontmatter | `CustomAgentConfig` in code |
|
||||
| Skills | `SKILL.md` in named subdirs | `SKILL.md` (cloud variant) | `skillDirectories` + `skills[]` |
|
||||
| Hooks | `hooks.json` | Not supported | Not applicable |
|
||||
| MCP servers | `.mcp.json` | `mcp-servers:` frontmatter block | `mcpServers` in `SessionConfig` |
|
||||
| LSP servers | `lsp-config/servers.json` | Not supported | Not applicable |
|
||||
|
||||
## Loading Hierarchy (CLI)
|
||||
|
||||
For agents and skills, the first-found instance wins when names collide:
|
||||
|
||||
1. Project-level: `.github/agents/`, `.claude/agents/`
|
||||
2. Personal: `~/.copilot/agents/`, `~/.copilot/skills/`
|
||||
3. Plugin-provided components
|
||||
4. Remote org/enterprise agents (lowest priority)
|
||||
|
||||
For MCP servers the rule is reversed: last-wins. The `--additional-mcp-config` CLI flag takes highest priority.
|
||||
|
||||
Built-in agents (`explore`, `code-review`, `general-purpose`, `research`, `task`) and built-in tools (`bash`, `view`, `edit`, `grep`, `glob`) cannot be overridden.
|
||||
|
||||
## Sub-Agent Architecture
|
||||
|
||||
All three tracks support the sub-agent pattern: a coordinating agent delegates subtasks to specialized agents with restricted tool sets and isolated context windows. In the CLI and SDK, agents can spawn sub-agents; the SDK additionally streams structured lifecycle events (`subagent.started`, `subagent.completed`, `subagent.failed`) so host applications can display an agent-activity tree.
|
||||
@@ -0,0 +1,159 @@
|
||||
---
|
||||
topic: sdk
|
||||
source_keys:
|
||||
- github-sdk-custom-agents
|
||||
- context7-github-en-copilot
|
||||
---
|
||||
|
||||
# Copilot SDK — Custom Agents
|
||||
|
||||
The Copilot SDK is the programmatic interface for building Copilot-powered applications. Custom agents in the SDK context are runtime configurations attached to a session rather than files on disk.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
- **Custom agent** — a named configuration with its own system prompt, restricted tool set, and optional MCP servers.
|
||||
- **Sub-agent** — a custom agent invoked by the Copilot runtime to handle a portion of a task in an isolated context window.
|
||||
- **Inference** — the runtime's automatic selection of an agent based on user intent. Enabled by default (`infer: true`). Set `infer: false` on agents that should only run when explicitly requested (especially destructive agents).
|
||||
|
||||
## Session Creation
|
||||
|
||||
Pass `customAgents` to `client.createSession()` along with a permission handler. Permission handling is session-wide — there is no per-agent override.
|
||||
|
||||
```typescript
|
||||
import { CopilotClient } from "@github/copilot-sdk";
|
||||
|
||||
const client = new CopilotClient();
|
||||
await client.start();
|
||||
|
||||
const session = await client.createSession({
|
||||
model: "gpt-4.1",
|
||||
customAgents: [
|
||||
{
|
||||
name: "researcher",
|
||||
displayName: "Research Agent",
|
||||
description: "Read-only codebase exploration",
|
||||
tools: ["grep", "glob", "view"],
|
||||
prompt: "You are a research assistant. Do not modify files.",
|
||||
},
|
||||
{
|
||||
name: "editor",
|
||||
displayName: "Editor Agent",
|
||||
description: "Makes targeted code changes",
|
||||
tools: ["view", "edit", "bash"],
|
||||
prompt: "You are a code editor. Make minimal changes.",
|
||||
},
|
||||
],
|
||||
onPermissionRequest: async () => ({ kind: "approve-once" }),
|
||||
});
|
||||
```
|
||||
|
||||
## `CustomAgentConfig` Fields
|
||||
|
||||
| Field | Required | Default | Notes |
|
||||
|---|---|---|---|
|
||||
| `name` | Yes | — | Identifier; must match `agent` pre-selection exactly |
|
||||
| `displayName` | No | — | Label shown in lifecycle events |
|
||||
| `description` | No | — | Used for runtime intent matching; quality directly affects routing accuracy |
|
||||
| `tools` | No | all session tools | `null` or omitted = all; explicit list = restrict |
|
||||
| `prompt` | Yes | — | System prompt injected into this agent's context |
|
||||
| `mcpServers` | No | — | Agent-scoped MCP config; not inherited from session; not visible to other agents |
|
||||
| `infer` | No | `true` | Set `false` for agents that should not be auto-selected |
|
||||
| `skills` | No | — | Skill names from `skillDirectories`; eagerly injected at startup; not inherited by sub-agents |
|
||||
|
||||
## Session-Level Fields Relevant to Agents
|
||||
|
||||
| Field | Type | Notes |
|
||||
|---|---|---|
|
||||
| `customAgents` | array | Agent definitions |
|
||||
| `agent` | string | Pre-activate a named agent; exact name match required |
|
||||
| `skillDirectories` | string[] | Directories for resolving `skills` names |
|
||||
| `defaultAgent.excludedTools` | string[] | Hides tools from main agent; sub-agents still see them |
|
||||
| `model` | string | Default model for all agents |
|
||||
|
||||
## Tool Scoping
|
||||
|
||||
Two orthogonal mechanisms control tool access:
|
||||
|
||||
**Per-agent `tools` list** — restricts what that agent can call. `null` or omitting the field means all session tools are available.
|
||||
|
||||
**`defaultAgent.excludedTools`** — hides tools from the built-in (main/orchestrator) agent while keeping them available to named sub-agents. Use this to prevent the orchestrator from using heavy-context or destructive tools directly.
|
||||
|
||||
Precedence: session-level `excludedTools` beats `defaultAgent.excludedTools`. If a tool appears in both, no agent gets it.
|
||||
|
||||
## Permission Handling
|
||||
|
||||
```typescript
|
||||
// TypeScript
|
||||
onPermissionRequest: async () => ({ kind: "approve-once" })
|
||||
|
||||
// Python
|
||||
on_permission_request=lambda req, inv: PermissionDecisionApproveOnce()
|
||||
|
||||
// Go
|
||||
OnPermissionRequest: func(req, inv) (rpc.PermissionDecision, error) {
|
||||
return &rpc.PermissionDecisionApproveOnce{}, nil
|
||||
},
|
||||
|
||||
// .NET
|
||||
OnPermissionRequest = (req, inv) => Task.FromResult(PermissionDecision.ApproveOnce())
|
||||
|
||||
// Java
|
||||
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
|
||||
```
|
||||
|
||||
## Sub-Agent Lifecycle Events
|
||||
|
||||
Subscribe to all session events via `session.on(handler)`. Filter by `event.type`:
|
||||
|
||||
| Event Type | Key Fields |
|
||||
|---|---|
|
||||
| `subagent.selected` | `agentName`, `agentDisplayName`, `tools` |
|
||||
| `subagent.started` | `toolCallId`, `agentName`, `agentDisplayName`, `agentDescription` |
|
||||
| `subagent.completed` | `toolCallId`, `agentName`, `agentDisplayName` |
|
||||
| `subagent.failed` | `toolCallId`, `agentName`, `agentDisplayName`, `error` |
|
||||
| `subagent.deselected` | (no data) |
|
||||
|
||||
`toolCallId` is stable across `started`/`completed`/`failed` for a single invocation — key an agent-tree map on it.
|
||||
|
||||
```typescript
|
||||
const agentTree = new Map();
|
||||
|
||||
session.on((event) => {
|
||||
if (event.type === "subagent.started") {
|
||||
agentTree.set(event.toolCallId, {
|
||||
name: event.agentName,
|
||||
status: "running",
|
||||
startedAt: Date.now(),
|
||||
});
|
||||
}
|
||||
if (event.type === "subagent.completed") {
|
||||
const node = agentTree.get(event.toolCallId);
|
||||
if (node) node.status = "done";
|
||||
}
|
||||
if (event.type === "subagent.failed") {
|
||||
const node = agentTree.get(event.toolCallId);
|
||||
if (node) { node.status = "failed"; node.error = event.error; }
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Language-Specific Notes
|
||||
|
||||
**TypeScript**: camelCase field names (`customAgents`, `displayName`, `onPermissionRequest`).
|
||||
|
||||
**Python**: snake_case (`custom_agents`, `display_name`, `on_permission_request`).
|
||||
|
||||
**Go**: PascalCase struct fields (`CustomAgents`, `DisplayName`); `copilot.CustomAgentConfig` struct.
|
||||
|
||||
**.NET**: `SessionConfig` object initializer with `CustomAgents = new List<CustomAgentConfig> { new() { ... } }`.
|
||||
|
||||
**Java**: builder pattern — `new CustomAgentConfig().setName(...).setTools(List.of(...)).setPrompt(...)`.
|
||||
|
||||
## Key Gotchas
|
||||
|
||||
- **Description quality directly affects routing.** Vague descriptions produce bad inference. Be specific about what the agent does and what it will not do.
|
||||
- **`infer: true` is the default.** Explicitly set `infer: false` on agents with destructive capability (file deletion, schema migrations) so the runtime cannot select them autonomously.
|
||||
- **Sub-agents do not inherit parent skills.** Each agent must declare its own `skills` list.
|
||||
- **Agent-scoped MCP is not shared.** An MCP server in a sub-agent's `mcpServers` block is invisible to the main agent and other sub-agents.
|
||||
- **`subagent.failed` requires explicit handling.** The runtime does not retry or fall back automatically.
|
||||
- **`agent` pre-selection is an exact match.** A mismatch silently falls through to inference.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Sources
|
||||
|
||||
## context7-github-en-copilot
|
||||
|
||||
- **URL:** context7:/websites/github_en_copilot
|
||||
- **Description:** Official GitHub Copilot documentation indexed by Context7; covers CLI plugins, custom agents, SDK, and marketplace
|
||||
- **Contributing files:** overview.md, agent-definition.md, configuration.md, installation.md, marketplace.md, api-reference.md, examples.md, sdk.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-custom-agents-configuration
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/reference/custom-agents-configuration
|
||||
- **Description:** Reference for cloud and IDE custom agent definition format — frontmatter fields, tool aliases, MCP server config, secrets interpolation, scoping hierarchy
|
||||
- **Contributing files:** overview.md, agent-definition.md, configuration.md, api-reference.md, examples.md, troubleshooting.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-cli-plugin-reference
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-plugin-reference
|
||||
- **Description:** Full CLI plugin reference — `plugin.json` schema, marketplace.json schema, all CLI commands and flags, install specification formats, loading precedence, env vars, LSP config
|
||||
- **Contributing files:** overview.md, configuration.md, installation.md, marketplace.md, api-reference.md, examples.md, troubleshooting.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-plugins-creating
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/plugins-creating
|
||||
- **Description:** How-to for creating Copilot CLI plugins — plugin structure, agent and skill authoring, hooks format, MCP config, development lifecycle
|
||||
- **Contributing files:** overview.md, agent-definition.md, configuration.md, installation.md, examples.md, troubleshooting.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-plugins-finding-installing
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/plugins-finding-installing
|
||||
- **Description:** User-facing guide to discovering and installing CLI plugins — marketplace browsing commands, install/update/uninstall workflow
|
||||
- **Contributing files:** installation.md, marketplace.md, api-reference.md, troubleshooting.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-plugins-marketplace
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/plugins-marketplace
|
||||
- **Description:** How-to for creating and publishing a plugin marketplace — marketplace.json structure, hosting options, registration commands
|
||||
- **Contributing files:** marketplace.md, api-reference.md, examples.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## github-sdk-custom-agents
|
||||
|
||||
- **URL:** https://docs.github.com/en/copilot/how-tos/copilot-sdk/features/custom-agents
|
||||
- **Description:** SDK custom agent API — CustomAgentConfig fields in all five languages, session config, sub-agent lifecycle events, tool scoping, permission handling
|
||||
- **Contributing files:** overview.md, agent-definition.md, api-reference.md, examples.md, sdk.md, troubleshooting.md
|
||||
- **Status:** `extracted`
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
topic: troubleshooting
|
||||
source_keys:
|
||||
- github-cli-plugin-reference
|
||||
- github-plugins-creating
|
||||
- github-custom-agents-configuration
|
||||
- github-sdk-custom-agents
|
||||
- github-plugins-finding-installing
|
||||
---
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
## CLI Plugin System
|
||||
|
||||
**Changes to a locally-installed plugin are not reflected.**
|
||||
Plugins are cached on install. Editing files on disk has no effect until you reinstall:
|
||||
```shell
|
||||
copilot plugin install ./my-plugin
|
||||
```
|
||||
|
||||
**Agent or skill not loading after install.**
|
||||
Use `/agent` and `/skills list` to verify what loaded. If a component is missing, check for name collisions — the first-found instance wins for agents and skills. Plugin-provided components lose to project-level (`.github/agents/`, `.claude/agents/`) and personal (`~/.copilot/agents/`) components with the same name.
|
||||
|
||||
**`copilot plugin marketplace remove` fails.**
|
||||
The CLI refuses to remove a marketplace that has installed plugins. Either uninstall those plugins first, or use `--force` to remove the marketplace and uninstall all its plugins simultaneously.
|
||||
|
||||
**Plugin manifest not found.**
|
||||
The CLI checks `.plugin/plugin.json` → `plugin.json` → `.github/plugin/plugin.json` → `.claude-plugin/plugin.json`. Do not put conflicting manifests in multiple of these locations — the first one found wins.
|
||||
|
||||
**Name collision for agents/skills.**
|
||||
Duplicate names are silently ignored; only the first-found instance is loaded. Plugin-provided components always lose to project-level and personal components. Rename the conflicting file to resolve.
|
||||
|
||||
**MCP server override not working.**
|
||||
Unlike agents and skills, MCP servers use last-wins resolution. The `--additional-mcp-config` flag takes the highest priority and can silently override plugin-provided MCP servers. Check the loading order: `~/.copilot/mcp-config.json` < plugin MCP configs < `--additional-mcp-config`.
|
||||
|
||||
**`extensions: { exclusive: true }` broke the session.**
|
||||
This flag disables ALL built-in extensions, not just the one you want to replace. Use with care and only when you are fully replacing the built-in extension set.
|
||||
|
||||
**`COPILOT_PLUGIN_DATA` not persisting between updates.**
|
||||
Make sure you are reading/writing to `${COPILOT_PLUGIN_DATA}` (or `${CLAUDE_PLUGIN_DATA}`), not a path derived from `${PLUGIN_ROOT}`. The root path changes on each install; the data path is stable.
|
||||
|
||||
**Cache issues in CI.**
|
||||
Set `COPILOT_CACHE_HOME` to a writable directory. Default locations (`~/.cache/copilot/` on Linux, `~/Library/Caches/copilot/` on macOS) may not exist or may not be writable in containerized environments.
|
||||
|
||||
## Cloud / IDE Custom Agents
|
||||
|
||||
**Agent runs with different behavior than expected.**
|
||||
Check for shadowing: the scoping hierarchy is repo > org > enterprise. A repo-level agent file silently overrides higher-level agents with the same name.
|
||||
|
||||
**`mcp-servers` frontmatter block is ignored.**
|
||||
This field is only processed by the cloud agent runtime. It is silently ignored in VS Code and most IDEs. MCP tools declared here will not be available outside the cloud agent context.
|
||||
|
||||
**`metadata` field is ignored.**
|
||||
Like `mcp-servers`, the `metadata` annotation block is not processed in VS Code.
|
||||
|
||||
**`stdio` type for MCP server not working.**
|
||||
Use `type: 'local'` in cloud agent files, not `type: 'stdio'`. The `stdio` alias maps correctly in VS Code `.mcp.json` but not in agent frontmatter.
|
||||
|
||||
**Agent auto-selected when it shouldn't be.**
|
||||
Set `disable-model-invocation: true` to prevent the runtime from autonomously selecting this agent. This is important for agents with destructive or irreversible tool access.
|
||||
|
||||
**Prompt truncated.**
|
||||
The prompt body cap is 30,000 characters. Content beyond this is silently truncated. Split long prompts into skills where possible.
|
||||
|
||||
**`infer` field not recognized.**
|
||||
`infer` is retired. Replace with `disable-model-invocation: false` (equivalent to old `infer: true`) and `user-invocable: true`.
|
||||
|
||||
**MCP token can only access the source repository.**
|
||||
The built-in `github` MCP server's token is scoped to the repository the agent was triggered from. Cross-repository reads require explicit additional configuration.
|
||||
|
||||
## SDK Custom Agents
|
||||
|
||||
**Agent not auto-selected by runtime.**
|
||||
Check the `description` field quality. Vague descriptions like "helps with code" produce poor inference. Be specific about capabilities and constraints. Also confirm `infer` is not set to `false`.
|
||||
|
||||
**`agent` pre-selection not working.**
|
||||
The `agent` session field requires an exact match against `customAgents[].name`. A mismatch silently falls through to inference rather than erroring.
|
||||
|
||||
**Sub-agent failed with no error handling.**
|
||||
`subagent.failed` events are not automatically retried or surfaced by the runtime. Wire up explicit error handling on the `subagent.failed` event before going to production.
|
||||
|
||||
**Tool excluded at session level still not available to sub-agent.**
|
||||
Session-level `excludedTools` applies to everyone including named sub-agents. `defaultAgent.excludedTools` only restricts the main (built-in) agent. If a tool needs to be available to sub-agents but not the main agent, use `defaultAgent.excludedTools`, not the session-level blocklist.
|
||||
|
||||
**Sub-agent not seeing parent's skills.**
|
||||
Skills are not inherited by sub-agents. Each agent must explicitly declare the `skills` it needs via the `skills` array, and `skillDirectories` must be set at session level.
|
||||
|
||||
**Agent-scoped MCP server tools not visible across agents.**
|
||||
MCP servers declared in a `CustomAgentConfig.mcpServers` block are scoped to that agent only. Other agents, including the main agent, do not see those tools unless the same MCP server is also declared at the session level.
|
||||
|
||||
## Hooks
|
||||
|
||||
**Hooks not executing.**
|
||||
Confirm `version: 1` is present in `hooks.json`. Without it the config is treated as invalid.
|
||||
|
||||
**Hook script not found or not executable.**
|
||||
Run `chmod +x` on the script. Use `set -x` at the top of bash scripts for verbose debugging. Validate that the `cwd` field points to the correct working directory.
|
||||
|
||||
**Hook timing out.**
|
||||
The default `timeoutSec` is 30. Increase it for slow scripts. Long-running hooks block the lifecycle event they are attached to.
|
||||
|
||||
**Skill pre-approving tools you didn't intend.**
|
||||
The `allowed-tools` field in `SKILL.md` bypasses per-use permission prompts for the listed tools. Only set this after fully reviewing the skill source — any skill with `allowed-tools: [shell]` from an untrusted source can run arbitrary shell commands without prompting the user.
|
||||
Reference in New Issue
Block a user