欢迎光临
我们一直在努力

如何自定义 VS Code Copilot Agent:从“每次重复说一遍“到“一次配置,处处生效“

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}

一句话结论:VS Code 里"自定义 Copilot"不是一个开关,而是一套分层的定制机制。选错机制,是绝大多数"我配置了但没生效"的根源。

先破一个常见误区

很多人的操作路径是这样的:在设置里翻找"Copilot 自定义"选项,复制一大段 prompt 进去,然后发现 Copilot 时灵时不灵。

原因很直接:VS Code 把 AI 行为定制拆成了五种机制,触发时机完全不同。

记忆口诀:指令是被动的家规,Agent 是你进入并停留的模式,Prompt 是手动敲一次的命令,Skill 是按需加载的知识包,Hook 是必须跑的硬脚本,MCP 是外接系统。

顺便提醒一个 2026 年的命名变化:自定义 Agent 过去叫"自定义聊天模式"(Custom Chat Modes),后缀是 .chatmode.md,这个后缀已经废弃,现在统一用 .agent.md。网上旧教程写 *.chatmode.md 的,直接按新名字替换即可。


一、机制全景:一张图看懂五层

flowchart TB
subgraph L1["① 常驻指令(始终/按路径生效)"]
I1[".github/copilot-instructions.md<br/>仓库级"]
I2[".github/instructions/*.instructions.md<br/>路径级 applyTo"]
I3["~/.copilot/copilot-instructions.md<br/>个人级"]
end
subgraph L2["② 角色模式(选中后生效)"]
A1[".github/agents/*.agent.md"]
end
subgraph L3["③ 按需调用"]
P1[".github/prompts/*.prompt.md"]
S1[".github/skills/*/SKILL.md"]
end
subgraph L4["④ 确定性执行"]
H1[".github/hooks/*.json<br/>(预览版)"]
end
subgraph L5["⑤ 外部系统"]
M1[".vscode/mcp.json / settings.json"]
end
L1 –> L2 –> L3 –> L4 –> L5
style L2 fill:#1f6feb,color:#fff
style L4 fill:#bf8700,color:#fff

关键洞察:这五层的可靠程度是递增的。指令和 Agent 依赖模型"读懂并遵守",是概率性的;Hook 是确定性脚本,说跑就跑;MCP 则把能力边界直接扩展到外部系统。把"必须做到"的事往右挪,把"希望做到"的事往左放。


二、第一层:项目级指令,投入产出比最高

先在仓库根目录建 .github/copilot-instructions.md。它会被 Copilot 自动读取并追加到每次对话的系统提示,你不需要 import、不需要引用。

最快的起步方式是直接在 Chat 里输入 /init,Copilot 会扫描你的代码库,自动生成一份贴合项目的初稿,你在上面改。

示例 1:一个 Node.js API 项目的最小指令

# 项目概览
订单管理 REST API。Node.js 20、Express、PostgreSQL、Prisma ORM。

# 技术栈
– 运行时:Node.js 20(ESM)
– 数据库:PostgreSQL 16,走 Prisma
– 测试:Vitest + Supertest
– 改动代码后必须运行 `pnpm test`,不通过等于没做完

# 编码规范
– TypeScript strict 模式,禁止 `any`
– 请求校验统一用 zod
– 偏好 named export
– 错误响应遵循 RFC 9457(Problem Details)

# 项目结构
– HTTP handler 放在 `src/api/routes`
– 数据访问放在 `src/repositories`,保持 handler 可独立测试
– 禁止修改 `src/generated/` 下的文件,那是代码生成的

怎么写才有效

做法

原因

写祈使句规则

"禁止 any"比"请尽量更准确"有效得多

用列表和标题,别写叙事段落

结构化内容模型遵循率更高

控制在两页以内​

接近 1000 行的指令文件会让代码审查的一致性明显下降——系统提示 token 预算被挤占,真正该被理解的对话和代码反而变少了

不要塞完整文档,用 Markdown 链接指向它

但代码审查场景读不了链接,审查内容要内联

不要塞任务级指令

那属于 Prompt 文件或路径级指令的地盘

保持工具中立

工具专属语法(Claude Code / Cursor 指令)Copilot 会无视


三、第二层:路径级指令,让规则只在需要的地方生效

