Custom Agents, Skills, and Prompts
Purpose and Scope
Custom agents, skills, and prompt-style customizations let a VS Code user shape Copilot into task-specific helpers instead of relying on one general assistant for every workflow. The official user model describes custom agents as personas with their own instructions, available tools, and behavior, while agent skills are portable folders of instructions, scripts, examples, and resources that are loaded when relevant. In this repository, those ideas are represented by markdown customization contracts, an organization-backed provider, agent-host protocol helpers, and workbench services that discover, expand, display, and synchronize customizations for agent sessions.
Sources: extensions/copilot/assets/prompts/skills/agent-customization/references/agents.md, src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationContentExpander.ts
This page is for developers connecting the product concepts to the implementation path. A customization can begin as a workspace file, a user-profile file, a plugin-style root containing canonical folders, or an organization resource fetched through Copilot. The workbench does not treat all of those as the same raw document. It normalizes them into typed items such as agents, skills, command prompts, and rules, then the agent-host picker logic computes which agents are usable in the current session. That separation keeps authoring flexible while giving the UI stable names, URIs, and ordering.
Sources: src/vs/platform/agentHost/common/customAgents.ts, src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationItemProvider.ts
Relevant Source Files
extensions/copilot/assets/prompts/skills/agent-customization/references/agents.mddocuments custom agent locations, frontmatter fields, invocation control, tool aliases, model fallback, templates, hooks, and anti-patterns.extensions/copilot/src/extension/agents/vscode-node/githubOrgCustomAgentProvider.tsimplements a GitHub organization custom-agent provider for the Copilot extension and exposes agents through the VS Code chat custom agent provider API.src/vs/platform/agentHost/common/customAgents.tscontains helper functions for computing effective session agents, building picker storage keys, and resolving the selected agent from session or stored state.src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationContentExpander.tsscans plugin roots and expands canonical customization folders into individual agent, skill, command, and rule items.src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationItemProvider.tswires customization service changes, remote URI conversion, cached content expansion, and item-provider behavior for the customization harness.src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationSyncProvider.tspersists per-harness synchronization opt-outs for local customization URIs.
Core Primitives
A custom agent is authored as an agent markdown file with frontmatter and body instructions. The repository guidance defines workspace and user-profile locations, then lists metadata fields used by picker discovery and subagent routing. The required description is more than display text: it gives users and parent agents a reason to select the persona. Optional fields cover the display name, tool set, preferred model, argument hint, allowed subagents, picker visibility, model-invocation guard, handoffs, and inline lifecycle hooks. The intended design is a narrow role with clear boundaries, not a general assistant with every tool enabled.
Sources: extensions/copilot/assets/prompts/skills/agent-customization/references/agents.md
Skills are adjacent to agents but serve a different purpose. The docs describe skills as folders that can include instructions, scripts, examples, and resources, and the workbench expansion code preserves that distinction. Plugin roots are scanned through canonical folders named agents, skills, commands, and rules. Regular folders map to prompt types directly, while skills are collected from skill subfolders that contain the expected skill markdown file and metadata. This folder-based contract lets one repository-backed bundle contribute several capabilities without forcing agents, skills, reusable prompts, and rules into one flattened format.
Sources: src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationContentExpander.ts
Prompts and rules appear in the same expansion pipeline because they are customization content, but they are not interchangeable with agents. In the source mapping, commands become prompt items and rules become instruction items, while agents and skills keep their own prompt types. That distinction is important for both UX and agent behavior: a selectable persona, an on-demand skill, a reusable command prompt, and an always-or-conditionally-applied rule should be displayed and invoked differently. The expander sorts children by type and name, which gives the customization harness deterministic ordering even when the backing filesystem returns entries differently.
Sources: src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationContentExpander.ts
Authoring Contract
The agent reference encourages authors to start with the job the agent should perform, then restrict the tools to the minimum useful set. Tool entries can use built-in aliases such as execute, read, edit, search, agent, web, and todo, can target an MCP server namespace, can name extension tools, or can intentionally be an empty list for a conversational-only persona. Omitting tools means default tool behavior, while an empty list is an explicit denial of tool access. Model fallback is supported with an ordered array, so the first available model can be selected without editing the agent body.
Sources: extensions/copilot/assets/prompts/skills/agent-customization/references/agents.md
| Field | Meaning | Practical effect |
|---|---|---|
description | Required picker and discovery text | Helps users and parent agents know when to use the agent |
tools | Tool aliases, MCP namespaces, or extension tools | Restricts what the persona can do |
agents | Allowed subagent names | Limits delegation paths |
user-invocable | Picker visibility flag | Can hide a helper that is meant only for subagent use |
disable-model-invocation | Subagent invocation guard | Prevents other agents from invoking this agent |
handoffs | Transition metadata | Supports guided movement between specialized agents |
hooks | Inline lifecycle commands | Runs command hooks around agent lifecycle points |
A practical agent file should read like a small operating manual. The template in the repository guidance starts with a use-when description, a minimal tools list, and optional invisibility for subagent-only helpers. The body then states the role, constraints, approach, and output format. That shape matters because the same content can be used by a human selecting from the agent picker and by another agent deciding whether delegation is appropriate. Anti-patterns in the guidance, including vague descriptions, role confusion, circular handoffs, and Swiss-army agents, all make selection and delegation less reliable.
Sources: extensions/copilot/assets/prompts/skills/agent-customization/references/agents.md
System-to-Code Mapping
The workbench path starts with customization containers rather than individual files. The item provider subscribes to the agent-host customization service and fires its own change event when the underlying list changes. It owns a content expander and an expansion cache keyed by plugin URI, nonce, and display label, so repeated UI reads can reuse previous expansion results until the content identity or presentation changes. Remote URI handling is explicit because customizations may be exposed through an agent-host filesystem scheme, not only through normal local files. This is the bridge between repository-backed content and UI-ready customization items.
Sources: src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationItemProvider.ts, src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationContentExpander.ts
Once child customizations exist, platform helpers decide which agents are actually selectable for a session. The effective-agent function walks the session customization containers, skips MCP server containers, skips disabled containers, and ignores containers whose children are not yet known. It considers only children typed as agents, deduplicates them by stable URI, and sorts by name and URI. Selection resolution first honors the session’s current agent URI when it still exists, then falls back to a stored URI, and otherwise returns no specific agent so the UI can show the default agent placeholder.
Sources: src/vs/platform/agentHost/common/customAgents.ts
| Component | Public contract visible in source |
|---|---|
GitHubOrgCustomAgentProvider | Implements vscode.ChatCustomAgentProvider and provides provideCustomAgents plus onDidChangeCustomAgents |
getEffectiveAgents | Accepts session customizations and returns sorted, deduplicated agent customizations |
agentHostAgentPickerStorageKey | Builds the shared picker storage key for a resource scheme |
resolveAgentHostAgent | Chooses the current, stored, or undefined agent selection |
AgentCustomizationContentExpander | Expands plugin roots into agents, skills, commands, and rules |
AgentCustomizationSyncProvider | Implements disabled-sync tracking for customization URIs |
Organization Agents and Sync Behavior
Organization-scoped agents are supplied by a provider in the Copilot extension. The provider implements the VS Code chat custom agent provider shape, exposes a change event, and reads cached chat resources for the preferred organization. A polling loop refreshes every five minutes because it must fetch full agent details, including prompt content. During polling, it obtains an accessible organization repository, requests custom agents with organization and enterprise sources, retrieves details for each agent, compares the results with cached files, and notifies consumers when content changes. Cancellation, missing organization state, empty repositories, and cache-read errors return empty results rather than breaking the agent picker.
Sources: extensions/copilot/src/extension/agents/vscode-node/githubOrgCustomAgentProvider.ts
Synchronization is intentionally modeled as opt-out. The sync provider stores only local customization URIs that a user has disabled for a particular harness, using a profile-scoped key derived from the harness identifier. With no stored value, local customizations are considered syncable by default. When a user disables or re-enables one URI, the provider updates an in-memory set, persists a serialized list with machine storage target, and fires a change event. Malformed stored JSON is ignored by falling back to an empty set, which keeps the customization UI usable after storage corruption or manual storage edits.
Sources: src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationSyncProvider.ts
Execution Flow and Edge Cases
A typical repository-backed flow starts when a workspace, profile, plugin bundle, or organization supplies customization content. The item provider receives container state from the agent-host customization service and converts relevant URIs for the agent-host filesystem. The content expander checks whether the file service can handle the root, resolves supported folders, reads metadata where needed, and returns typed children. Picker helpers then compute the effective agent list from enabled containers and restore a current or stored selection when possible. The same stable selection logic lets the Agents Window and chat-editor surfaces agree for new sessions that share the same resource scheme.
Sources: src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationItemProvider.ts, src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationContentExpander.ts, src/vs/platform/agentHost/common/customAgents.ts
Several edge cases are deliberate rather than incidental. Expansion returns no items when the backing filesystem cannot handle a plugin root, when cancellation is requested, when expected directories are missing, or when expansion throws. Dotfile skill children are skipped before metadata reads. Disabled containers do not contribute agents, and containers with absent children are treated as unknown instead of empty. The GitHub organization provider avoids surfacing partial failures for missing preferred organizations, inaccessible repositories, cancellation, or cache errors. These choices favor predictable UI behavior over aggressive failure propagation in an agent customization surface.
Sources: extensions/copilot/src/extension/agents/vscode-node/githubOrgCustomAgentProvider.ts, src/vs/workbench/contrib/chat/browser/agentSessions/agentHost/agentCustomizationContentExpander.ts, src/vs/platform/agentHost/common/customAgents.ts
Next Steps
When extending this area, decide first whether the new behavior is an agent persona, a portable skill, a command prompt, a rule, or a provider-backed source of those items. Then keep the authoring contract narrow, provide stable URIs and names, and use the existing expansion and selection helpers instead of building parallel picker state. For adjacent concepts, read Agents Window for the agent-first surface, MCP Servers for server-backed tool namespaces, Agent Hooks and Plugins for lifecycle automation, Agent Customization Instructions for instruction rules, and Chat Tools and Approvals for tool permission boundaries.