
make-custom-agent
Create, review, or fix custom GitHub Copilot agents. Use when asked to create, scaffold, configure, review, or restrict a custom agent, declarative agent, or @-invokable chat participant for GitHub Copilot.
- Installs
- 46
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/dotnet/efcore --skill make-custom-agent- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads make-custom-agent automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Create Custom Agent
This skill guides you through creating a custom GitHub Copilot agent — an @-invokable chat participant that extends Copilot with domain-specific expertise. Custom agents are distinct from Agent Skills: skills provide reusable instructions loaded on demand, while agents own the full conversational interaction and can orchestrate tools, call APIs, and maintain their own prompt strategies.
When Not to Use
- Adding reusable, invokable workflows — use Agent Skills (
.agents/skills/) instead - Adding background coding guidelines — use file-based instructions (
.github/instructions/) instead - Adding project-wide context for Copilot — use
.github/copilot-instructions.mdinstead - Creating reusable prompts — use .prompt.md instead
Workflow
For an existing proposal, audit the full definition rather than just its tools: the description must identify natural requests that should discover it, the body must add domain knowledge beyond root instructions, and the paired eval must isolate its contribution. Compare every tool and behavior to the user's intended authority. A command-free reviewer must not gain command execution or publication through a wildcard tool, handoff, or otherwise read-only workflow.
Step 1: Choose the agent type
| Type | Location | Best for |
|---|---|---|
| Declarative (prompt file) | .github/agents/<name>.md | Simple prompt-driven cross-surface agents with no code |
| Extension-based (chat participant) | VS Code extension project | Full control, tool calling, VS Code API access |
| GitHub App (Copilot Extension) | Hosted service + GitHub App | Cross-surface agents (github.com, VS Code, Visual Studio) |
If the agent only needs a scoped system prompt and doesn't require custom code, start with a declarative agent.
Step 2: Create a declarative agent (prompt file)
Declarative agents are Markdown files in .github/agents/. VS Code and GitHub Copilot discover them automatically.
.github/agents/
└── <agent-name>.md # Agent definition
Template:
---
name: my-agent
description: A short description of what this agent does and when to use it.
---
# <Agent Title>
You are an expert in <domain>. Your job is to:
- <behavior 1>
- <behavior 2>
## Guidelines
- <guideline 1>
- <guideline 2>
## Workflow
1. <step 1>
2. <step 2>
## Constraints
- <constraint 1>
- <constraint 2>
Supported frontmatter fields:
| Field | Required | Description |
|---|---|---|
name | Yes | Lowercase, hyphens allowed. Used for @-mention. |
description | Yes | What the agent does and when to use it. Shown in the participant list. |
target | No | Target environment: vscode or github-copilot (defaults to both) |
tools | No | List of allowed tools/tool sets |
model | No | LLM name or prioritized array of models |
user-invocable | No | Show in agents dropdown (default: true) |
disable-model-invocation | No | Prevent subagent invocation (default: false) |
mcp-servers | No | MCP server configs for GitHub Copilot target |
metadata | No | Key-value mapping for additional arbitrary metadata. |
argument-hint | No | Hint text guiding user interaction (VS Code only) |
agents | No | List of allowed subagents (* for all, [] for none, VS Code only) |
handoffs | No | List of next-step agent transitions (VS Code only) |
Tips for instructions:
- Use Markdown links to reference other files
- Reference tools with
#tool:<tool-name>syntax - Be specific about agent behavior and constraints
Step 3: Configure tools
Specify which tools the agent can use:
tools:
- search # Built-in tool
- fetch # Built-in tool
- codebase # Tool set
- myServer/* # All tools from MCP server
Common tool patterns:
- Read-only agents:
['search', 'fetch', 'codebase'] - Full editing agents:
['*']or specific editing tools - Specialized agents: Cherry-pick specific tools
Step 4: Add handoffs (optional, VS Code only)
Configure transitions to other agents:
handoffs:
- label: Start Implementation
agent: implementation
prompt: Implement the plan outlined above.
send: false
model: GPT-5.2 (copilot)
Handoff fields:
label: Button text displayed to useragent: Target agent identifierprompt: Pre-filled prompt for target agentsend: Auto-submit prompt (default: false)model: Optional model override for handoff
Step 5: Create an extension-based chat participant (VS Code only)
For full control, implement a VS Code extension with a chat participant:
- Define the participant in
package.json:
"contributes": {
"chatParticipants": [
{
"id": "my-extension.my-agent",
"name": "my-agent",
"fullName": "My Agent",
"description": "Short description shown in chat input",
"isSticky": false,
"commands": [
{
"name": "explain",
"description": "Explain the selected code"
}
]
}
]
}
- Register and implement the request handler in
extension.ts:
export function activate(context: vscode.ExtensionContext) {
const agent = vscode.chat.createChatParticipant('my-extension.my-agent', handler);
agent.iconPath = vscode.Uri.joinPath(context.extensionUri, 'icon.png');
}
const handler: vscode.ChatRequestHandler = async (
request: vscode.ChatRequest,
context: vscode.ChatContext,
stream: vscode.ChatResponseStream,
token: vscode.CancellationToken
) => {
const model = request.model;
const messages = [
vscode.LanguageModelChatMessage.User(request.prompt)
];
const response = await model.sendRequest(messages, {}, token);
for await (const fragment of response.text) {
stream.markdown(fragment);
}
};
- Declare the extension dependency in
package.json:
"extensionDependencies": ["github.copilot-chat"]
- Add tool calling (optional)
Agents can invoke language model tools registered by other extensions:
const tools = vscode.lm.tools.filter(tool => tool.tags.includes('my-domain'));
const result = await chatUtils.sendChatParticipantRequest(request, context, {
prompt: 'You are an expert in <domain>.',
tools,
responseStreamOptions: { stream, references: true, responseText: true }
}, token);
return await result.result;
Step 6: Create a GitHub App (Copilot Extension) for cross-surface availability (optional)
If the agent should be available on GitHub.com, Visual Studio, JetBrains, and VS Code simultaneously, implement a GitHub App that acts as a Copilot Extension. The app registers a webhook endpoint, receives chat requests, and streams responses back.
Key considerations:
- The GitHub App must be installed on the user's account or organization
- Responses are streamed via Server-Sent Events (SSE)
- Use the GitHub Copilot Extensions documentation for the full integration guide
- For VS Code-specific features (editor access, file trees, command buttons), prefer an extension-based participant instead
Step 7: Author the harness evaluation
Create eng/harness-evaluation/agents/<agent-id>/eval.yaml and follow eng/harness-evaluation/README.md.
- Declare only the agent file in the eval's root
agent_environment.files; the experiment removes it from the control. - Use realistic stimuli that exercise behavior distinctive to the agent without stating the expected diagnosis or implementation in the prompt.
- Combine deterministic output checks, a focused semantic rubric, bounded resources, token grading, and a committed scoring threshold.
- Keep the eval name and directory-derived component ID identical to the agent ID.
Step 8: Validate
After creating or modifying an agent, verify:
-
nameis lowercase, uses hyphens (no spaces), and is unique -
descriptionclearly describes what the agent does and when to invoke it - Frontmatter YAML is valid (no syntax errors)
- Declarative agent file is in
.github/agents/ - Tools list contains only available tools
- Extension-based agent: participant ID matches in
package.jsonandcreateChatParticipantcall - Agent does not duplicate functionality of built-in agents (
@workspace,@vscode,@terminal) - Handoff agent names match existing agents
- Agent instructions don't include secrets, tokens, or internal URLs
- The paired harness eval targets only this agent and is meant to meaningfully distinguish treatment from control
Common Pitfalls
| Pitfall | Solution |
|---|---|
| Agent name conflicts with built-in participants | Use a unique prefix (domain name) |
| Description is too vague | Include specific keywords users would naturally say |
| System prompt is too long | Keep instructions to essential behaviors; move reference material to Agent Skills |
| Agent requires VS Code API but is authored as declarative | Switch to extension-based participant |
Using isSticky: true unnecessarily | Only set sticky if the agent should persist between turns by default |
No extensionDependencies on github.copilot-chat | Add it; otherwise the contribution point may not be available |
| Agent invoked as subagent unexpectedly | Set disable-model-invocation: true |
| Subagent appears in the dropdown | Set user-invocable: false |
References
- VS Code Chat Participant API
- VS Code AI Extensibility Overview
- VS Code Extension Samples – chat-sample
- GitHub Copilot Extensions documentation
- GitHub Copilot Custom agents configuration
- Agent Skills Specification
- Related repository skills:
make-skillandmake-instructions
FAQ
What does the make-custom-agent skill do?
Create, review, or fix custom GitHub Copilot agents. Use when asked to create, scaffold, configure, review, or restrict a custom agent, declarative agent, or @-invokable chat participant for GitHub Copilot.
How do I install make-custom-agent?
Run npx skills add https://github.com/dotnet/efcore --skill make-custom-agent in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/make-custom-agent/ (personal) or .claude/skills/make-custom-agent/ (project).
Which AI agents can use make-custom-agent?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is make-custom-agent safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains make-custom-agent?
It is published by dotnet in dotnet/efcore. It has 46 recorded installs.
More from dotnet/efcore
model-building
dotnet/efcore
Open the skill to read its SKILL.md instructions.
update-pipeline
dotnet/efcore
Open the skill to read its SKILL.md instructions.
sqlite-adonet
dotnet/efcore
Open the skill to read its SKILL.md instructions.
change-tracking
dotnet/efcore
Open the skill to read its SKILL.md instructions.
Popular code quality & workflow skills
grill-me
mattpocock/skills
A relentless interview to sharpen a plan or design.
improve-codebase-architecture
mattpocock/skills
Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.
handoff
mattpocock/skills
Compact the current conversation into a handoff document for another agent to pick up.
domain-modeling
mattpocock/skills
Build and sharpen a project's domain model. Use when discussing codebase terminology, writing or editing a GLOSSARY.md, or recording or editing an ADR.
codebase-design
mattpocock/skills
Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.
diagnosing-bugs
mattpocock/skills
Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.