DEV Community

Cover image for O que é DESIGN.md para Agentes de Programação?
Lucas
Lucas

Posted on • Originally published at apidog.com

O que é DESIGN.md para Agentes de Programação?

Agentes de codificação são rápidos, confiantes e inicialmente alheios à arquitetura da sua base de código. Se você entregar ao Claude Code, Codex ou Cursor um ticket vago, ele pode gerar código que compila, passa em testes simples e ainda assim viola limites importantes entre domínio, aplicação, infraestrutura e HTTP. Um DESIGN.md reduz esse risco ao registrar a intenção arquitetônica no lugar onde o agente realmente pode ler: o próprio repositório.

Experimente o Apidog hoje

TL;DR

DESIGN.md é um arquivo Markdown no repositório que documenta decisões arquitetônicas, invariantes e restrições de design para humanos e agentes de codificação. Ele responde a:

Por que este sistema é estruturado dessa forma?

Enquanto isso:

  • README.md explica o que o projeto é e como começar.
  • AGENTS.md explica como agentes devem construir, testar e trabalhar no projeto.
  • CLAUDE.md contém instruções específicas para Claude Code.
  • DESIGN.md registra o raciocínio arquitetônico que não é óbvio lendo apenas o código.

Introdução

O problema aparece rápido em equipes que adotam agentes de codificação.

Você pede a um agente para adicionar um endpoint de reembolso em um serviço de pagamentos. Ele cria um handler funcional, chama o banco diretamente no controller, ignora um erro do gateway e inventa um novo tipo de moeda porque não percebeu que já existia um no domínio.

O diff parece limpo. Os testes passam. Mas o código está errado em pontos que só alguém com contexto arquitetônico percebe.

O agente não é necessariamente ruim em programar. Ele só não conhece decisões que vivem:

  • na cabeça de engenheiros seniores;
  • em páginas antigas do Notion;
  • em threads do Slack;
  • em ADRs esquecidos;
  • ou em padrões implícitos espalhados pelo código.

DESIGN.md resolve isso tornando explícitas as regras que o agente não consegue inferir com segurança.

O que DESIGN.md realmente é

DESIGN.md é um registro em texto puro do porquê seu código é organizado de determinada forma.

Ele não substitui o README, não é um tutorial de setup e não deve virar uma wiki genérica. Ele deve capturar decisões como:

  • “A camada de domínio nunca importa o framework web.”
  • “Dinheiro é sempre representado como inteiro em unidades menores, nunca float.”
  • “Chamadas ao gateway de pagamento passam pelo padrão outbox.”
  • “O agregado Account é o único caminho de escrita no livro-razão.”
  • “A especificação OpenAPI é a fonte de verdade para contratos de API.”

Essas regras são difíceis de inferir lendo arquivos isolados. O código mostra o resultado da decisão, mas não explica a decisão.

Um agente pode ver que Account.debit() existe. Mas, sem contexto, ele pode criar outro caminho de escrita para saldo porque não sabe que aquele método é deliberadamente o único ponto permitido.

A ideia tem relação com práticas conhecidas como ARCHITECTURE.md e ADRs. A diferença é o público: DESIGN.md é escrito para humanos e agentes de codificação. Por isso, deve ser:

  • direto;
  • declarativo;
  • fácil de escanear;
  • focado em invariantes;
  • mantido dentro do repositório.

DESIGN.md vs AGENTS.md vs CLAUDE.md vs README.md

Esses arquivos se complementam. Não coloque tudo em um só.

Arquivo Público Responde a Frequência de mudança Tamanho recomendado
README.md Humanos O que é o projeto e como começar Muda com funcionalidades Médio
AGENTS.md Agentes de codificação Como buildar, testar, lintar e contribuir Muda com ferramentas Curto
CLAUDE.md Claude Code Instruções específicas para Claude Muda com ferramentas Curto
DESIGN.md Agentes, engenheiros e revisores Por que a arquitetura é assim e o que não pode quebrar Muda raramente Médio e denso

O projeto agents.md descreve AGENTS.md como um formato aberto para orientar agentes de codificação. Ele é operacional: comandos, testes, estilo, convenções de commit.

A documentação de memória do Claude Code descreve CLAUDE.md como um arquivo de instruções para o Claude. Ela também recomenda manter esse arquivo curto. Se você já usa AGENTS.md, uma configuração comum é fazer o CLAUDE.md importar esse conteúdo.

Exemplo:

@AGENTS.md
Enter fullscreen mode Exit fullscreen mode

