同一个仓库,五个人的电脑里跑着五种编码 Agent 配置:A 的 Claude Code 有代码评审技能,B 的 Copilot 没有;C 手动改过提示词,谁也说不出改了哪一版;D 新克隆仓库后,Agent 什么规范都读不到。Microsoft APM(Agent Package Manager)把技能、提示词、说明文件、自定义 Agent、钩子、插件与 MCP 服务器当作「依赖」来管理:一份 apm.yml 声明要用什么,一条 apm install 就把它们落到各个客户端该去的目录,锁文件钉住来源与内容哈希。本教程按官方 README 与 Quickstart 六步落地,命令与字段均照官方文档原样给出。
先弄清:APM 管的是上下文,不是运行时
APM 不替你跑模型,也不改客户端的执行权限。它解决的是「分发与复现」:声明一次、锁定一次、部署到每个客户端。四个文件要先分清:
| 文件 | 作用 | 要不要提交 |
|---|---|---|
| apm.yml | 清单,声明 targets 与 dependencies | 提交 |
| apm.lock.yaml | 钉住解析出的来源、提交与内容哈希 | 提交 |
| apm_modules/ | 本地包缓存,安装时自动写进 gitignore | 不提交 |
| apm-policy.yml | 组织级准入规则,安装时生效 | 由团队统一维护 |
版本口径先说清:官方 README 没有写死当前版本号,请用 apm --version 自行确认;第三方文章在 2026-10-22 记录的版本为 0.35.0,前导零意味着命令面仍可能调整。另外,一次 apm install 会同时写入多个客户端目录,改动是可评审的文本文件,但确实会落到你仓库里,先在测试仓库跑一遍再进正式项目。
Step 1:装 CLI 并确认版本
官方给出四条路线,任选其一即可。Windows 用户走 PowerShell,Linux 与 macOS 无 Homebrew 时走脚本或 pip:
# Windows(PowerShell)
irm https://aka.ms/apm-windows | iex
# macOS(Homebrew,无需自定义 tap)
brew install apm
# Linux / macOS 无 Homebrew
curl -sSL https://aka.ms/apm-unix | sh
# 跨平台 pip(Python 3.10+)
pip install apm-cli
# Windows 另可选
winget install --id Microsoft.APM --exact --source winget
# 验证
apm --version
brew upgrade apm,独立安装才用 apm self-update,两者不要混用。管道执行要过一遍眼:irm ... | iex 与 curl ... | sh 都是直接执行远端脚本。团队机器建议先下载脚本查看,或用 pip / winget 这类包管理器路线;私有包则按官方文档设置 GITHUB_APM_PAT。
Step 2:用 apm init 生成清单,读懂四个字段
apm init my-agent
cd my-agent
这条命令只写一个 apm.yml。把它改成下面这样,字段含义见注释(YAML 里注释不参与安装):
name: my-agent
version: 1.0.0
description: APM project for my-agent
author: your-handle
# 不写 targets 时,APM 靠 .github/ .claude/ .cursor/ 等标记自动探测
# targets:
# - copilot
# - claude
dependencies:
apm: []
mcp: []
includes: auto
scripts: {}
dependencies.apm 放包与技能,dependencies.mcp 放 MCP 服务器,targets 指定落到哪几个客户端。includes: auto 会把本地 .apm/ 或插件原生目录里的自制内容一起带上;scripts 配合实验性的 apm run 用,不在主线上。Step 3:装官方示例包,看它到底往哪儿写
apm install microsoft/apm-sample-package#v1.0.0 --target copilot
官方 Quickstart 给出的回显大致如下,注意每一行都在告诉你产物落到了哪个目录:
[+] microsoft/apm-sample-package #v1.0.0 @fb285168
|-- 2 prompts integrated -> .github/prompts/
|-- 1 agents integrated -> .github/agents/
|-- 1 instruction(s) integrated -> .github/instructions/
|-- 1 skill(s) integrated -> .agents/skills/
[+] github.com/github/awesome-copilot/skills/review-and-refactor
|-- Skill integrated -> .agents/skills/
[*] Installed 2 APM dependencies in 1.4s.
示例包自身还依赖了 review-and-refactor,APM 在同一次安装里把传递依赖也解析并落地了。此时仓库里会多出 apm.lock.yaml、apm_modules/、.agents/ 与 .github/ 下若干文件。
--target copilot 在全新项目里必须显式给出;一旦仓库存在 .github/copilot-instructions.md 这类已识别标记,这个参数就可以省略。把 apm.yml、apm.lock.yaml 与这些部署目录一并提交,同事克隆后跑 apm install 才能得到同一套上下文。别把缓存当源码:apm_modules/ 会被自动忽略,它只是本地缓存;真正需要评审的是部署目录里的文本文件。官方也提醒「可发现不等于可用」,被技能引用的外部资源在 Agent 运行时仍要存在。
Step 4:把技能、插件和 MCP 服务器写进清单
README 给的清单片段可以直接照抄,它同时示范了子目录引用、插件、单个 Agent 原语、完整 APM 包和 MCP 服务器:
dependencies:
apm:
- anthropics/skills/skills/frontend-design
- github/awesome-copilot/plugins/context-engineering
- github/awesome-copilot/agents/api-architect.agent.md
- microsoft/apm-sample-package#v1.0.0
mcp:
- name: io.github.github/github-mcp-server
transport: http
也可以从命令行增量添加,效果一样,改动会写回 apm.yml:
apm install vercel-labs/agent-skills
apm install vercel-labs/agent-skills --skill deploy-to-vercel
apm install --mcp io.github.github/github-mcp-server --transport http
apm marketplace add github/awesome-copilot
apm install azure-cloud-development@awesome-copilot
两个容易踩的点:① transport: http 说的是 MCP 传输名,不是 URL scheme,官方注明它仍通过 HTTPS 连接,别照字面拼一个 http 地址进去;② dependencies.mcp 里的服务器会写进每一个选中的 target,而包的传递依赖里若带出未声明的 MCP 服务器,APM 会要求显式同意,不会悄悄放行。初次接入外部 MCP 服务前,先确认它要哪些凭据。
apm compile -t copilot,它会写出 .github/copilot-instructions.md,VS Code 与 Copilot 会自动读取,官方自己也在仓库里这么用。Step 5:用锁文件复现,用 audit 查漂移
# CI 或新同事克隆后:只按锁文件安装,遇到不一致直接失败
apm install --frozen
# 需要升级依赖时,确认提示后再更新
apm update
# 重建上下文并与工作树对比,抓手改
apm audit
apm audit --ci
# 从锁文件导出供应链清单
apm lock export --format cyclonedx
apm lock export --format spdx
# 清理与查看
apm prune
apm outdated
apm.lock.yaml 记录解析出的来源、精确提交与内容哈希;改了 apm.yml 之后要重新跑 apm install,并把清单、锁文件、部署目录一起提交。apm audit --ci 适合挂到分支保护上,防止有人绕过安装流程直接改生成文件。
apm install 安装并部署,apm update 刷新版本,apm install --frozen 等价于 npm ci,apm prune 清理缓存里已不在清单中的包。全局配置走 apm install --global(读 ~/.apm/apm.yml),换机复现可用 apm install --global --frozen。--frozen 会拒绝「差不多」:清单与锁文件不匹配时它直接失败,这正是它在 CI 里的价值,不要加参数绕过。另外 CycloneDX / SPDX 导出的是「哪些内容落到了磁盘」的清单,便于采购与盘点,官方明确它不是合规证明。
Step 6:看清安全边界,再谈团队治理
每次安装前 APM 会扫隐藏 Unicode(标签字符 U+E0001 到 U+E007F、双向覆盖符、变体选择符等),严重发现会阻断安装;组织侧可下发 apm-policy.yml,按企业、组织、仓库三级只收窄不放松地继承,并允许在 CI 里先跑审计模式。
# 安装即扫描;也可随时单独跑一次
apm install
apm audit
# 把审计挂进 CI 与分支保护
apm audit --ci
# 生成给 Copilot 的聚合说明,作为可评审产物
apm compile -t copilot
哈希不等于安全:官方文档与第三方分析都写明,扫描不检测明文提示词注入、同形字替换、语义操纵与二进制载荷,不做依赖代码的恶意分析,也不给包签名;内容哈希只证明「这次装到的字节与上次一致」,不证明这段提示词在当前模型、工具集与权限组合下无害。加 --force 会越过严重发现的阻断,除非你已逐字读过改动,否则别用。
策略面与运行面是两层:apm-policy.yml 管「什么能被装进来」,客户端管「装进来后能跑什么」,两者不重叠。GitHub 在 2026-11-03 的更新日志里加入了对 apm 清单的 Dependabot 版本更新(仅版本更新,不含安全更新),但机器人改的是清单与锁文件,部署目录里的生成文件仍需人跑一次 apm install 才会刷新,别把自动合并当成已部署。
常见问题速查
| 现象 | 排查方向 |
|---|---|
| 终端提示找不到 apm | 原生安装需重开 shell,或执行脚本打印的 PATH 命令;Homebrew 路线确认已 brew link |
| apm install 没写入任何客户端目录 | 全新仓库缺 targets 也缺探测标记,补 --target copilot 或写明 targets |
CI 里 --frozen 失败 | 有人改了 apm.yml 却没重跑 apm install,本地更新锁文件后连部署目录一起提交 |
| 某个技能没被 Agent 读到 | 检查部署目录是否在客户端实际读取的路径下,以及技能引用的外部资源是否随仓库保留 |
| 安装被安全扫描拦下 | 看回显里的发现位置,检查是否含隐藏字符;不要直接 --force,先修上游包 |
| 私有仓库拉不到包 | 按官方文档配置 GITHUB_APM_PAT,确认该凭据有读权限且未写进仓库 |
做到哪一步算成功
在测试仓库里:apm install microsoft/apm-sample-package#v1.0.0 --target copilot 的回显列出 prompts、agents、instructions、skills 四类产物与一个传递依赖;仓库里同时出现 apm.lock.yaml 且 apm_modules/ 被忽略;把清单改成带 dependencies.mcp 后重跑安装,MCP 服务器写进所选 target;apm audit --ci 在干净工作树上通过,而手动改一处生成文件后再次运行应当报错——这条「反例」能证明漂移检查确实生效。项目为 MIT 许可,文档入口是 microsoft.github.io/apm/。
apm list、apm deps、apm policy、apm mcp、apm pack 等子命令,字段与默认值以 reference 与 enterprise 章节为准;本教程六步只覆盖安装、声明、部署、复现与治理这条主线。