Todos os artigos

// Knowledge.log — 技術記事

Coding agent no repositório: gates antes do primeiro PR

Configure AGENTS.md, CODEOWNERS, CI e auditoria antes de permitir que um coding agent abra PRs no seu repositório.

Dar a um coding agent acesso para abrir pull requests parece uma extensão natural do autocomplete. Não é. O agente passa a explorar o repositório, editar vários arquivos, executar comandos e propor uma mudança que alguém talvez aprove com pressa porque o CI ficou verde.

O resultado esperado não é “confiar mais no modelo”. É montar um caminho em que uma tarefa pequena pode virar um draft PR, mas uma mudança inadequada não consegue chegar à branch protegida só porque foi escrita com muita convicção.

A divisão de responsabilidades é simples:

  • AGENTS.md registra contexto e limites para o agente;
  • CODEOWNERS, reviews obrigatórias e CI fazem o bloqueio real;
  • uma auditoria curta mostra quando as falhas estão se repetindo;
  • tarefas de alto impacto continuam com pessoas desde o início.

O contexto mínimo antes da autonomia

Um coding agent ainda trabalha com contexto limitado, pode escolher uma API inexistente e pode produzir código válido na aparência que não atende ao requisito. Um contexto enorme não elimina o primeiro problema: o estudo Lost in the Middle encontrou degradação quando a informação relevante ficava no meio de entradas longas. Por isso, mantenha as instruções curtas, específicas e próximas do código a que se aplicam, em vez de despejar o manual inteiro da empresa no prompt. O linter já conhece o style guide; ele não precisa de uma leitura dramática feita pelo agente.

Dependências inventadas também não são um caso folclórico. Spracklen et al., em We Have a Package for You!, analisaram 16 LLMs e 576.000 amostras. O resumo reporta média de pelo menos 5,2% de pacotes alucinados em modelos comerciais, 21,7% em modelos open source e 205.474 nomes únicos inventados. A correção prática é exigir confirmação no lockfile, no registry e na documentação oficial antes de adicionar uma dependência. A observação segura em produção é registrar no PR toda alteração de manifesto ou lockfile e fazê-la passar por review de owner e scanner de dependências.

Há ainda limites do produto escolhido. No GitHub, o Copilot cloud agent trabalha em um repositório e um branch por tarefa, abre um draft PR e tem timeout rígido de 59 minutos. O branch usa o prefixo copilot/. Workflows enviados pelo agente precisam de uma pessoa em Approve and run workflows; há uma aprovação adicional quando o PR não é atribuído a uma pessoa. Esses controles existem porque um workflow ainda não revisado pode alcançar permissões e secrets. O sinal observável é direto: draft PR incompleto, sessão encerrada no limite ou workflow aguardando aprovação não deve ser “resolvido” relaxando o ruleset; reduza o escopo da tarefa.

AGENTS.md: política versionada, não catraca

AGENTS.md é uma convenção aberta em Markdown, sem schema obrigatório. Ferramentas compatíveis leem o arquivo da raiz e podem aplicar instruções mais próximas do diretório editado. Isso permite regras específicas em um monorepo sem acoplar a política a um único fornecedor.

Mas vale dizer uma vez, sem rodeio: AGENTS.md é convenção, não enforcement. Ele orienta o agente; não impede um commit, não exige review e não substitui autorização no GitHub.

Um arquivo de raiz pode começar assim:

# AGENTS.md

## Escopo
- Trabalhe somente neste repositório, em um branch e um draft PR por tarefa.
- Não faça commit direto em `main`.
- Mantenha a mudança restrita aos arquivos e critérios de aceite da issue.

## Regras por tipo de arquivo
- Código em `src/`: toda mudança de comportamento exige teste novo ou atualizado.
- Arquivos em `tests/`: podem ser alterados sem o gate inverso.
- Não altere `migrations/`, arquivos de autenticação, `.env*`, secrets ou
  `.github/workflows/`. Pare e solicite intervenção humana.
- Documentação pode mudar sem teste de código.