O que não cabe bem em AGENTS.md ou CLAUDE.md é justificativa arquitetônica profunda. Para isso, use DESIGN.md.

Uma estrutura prática:

repo/
  README.md
  AGENTS.md
  CLAUDE.md
  DESIGN.md
  api/openapi.yaml
  src/
Enter fullscreen mode Exit fullscreen mode

No AGENTS.md, adicione uma referência curta:

## Arquitetura

Antes de alterar camadas, contratos de API, persistência, transações ou integrações externas, leia `DESIGN.md`.
Enter fullscreen mode Exit fullscreen mode

No CLAUDE.md, se necessário:

@AGENTS.md
@DESIGN.md
Enter fullscreen mode Exit fullscreen mode

Se você quer estruturar melhor o contexto do Claude nesses arquivos, veja Fluxos de trabalho do Claude Code.

O que colocar em DESIGN.md

Inclua regras que um agente não consegue inferir com segurança do código.

Um bom DESIGN.md deve cobrir:

  1. Forma do sistema

    • camadas;
    • módulos;
    • direção das dependências.
  2. Invariantes

    • regras que devem ser sempre verdadeiras.
  3. Decisões-chave e justificativa

    • o que foi escolhido;
    • por que foi escolhido.
  4. Alternativas rejeitadas

    • o que a equipe decidiu não fazer;
    • por que não deve ser reintroduzido.
  5. Regras de domínio e dados

    • moeda;
    • datas;
    • IDs;
    • soft delete;
    • multi-tenancy.
  6. Fonte de verdade do contrato da API

    • onde está o OpenAPI;
    • o que é gerado;
    • o que não deve ser editado manualmente.
  7. Onde colocar novo código

    • mapa prático para endpoints, casos de uso, integrações e middlewares.
  8. O que não tocar

    • código gerado;
    • módulos legados;
    • migrações aplicadas.

Modelo de DESIGN.md para uma API de pagamentos

Use este modelo como ponto de partida:

# DESIGN.md: Serviço de API de Pagamentos

Este arquivo registra a intenção arquitetônica e as decisões por trás dela.

Leia antes de gerar ou modificar código. Se uma alteração entrar em conflito
com uma regra abaixo, sinalize o conflito em vez de contorná-lo.

## Forma do sistema

Arquitetura em camadas. Dependências apontam apenas para dentro:

http -> app -> domain <- infra

- `domain/` não importa `http/`, `app/` nem frameworks.
- `infra/` implementa interfaces declaradas em `domain/` ou `app/`.
- `http/` nunca acessa banco de dados ou gateway de pagamento diretamente.
- `http/` chama casos de uso em `app/`.

## Invariantes

- Uma entrada de livro-razão é imutável após escrita.
- Correções financeiras são novas entradas compensatórias.
- Saldo é derivado das entradas do livro-razão.
- Dinheiro é inteiro em unidades menores, mais código ISO-4217.
- Nunca use `float` para dinheiro.
- Toda chamada externa a gateway de pagamento é idempotente por `idempotency_key`.
- Saldos não ficam negativos sem uma `OverdraftPolicy` explícita.

## Decisões-chave

### Padrão Outbox para chamadas de gateway

Handlers escrevem uma intenção na mesma transação de banco da alteração de negócio.
Um worker processa essa intenção e chama o gateway.

Justificativa: o gateway pode expirar sob carga. Chamadas inline tornam latência,
retries e tratamento de falhas difíceis de controlar.

Regra: não chame o gateway diretamente de um handler HTTP.

### Único caminho de escrita por agregado

Apenas `Account.post_entry()` escreve no livro-razão.

Justificativa: múltiplos caminhos de escrita já causaram desvio de saldo.

Regra: adicione comportamento ao agregado, não queries paralelas de escrita.

## Alternativas rejeitadas

- Lazy-loading de ORM entre agregados.
- Saldo persistido como coluna mutável.
- Uso de `float` para valores monetários.
- Webhooks síncronos executados na thread da requisição.
- Edição manual de tipos gerados a partir do OpenAPI.

## Regras de dados e domínio

- Todos os timestamps são UTC.
- Timestamps são formatados como RFC 3339 na borda HTTP.
- IDs são ULIDs gerados na camada de aplicação.
- Soft delete não é usado.
- Toda query multi-tenant deve ter escopo por `tenant_id`.
- Um método de repositório sem escopo de tenant é bug.

## Contrato da API