当你希望"前端一套规矩、后端另一套",或者"只有 .py 文件才要求类型注解"时,用 *.instructions.md 配合 applyTo 的 glob 模式,默认放在 .github/instructions/。

示例 2:按文件类型分工的两份指令

.github/instructions/python.instructions.md:

—
description: Python 编码标准,涉及 .py 文件时自动加载
applyTo: "**/*.py"
—
– 所有函数签名必须带类型注解
– 结构化数据用 dataclass,别用 dict
– 抛具体异常,禁止裸 `except Exception`
– 日志用 structlog,不用 print

.github/instructions/api.instructions.md:

—
description: API 层约定
applyTo: "src/api/**/*.ts"
—
– 每个端点用 Zod schema 先校验输入再使用
– handler 必须包一层共享的 `withErrorEnvelope`
– 新增端点必须同步在 `src/api/routes/index.ts` 注册

当聊天上下文出现匹配 glob 的文件,对应指令自动挂上,多个文件可同时命中。

架构建议:把语言/框架相关规则往 applyTo 文件里挪,让仓库级 copilot-instructions.md 保持精简——这个文件越短,每条规则被真正记住的概率越高。

跨工具共享:用 AGENTS.md 作为单一事实来源

VS Code 现在区分 harness(运行框架,比如 Copilot、Claude、Codex),不同 harness 发现的指令文件格式不同。团队混用工具时,优先选大家都支持的 AGENTS.md 放根目录——VS Code、Claude Code 及其他遵循该约定的 Agent 能读同一份事实来源。


四、第三层:自定义 Agent,这才是"角色"

前两层只喂上下文。Agent 则是把角色、一套精简后的工具权限、一个可选的固定模型打包成可复用模式,出现在 Copilot 聊天的下拉框里,和内置的 Ask / Edit / Agent 并列。

示例 3:只读的规划 Agent

存为 .github/agents/planner.agent.md:

—
name: planner
description: 生成实现方案,但不改动任何代码
tools: ['search/codebase', 'web/fetch', 'search/usages']
model: ['Claude Opus 4.5', 'GPT-5.2']
handoffs:
– label: 开始实现
agent: implementer
prompt: 请按上面的方案开始实现。
send: false
—
你是资深软件架构师。用户描述功能或变更时:
1. 先分析需求,列出待创建/修改的文件
2. 给出按逻辑顺序排列的实现步骤
3. 标注风险与待确认项
4. 输出测试新增/修改清单
禁止编辑任何文件。需求模糊时先提问。

示例 4:团队专属的代码审查 Agent

内置审查 Agent 只会套通用最佳实践,而自定义的能套用你的审查清单:

—
name: reviewer
description: 按团队规范审查代码质量、安全与性能,绝不改文件
tools: ['search/codebase', 'web/fetch']
—
你是本项目的代码审查员。严格对照 .github/instructions/ 下的规范审查:
– 安全漏洞(SQL 注入、XSS、鉴权缺陷)
– 是否误改了 src/generated/ 下的生成文件
– 错误处理是否遵循 RFC 9457
– 是否有未处理的 await、裸 any、重复代码

输出格式:
| 严重度 | 文件:行号 | 问题 | 建议 |
严重/一般/提示 三级分类,末尾给整体评估。不要直接改代码。

示例 5:用 handoffs 串成流水线,并配一个"纯编排"总控

handoffs 会在 Agent 回复后显示成按钮,一键切换到另一个 Agent,可选自动提交:

# .github/agents/implementer.agent.md
—
name: implementer
description: 按方案实现代码改动
tools: ['edit', 'read/terminalLastCommand', 'search/codebase']
handoffs:
– label: 交给审查
agent: reviewer
prompt: 请审查刚才的改动,重点看安全与规范。
send: false

# .github/agents/orchestrator.agent.md
—
name: orchestrator
description: 全自动走完 翻译→情感分析→应答 全流程
disable-model-invocation: true # 自己不生成文本,只编排
tools: ['agent'] # 仅允许拉起子 Agent
agents: ['translator', 'sentiment', 'supporter', 'acknowledgment', 'information']
—
依次拉起子 Agent:先 translator 翻译,再 sentiment 分类情感,
根据 Positive/Negative/Neutral 拉起对应应答 Agent,最后只返回面向用户的那一句。

真实工作流示意(来自官方示例的翻译→情感分类→应答编排):

