Agent Package Manager:用 Dependabot 让技能保持更新
Agent Package Manager(APM)解决的是我在几乎所有引入 AI 智能体的仓库里都能看到的一个毛病:好的技能和指令只写一次,然后就被到处复制。一个团队为发布说明写了一份很扎实的 SKILL.md,下一个团队把它拷过去改了两行,三个月后就出现了五个版本,结果谁也说不清哪一份才是最新的。
可是代码领域的这个问题,我们很多年前就解决了:包管理器、版本号、锁文件、自动更新。APM 现在把这一套原封不动地搬到了智能体上下文上;而且从 2026 年 11 月 3 日起,github.com 上的 Dependabot 也能让这些包保持更新。
下面我用一家虚构的自行车租赁公司做例子,演示怎么建一个共享规则包、在服务仓库里引用它、在 CI 里检查它,再用 Dependabot 更新它。过程中你还会撞上一个所有公告都没提的坑。
简单说,APM 把技能、指令、智能体和 MCP 服务器当成 npm 包来管理:一份 apm.yml 清单、一份 apm.lock.yaml 锁文件,一条命令就能把所有东西部署到 Copilot、Claude Code 等工具里。Dependabot 现在会更新清单和锁文件。最大的坑在于:Dependabot 不会刷新仓库里已经部署出去的文件,所以这一步得单独处理。
本文你会学到什么
- Agent Package Manager 是什么,它会把哪些文件写到哪里
- 怎么用一条技能加一条指令,构建并给自己的规则包打版本
- 怎么在 CI 里用
apm audit --ci保护 APM 包 - Dependabot 如何更新 APM 包,边界又在哪里
- 为什么提示词里的隐藏字符是真实风险
Agent Package Manager(APM)是什么?
APM 是微软推出的开源包管理器,采用 MIT 许可证。它管理的是给 AI 编程智能体提供上下文的一切东西:技能、指令(针对特定文件的规则)、提示词、自定义智能体、钩子、插件和 MCP 服务器。MCP 是 Model Context Protocol(模型上下文协议)的缩写,是智能体调用外部工具所用的开放标准。
所以项目主页把 APM 称作“智能体上下文的 npm”,这个类比很贴切。你在 apm.yml 里声明仓库需要哪些包。
apm install 会从 Git 仓库拉取这些文件,生成 apm.lock.yaml,记录确切的 commit 和哈希值,再把文件复制到各个工具期望的目录。目前支持的工具包括 GitHub Copilot、Claude Code、Cursor、Codex、Gemini CLI、OpenCode、Windsurf 和 Kiro。写作时最新版本是 2026 年 10 月 22 日发布的 0.35.0。换句话说,版本号前面的那个 0 很关键:细节还在频繁变化。
补充一点背景:APM 建立在你可能已经在用的开放格式之上。技能(Skill)遵循 Agent Skills 格式,核心是一个 SKILL.md 文件,我在《编写 Agent 技能》一文中有详细说明。项目级别的通用规则则仍然放在 AGENTS.md 里,具体做法见《AGENTS.md 配置指南》。也就是说,APM 并不取代这些格式,它的作用是分发和版本管理。
为什么 Agent 的上下文需要包管理器
一开始,每个仓库放一份 AGENTS.md 完全够用。但一旦多个仓库需要相同的规则,事情就变麻烦了:一样的 TypeScript 编码约定,一样的发布说明技能,一样的测试编写规范。于是你开始复制粘贴,随之而来的是三个老问题。
第一,副本会逐渐走样,因为每次改进只落在某一个仓库里。第二,你无法确定 Agent 当前读到的是哪个版本的技能。第三,没有人检查实际被复制进来的内容到底是什么。最后这一点最容易被低估,因为技能本质上就是一段文本,而 Agent 会带着你的权限去执行它。所以在我看来,提示词和技能都属于供应链的一部分,和 npm 包没什么两样。顺带一提,如何利用等待期来规避刚发布的恶意 npm 版本,可以参考《npm 最小发布龄》一文。
Agent Package Manager 用一套熟悉的方式解决了这三个问题:只有一个来源;每个版本对应一个 Git tag;锁文件记录最终进入仓库的是哪个 commit、哈希值是多少。
Agent Package Manager 把文件写到哪里?
首先,每个工具期望的文件位置都不一样。APM 把这些工具称为「target」(目标),安装时转换成各自的格式。下面的表格摘自文档中的 targets 矩阵,展示的是项目级文件的部分内容。
| 目标 | 指令目录 | 技能目录 | 生效条件 |
|---|---|---|---|
| copilot | .github/instructions/ |
.agents/skills/ |
存在 .github/copilot-instructions.md,或 .github/ 下有匹配的文件夹 |
| claude | .claude/rules/ |
.claude/skills/ |
存在 .claude/ 或 CLAUDE.md |
| cursor | .cursor/rules/(以 .mdc 形式) |
.agents/skills/ |
存在 .cursor/ 或 .cursorrules |
| codex | 只能通过 apm compile 写入 AGENTS.md |
.agents/skills/ |
存在 .codex/ |
| gemini | 只能通过 apm compile 写入 GEMINI.md |
.agents/skills/ |
存在 .gemini/ 或 GEMINI.md |
APM 如何选择目标
APM 按以下顺序决定哪些目标生效:先是命令行上的 --target,接着是 apm.yml 里的 targets:,最后才根据现有文件夹做自动检测。
正因如此,我每次都会把目标固定下来。这样结果就不会因为「某人恰好建了个 .cursor/ 文件夹」而变来变去。用 apm targets 可以随时查看当前生效的目标。
一个包,多个 Agent:apm install 会把同一套规则分别写进每个工具的目录里。
一步步搭建 Agent Package Manager
下面的例子是虚构的:一家自行车租赁公司,GitHub 组织名叫 beispiel-velo。组织里有一个存放共享规则的仓库 agent-standards,还有若干服务仓库(比如 booking-api)要用到这些规则。
我用 APM 0.35.0 复现了全部步骤,用的是该包的本地副本。
前置条件
- 已安装 Git,并有一个可以在
.github/下创建文件的 GitHub 仓库 - 用 pip 安装需要 Python 3,或者改用 Homebrew
- 一个能读取这些文件的 Agent,例如 VS Code 里的 Copilot 或 Claude Code
- 如果包仓库是私有的,需要一个有读权限的 token(下文详述)
第 1 步:安装 APM
在 macOS 上用 Homebrew 安装 Agent Package Manager,在 Linux 上用项目的安装脚本。我在测试里用的是 pip,因为它可以锁定版本。
brew install apm
# 或者不用 Homebrew(Linux/macOS):
curl -sSL https://aka.ms/apm-unix | sh
# 或者用 pip 锁定版本:
pip install apm-cli==0.35.0
第 2 步:创建共享包
Agent Package Manager 的包就是一个普通 Git 仓库,外加一个 apm.yml 文件。包内容放在 .apm/ 目录下,按类型分组。agent-standards 仓库的结构如下:
agent-standards/
├── apm.yml
└── .apm/
├── instructions/
│ └── typescript.instructions.md
└── skills/
└── release-notes/
└── SKILL.md
apm.yml 内容:
name: agent-standards
version: 1.0.0
description: Shared AI rules for all repos of the bike rental company
这条指令只对 TypeScript 文件生效,由文件头部的 applyTo 字段控制:
<!-- .apm/instructions/typescript.instructions.md -->
---
applyTo: "**/*.ts"
---
- Enable `strict` and avoid `any`.
- Use named exports instead of `export default`.
- Write a test with `node:test` for every new function.
技能描述的是 agent 按需加载的任务。关键在于 description 字段,它告诉 agent 什么时候该用这个技能:
<!-- .apm/skills/release-notes/SKILL.md -->
---
name: release-notes
description: Writes release notes from the commits since the last tag. Use this skill when someone asks for release notes, a changelog or "what's new".
---
# Write release notes
1. Find the last tag with `git describe --tags --abbrev=0`.
2. Read the commits since that tag with `git log <tag>..HEAD --oneline`.
3. Sort them into the sections "New", "Fixed" and "Internal".
4. Phrase every item from the user's point of view, not the developer's.
5. Leave out commits that only touch tests, formatting or CI.
最后提交并打一个 SemVer 标签,后面 Dependabot 会用到:
git add -A
git commit -m "agent-standards v1.0.0"
git tag v1.0.0
git push origin main --tags
第三步:在服务仓库中使用这个包
在 booking-api 仓库里,运行 apm init 会生成一个 apm.yml。接着添加目标(targets)和带固定 tag 的包。这里用简写形式 organization/repo#tag 是有意为之:只有这种写法,Dependabot 之后才会去更新。
# apm.yml
name: booking-api
version: 1.0.0
description: Booking API of the bike rental company
targets:
- copilot
- claude
dependencies:
apm:
- beispiel-velo/agent-standards#v1.0.0
mcp: []
apm install
在我的测试中,输出大致如下(有删减;因为我用的是本地副本,所以显示的是路径,而不是 tag 和 commit):
[i] Targets: claude, copilot (source: apm.yml)
[+] ../agent-standards (local)
|-- 2 instruction(s) integrated -> .claude/rules/, .github/instructions/
|-- 1 skill(s) integrated -> .agents/skills/, .claude/skills/
[i] Added apm_modules/ to .gitignore
[*] Installed 1 APM dependency in 0.1s.
最终写入 .claude/rules/typescript.md 的内容很能说明问题。APM 会自动把 Copilot 的 applyTo 字段,转换成 Claude Code 为路径作用域规则所期望的 paths 字段:
<!-- .claude/rules/typescript.md (generated by APM) -->
---
paths:
- "**/*.ts"
---
- 开启
strict,避免出现any。以前这种转换我都是手动做的,每次都会漏掉某个文件。APM 还会生成apm.lock.yaml,对每个包记录来源、版本、部署文件清单,以及每个文件的 SHA-256 哈希值。
第 4 步:决定哪些文件放进仓库
| 路径 | 是否提交 | 原因 |
|---|---|---|
apm.yml |
是 | 整个团队共享的清单文件 |
apm.lock.yaml |
是 | 记录提交和哈希 |
.github/、.claude/、.agents/ |
是 | Copilot cloud agent 这类云端智能体直接从仓库读取文件 |
apm_modules/ |
否 | 包缓存,APM 会自己把它加入 .gitignore |
APM 文档同样建议提交已部署的文件。这样一来,任何人克隆仓库后马上就有完整上下文,即使没装 APM 也一样。不过这个决定会给 Dependabot 带来一个后果,我稍后会说。
第 5 步:让 CI 检查智能体上下文
apm audit --ci 会把锁文件和仓库里的文件做比对:
- 部署的文件是否齐全?
- 哈希值是否对得上?
- 有没有藏起来的 Unicode 字符?
- 是否有人手动改过某个已部署的文件?
GitHub Actions 有官方的 microsoft/apm-action。加上 setup-only 时它只安装 CLI,审计检查的正好是拉取请求里的文件。
# .github/workflows/agent-context.yml
name: Check agent context
on:
pull_request:
paths:
- "apm.yml"
- "apm.lock.yaml"
- ".agents/**"
- ".claude/**"
- ".github/instructions/**"
permissions:
contents: read
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: microsoft/apm-action@v1
with:
setup-only: true
apm-version: "0.35.0"
- name: Check lockfile, hashes and drift
run: apm audit --ci
所以要显式设置 apm-version。否则这个 action 会安装一个固定的默认版本,我查看它的 action.yml 时,那个版本比当前发布版老得多。
之后我故意搞坏审计:手动往 .claude/rules/typescript.md 里加了一行。结果正是那个文件报出 hash-drift,退出码为 1,并提示运行 apm install。本该如此,因为改动应该做在包里,而不是做在副本里。
Agent Package Manager:用 Dependabot 保持技能更新
用 Dependabot 让 Agent Package Manager 保持最新。自 2026 年 11 月 3 日起,github.com 上的 Dependabot 已在所有 GitHub 方案中支持 apm 生态,GitHub Enterprise Server 将在 3.24 版本跟进。配置也很简短:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "apm"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 3
labels:
- "agent-context"
directory 指向存放 apm.yml 的文件夹。借助 cooldown,Dependabot 会在新 tag 发布后等三天才开 pull request。对第三方包,我认为这是必须的;对你自己发布的包,可以设更短。同样,labels 让这些 PR 在 review 时更容易找到,但前提是仓库里已经存在这个 label。
只做版本更新
有一个限制你需要知道:这里的 Dependabot 只做版本更新,不做安全更新。毕竟,技能和提示词目前还没有像 npm 包那样的已知漏洞数据库。
Dependabot 会更新哪些条目
首先,Dependabot 会读取 dependencies.apm 和 devDependencies.apm 下的条目。之后怎么处理,取决于你如何固定版本:
| 固定方式 | 示例 | Dependabot 的行为 |
|---|---|---|
| SemVer tag | beispiel-velo/agent-standards#v1.0.0 |
升级到最新的 SemVer tag |
| Commit SHA(40 字符) | beispiel-velo/agent-standards#<sha> |
设为最新 release tag 对应的 commit,并把该 tag 作为注释加上 |
| 分支 | beispiel-velo/agent-standards#main |
只改 lockfile,且仅在 lockfile 已存在时 |
同样重要的是 Dependabot 会跳过的条目清单,包括:带 git: 和 path: 的对象形式条目、所有 MCP 条目、没有版本的条目、本地路径、Azure DevOps 上的包,以及缩写的 commit SHA。所以,如果你像 APM 项目页上的示例那样使用 git: 对象,就不会收到任何 pull request。
Dependabot 会用 apm lock 重新生成已有的 lockfile,但不会创建缺失的 lockfile。
陷阱:新的 lockfile,旧的文件
有意思的地方来了。根据其帮助文本,apm lock 只解析依赖并写入 lockfile,但不会部署任何文件。
随之而来的是,.github/ 和 .claude/ 里的副本还停留在旧版本。我复现了一遍来验证:把包版本改成 1.1.0,运行 apm lock,再运行 apm audit --ci。结果:两个文件出现漂移,退出码为 1。对你来说,实际影响大概是:第 5 步里的工作流一跑,Dependabot 的 PR 立刻变红。
不过我并不介意。我会检出这个分支,运行 apm install,读一遍规则 diff,然后提交。毕竟,这份 diff 正是新指令正式生效前,人应该看到的东西。如果你想自动化,也可以做一个工作流,在 Dependabot 的 PR 上运行 apm install,再把结果推回去。但权限较高的 pull request 工作流要谨慎,pull_request_target 被拦截的原因就说明了这一点。
🎬 Agent Package Manager 与 Dependabot 的更新循环 —— 这个动画图只在我的网站上运行:去 sascha-ms.de 观看
APM 包有多安全?
技能本质上是给模型的一段指令。有人只要在其中藏入不可见字符,就能把东西偷偷塞给 agent,而人工审查时完全看不到。所以 APM 每次安装都会检查隐藏的 Unicode 字符。为了测试,我在 SKILL.md 里加了一个反转文字方向的字符和一个零宽空格。apm install 拦下了这个包,指出受影响的文件,并且什么都没部署。用 --force 可以覆盖,但这只应在你自己审查过之后使用。
组织级策略
除此之外,还有两项防护,我会在较大组织里使用。包间接引入的 MCP 服务器默认不会安装,除非你自己声明或批准。另外,在组织的 .github 仓库里放一个 apm-policy.yml 策略文件,就能规定包可以来自哪些来源:
# beispiel-velo/.github 仓库中的 apm-policy.yml
name: "Agent context at the bike rental company"
version: "1.0.0"
enforcement: warn
dependencies:
allow:
- "beispiel-velo/*"
mcp:
allow:
- "io.github.github/*"
注意 enforcement 的取值:设为 warn 时,违规会出现在报告里,但检查仍算通过。
我测试时,apm audit --ci --policy apm-policy.yml 报告了一个不允许的来源,却仍然以退出码 0 结束。相反,只有设置 enforcement: block,同样的运行才会失败。因此,我建议先设成 warn,看一周报告,再切到 block。策略还可以继承,下级只能收紧规则。
常见错误及避免方法
apm install 找不到目标
在一个没有 .github/ 或 .claude/ 的新仓库里,APM 检测不到目标,会直接中止。可以在 apm.yml 里加上 targets:,或者先传一次 --target copilot。
Dependabot 不开 pull request
多数情况下是版本写法的问题。检查你的条目是否用了带 #tag 的短格式,以及包仓库是否有 v1.2.0 这样的语义化版本标签。Dependabot 会把 v1.2.0-rc.1 这类预发布版单独处理。
有人手动改了部署的文件
这很容易发生,因为文件就在仓库里。审计会把它报告为漂移(drift)。在 AGENTS.md 里加一句简短说明会有帮助:规则要在包里改,而不是在副本里改。
私有包仓库在 CI 里失败
对于私有依赖,APM 需要 GITHUB_APM_PAT 里的令牌。默认的 GITHUB_TOKEN 对其他仓库不够用,文档也明确不建议这么做。用 Dependabot 时,需要在 dependabot.yml 里通过 Git registry 单独配置访问权限。
我的看法
我认为 Agent Package Manager 背后的思路是对的,原因与技术关系不大。只要技能靠复制粘贴传播,就没有人真正负责。有了包,就突然有了仓库、版本历史和审查 pull request 的人。这样一来,零散的提示词就变成了被维护的团队知识。加上 Dependabot 之后,日常使用也变得实际可行,因为更新不再依赖谁记得去做。
同时,我也同样清楚地看到它的局限。APM 还在 0.35 版本,变更日志很长,schema 版本之类的东西还在变。目前,我只会用它管理自己内部的包,对第三方包非常挑剔:固定 tag、冷却期、策略里的白名单。最后,要克制住把所有东西都打包的冲动。
项目规则只涉及一个仓库时,留在它的 AGENTS.md 里。相比之下,同一条规则需要在两个以上仓库使用时,打包才划算。
常见问题
什么是 Agent Package Manager?
这是微软推出的开源包管理器,用于管理 agent 上下文。它从 Git 仓库安装技能、指令、提示词、agent 和 MCP 服务器,生成锁文件,并把文件部署到 Copilot、Claude Code 等工具中。
Dependabot 需要哪个 package-ecosystem 值来支持 APM?
值是 apm。directory 指向包含 apm.yml 的文件夹。只支持版本更新,不支持安全更新。
APM 生成的文件必须提交吗?
文档建议提交,这样云端 agent 和没有安装 APM 的团队成员也能立刻拿到上下文。只有 apm_modules/ 缓存不该进仓库。
APM 会取代 AGENTS.md 吗?
不会。AGENTS.md 仍然是单个仓库规则的归属地。APM 负责分发和版本化多个仓库共享的内容。
下一步
先在你的仓库里搜索出现超过两次的技能和指令。哪怕只有一条,也够做第一个包了:建一个独立仓库,写 apm.yml,打上 v1.0.0 标签,然后在服务仓库里执行 apm install,再加上本文的 dependabot.yml。
你最常从仓库复制到仓库的规则是哪一条?欢迎在评论区告诉我。
参考资料
- Dependabot 版本更新支持 Agent Package Manager(GitHub Changelog,2026 年 3 月 11 日)
- Dependabot 支持的生态系统和仓库,APM 部分(GitHub Docs)
- Dependabot 选项参考(GitHub Docs)
- APM – Agent Package Manager 快速入门、目标矩阵和清单 schema(微软)
- APM 治理指南和 CI/CD 集成(微软)
- microsoft/apm 的变更日志和 microsoft/apm-action(GitHub)
本文在 AI 辅助下完成。
👉 下一步:刚来这里?我的起始页汇集了最好的文章、工具和学习路径。
最初发布于 sascha-ms.de。更多关于 serverless、AI 在日常开发中的应用以及领导技术团队的文章:sascha-ms.de/en
几乎所有让 AI 智能体参与协作的代码仓库里,都能见到同一个毛病的翻版:好的技能和指令只写了一次,之后就被反复复制。一个团队为发布说明写了一份质量不错的 SKILL.md,另一个团队直接照搬,只改了两行;三个月后,同一份东西出现了五个版本,结果没人说得清哪个才是当前版本。而代码领域多年前就解决了这类问题:包管理器、版本号、锁文件、自动更新。现在,APM 把这套机制原样搬到了智能体技能上。