- `api/openapi.yaml` é a fonte de verdade.
- Tipos de request/response são gerados a partir do OpenAPI.
- Não edite manualmente arquivos em `http/generated/`.
- Para endpoints novos ou alterados:
  1. atualize `api/openapi.yaml`;
  2. regenere os tipos;
  3. implemente o handler;
  4. adicione testes de contrato.

- Respostas de erro seguem RFC 9457 (`problem+json`).
- Use o helper `problem()`.
- Não crie envelopes de erro ad-hoc.

## Onde o novo código vai

- Novo endpoint:
  - rota em `http/routes/`;
  - DTO em `http/dto/`;
  - caso de uso em `app/usecases/`;
  - regra de negócio em `domain/`.

- Nova integração externa:
  - interface em `app/ports/`;
  - implementação em `infra/clients/`.

- Cross-cutting concerns:
  - autenticação, logging e idempotência ficam em middleware;
  - não implemente inline em handlers.

## Fora do escopo

- `http/generated/`: código gerado. Não editar manualmente.
- `legacy/billing_v1/`: congelado. Não estender.
- `migrations/`: nunca edite migração já aplicada. Crie uma nova.

## Em caso de dúvida

Se uma solicitação exigir quebrar uma regra deste arquivo, sinalize o conflito
e proponha a menor alternativa compatível com o design.
Enter fullscreen mode Exit fullscreen mode

A seção “Em caso de dúvida” é importante. Ela diz ao agente como agir quando a tarefa conflita com a arquitetura. Sem isso, o agente tende a contornar a regra para completar o ticket.

Como agentes realmente consomem DESIGN.md

Agentes não têm um parser especial para DESIGN.md. Eles leem o arquivo como contexto.

Por isso, você precisa tornar o arquivo fácil de encontrar.

Para Claude Code

No CLAUDE.md:

@DESIGN.md
Enter fullscreen mode Exit fullscreen mode

Ou, se você centraliza instruções em AGENTS.md:

@AGENTS.md
@DESIGN.md
Enter fullscreen mode Exit fullscreen mode

Para agentes que usam AGENTS.md

No AGENTS.md:

## Design e arquitetura

Leia `DESIGN.md` antes de alterar:

- camadas;
- contratos de API;
- modelos de domínio;
- transações;
- integrações externas;
- persistência;
- autenticação;
- multi-tenancy.
Enter fullscreen mode Exit fullscreen mode

Escreva para recuperação, não para leitura linear

Prefira:

- `http/` nunca acessa o banco diretamente.
Enter fullscreen mode Exit fullscreen mode

Em vez de:

Idealmente, tentamos manter uma separação razoável entre a camada HTTP e as
partes internas do sistema, embora em alguns casos seja aceitável...
Enter fullscreen mode Exit fullscreen mode

Agentes seguem melhor regras curtas, absolutas e testáveis.

Equipes que constroem fluxos autônomos com agentes dependem desse ciclo de contexto e correção. Veja também construa seu próprio Claude Code.

Antipadrões

1. Repetir o código

Evite frases como:

UserService gerencia usuários.
Enter fullscreen mode Exit fullscreen mode

Isso o agente já vê no código.

Prefira registrar intenção:

`UserService` não aplica regras de autorização. Autorização fica em `app/policies/`.
Enter fullscreen mode Exit fullscreen mode

2. Transformar DESIGN.md em tutorial

Comandos de setup, instruções de build e scripts pertencem a README.md, CONTRIBUTING.md ou AGENTS.md.

Não coloque isso em DESIGN.md:

npm install
npm run dev
npm test
Enter fullscreen mode Exit fullscreen mode

3. Documentar aspiração como realidade

Errado:

O sistema usa CQRS.
Enter fullscreen mode Exit fullscreen mode

Se apenas parte do sistema usa CQRS, escreva:

Meta: novas escritas passam por casos de uso em `app/usecases/`.

Atual: `legacy/` ainda possui handlers que acessam repositórios diretamente.
Não estenda esse padrão.
Enter fullscreen mode Exit fullscreen mode

4. Não definir dono

Sem dono, o arquivo vira ficção.

Adicione ao template de PR:

- [ ] Esta mudança altera uma decisão em `DESIGN.md`?
- [ ] Se sim, atualizei `DESIGN.md` na mesma PR.
Enter fullscreen mode Exit fullscreen mode

5. Sincronizar linha a linha com o código

Não tente documentar cada classe, função ou pacote. Isso apodrece rápido.

Documente decisões que mudam pouco:

  • limites de camada;
  • invariantes;
  • formatos de erro;
  • política de transação;
  • fonte de verdade do contrato;
  • regras de domínio.