关键字段速查

字段

说明

name

必填,唯一标识,小写加连字符,最长 64 字符

description

选中该 Agent 时显示的输入框占位文字,也帮助模型判断何时调用它

tools

白名单。read/edit/search 是标准别名;['*'] 或全部可用;[] 则禁用所有工具​

model

可选,固定偏好模型或按优先级排列的数组

agents

可拉起的子 Agent 列表,* 为全部,[] 为禁止

user-invocable

是否出现在下拉框,默认 true

disable-model-invocation

是否禁止被其他 Agent 当作子 Agent 拉起

argument-hint

输入框提示文本

mcp-servers

Agent 专属的 MCP 配置

handoffs

下一步动作链,含 label/agent/prompt/send/model

注意优先级:Agent 自己的指令会合并进你的自定义指令,冲突时以 Agent 指令为准。所以仓库级文件写通用规范,Agent 文件写角色专属约束,二者叠加而不冲突。

最有价值的一点:通过剥夺 edit 权限,你能造出一个"只说不改"的审查员——这比一百行"请不要修改代码"的提示词可靠得多。


五、第四层:Agent Skills,按需加载的专业能力

Agent Skills 是可复用的专业工作流,Agent 判断相关时自动加载,也可手动 /skill-name 调用。它是开放标准,可被多个 Agent 共用。

目录结构

.github/skills/your-skill/
├── SKILL.md # 必需,文件名必须与文件夹名一致
├── FEEDBACK.md # 推荐,反馈协议
├── .skillconfig.json # 可选,per-skill 设置(如 forceGlobal)
├── scripts/ # 可选,可执行代码
├── references/ # 可选,按需加载的参考文档
│ ├── api-reference.md
│ └── troubleshooting.md
└── assets/ # 可选,模板、样板文件

核心技巧是"渐进式加载":主文件只留精简流程,references/ 下沉细节文档,用到时再读。这样既不浪费上下文 token,又能给复杂场景完整知识。

示例 6:起草发版说明的 Skill

.github/skills/release-notes/SKILL.md:

—
name: release-notes
description: "**WORKFLOW SKILL** — 从当前仓库改动起草发版说明。
USE FOR: 准备 release summary、changelog 条目、PR 发版说明。
DO NOT USE FOR: 修改项目文件、编造 issue 编号。"
argument-hint: 指定对比分支或发版范围
—
# Release notes

## 流程
1. 查看当前分支相对默认分支的改动
2. 读取相关 commit message 与变更文件,草稿中不含密钥或敏感值
3. 按 Added / Changed / Fixed / Removed 分组,空组省略
4. 每条从"用户能感知的影响"角度写
5. 对比分支或范围不清时,先问清再动手
6. 除非用户明确要求,否则不编辑项目文件

## 输出格式
– 一句话摘要
– Markdown 发版说明草稿
– 已查阅的文件/commit 清单
– 待确认项与验证点

保持事实性。不得编造 issue 编号、性能数据、兼容性声明或破坏性变更。

保存后打开 Chat 输入 /,release-notes 应出现在列表里。没出现?依次检查:VS Code 是否打开了仓库根目录、文件名是否精确为 SKILL.md、name 是否与目录名一致且不含大写字母/斜杠/点号、frontmatter 是否以 — 包裹,最后关闭重开 Chat 刷新列表。

description 是 Skill 最重要的字段——模型靠它决定是否激活。写得含糊,这个 Skill 就永远不会被用到。


六、第五层:Hooks,唯一"必须执行"的东西

前四层都依赖模型自觉。Hooks 是在 Agent 工作流特定生命周期点确定性地执行 shell 命令,目前是预览版。这是唯一能保证执行的东西。

示例 7:编辑后自动格式化 + 审计日志

.github/hooks/format.json:

{
"version": 1,
"hooks": {
"postToolUse": [{
"type": "command",
"command": "node .github/hooks/format.cjs",
"timeoutSec": 15
}],
"preToolUse": [{
"type": "command",
"command": "node .github/hooks/audit.cjs",
"timeoutSec": 10
}]
}
}

.github/hooks/audit.cjs:

const fs = require('node:fs');
const event = JSON.parse(fs.readFileSync(0, 'utf8')); // 从 stdin 读事件
if (typeof event.toolName === 'string') {
const line = `${new Date().toISOString()} ${event.toolName}\\n`;
fs.appendFileSync('.github/hooks/tool-audit.log', line);
}

