agent-context-router
Loads agent instruction modules from ordinary Git repositories, fast-forwarding local clones from their remotes when available and returning the commit read along with sync status.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agent-context-routerload the pr-description module before writing this PR summary"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
agent-context-router
An MCP server that loads agent instructions on demand.
A long AGENTS.md costs tokens on every request, and most of it applies to only a few tasks. agent-context-router splits it in two: a slim AGENTS.md that holds the rules for every turn and lists the rest as modules, each with a trigger, and this server, which reads a module when the agent reaches the work its trigger names. Modules live in ordinary git repos. Before reading one, the router fast-forwards the local clone from its remote (at most once every 30 minutes, and never over local work), then returns the module text with the commit it read.
It works with any MCP client. It's tested with goose and Claude Code.
HUMAN.md covers what changes for you once it's set up, what stays your call, and how to turn it off.
Results
In a test harness of four scenarios with five runs each, the agent used the router in all 20 runs and passed every behavior check. Median input tokens per run, slim AGENTS.md plus router vs the full AGENTS.md:
Device install: 84,964 vs 206,044
PR description: 60,782 vs 180,964
Review comment: 61,231 vs 117,576
Delegated device install: 139,984 vs 265,154. The subagent loaded the device module on its own before any device command, in 5 of 5 runs.
These come from a small fixture, so real sessions with long conversations will save less as a percentage. Method, rounds and raw data: docs/results/2026-10-25-router.md and docs/results/.
Related MCP server: Instruction MCP Server
Quick start
Requires Python 3.10+ and uv.
git clone https://github.com/dakotafabro/agent-context-router.git
cd agent-context-router
uv syncOr install it with bpm, which puts a copy in ~/.bpm/packages/agent-context-router@<version> and lists it in your project's AGENTS.md:
bpm install agent-context-routerWith bpm, use that folder wherever these steps say /path/to/agent-context-router.
Try it with the bundled example, which has three modules and a slim AGENTS.md in examples/:
ACR_REGISTRY="$PWD/examples/modules.yaml" uv run agent-context-routerRegister it in goose
Add this under extensions: in ~/.config/goose/config.yaml, with your clone's absolute path:
agent-context-router:
enabled: true
type: stdio
name: agent-context-router
description: Loads agent instruction modules on demand
cmd: uv
args: [run, --directory, /path/to/agent-context-router, agent-context-router]
envs:
ACR_REGISTRY: /path/to/agent-context-router/examples/modules.yaml
timeout: 60Or try it for one session without editing config:
goose session --with-extension "ACR_REGISTRY=/path/to/agent-context-router/examples/modules.yaml uv run --directory /path/to/agent-context-router agent-context-router"Register it in Claude Code
claude mcp add -s user agent-context-router \
-e ACR_REGISTRY=/path/to/agent-context-router/examples/modules.yaml \
-- uv run --directory /path/to/agent-context-router agent-context-routerThen copy examples/AGENTS.md into a project (or your global hints file) and ask the agent to write a PR description. It should call load_module with pr-description before writing.
Checked on 2026-10-26 in both clients with the bundled example: goose v1.56.0 (--with-extension) loaded pr-description before writing a PR description, and Claude Code 2.1.42 (claude -p with --mcp-config, project settings only) loaded commit-messages before writing a commit message. Each load appeared in the router's log.
Tools
list_modules: every module available on this machine, with its triggerload_module(id): the module's text, plus the commit it was read at, the repo's sync status and any warningsearch_context(query, top_k): modules that match a task description, for when no trigger obviously applies
Each load_module and search_context call is appended to ~/.local/state/agent-context-router/loads.jsonl, so you can see which modules agents actually load.
Migrating an existing AGENTS.md
The router never changes your config or your instruction files. To split a file you already have, use migrate, which works on one file at a time and keeps the original until you choose to switch:
uv run agent-context-router migrate plan ~/.config/goose/AGENTS.md ~/agent-context
uv run agent-context-router migrate decide ~/agent-context # answers the plan's questions, then offers to run apply
uv run agent-context-router migrate apply ~/agent-context
uv run agent-context-router migrate review ~/agent-context
uv run agent-context-router migrate switch ~/agent-contextplanreads the source and writes onlyplan.yaml, into a folder that must be empty. It splits the file at its main heading level, suggests sections over about 1.2 KB as modules, picks out one-line "never / always / before" rules to keep loaded, and warns about anything that looks like a secret.decideasks the plan's questions in the terminal: for each suggested module, keep it loaded or make it a module, when it should load, and which of its rules stay loaded; then which kept sections to move; then whether you approve the split. Answers are saved as you go, soqpauses and the next run resumes. It needs a terminal. You can editplan.yamlby hand instead, and setapproved_by_person: trueyourself.applyrefuses until the plan is approved (approved_by_person: true). It copies the source intobackup/with its sha256, then writesmodules/, a slimAGENTS.mdandmodules.yamlinto the same folder. With git installed, the folder becomes a repo whose first commit is the untouched original, with no remote. It refuses a plan with a module that has no trigger, or a source that changed since the plan, and it won't overwrite files in the folder it didn't write.verifychecks that every non-blank line of the original is in the slim file or a module. Text may move; it may not be dropped or reworded.applyandswitchrun it too.reviewshows what switch would install (sizes, kept sections, each module's trigger and kept rules, and a diff with--diff), asks for your approval, and records one hash over those exact files.switchinstalls only the reviewed files: it refuses if anything changed after the review. It shows the summary again and asks before replacing the source, refuses if the source changed since the backup, and copies the current file aside first. It doesn't ask when there's no terminal, so it never switches unattended unless you pass--yes.restoreputs the original back. It refuses if the file was edited after the switch (pass--forceto restore anyway; the edited file is copied aside first).
Which sections stay loaded is your call: plan only suggests. The full walkthrough, including where you approve each change, is in docs/migrate.md. Project and subdirectory AGENTS.md files aren't handled yet, since moving their rules changes which rule wins. On the author's 60 KB policy, plan found 36 sections and suggested 15 as modules; after apply, the always-loaded file was 13 KB and verify found all 330 lines of the original.
Writing the slim AGENTS.md
The pattern that held up in testing:
Keep the rules that apply every turn, and keep a one-line version of any safety rule even when its module has the detail. A rule should still hold if its module never loads.
List each module with a trigger that names the moment to load it, phrased as "before X" where order matters.
Name the router as the way to load, not one of two options. When the policy offered "call the tool or read the file," the agent read the file in 18 of 20 runs and skipped the sync.
Give the exact call. In clients with tool discovery (goose Code Mode), a policy that left the agent guessing the parameter name cost a failed call and two discovery round trips per load.
Tell delegates which module to load. A subagent gets its own context, so name the module id in its instructions when its task hits a trigger.
See examples/AGENTS.md.
Registry
The registry is a YAML file. The router reads it from ACR_REGISTRY, or from ~/.config/agent-context-router/modules.yaml when that's unset.
repos:
team-policy:
remote: git@github.com:your-org/agent-policy.git
path: ~/src/agent-policy
branch: main
local:
path: .
modules:
- {id: pr-description, repo: team-policy, file: modules/pr-description.md, trigger: "Writing or updating a PR description"}
- {id: device-testing, repo: team-policy, file: modules/device-testing.md, trigger: "Before any adb command or device install", profile: work}pathmay start with~, and a relative path is resolved from the registry file's directory.A repo without
remoteis read as it is, with statuslocal.A module with
profileloads only on machines with that profile, fromAGENT_MACHINEor~/.agent-machine(workorpersonal, defaultwork). A module without one loads everywhere.A module's
filemust stay inside its repo.
Sync
For repos with a remote, the router fetches and fast-forwards only. It never resets, rebases or stashes. When it can't update, it reads the local copy and says why, so the agent can tell you the module may be stale:
current,updated: up to date with the remotedirty,ahead,diverged,other-branch,behind: local state it won't overwriteoffline: the fetch failed or timed out (15 seconds)missing: no clone atpath
Configuration
ACR_REGISTRY: registry fileACR_SYNC_WINDOW: seconds between fetches of the same repo (default 1800)ACR_CACHE_DIR: sync state (default~/.cache/agent-context-router)ACR_LOG: load log (default~/.local/state/agent-context-router/loads.jsonl)AGENT_MACHINE: machine profile
Development
uv run pytesttests/harness/run.py is the scenario harness behind the results above. It runs each scenario in an isolated goose root (its own GOOSE_PATH_ROOT, so your sessions and config aren't touched), with fake adb, gradlew and iterm-title that only log their calls. It builds both policies with the author's policy repo, so to run it against your own, point ACR_POLICY_REPO at a repo with a scripts/assemble-goose-policy.sh that honors POLICY_SET=full|slim. ACR_GOOSE_CONFIG sets the goose config to copy provider settings from.
Background
docs/migrate.md: the migrate steps in fulldocs/plan.md: decisions, build phases and measurementdocs/baseline-2026-10-25.md: token and adherence numbers before the routerdocs/policy-sort.md: how each section of a 60 KB AGENTS.md was sorted into always-loaded or on demandaaif-goose/goose#13148: found while measuring the baseline. goose reloads a parent directory's hints file for each new subdirectory, which multiplies the cost of a long AGENTS.md.
License
Apache 2.0
This server cannot be deployed
Maintenance
Related MCP Connectors
Git-backed platform for skills, tools, and context for AI agents
- SetForkOAuthcom.setfork
Runnable, versioned lists for agents: tools, prompts and lists as resources. Git under the hood.
Code-map tools for AI agents: see a repo's structure first, then edit only what matters.
Your organization's knowledge as OKF trees in Git, for AI assistants to search, read, and cite
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to fetch, search, and retrieve markdown content from remote Git repositories. Supports both public and private repositories with authentication, allowing AI assistants to access documentation and notes stored in Git.MIT
- AlicenseNot gradedqualityDmaintenanceServes markdown instructions as tools to provide LLMs with team playbooks, coding standards, domain knowledge, and personal workflows through version-controlled files.4 npmMIT

RepoPrimerofficial
AlicenseAqualityDmaintenanceProvides fresh project context to coding agents by combining Markdown documentation and live Git state, enabling deterministic startup briefs and bounded document retrieval for MCP-compatible tools.41 npmApache 2.0- AlicenseBqualityDmaintenanceEnables AI agents to read git commits from local repositories and generate beautifully formatted, categorized changelogs.23 npmMIT