6. Contradizer AGENTS.md

Evite duplicar regras operacionais em vários arquivos.

Bom:

AGENTS.md -> comandos, testes, lint, fluxo de contribuição
DESIGN.md -> arquitetura, invariantes, decisões
Enter fullscreen mode Exit fullscreen mode

Ruim:

AGENTS.md diz para usar problem+json.
DESIGN.md diz para usar outro envelope de erro.
Enter fullscreen mode Exit fullscreen mode

DESIGN.md para APIs e backend

Em APIs e serviços backend, DESIGN.md costuma ter alto impacto porque muitos erros de agentes acontecem em áreas invisíveis:

  • contratos HTTP;
  • idempotência;
  • transações;
  • consistência;
  • autenticação;
  • multi-tenancy;
  • paginação;
  • erros;
  • integrações externas.

Declare a fonte de verdade do contrato

Se sua API usa OpenAPI, seja explícito:

`api/openapi.yaml` é a fonte de verdade do contrato HTTP.
Handlers, DTOs, testes e documentação devem estar em conformidade com esse arquivo.
Enter fullscreen mode Exit fullscreen mode

Também declare o que não fazer:

Não edite manualmente tipos gerados em `http/generated/`.
Atualize o OpenAPI, regenere os tipos e depois implemente.
Enter fullscreen mode Exit fullscreen mode

Se você projeta o contrato primeiro no Apidog e exporta o OpenAPI para o repositório, o agente passa a ter um alvo claro. O raciocínio por trás de design-first para agentes é abordado em projetando APIs para agentes de IA.

Defina limites de transação

Exemplo:

Chamadas externas nunca acontecem dentro de uma transação de banco.
Use outbox para efeitos colaterais externos.
Enter fullscreen mode Exit fullscreen mode

Sem essa regra, o agente tende a implementar a versão ingênua:

await db.transaction(async () => {
  await paymentGateway.charge(...)
  await orderRepository.markPaid(...)
})
Enter fullscreen mode Exit fullscreen mode

A versão alinhada ao design seria:

await db.transaction(async () => {
  await orderRepository.markPaymentPending(orderId)

  await outboxRepository.enqueue({
    type: "payment.charge.requested",
    payload: {
      orderId,
      idempotencyKey,
    },
  })
})
Enter fullscreen mode Exit fullscreen mode

Defina idempotência como invariante

Para pagamentos, pedidos e provisionamento, escreva:

Endpoints que criam efeitos externos devem exigir `Idempotency-Key`.
Retries com a mesma chave não podem duplicar cobrança, pedido ou provisionamento.
Enter fullscreen mode Exit fullscreen mode

Padronize erros

Exemplo:

Todas as respostas de erro seguem RFC 9457 (`application/problem+json`).
Use o helper `problem()`.
Não crie formatos de erro específicos por endpoint.
Enter fullscreen mode Exit fullscreen mode

Isso evita respostas inconsistentes como:

{ "error": "Invalid request" }
Enter fullscreen mode Exit fullscreen mode

em um endpoint e:

{ "message": "Invalid request", "code": 400 }
Enter fullscreen mode Exit fullscreen mode

em outro.

Proteja multi-tenancy

Exemplo:

Toda query deve ter escopo por `tenant_id`.
Um método de repositório sem `tenant_id` é bug de segurança.
Enter fullscreen mode Exit fullscreen mode

Essa regra é crítica porque uma query isolada pode parecer correta, mas ainda assim vazar dados entre tenants.

Defina regras de versionamento

Exemplo:

Remover campo, renomear campo ou alterar semântica de resposta é breaking change.
Breaking changes exigem nova versão da API.
Campos novos opcionais são permitidos em versões menores.
Enter fullscreen mode Exit fullscreen mode

Sem isso, agentes podem “limpar” respostas e quebrar clientes.

Exemplo de fluxo prático

Para adicionar um endpoint novo com agente:

  1. Atualize o contrato OpenAPI.
  2. Gere os tipos.
  3. Peça ao agente para ler DESIGN.md.
  4. Peça para implementar apenas nos locais definidos.
  5. Rode testes.
  6. Revise o diff contra os invariantes.

Prompt útil:

Leia `DESIGN.md` antes de implementar.

Adicione o endpoint POST /refunds conforme `api/openapi.yaml`.

Restrições:
- não edite arquivos gerados;
- não chame gateway diretamente do handler;
- use o padrão outbox;
- preserve idempotência por Idempotency-Key;
- use problem+json para erros.