事件通过 stdin​ 传入(JSON),脚本靠退出码表态:

退出码

含义

0

通过,继续执行

2

阻断,拒绝本次工具调用(适合密钥扫描)

其他非零

视为错误,工具调用仍会执行

典型用途矩阵:

生命周期

命令

用途

preToolUse

密钥扫描脚本

阻断含 GH_/AWS_ 等凭据的写操作

postToolUse

格式化 / lint

每次改文件后自动 prettier –write

postToolUse

测试

改动后自动跑受影响测试

注意:诸如 chat.useHooks 之类的本地设置不会阻止 Copilot 工具链加载配置;chat.hookFilesLocations 也不会配置 Copilot 的发现机制;在远程会话和容器中,可执行依赖必须装在执行主机上。


七、第六层:MCP,把能力扩展到外部系统

MCP 让 Agent 能调用外部服务。VS Code 从 1.99 起内置支持,配置在 .vscode/mcp.json(工作区级,可提交进仓库)或用户 settings.json 的 mcp 键下。

示例 8:工作区级 MCP 配置

.vscode/mcp.json:

{
"servers": {
"project-db": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "${env:DATABASE_URL}"]
},
"github": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "${env:GITHUB_TOKEN}" }
},
"remote-api": {
"type": "sse",
"url": "https://api.example.com/sse",
"headers": { "Authorization": "Bearer ${env:API_TOKEN}" }
}
}
}

也可以在自定义 Agent 里通过 mcp-servers 字段做专属配置。工作区配置会覆盖用户设置,便于团队统一而不泄露密钥。

安全提醒:MCP 工具默认执行前会要求审批——你可以单次批准、始终允许,或直接拒绝。对陌生服务器保持"每次询问"是明智的。另外,MCP 工具只在 Agent 模式下可用,Ask / Edit 模式看不到。


八、组合实战:一条 PR 的完整定制链

把上面所有机制串起来,看一个真实场景:

这条链里每一层各司其职,互不越界:

  • 常驻指令保证"生成的代码天生合规范"
  • Agent保证"规划不动代码、实现不乱审查"
  • Skill保证"发版说明格式统一、不编造编号"
  • Hook保证"文件一定被格式化、凭据一定被拦"
  • MCP保证"PR 直接从编辑器里开出来"

九、决策图:该用哪个?


十、排错清单

配好了却没生效?按这个顺序查:

  • 文件位置对不对:Agent 在 .github/agents/,路径级指令在 .github/instructions/,拼写错一个字母都不被发现
  • harness 选对了没:先在 Agent Customizations 编辑器里确认当前 Session Target,不同 harness 的发现规则不同
  • Agent 没出现在下拉框:检查 user-invocable 是否被设成 false,以及文件位置是否在当前 harness 支持列表里
  • 指令被覆盖:冲突时优先级是 Agent 指令 > 个人设置 > 仓库级 > 组织级;个人级指令会静默覆盖仓库级,队友个人配置不同,看到的行为就不同
  • 文件太长:超长指令挤占上下文预算,表现为"规范越多越不遵守",砍到两页以内再试
  • IDE 能力差异:Visual Studio(Windows 那款)只读仓库级文件,不支持 applyTo 路径级规则,会静默失效
  • MCP 工具不出现:确认处在 Agent 模式,Ask / Edit 模式看不到 MCP 工具
  • Skill 不出现在 / 列表:按第六节末尾那四条逐一核对
  • 别指望 100% 遵从:官方自己说的是"提供指令不能保证完美代码",同一条指令在不同会话里结果可能不同。把指令当作概率性引导,而非合同

  • 十一、推荐的落地顺序

    别一口气全上,按这个节奏推进:

    最后一句

    自定义 Agent 的价值不在 prompt 写得漂亮,而在工具权限收得准。​ 一个被剥夺了 edit 权限的审查 Agent,比一百行"请不要修改代码"的提示词可靠得多;一个 postToolUse Hook,比任何"记得格式化"的叮嘱都管用。

    赞(0)
    未经允许不得转载:171主机测评 » 如何自定义 VS Code Copilot Agent:从“每次重复说一遍“到“一次配置,处处生效“
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址