Desligou a telemetria e o projeto perdeu as instruções

Claude Code com suporte a AGENTS.md parecia a solução simples que faltava para quem mantém um único arquivo de instruções para vários agentes. Você cria o AGENTS.md na raiz, qualquer ferramenta lê, todo mundo segue as mesmas regras. Na prática, foi isso que a versão 2.1.277 prometeu: se não existir CLAUDE.md no projeto, o Claude Code leria o AGENTS.md automaticamente. Só que tem um detalhe que muda tudo para quem opera com privacidade ligada. Se você desliga telemetria ou tráfego não essencial, o arquivo é ignorado em silêncio. Nenhum aviso, nenhum erro, nenhum log claro. O modelo apenas responde como se o projeto não tivesse instruções.

Eu deixo DISABLE_TELEMETRY ligado em quase tudo por padrão. Não é paranoia, é higiene operacional. Menos chamada para fora, menos superfície, menos custo escondido. Quando comecei a testar o AGENTS.md em repo novo, a primeira hipótese foi erro meu. Arquivo no lugar errado, sintaxe estranha, cache, sessão antiga. Depois repeti o teste com palavra canário e ficou óbvio que não era erro local. O arquivo simplesmente nunca entrava no contexto. E isso com um arquivo de texto puro, lido do próprio disco, que não precisaria de rede para nada.

O fato: suporte anunciado, mas atrás de flag remoto

O que aconteceu é direto. A Anthropic lançou o suporte a AGENTS.md no Claude Code 2.1.277. A proposta era boa para padronização: se o projeto não tem CLAUDE.md, usa o AGENTS.md como instrução de projeto. Só que a implementação veio como um plugin interno chamado agents-md, e esse plugin não vem ativo por padrão no binário. No bundle da versão 2.1.280 dá para ver a lógica de registro. O valor de isOnByDefault é falso e a função isAvailable consulta um flag remoto chamado tengu_agents_md_mod, com falso como fallback.

Na prática isso significa que o Claude Code precisa conseguir buscar esse flag no servidor para liberar a leitura de um arquivo local. Se ele não consegue buscar, por telemetria desligada, por bloqueio de tráfego não essencial, por gateway de terceiros, por Bedrock ou Vertex, o plugin fica indisponível e o AGENTS.md nunca é lido. Leitura de markdown do diretório de trabalho não precisa de rede, mas aqui ela espera um switch do lado do servidor. É uma decisão de arquitetura estranha e é ela que gera todo o atrito.

Como funciona por dentro, na visão de quem opera

Pensa em termos de boot de sessão. Quando você abre o Claude Code, ele resolve configuração, resolve flags, monta plugins e depois monta contexto. O loader do AGENTS.md entrou como plugin opcional, não como parte do núcleo de leitura de instruções. Isso já explica parte da latência estranha relatada nos testes. Cada setup precisa de duas sessões porque a primeira sessão em uma configuração nova só busca o flag e a segunda é que usa o valor. Ou seja, existe um estado remoto com cache local, e esse estado define se um arquivo local entra ou não no prompt.

Os testes com palavra canário deixam o comportamento bem visível. Você cria um diretório vazio só com um AGENTS.md contendo algo como 'The canary word is PERIWINKLE' e pergunta em modo print sem deixar o modelo ler arquivos por conta própria. Se o loader funcionou, ele responde PERIWINKLE porque a instrução já veio no contexto. Se não funcionou, responde NONE. Com CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC igual a 1, o teste falha. Com DISABLE_TELEMETRY igual a 1, também falha. E aqui tem uma pegadinha clássica de variável de ambiente que muita gente erra em produção. Qualquer valor conta, inclusive 0. Colocar 0 não reativa. A documentação diz isso, mas quase ninguém espera que 0 seja igual a ligado para bloqueio.

Outro ponto importante para quem tenta isolar por repo. Um bloco env dentro de .claude/settings.json do projeto, limpando as duas variáveis, não tem efeito para reativar o recurso. Não existe hoje uma forma de ligar isso só para um repositório. O override que funciona é no nível da sessão, a partir da segunda sessão, passando settings com env vazio para DISABLE_TELEMETRY e CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC. Funciona, mas é frágil, depende de ordem de sessão e quebra a ideia de configuração declarativa por projeto. E em nenhum desses casos há warning. A sessão abre normal, o modelo responde normal, só que sem suas instruções.

