{"id":1115,"date":"2026-08-19T04:01:18","date_gmt":"2026-08-19T07:01:18","guid":{"rendered":"https:\/\/adrianosantostreina.com.br\/blog\/arquitetura-estacao-trabalho-ia-camadas-contexto\/"},"modified":"2026-08-19T04:01:25","modified_gmt":"2026-08-19T07:01:25","slug":"arquitetura-estacao-trabalho-ia-camadas-contexto","status":"publish","type":"post","link":"https:\/\/adrianosantostreina.com.br\/blog\/arquitetura-estacao-trabalho-ia-camadas-contexto\/","title":{"rendered":"Arquitetura de Esta\u00e7\u00e3o de Trabalho: Como Compor Camadas de IA sem Criar um Frankenstein de Contexto Duplicado"},"content":{"rendered":"<p>Voc\u00ea provavelmente j\u00e1 passou por isso: o Copilot sugere uma fun\u00e7\u00e3o inline, o Claude Code reescreve o mesmo arquivo dez minutos depois com uma conven\u00e7\u00e3o diferente, e o Cursor, numa terceira sess\u00e3o, &#8220;aprende&#8221; um padr\u00e3o de nomenclatura que voc\u00ea nunca pediu \u2014 porque leu um trecho desatualizado do seu pr\u00f3prio README. Tr\u00eas ferramentas, tr\u00eas vers\u00f5es de contexto sobre o mesmo projeto, nenhuma delas sincronizada com a realidade do c\u00f3digo. O resultado n\u00e3o \u00e9 produtividade turbinada. \u00c9 um comit\u00ea de assistentes discordando entre si, e voc\u00ea arbitrando a discuss\u00e3o em vez de programar.<\/p>\n<p>Esse \u00e9 o problema real de quem monta um setup de desenvolvimento com m\u00faltiplas camadas de IA sem pensar em arquitetura: cada ferramenta acumula seu pr\u00f3prio modelo mental do projeto, e como elas n\u00e3o conversam entre si, voc\u00ea paga o custo de manter tr\u00eas fontes de verdade paralelas. Neste artigo, a proposta n\u00e3o \u00e9 listar &#8220;as 15 melhores ferramentas de IA para 2024&#8221; \u2014 isso qualquer busca resolve. A proposta \u00e9 discutir como projetar as camadas do seu setup para que elas compartilhem uma \u00fanica fonte de contexto, minimizem duplica\u00e7\u00e3o e mantenham rastreabilidade de decis\u00f5es, tratando seu ambiente de desenvolvimento como um sistema distribu\u00eddo \u2014 porque, na pr\u00e1tica, \u00e9 exatamente isso que ele se tornou.<\/p>\n<h2>O setup como sistema distribu\u00eddo: o problema que ningu\u00e9m nomeia<\/h2>\n<p>Quando voc\u00ea tem um LLM no editor (autocomplete), um agente de terminal (Claude Code, Aider), um assistente de revis\u00e3o de PR e um MCP server conectado ao banco de dados, voc\u00ea n\u00e3o tem &#8220;ferramentas de IA&#8221;. Voc\u00ea tem um sistema distribu\u00eddo com m\u00faltiplos n\u00f3s de infer\u00eancia, cada um mantendo estado local sobre o mesmo dom\u00ednio: seu c\u00f3digo-fonte. E sistemas distribu\u00eddos t\u00eam um problema cl\u00e1ssico \u2014 consist\u00eancia de estado entre n\u00f3s.<\/p>\n<p>A diferen\u00e7a \u00e9 que aqui o &#8220;estado&#8221; \u00e9 contexto textual: conven\u00e7\u00f5es de c\u00f3digo, decis\u00f5es de arquitetura, d\u00e9bitos t\u00e9cnicos conhecidos, padr\u00f5es de nomenclatura. Se cada ferramenta infere esse estado de forma independente \u2014 lendo arquivos diferentes, em momentos diferentes, com janelas de contexto diferentes \u2014 voc\u00ea tem inconsist\u00eancia garantida. A pergunta arquitetural correta n\u00e3o \u00e9 &#8220;qual ferramenta \u00e9 melhor&#8221;, \u00e9: <strong>como eu desenho uma fonte \u00fanica de contexto que todas as ferramentas consultam, em vez de inferir?<\/strong><\/p>\n<h3>Camada 1 \u2014 Contexto est\u00e1tico versionado<\/h3>\n<p>A base de qualquer setup s\u00e9rio \u00e9 um conjunto de arquivos de contexto versionados no reposit\u00f3rio, n\u00e3o em configura\u00e7\u00f5es locais da IDE. O <code>CLAUDE.md<\/code> do Claude Code, o <code>.cursorrules<\/code> do Cursor e os <code>copilot-instructions.md<\/code> do GitHub Copilot resolvem o mesmo problema com sintaxes diferentes \u2014 e a armadilha comum \u00e9 escrever tr\u00eas vers\u00f5es distintas do mesmo conte\u00fado.<\/p>\n<pre><code># context\/ARCHITECTURE.md \u2014 fonte \u00fanica, versionada\n## Conven\u00e7\u00f5es de c\u00f3digo\n- Reposit\u00f3rios seguem o padr\u00e3o Repository + UnitOfWork (ver src\/core\/persistence)\n- Erros de dom\u00ednio usam Result, nunca exce\u00e7\u00f5es para fluxo de controle\n- Testes de integra\u00e7\u00e3o usam Testcontainers, n\u00e3o mocks de banco\n\n## Decis\u00f5es arquiteturais ativas\n- ADR-014: migra\u00e7\u00e3o gradual de REST para gRPC nos servi\u00e7os internos\n- ADR-021: fila de eventos usa outbox pattern, n\u00e3o publish direto\n\n## O que N\u00c3O fazer\n- N\u00e3o introduzir novas depend\u00eancias de HTTP client (usar o wrapper em src\/http)\n- N\u00e3o gerar migrations sem revis\u00e3o humana expl\u00edcita\n<\/code><\/pre>\n<p>A pr\u00e1tica que funciona na pr\u00e1tica: mantenha esse conte\u00fado em <strong>um \u00fanico arquivo can\u00f4nico<\/strong> (por exemplo, <code>context\/ARCHITECTURE.md<\/code>) e gere os arquivos espec\u00edficos de cada ferramenta a partir dele, via script ou symlink, no momento do build ou pre-commit. Isso elimina o drift entre &#8220;o que o Claude Code sabe&#8221; e &#8220;o que o Cursor sabe&#8221; \u2014 ambos leem a mesma fonte.<\/p>\n<pre><code># scripts\/sync-ai-context.sh\n#!\/usr\/bin\/env bash\nset -euo pipefail\n\nSOURCE=\"context\/ARCHITECTURE.md\"\n\ncp \"$SOURCE\" CLAUDE.md\ncp \"$SOURCE\" .cursorrules\ncp \"$SOURCE\" .github\/copilot-instructions.md\n\necho \"Contexto sincronizado a partir de $SOURCE\"\n<\/code><\/pre>\n<p>Rode esse script como hook de <code>pre-commit<\/code> ou como etapa de CI que falha se os arquivos derivados estiverem desatualizados em rela\u00e7\u00e3o \u00e0 fonte. \u00c9 um detalhe operacional, mas \u00e9 exatamente o tipo de coisa que separa um setup &#8220;que funciona no meu ambiente&#8221; de um setup que sobrevive \u00e0 entrada de novos membros no time.<\/p>\n<blockquote><p><strong>\ud83d\udca1 Dica do Mestre:<\/strong> a documenta\u00e7\u00e3o oficial do <a href=\"https:\/\/docs.anthropic.com\/en\/docs\/claude-code\/memory\" target=\"_blank\" rel=\"noopener\">Claude Code sobre gerenciamento de mem\u00f3ria<\/a> descreve bem a hierarquia de arquivos <code>CLAUDE.md<\/code> (projeto, usu\u00e1rio, diret\u00f3rio), mas n\u00e3o menciona estrat\u00e9gias de sincroniza\u00e7\u00e3o entre ferramentas concorrentes \u2014 isso \u00e9 responsabilidade sua como arquiteto do setup.<\/p><\/blockquote>\n<h3>Camada 2 \u2014 Contexto din\u00e2mico via MCP<\/h3>\n<p>Arquivos est\u00e1ticos resolvem conven\u00e7\u00f5es e decis\u00f5es, mas n\u00e3o resolvem estado vivo: schema atual do banco, endpoints ativos, m\u00e9tricas de produ\u00e7\u00e3o. Para isso, a pe\u00e7a certa \u00e9 o <a href=\"https:\/\/modelcontextprotocol.io\" target=\"_blank\" rel=\"noopener\">Model Context Protocol (MCP)<\/a>, que permite que o agente consulte a fonte de verdade em tempo real em vez de confiar em uma descri\u00e7\u00e3o textual que pode estar desatualizada.<\/p>\n<p>A decis\u00e3o arquitetural aqui \u00e9 sutil: quando usar arquivo est\u00e1tico versus MCP server. A regra pr\u00e1tica que uso: <strong>se a informa\u00e7\u00e3o muda com o mesmo ritmo do c\u00f3digo-fonte, vai em arquivo versionado; se muda em ritmo diferente (schema de produ\u00e7\u00e3o, m\u00e9tricas, tickets abertos), vai em MCP<\/strong>. Colocar schema de banco em Markdown est\u00e1tico \u00e9 garantia de desatualiza\u00e7\u00e3o em tr\u00eas sprints.<\/p>\n<pre><code>\/\/ mcp-config.json \u2014 exemplo de configura\u00e7\u00e3o de servidor MCP para Postgres\n{\n  \"mcpServers\": {\n    \"postgres-readonly\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"@modelcontextprotocol\/server-postgres\",\n        \"postgresql:\/\/readonly_user:senha@localhost:5432\/app_db\"\n      ]\n    }\n  }\n}\n<\/code><\/pre>\n<p>Note o detalhe de seguran\u00e7a: usu\u00e1rio <code>readonly_user<\/code>. Isso n\u00e3o \u00e9 paranoia \u2014 \u00e9 a primeira decis\u00e3o de arquitetura que muita gente esquece ao plugar um agente aut\u00f4nomo em uma fonte de dados real. O agente vai gerar queries; voc\u00ea quer que erros de gera\u00e7\u00e3o resultem em SELECT malformado, n\u00e3o em DELETE acidental. O <a href=\"https:\/\/modelcontextprotocol.io\/docs\/concepts\/architecture\" target=\"_blank\" rel=\"noopener\">modelo de arquitetura do MCP<\/a> n\u00e3o imp\u00f5e esse isolamento por voc\u00ea \u2014 \u00e9 responsabilidade de quem configura o servidor.<\/p>\n<h3>Camada 3 \u2014 Orquestra\u00e7\u00e3o de agentes e limites de autonomia<\/h3>\n<p>Com contexto est\u00e1tico e din\u00e2mico resolvidos, a terceira camada \u00e9 onde a maioria dos setups falha silenciosamente: definir at\u00e9 onde cada agente pode ir sem supervis\u00e3o. Um agente de terminal com acesso a <code>git push --force<\/code> e um MCP server com credencial de escrita em produ\u00e7\u00e3o n\u00e3o s\u00e3o &#8220;produtividade turbinada&#8221; \u2014 s\u00e3o incidentes aguardando o prompt errado.<\/p>\n<p>A pr\u00e1tica mais robusta \u00e9 segmentar por ambiente e por opera\u00e7\u00e3o, n\u00e3o por ferramenta:<\/p>\n<ul>\n<li><strong>Leitura irrestrita:<\/strong> c\u00f3digo-fonte, logs, schema de staging \u2014 qualquer agente pode consultar livremente.<\/li>\n<li><strong>Escrita supervisionada:<\/strong> commits, PRs, migrations \u2014 o agente prop\u00f5e, um humano aprova antes do merge.<\/li>\n<li><strong>Escrita proibida:<\/strong> produ\u00e7\u00e3o, secrets, infraestrutura \u2014 nenhum agente tem credencial de escrita, ponto final.<\/li>\n<\/ul>\n<p>Ferramentas como Claude Code j\u00e1 oferecem <a href=\"https:\/\/docs.anthropic.com\/en\/docs\/claude-code\/settings\" target=\"_blank\" rel=\"noopener\">configura\u00e7\u00e3o granular de permiss\u00f5es<\/a> por comando (<code>allow<\/code>, <code>ask<\/code>, <code>deny<\/code>), e vale a pena investir tempo real nesse arquivo em vez de aceitar o padr\u00e3o &#8220;permitir tudo, perguntar depois&#8221;:<\/p>\n<pre><code>\/\/ .claude\/settings.json\n{\n  \"permissions\": {\n    \"allow\": [\n      \"Read(*)\",\n      \"Bash(git diff:*)\",\n      \"Bash(npm test:*)\"\n    ],\n    \"ask\": [\n      \"Bash(git commit:*)\",\n      \"Bash(git push:*)\",\n      \"Edit(migrations\/*)\"\n    ],\n    \"deny\": [\n      \"Bash(git push --force:*)\",\n      \"Bash(rm -rf:*)\",\n      \"Read(.env*)\"\n    ]\n  }\n}\n<\/code><\/pre>\n<p>Esse arquivo, versionado junto do reposit\u00f3rio, vira parte do contrato de onboarding: qualquer pessoa que clona o projeto e ativa o Claude Code herda os mesmos limites de autonomia. Isso \u00e9 infraestrutura de seguran\u00e7a tratada como c\u00f3digo \u2014 n\u00e3o configura\u00e7\u00e3o pessoal esquecida em algum dotfile.<\/p>\n<h2>O custo de manuten\u00e7\u00e3o que a propaganda n\u00e3o mostra<\/h2>\n<p>Todo material promocional de setup com IA mostra o ganho de velocidade no primeiro dia. Raramente algu\u00e9m fala do custo recorrente: manter tr\u00eas arquivos de contexto sincronizados, revisar permiss\u00f5es de agentes a cada nova integra\u00e7\u00e3o, e \u2014 o mais subestimado \u2014 <strong>auditar o que os agentes de fato fizeram<\/strong>, porque &#8220;a IA sugeriu&#8221; n\u00e3o \u00e9 uma resposta aceit\u00e1vel em um post-mortem de incidente.<\/p>\n<p>Isso significa que seu setup precisa de observabilidade pr\u00f3pria. N\u00e3o \u00e9 suficiente confiar na sa\u00edda do terminal do agente; voc\u00ea precisa de log estruturado das a\u00e7\u00f5es que ferramentas aut\u00f4nomas executaram no seu reposit\u00f3rio e nos seus sistemas conectados via MCP.<\/p>\n<pre><code># .claude\/hooks\/log-actions.sh \u2014 hook p\u00f3s-execu\u00e7\u00e3o para auditoria\n#!\/usr\/bin\/env bash\necho \"$(date -u +%Y-%m-%dT%H:%M:%SZ) | tool=$CLAUDE_TOOL_NAME | args=$CLAUDE_TOOL_ARGS\" \\\n  &gt;&gt; .claude\/audit.log\n<\/code><\/pre>\n<p>Um arquivo de auditoria simples, versionado ou enviado a um coletor de logs, transforma &#8220;a IA fez algo estranho ontem&#8221; em uma investiga\u00e7\u00e3o rastre\u00e1vel de trinta segundos. Sem isso, voc\u00ea est\u00e1 depurando um sistema distribu\u00eddo sem trace \u2014 e sabemos como essa hist\u00f3ria termina.<\/p>\n<h3>Onde o setup generalista quebra: linguagens e stacks diferentes<\/h3>\n<p>Um erro comum de quem trabalha com m\u00faltiplas stacks \u2014 Python num servi\u00e7o, TypeScript no frontend, Delphi mantendo um sistema legado de ERP \u2014 \u00e9 assumir que o mesmo arquivo de contexto serve para tudo. N\u00e3o serve. Conven\u00e7\u00f5es de tratamento de erro em Go (retorno expl\u00edcito) e em uma aplica\u00e7\u00e3o Delphi orientada a exce\u00e7\u00f5es (<code>try..except<\/code>) s\u00e3o conceitualmente opostas, e um agente que recebe instru\u00e7\u00f5es gen\u00e9ricas tende a &#8220;vazar&#8221; o idioma de uma stack para outra.<\/p>\n<p>A solu\u00e7\u00e3o estrutural \u00e9 hierarquizar o contexto por diret\u00f3rio, n\u00e3o por projeto inteiro:<\/p>\n<pre><code>context\/\n\u251c\u2500\u2500 ARCHITECTURE.md          # decis\u00f5es globais, v\u00e1lidas em todo lugar\n\u251c\u2500\u2500 services\/\n\u2502   \u251c\u2500\u2500 billing-api\/CLAUDE.md   # espec\u00edfico do servi\u00e7o Python\n\u2502   \u2514\u2500\u2500 legacy-erp\/CLAUDE.md    # espec\u00edfico do m\u00f3dulo Delphi\n\u2514\u2500\u2500 frontend\/CLAUDE.md          # espec\u00edfico do TypeScript\/React\n<\/code><\/pre>\n<p>O Claude Code, por exemplo, respeita <a href=\"https:\/\/docs.anthropic.com\/en\/docs\/claude-code\/memory#claude-md-file-locations\" target=\"_blank\" rel=\"noopener\">arquivos <code>CLAUDE.md<\/code> em subdiret\u00f3rios<\/a>, compondo o contexto conforme a profundidade da sess\u00e3o. Use isso deliberadamente em vez de escrever um \u00fanico arquivo de 500 linhas tentando cobrir cinco linguagens com regras gen\u00e9ricas que n\u00e3o valem para nenhuma delas de fato.<\/p>\n<h2>Checklist de decis\u00e3o para montar (ou revisar) seu setup<\/h2>\n<ul>\n<li>Existe uma \u00fanica fonte can\u00f4nica de contexto est\u00e1tico, ou voc\u00ea tem tr\u00eas arquivos divergentes?<\/li>\n<li>Informa\u00e7\u00f5es vol\u00e1teis (schema, m\u00e9tricas, tickets) est\u00e3o em MCP, ou congeladas em Markdown desatualizado?<\/li>\n<li>Cada agente tem permiss\u00f5es expl\u00edcitas de leitura\/escrita, ou todos operam com acesso irrestrito por padr\u00e3o?<\/li>\n<li>Existe log de auditoria das a\u00e7\u00f5es aut\u00f4nomas, ou voc\u00ea confia na mem\u00f3ria do terminal?<\/li>\n<li>O contexto est\u00e1 hierarquizado por stack\/servi\u00e7o, ou \u00e9 um documento \u00fanico tentando cobrir tudo?<\/li>\n<\/ul>\n<p>Se a resposta a mais de duas dessas perguntas for a alternativa desfavor\u00e1vel, o problema n\u00e3o \u00e9 a ferramenta que voc\u00ea escolheu \u2014 \u00e9 a aus\u00eancia de arquitetura por tr\u00e1s da escolha.<\/p>\n<blockquote><p><strong>\ud83d\udca1 Dica do Mestre:<\/strong> vale a leitura do artigo <a href=\"https:\/\/martinfowler.com\/articles\/exploring-gen-ai.html\" target=\"_blank\" rel=\"noopener\">&#8220;Exploring Generative AI&#8221; da Martin Fowler&#8217;s blog<\/a>, que discute justamente os padr\u00f5es emergentes de uso de LLMs em times de engenharia \u2014 incluindo os riscos de contexto duplicado e autonomia mal calibrada que abordamos aqui.<\/p><\/blockquote>\n<h2>Junte-se \u00e0 comunidade que discute isso na pr\u00e1tica<\/h2>\n<p>Arquitetar um setup de desenvolvimento com m\u00faltiplas camadas de IA \u00e9 um problema de engenharia, n\u00e3o de configura\u00e7\u00e3o pontual \u2014 e como todo problema de engenharia, se beneficia de troca com quem j\u00e1 bateu de frente com as mesmas decis\u00f5es. Na <a href=\"https:\/\/adrianosantos.link\/ComunidadeDevAI\" target=\"_blank\" rel=\"noopener\">Comunidade Dev&#8217;s AI<\/a>, discutimos exatamente esse tipo de trade-off: como calibrar permiss\u00f5es de agentes, como estruturar contexto para stacks mistas, e como auditar o que a IA realmente fez no seu c\u00f3digo. Se voc\u00ea quer ir al\u00e9m do tutorial de instala\u00e7\u00e3o e entender a arquitetura por tr\u00e1s do setup, \u00e9 o lugar certo para continuar essa conversa.<\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>Um setup de desenvolvimento turbinado com IA n\u00e3o se mede pelo n\u00famero de ferramentas instaladas, mas pela consist\u00eancia do contexto que elas compartilham e pelos limites de autonomia que voc\u00ea desenhou com inten\u00e7\u00e3o. Tratar seu ambiente como um sistema distribu\u00eddo \u2014 com fonte \u00fanica de verdade, contexto din\u00e2mico via MCP, permiss\u00f5es expl\u00edcitas e auditoria de a\u00e7\u00f5es \u2014 \u00e9 o que separa produtividade real de uma cole\u00e7\u00e3o de assistentes trabalhando com informa\u00e7\u00f5es divergentes sobre o mesmo c\u00f3digo. A ferramenta certa importa menos do que a arquitetura que voc\u00ea constr\u00f3i em torno dela; e essa arquitetura, como qualquer decis\u00e3o t\u00e9cnica s\u00e9ria, exige manuten\u00e7\u00e3o cont\u00ednua, n\u00e3o configura\u00e7\u00e3o \u00fanica.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Voc\u00ea provavelmente j\u00e1 passou por isso: o Copilot sugere uma fun\u00e7\u00e3o inline, o Claude Code reescreve o mesmo arquivo dez minutos depois com uma conven\u00e7\u00e3o diferente, e o Cursor, numa terceira sess\u00e3o, &#8220;aprende&#8221; um padr\u00e3o de nomenclatura que voc\u00ea nunca pediu \u2014 porque leu um trecho desatualizado do seu pr\u00f3prio README. Tr\u00eas ferramentas, tr\u00eas vers\u00f5es [&hellip;]<\/p>\n","protected":false},"author":127,"featured_media":1116,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1115","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1115","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/users\/127"}],"replies":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/comments?post=1115"}],"version-history":[{"count":1,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1115\/revisions"}],"predecessor-version":[{"id":1117,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1115\/revisions\/1117"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media\/1116"}],"wp:attachment":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media?parent=1115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/categories?post=1115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/tags?post=1115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}