Se alguma solicitação conflitar com `DESIGN.md`, pare e explique.
Enter fullscreen mode Exit fullscreen mode

Esse tipo de prompt funciona melhor quando DESIGN.md já contém as regras como absolutos.

Para validar a API gerada contra o contrato, Baixe o Apidog e use o fluxo design-first com exportação OpenAPI, depuração e testes de endpoint.

Conclusão

DESIGN.md é um guardrail simples para agentes de codificação.

Use-o para registrar:

  • por que a arquitetura existe;
  • quais invariantes não podem ser quebrados;
  • quais alternativas já foram rejeitadas;
  • onde novos códigos devem ser colocados;
  • qual arquivo é a fonte de verdade do contrato da API.

Ele não substitui AGENTS.md, CLAUDE.md ou README.md. Ele complementa esses arquivos com o contexto que agentes normalmente não têm.

Para backend e APIs, o maior ganho é declarar a especificação OpenAPI como autoritativa. Assim, agentes deixam de inventar schemas e passam a implementar contra um contrato explícito.

Projete esse contrato primeiro. Baixe o Apidog para criar APIs com abordagem design-first, exportar OpenAPI e validar se endpoints gerados por agentes realmente seguem o contrato.

Perguntas Frequentes

DESIGN.md é um padrão oficial como AGENTS.md?

Não. AGENTS.md é um formato definido e amplamente adotado. DESIGN.md é uma convenção de comunidade, semelhante a ARCHITECTURE.md e ADRs.

Use como um padrão prático, não como uma especificação formal.

Preciso de DESIGN.md se já tenho AGENTS.md ou CLAUDE.md?

Sim, se sua arquitetura possui restrições não óbvias.

AGENTS.md e CLAUDE.md devem continuar curtos e operacionais. Coloque decisões arquitetônicas em DESIGN.md e apenas referencie esse arquivo.

Para o arquivo operacional, veja como escrever arquivos AGENTS.md.

Como DESIGN.md difere de ARCHITECTURE.md?

A diferença principal está no público e no estilo.

ARCHITECTURE.md costuma ser escrito para humanos. DESIGN.md é escrito para humanos e agentes, então tende a ser mais declarativo, mais focado em invariantes e mais fácil de usar como contexto em ferramentas de codificação.

Qual deve ser o tamanho de DESIGN.md?

O suficiente para cobrir decisões importantes. Curto o suficiente para cada linha importar.

Como regra prática:

  • 2 a 4 páginas focadas funcionam bem;
  • listas são melhores que longos parágrafos;
  • invariantes são melhores que explicações genéricas;
  • corte qualquer coisa que apenas repita o código.

Como faço o agente realmente ler DESIGN.md?

Referencie-o no arquivo que o agente já carrega.

Para Claude Code:

@DESIGN.md
Enter fullscreen mode Exit fullscreen mode

Para AGENTS.md:

Leia `DESIGN.md` antes de mudanças estruturais, contratos de API, persistência ou integrações externas.
Enter fullscreen mode Exit fullscreen mode

O agente sempre seguirá DESIGN.md?

Não. Arquivos de instrução são contexto, não enforcement rígido.

Mas regras claras aumentam muito a chance de adesão. Além disso, revisores podem apontar violações diretamente:

Isso quebra a regra de caminho único de escrita em `DESIGN.md`.
Corrija mantendo o design.
Enter fullscreen mode Exit fullscreen mode

Esse feedback costuma produzir correções melhores e mais rápidas.

DESIGN.md ajuda com contratos de API?

Sim. Um dos usos mais valiosos é declarar que a especificação OpenAPI é autoritativa.

Exemplo:

`api/openapi.yaml` é a fonte de verdade.
Não invente schemas no handler.
Não edite tipos gerados manualmente.
Enter fullscreen mode Exit fullscreen mode

Projetar esse contrato primeiro em uma ferramenta como Apidog dá ao agente um alvo explícito.

Onde DESIGN.md deve ficar?

Na raiz do repositório:

repo/
  README.md
  AGENTS.md
  CLAUDE.md
  DESIGN.md
Enter fullscreen mode Exit fullscreen mode

Em monorepos, use:

repo/
  DESIGN.md              # regras globais
  services/payments/DESIGN.md
  services/billing/DESIGN.md
Enter fullscreen mode Exit fullscreen mode

O arquivo global define regras do sistema. Arquivos locais definem decisões específicas de cada serviço.

Top comments (0)