## Verificação
- Execute a suíte, o linter e o type checker definidos pelo repositório.
- Não adicione dependências sem confirmação humana.
- Confirme pacotes, APIs e flags no lockfile e na documentação oficial.

## Pull request
- Use o título `[agent] <área> — <objetivo>`.
- Informe os testes executados e o que ficou fora do escopo.

A remediação para instruções ignoradas é reduzir conflitos, criar um AGENTS.md aninhado quando a regra for local e transformar limites críticos em controles externos. Observe isso nos PRs: se o mesmo desvio aparece duas vezes, ajuste a instrução; se o desvio tem impacto de segurança, não espere a terceira tentativa para criar um gate.

CODEOWNERS e ruleset: onde a política ganha dentes

O arquivo abaixo solicita os revisores adequados para caminhos sensíveis:

# .github/CODEOWNERS
*                      @org/dev-leads
/src/                  @org/dev-leads
**/migrations/**       @org/db-owners
**/*auth*              @org/security
**/.env*               @org/security
.github/               @org/dev-leads
.github/CODEOWNERS     @org/dev-leads

Troque @org/... pelos times reais, com permissão de escrita, e proteja o próprio CODEOWNERS. Depois, no ruleset da branch principal, habilite Require review from Code Owners, exija ao menos uma aprovação e torne os checks de CI obrigatórios. O GitHub documenta o comportamento e as regras de sintaxe do CODEOWNERS.

Se um agente tocar autenticação ou uma migration, a remediação é bloquear o merge até a análise do owner, não pedir ao próprio agente que “revise com mais cuidado”. A observação segura é o histórico de reviews por caminho: toda mudança sensível precisa deixar o nome de quem aprovou e os checks executados.

CI: produção mudou, teste também precisa mudar

A regra “mudou comportamento, mudou teste” precisa sair do Markdown e entrar no CI. O script abaixo falha quando encontra arquivo de produção no diff, mas nenhum arquivo de teste:

#!/usr/bin/env python3
"""Falha se o diff tocar produção sem tocar testes. Heurística, não cobertura."""
import os
import subprocess
import sys

base = os.environ.get("GITHUB_BASE_REF") or os.environ.get("BASE_SHA") or "origin/main"
try:
    output = subprocess.check_output(
        ["git", "diff", "--name-only", f"{base}...HEAD"],
        text=True,
    )
except subprocess.CalledProcessError:
    output = subprocess.check_output(
        ["git", "diff", "--name-only", "HEAD~1"],
        text=True,
    )

files = [line.strip() for line in output.splitlines() if line.strip()]


def is_test(path):
    name = path.replace("\\", "/").lower()
    return (
        "/test/" in f"/{name}/"
        or "/tests/" in f"/{name}/"
        or name.endswith(
            (
                "_test.py", "_test.go", "_test.ts", "_test.tsx",
                ".test.js", ".test.ts", ".spec.ts", ".spec.js", "test.java",
            )
        )
        or name.startswith("tests/")
    )


def is_production(path):
    name = path.replace("\\", "/").lower()
    if is_test(name) or name.endswith((".md", ".txt", ".rst")):
        return False
    if name.startswith((".github/", "docs/", "automation/")):
        return False
    return name.endswith(
        (".py", ".go", ".ts", ".tsx", ".js", ".jsx", ".java", ".kt",
         ".rs", ".rb", ".c", ".cc", ".cpp")
    )


production = [path for path in files if is_production(path)]
tests = [path for path in files if is_test(path)]
if production and not tests:
    print("Produção alterada sem arquivo de teste no mesmo diff:")
    print("\n".join(production))
    print("Isto é heurística de presença, não prova de cobertura.")
    sys.exit(1)

print(f"ok: {len(production)} prod, {len(tests)} test files")

Salve-o como scripts/require_tests_with_prod.py. O workflow completo usa o actions/checkout@v7, release documentada em 2026-08-22, e busca o histórico necessário para comparar a branch:

name: agent-gates

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]

