The Agent Package Manager solves a problem I see in almost every repo where AI agents help out: good skills and instructions get written once and then copied. One team writes a strong SKILL.md for release notes, the next team copies it and tweaks two lines, and three months later there are five variants. As a result, nobody knows which one is current.
However, we solved this problem for code years ago: package managers, versions, lockfiles, automated updates. APM now brings exactly that to agent context, and since November 3, 2026, Dependabot on github.com keeps these packages up to date as well. Using a fictional bike rental company, I will show you how to build a shared rules package, use it in a service repo, check it in CI and update it with Dependabot. Along the way, you will also hit a gap that no announcement mentions.
In short
APM manages skills, instructions, agents and MCP servers like npm packages: an
apm.ymlmanifest, anapm.lock.yamllockfile, and one command deploys everything to Copilot, Claude Code and other tools. Dependabot now updates the manifest and lockfile. The biggest pitfall: Dependabot does not refresh the deployed files in your repo, so you need a separate step for that.
What you will learn in this article
- What the Agent Package Manager is and which files it writes where
- How to build and version your own rules package with a skill and an instruction
- How to protect APM packages in CI with
apm audit --ci - How Dependabot updates APM packages and where its limits are
- Why hidden characters in prompts are a real risk
What is the Agent Package Manager (APM)?
APM is an open source package manager from Microsoft under the MIT license. In short, it manages everything that gives an AI coding agent context: skills, instructions (rules for specific files), prompts, custom agents, hooks, plugins and MCP servers. MCP stands for Model Context Protocol, the open standard agents use to call external tools. The project page therefore calls APM npm for agent context, and the comparison fits.
You describe in an apm.yml which packages your repo needs. apm install fetches them from Git repos, writes an apm.lock.yaml with exact commits and hashes, and copies the files to wherever each tool expects them. For example, supported tools include GitHub Copilot, Claude Code, Cursor, Codex, Gemini CLI, OpenCode, Windsurf and Kiro. At the time of writing, version 0.35.0 from October 22, 2026 was current. In other words, the leading zero matters: details are still changing a lot.
For context: APM builds on open formats you may already use. Skills follow the Agent Skills format with a SKILL.md, which I explain in Write agent skills. For general project rules, AGENTS.md remains the right place, as described in AGENTS.md setup. In other words, APM does not replace these formats. Instead, it distributes and versions them.
Why agent context needs a package manager
At first, one AGENTS.md per repo is perfectly enough. However, it gets harder as soon as several repos need the same rules: the same TypeScript conventions, the same skill for release notes, the same instruction on how tests should look. Then the copying starts, and with it three familiar problems.
First, the copies drift apart because every improvement lands in only one repo. Second, you never know which version of a skill an agent is reading right now. Third, nobody checks what is actually being copied in. Above all, that last point is underestimated, because a skill is text that an agent acts on with your permissions. That is why I see prompts and skills as part of the supply chain, just like npm packages. By the way, how to use a waiting period against freshly published malicious npm versions is covered in npm minimum release age.
The Agent Package Manager solves all three problems in a familiar way: there is exactly one source, every version is a Git tag, and the lockfile records which commit with which hash ended up in the repo.
Where does the Agent Package Manager write the files?
First of all, each tool expects its files in a different place. APM calls the tools targets and converts to their format during installation. The table shows an excerpt from the targets matrix in the documentation, each for project files.
| Target | Instructions | Skills | Active when … |
|---|---|---|---|
| copilot | .github/instructions/ | .agents/skills/ | .github/copilot-instructions.md or a matching folder in .github/ exists |
| claude | .claude/rules/ | .claude/skills/ | .claude/ or CLAUDE.md exists |
| cursor | .cursor/rules/ (as .mdc) | .agents/skills/ | .cursor/ or .cursorrules exists |
| codex | only via apm compile into AGENTS.md | .agents/skills/ | .codex/ exists |
| gemini | only via apm compile into GEMINI.md | .agents/skills/ | .gemini/ or GEMINI.md exists |
How APM picks the targets
APM decides which targets apply in this order: first --target on the command line, then targets: in the apm.yml, and finally detection based on existing folders. For this reason, I always pin the targets. That way the result does not depend on whether someone happened to create a .cursor/ folder. With apm targets you can see at any time what is currently active.
One package, many agents: apm install writes the same rules into each tool’s folders.
Set up the Agent Package Manager step by step
The example is made up: a bike rental company has the GitHub organization beispiel-velo. It contains a repo agent-standards with shared rules, and several service repos such as booking-api should use them. I reproduced all steps with APM 0.35.0, using a local copy of the package.
Prerequisites
- Git and a GitHub repo where you may create files under
.github/ - Python 3 for the pip installation, or Homebrew instead
- An agent that reads the files, for example Copilot in VS Code or Claude Code
- For private package repos, a token with read access (more on that below)
Step 1: Install APM
You install the Agent Package Manager on macOS with Homebrew and on Linux with the project’s install script. In my test I used pip because it lets me pin the version.
brew install apm # or without Homebrew (Linux/macOS): curl -sSL https://aka.ms/apm-unix | sh # or with a pinned version via pip: pip install apm-cli==0.35.0 apm --version Expected result: Agent Package Manager (APM) CLI version 0.35.0. On Windows there is a PowerShell script, and the installation page of the docs lists all options.
Step 2: Create the shared package
A package for the Agent Package Manager is a regular Git repo with an apm.yml. The content lives in a .apm/ folder, grouped by type. This is what the agent-standards repo looks like:
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 The instruction applies only to TypeScript files. This is controlled by the applyTo field in the file header:
<!-- .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. The skill describes a task that the agent only loads when needed. The description is what matters, because it tells the agent when the skill fits:
<!-- .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. Finally, you commit and set a SemVer tag. You will need it later for Dependabot:
git add -A git commit -m "agent-standards v1.0.0" git tag v1.0.0 git push origin main --tags Step 3: Use the package in a service repo
In the booking-api repo, apm init creates an apm.yml. Then you add the targets and the package with a fixed tag. The short form organization/repo#tag is no accident: it is the only notation Dependabot will update later.
# 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 In my test, the output looked like this (shortened; because I used a local copy of the package, it shows a path instead of tag and 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. What ends up in .claude/rules/typescript.md is revealing. APM automatically converts the Copilot field applyTo into the paths field that Claude Code expects for path-scoped rules:
<!-- .claude/rules/typescript.md (generated by APM) --> --- paths: - "**/*.ts" --- - Enable `strict` and avoid `any`. Previously, I did exactly this conversion by hand and regularly forgot a file. APM also creates the apm.lock.yaml. For each package it records the source, the version, the list of deployed files and a SHA-256 hash for every file.
Step 4: Decide what belongs in the repo
| Path | Commit? | Why |
|---|---|---|
apm.yml | Yes | The manifest the whole team shares |
apm.lock.yaml | Yes | Records commits and hashes |
.github/, .claude/, .agents/ | Yes | Cloud agents such as the Copilot cloud agent read the files straight from the repo |
apm_modules/ | No | Package cache; APM adds it to .gitignore itself |
The APM documentation also recommends committing the deployed files. As a result, anyone who clones the repo gets the full context right away, even without APM installed. However, this decision has a consequence for Dependabot, which I will get to in a moment.
Step 5: Let CI check the agent context
apm audit --ci compares the lockfile with the files in the repo: Are all deployed files present? Do their hashes match? Are there hidden Unicode characters? Did someone edit a deployed file by hand? For GitHub Actions there is the official microsoft/apm-action. With setup-only it only installs the CLI, and the audit checks exactly the files in the pull request.
# .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 Therefore, set apm-version explicitly. Otherwise the action installs a pinned default version that, when I looked at its action.yml, was much older than the current release. Afterwards I deliberately sabotaged the audit and added a line to .claude/rules/typescript.md by hand. Result: hash-drift for exactly that file, exit code 1, and a hint to run apm install. That is how it should be, because changes belong in the package and not in the copy.
Keep the Agent Package Manager up to date with Dependabot
Since November 3, 2026, Dependabot on github.com supports the apm ecosystem on all GitHub plans. GitHub Enterprise Server is set to follow with version 3.24. Moreover, the configuration is short:
# .github/dependabot.yml version: 2 updates: - package-ecosystem: "apm" directory: "/" schedule: interval: "weekly" cooldown: default-days: 3 labels: - "agent-context" directory points to the folder with the apm.yml. With cooldown, Dependabot waits three days after a new tag before opening a pull request. For third-party packages I consider that mandatory; for your own packages you can choose a smaller value. Similarly, the label makes it easier to find these PRs in review, but it has to exist in the repo.
Version updates only
One limitation you should know: Dependabot only does version updates here, no security updates. After all, there is no database of known vulnerabilities for skills and prompts yet, like there is for npm packages.
Which entries Dependabot updates
To begin with, Dependabot reads the entries under dependencies.apm and devDependencies.apm. What happens next depends on how you pinned the version:
| Pinned as | Example | What Dependabot does |
|---|---|---|
| SemVer tag | beispiel-velo/agent-standards#v1.0.0 | Bumps it to the latest SemVer tag |
| Commit SHA (40 characters) | beispiel-velo/agent-standards#<sha> | Sets the commit of the latest release tag and adds the tag as a comment |
| Branch | beispiel-velo/agent-standards#main | Only changes the lockfile, and only if one exists |
Equally important is the list of entries Dependabot leaves alone. It includes object-form entries with git: and path:, all MCP entries, entries without a version, local paths, packages on Azure DevOps and abbreviated commit SHAs. So if you work with git: objects like the example on the APM project page, you will not get any pull requests. Dependabot regenerates an existing lockfile with apm lock, but it does not create a missing one.
The pitfall: new lockfile, old files
This is where it gets interesting. According to its help text, apm lock only resolves dependencies and writes the lockfile, but it does not deploy any files. Consequently, the copies in .github/ and .claude/ stay on the old version. To verify this, I reproduced it: changed the package to 1.1.0, ran apm lock, then apm audit --ci. Result: drift in two files, exit code 1.
For you, this means for example: the Dependabot PR turns red as soon as your workflow from step 5 runs. However, I do not mind that at all. I would check out the branch, run apm install, read the diff of the rules and commit. After all, this diff is exactly what a human should see before new instructions for an agent go live. If you want to automate it, you can build a workflow that runs apm install on Dependabot PRs and pushes back. I would be careful with pull request workflows that have elevated permissions, though; pull_request_target blocked explains why.
🎬 Update cycle with Agent Package Manager and Dependabot – this animated diagram only runs on my site: watch it on sascha-ms.de
How secure are APM packages?
A skill is an instruction to a model. Anyone who hides invisible characters in it can slip things past an agent that nobody sees in review. That is why APM checks for hidden Unicode characters on every install. To test this, I added a character that reverses the text direction and a zero-width space to the SKILL.md. apm install blocked the package, named the affected file and deployed nothing. Overriding it with --force is possible, but it is meant only after your own review.
Policies for organizations
On top of that, there are two safeguards I would use in larger organizations. MCP servers that a package brings in indirectly are not installed by default unless you declare or approve them yourself. And with an apm-policy.yml policy file in the organization’s .github repo, you define which sources packages may come from:
# apm-policy.yml in the beispiel-velo/.github repo name: "Agent context at the bike rental company" version: "1.0.0" enforcement: warn dependencies: allow: - "beispiel-velo/*" mcp: allow: - "io.github.github/*" Watch out with enforcement: warn: violations show up in the report, but the check still counts as passed. In my test, apm audit --ci --policy apm-policy.yml reported a source that was not allowed and still ended with exit code 0. In contrast, only with enforcement: block did the same run fail. Consequently, I would start with warn, read the reports for a week and then switch to block. Policies can also be inherited, and a lower level may only tighten rules.
Common mistakes and how to avoid them
apm install finds no target
In a fresh repo without .github/ or .claude/, APM detects no targets and aborts. Add targets: to the apm.yml or pass --target copilot once.
Dependabot opens no pull requests
In most cases, it is the notation. Check whether your entries use the short form with #tag and whether the package repo has SemVer tags such as v1.2.0. Dependabot treats pre-releases like v1.2.0-rc.1 separately.
Someone edits the deployed files by hand
This happens quickly, since the files live in the repo. The audit reports it as drift. Therefore, a short note in the AGENTS.md helps: rules are changed in the package, not in the copy.
Private package repos fail in CI
For private dependencies, APM expects a token in GITHUB_APM_PAT. The default GITHUB_TOKEN is not enough for other repos, and the docs explicitly advise against it. For Dependabot, you configure access separately through a Git registry in the dependabot.yml.
My take
I think the approach behind the Agent Package Manager is right, for a reason that has little to do with technology. As long as skills travel by copy and paste, nobody owns them. With a package, there is suddenly a repo, a version history and people who review pull requests. This way, loose prompts turn into maintained team knowledge. Adding Dependabot also makes it practical for everyday work, because updates no longer depend on someone remembering them.
At the same time, I see the limits just as clearly. APM is at version 0.35, the changelog is long, and things like schema versions are still changing. For now, I would use it for my own internal packages and be very selective with third-party packages: fixed tags, cooldown, an allow list in the policy. Finally, I would resist the temptation to package everything. Project rules that only concern one repo stay in its AGENTS.md. In contrast, a package pays off the moment the same rule is needed in more than two repos.
FAQ
What is the Agent Package Manager?
An open source package manager from Microsoft for agent context. It installs skills, instructions, prompts, agents and MCP servers from Git repos, writes a lockfile and deploys the files to Copilot, Claude Code and other tools.
Which package-ecosystem value does Dependabot need for APM?
The value apm. directory points to the folder with the apm.yml. Only version updates are supported, no security updates.
Do I have to commit the files APM generates?
The docs recommend it, so that cloud agents and team members without APM get the context right away. Only the apm_modules/ cache does not belong in the repo.
Does APM replace AGENTS.md?
No. AGENTS.md remains the place for the rules of a single repo. APM distributes and versions content that several repos share.
Your next step
First, search your repos for skills and instructions that appear more than twice. Even a single one is enough for a first package: its own repo, an apm.yml, tag v1.0.0, then apm install in a service repo and the dependabot.yml from this article. Which rule do you copy from repo to repo most often? Let me know in the comments.
Sources
- Dependabot version updates support Agent Package Manager (GitHub Changelog, 11/03/2026)
- Dependabot supported ecosystems and repositories, APM section (GitHub Docs)
- Dependabot options reference (GitHub Docs)
- APM – Agent Package Manager with Quickstart, targets matrix and manifest schema (Microsoft)
- APM Governance Guide and CI/CD integration (Microsoft)
- microsoft/apm with changelog and microsoft/apm-action (GitHub)
This post was created with AI assistance.
👉 Next step: New here? My start page collects the best articles, tools and learning paths in one place.
Originally published on sascha-ms.de. More articles on serverless, AI in everyday development and leading tech teams: sascha-ms.de/en

