When a Local AGENTS.md Depends on a Remote Switch
An AGENTS.md file is about as local as a project detail gets. It sits beside the source code, contains plain Markdown, and does not need a server to be useful. So when Claude Code ignores it because telemetry is disabled, the behavior feels less like a rollout problem and more like a missing page in a book.
That is the surprising story behind Claude Code’s early AGENTS.md support. Version 2.1.277, released on September 18, 2026, announced that a project with no CLAUDE.md could use AGENTS.md instead. A report filed on September 20 found a hidden dependency: the local loader was behind a remotely evaluated feature flag. As of September 23, the latest listed release is 2.1.280, and the current documentation still warns that direct AGENTS.md loading is unavailable in sessions with telemetry disabled or without feature-flag fetching. (github.com)
The file is local; the decision is remote
A feature flag is a server-provided switch that tells a client whether a feature is active. It is useful for staged rollouts, but here it sits in front of a file lookup. The loader is exposed as a built-in agents-md plugin, and the reported gate is named tengu_agents_md_mod. If the session cannot retrieve that flag, Claude Code falls back to its older behavior: it reads CLAUDE.md and never adds AGENTS.md to the prompt.
Telemetry means diagnostic information about product usage, not the contents of your repository. The confusing part is that Claude Code uses some of the same traffic for feature-flag fetching. DISABLE_TELEMETRY=1 therefore does more than stop telemetry; it also blocks feature flags. CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 does the same. The current environment-variable reference also documents a presence-based rule: for these variables, any non-empty value—including 0 or false—still means disabled. Unset the variable or set it to an empty string to allow the traffic again. (code.claude.com)
This creates two layers that are easy to mistake for one another. Reading Markdown from the working directory is local. Deciding whether the agents-md loader is available is remote-controlled. The first operation needs no network, but the second can prevent it from happening.
What Claude Code normally does
The default rule is narrower than “always read both instruction files.” When there is no CLAUDE.md, .claude/CLAUDE.md, or CLAUDE.local.md in the working directory or an ancestor, Claude Code loads the relevant AGENTS.md files instead. Once one of those Claude-specific project files exists, the default loader stands down and reads the CLAUDE.md files only.
The /config menu exposes a Project instructions setting with modes for the fallback behavior, reading both families, reading only CLAUDE.md, or loading organization-managed instructions only. That setting is useful when the feature is available, but it cannot conjure the plugin into existence when feature-flag fetching is blocked. The row can disappear entirely in an unavailable session. A first session after an upgrade can also behave differently while the new feature state is being fetched, so a reproducible test should use a fresh configuration and two runs.
That boundary is easy to miss in multi-agent repositories. AGENTS.md support means project-tree instruction discovery; it does not mean Claude Code treats every .agents/ directory as a generic configuration root. The current documentation explicitly excludes AGENTS.local.md, AGENTS.override.md, and anything under .agents/ from this loader.
A canary test beats a guess
A canary is a known value placed in a controlled test so you can tell whether a path was actually exercised. Make a temporary directory containing nothing but an AGENTS.md file:
tmp="$(mktemp -d)"
cd "$tmp"
printf 'The canary word is PERIWINKLE.\n' > AGENTS.md
claude -p 'What is the canary word from the project instructions? Answer NONE if no project instructions are loaded. Do not open files.'
claude -p 'Repeat the canary word from the project instructions. Answer NONE if no project instructions are loaded. Do not open files.'
Run the pair once with the environment variables unset, then repeat with each privacy setting you normally use. The second invocation matters in the reported behavior because the first session fetches the flag and the next session consumes the result. In an interactive session, the startup transcript or the /context command, which shows loaded context files, can also reveal whether an instruction file was loaded.
| Setup | What to expect |
|---|---|
| Both variables unset | AGENTS.md can load after the feature state is available |
DISABLE_TELEMETRY=1 |
AGENTS.md is skipped |
DISABLE_TELEMETRY=0 |
It is still skipped; 0 is non-empty |
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 |
AGENTS.md is skipped |
| Bedrock, a gateway, or another provider without flag access | The direct loader may be unavailable |
This behavior follows the same feature-flag dependency documented for telemetry-disabled and third-party-provider sessions. (code.claude.com)
An env block in a project settings file is therefore a poor escape hatch. A shell export can sit outside that settings layer, and the built-in plugin configuration is not read from project or local settings. For a one-session diagnostic, the useful override is to clear both variables explicitly:
claude --settings '{"env":{"DISABLE_TELEMETRY":"","CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC":""}}' -p 'What is the canary word? Answer NONE if it was not loaded.'
Use an empty string, not 0. If an organization blocks the traffic by policy, this command should not be treated as a way around that policy; it is a way to prove which layer is responsible. (code.claude.com)
The one-line bridge
The most dependable workaround is to put the shared file behind the loader Claude Code already knows how to use:
printf '@AGENTS.md\n' > CLAUDE.md
The @path form is an import, not a suggestion for Claude to open the file later. Claude Code expands it into the instruction context while loading CLAUDE.md, so it continues to work when direct AGENTS.md support is unavailable. If direct support is available later, the loader avoids adding an imported file a second time. That makes the one-line bridge safe to keep in a repository shared with other coding agents. (code.claude.com)
A symlink can express the same relationship on some systems, but an import is friendlier across Windows checkouts and tools that refuse to edit through symlinked files. The important property is the single source of truth: AGENTS.md remains the shared file, while CLAUDE.md is a compatibility shim.
Why the silence matters
Why is Claude Code ignoring my AGENTS.md? Without a canary, the natural answer is that the model missed an instruction or that the Markdown was written badly. In reality, the file may never have entered the model’s context. No prompt rewrite can repair a file that was skipped before the conversation began.
Privacy controls should narrow outbound diagnostics, not quietly change unrelated local behavior. Feature flags are reasonable for a staged rollout, but a failed flag lookup should either preserve the documented local fallback or show a clear warning: “AGENTS.md was present but unavailable because feature flags could not be fetched.” That message would turn an afternoon of binary inspection into a ten-second diagnosis.
The broader lesson is architectural. A local instruction file belongs to the project’s data path, while telemetry and rollout switches belong to the control path—the part that decides which features are active. Connecting the two may be convenient during development, but it makes privacy-conscious users, gateway deployments, and managed cloud providers pay for an implementation detail they were never told about.
Until those paths are fully independent, the practical checklist is short: check for an ancestor CLAUDE.md or CLAUDE.local.md, inspect the privacy variables for any non-empty value, run a canary, and keep @AGENTS.md in a compatibility CLAUDE.md when the environment cannot fetch feature flags. The file stays local. The surprising part is the switch in front of it.
Comments (0)
No comments yet. Be the first to respond!
Leave a Comment
Your comment will be visible after review.