jobs:
  require-tests-with-prod:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0
      - name: Verificar mudança de produção sem teste
        env:
          GITHUB_BASE_REF: origin/${{ github.base_ref }}
        run: python3 scripts/require_tests_with_prod.py

Marque agent-gates e a suíte real como required checks. Essa heurística verifica presença de arquivo de teste, não cobertura nem qualidade. Um teste pode existir e não exercitar nada — uma tradição antiga, agora automatizada. A remediação é combinar o gate com execução da suíte e review do comportamento. Observe em produção a taxa de PRs barrados pelo check e, após o merge, falhas associadas às áreas alteradas; recorrência pede teste mais específico ou redução do escopo aceito pelo agente.

Auditoria semanal sem inventar o usuário do bot

Uma vez por semana, liste os PRs recentes e filtre os que vieram do agente. Primeiro confirme o campo author em um PR real; o identificador pode variar e não deve ser hardcoded por palpite.

gh pr list \
  --search "is:pr created:>=$(date -u -d '7 days ago' +%F)" \
  --state all \
  --limit 50 \
  --json number,title,author,createdAt,mergeable,reviews,statusCheckRollup,files

Procure quatro padrões no mesmo ritual:

  1. pacote ou import que não existe no registry;
  2. código de produção sem teste significativo;
  3. tentativa de alterar auth, secrets, migrations ou workflows;
  4. PR incompleto, CI falhando ou sequência longa de pedidos de correção.

Para cada padrão, registre a ocorrência, a correção aplicada e o gate que evitará repetição. O método de observação é o próprio rastro do GitHub: autor, arquivos, checks, reviews e tempo até o PR sair de draft. Em organizações Enterprise, métricas de uso podem complementar essa leitura, mas não substituem abrir o diff. Dashboard nenhum percebe que o teste só chama o método feliz e vai embora satisfeito.

Ative também o secret scanning. Se houver alerta, revogue ou rotacione o segredo fora do agente, remova-o do histórico conforme o procedimento do time e revise como ele entrou no contexto.

Quando o agente deve ficar fora

O guia de boas práticas do GitHub recomenda evitar tarefas amplas, ambíguas, críticas para produção, ligadas a segurança, PII, autenticação ou resposta a incidentes. Na prática, deixe fora da autonomia:

  • migrations, schema e operações de banco com escrita;
  • autenticação, autorização, IAM e regras de acesso;
  • secrets, credenciais, .env e sua rotação;
  • workflows com permissões ou acesso a secrets;
  • correções production-critical e resposta a incidentes.

A OWASP GenAI LLM Top 10 de 2026 coloca Sensitive Information Disclosure em segundo e Excessive Agency em terceiro. Improper Output Handling agora inclui código inseguro gerado por assistentes. A resposta não é escrever um prompt mais severo: reduza ferramentas e permissões, não entregue credenciais no contexto e exija autorização no sistema que executa a ação. Observe tentativas negadas, arquivos sensíveis tocados e alertas de secret scanning sem expor o conteúdo do segredo nos logs.

A DevDojo deixaria um agente abrir PRs quando a tarefa fosse pequena, reversível, com critérios de aceite objetivos, sem auth, secrets, migrations ou criticidade de produção; o PR seria draft, com CI obrigatório e CODEOWNERS. O time recuaria para sugestão assistida — sem autonomia de PR — diante de dependências inventadas, repetição do mesmo desvio, testes decorativos, mudanças fora do escopo, alertas de segredo ou review ping-pong persistente.

Próximo passo

Escolha hoje uma issue pequena de documentação ou teste, adicione AGENTS.md, CODEOWNERS e o check agent-gates, proteja a branch e rode um único draft PR piloto. Só amplie o escopo depois de revisar o diff, os checks e o rastro de aprovação desse PR.

ai-agentsgithubdevex

// Continue.training — 次のステップ

Conhecimento só conta quando vira prática.

Volte ao artigo, execute os exemplos e compartilhe o que aprendeu.

Explorar mais artigos