O que isso muda na prática para quem constrói

Para time que já padronizou em AGENTS.md para Cursor, Codex, Copilot, Aider e Claude, o impacto é direto. Você acha que unificou o contrato e na verdade criou dois comportamentos diferentes. Com telemetria ligada, o Claude Code lê. Com telemetria desligada, ele finge que o arquivo não existe. Isso quebra onboarding, quebra CI assistida, quebra script que depende de convenções do repo. Pior ainda, quebra em silêncio, então o sintoma parece alucinação ou modelo ruim, quando na verdade é contexto faltando.

Quem mais perde é quem mais se importa com esse arquivo. Dev cuidadoso com privacidade, que mantém um instruction file único justamente para controlar o que cada ferramenta faz, costuma desligar telemetria. Time corporativo em Bedrock ou Vertex, ou atrás de gateway próprio, costuma bloquear tráfego não essencial por política. São exatamente esses usuários que recebem o recurso anunciado como disponível e depois veem zero efeito. Não é só inconveniência. É quebra de confiança, porque a escolha de privacidade passa a custar uma funcionalidade local que deveria ser offline por natureza.

A ação prática imediata é simples e feia. Crie um CLAUDE.md de uma linha ao lado do AGENTS.md com um import do tipo arroba mais o nome do arquivo. O suporte a import com arroba no CLAUDE.md não depende do mesmo flag, então com esse shim o teste canário volta a passar mesmo com bloqueio de tráfego não essencial ligado. O custo é um arquivo extra por repo, que é justamente o que o suporte nativo a AGENTS.md deveria eliminar. Para quem tem dezenas ou centenas de repos, vale automatizar. Um script que verifica se existe AGENTS.md sem CLAUDE.md e cria o shim resolve em minutos.

  • adicione o CLAUDE.md com import para AGENTS.md em repos que precisam funcionar com telemetria off
  • trave isso em template de repo novo e em hook de scaffolding para não depender de memória
  • inclua um teste canário no CI para validar que instrução de projeto realmente entrou no contexto

A tensão real: por que um arquivo local precisa de permissão remota

Aqui está a parte que me incomoda como operador. Flag remoto faz sentido para recurso que fala com servidor, modelo novo, roteamento, experimento de ranking. Não faz sentido para ler um markdown do disco. Se o arquivo está no working directory, a ferramenta já tem permissão para ler, já vai ler outros arquivos do projeto, já monta contexto local. Colocar uma gate de rede nisso adiciona ponto de falha, adiciona latência de resolução de flag, cria comportamento diferente entre primeira e segunda sessão e ainda acopla privacidade com funcionalidade.

E tem o problema do silêncio. Se fosse um erro explícito do tipo 'AGENTS.md ignorado porque flag indisponível', a gente ajustava e seguia. Do jeito atual, você só descobre com teste canário e inspeção de binário, coisa que quase ninguém vai fazer. A maioria vai concluir que o modelo ignorou a instrução ou que AGENTS.md não funciona bem no Claude Code, e vai duplicar instrução, colar prompt manual, aumentar token por sessão. No fim, um recurso criado para reduzir custo e fricção aumenta custo e fricção. Isso escala mal em organização grande, porque cada dev paga esse imposto invisível de um jeito diferente.

Vale perguntar também sobre custo e roadmap. Se amanhã a Anthropic ligar o flag para todo mundo por padrão, o problema some até a próxima gate. Mas o padrão arquitetural continua. Qualquer instrução local crítica pode voltar a depender de telemetria sem aviso. Para quem opera em ambiente regulado, isso é inaceitável. Privacidade não pode ser um toggle que remove capacidade offline básica. Ou o loader vira parte do núcleo, local e auditável, ou times vão manter o shim de CLAUDE.md para sempre por defesa.

Conclusão

O suporte a AGENTS.md no Claude Code existe, mas hoje ele só é confiável com telemetria ligada, e isso quebra o caso de uso mais sério. Enquanto não vira leitura local incondicional, use o shim de uma linha e valide com palavra canário. Resta saber quantos outros recursos locais estão esperando permissão da rede sem te contar.