🏗️ Arquitetura da Plataforma de Agentes
Neste modulo voce vai entender como organizar uma plataforma de agentes de IA desde o primeiro arquivo. Da estrutura de pastas ao fluxo de execucao, cada decisao arquitetural tomada aqui define se o projeto vai escalar ou colapsar.
🏛️ Arquitetura de Plataformas de Agentes
A arquitetura de uma plataforma de agentes nao e um diagrama bonito num slide. E a decisao que define quantos agentes o sistema suporta, como eles se comunicam, e se a plataforma sobrevive quando voce precisa trocar de provedor de IA as 3h da manha porque a API caiu.
Conceito Principal
Uma plataforma de agentes profissional se organiza em camadas com responsabilidades claras. A camada de entrada (app/) recebe requests de diferentes canais: Telegram, API REST, webhooks. A camada de decisao (agents/) contem a logica de cada agente e sua capacidade de raciocinio. A camada de ferramentas (tools/) oferece acoes atomicas que os agentes podem chamar. A camada de instrucoes (prompts/) armazena system prompts versionados e templates. A camada de habilidades (skills/) compoe multiplas tools em capacidades complexas. E a camada de estado (memory/) persiste tudo que precisa sobreviver entre execucoes.
O modelo event-driven e a cola entre essas camadas. Em vez de chamadas diretas e acopladas, cada componente emite e escuta eventos. Quando um usuario envia uma mensagem, o sistema emite um evento "message.received". O roteador escuta esse evento, classifica a intencao e emite "agent.selected". O agente processa e emite "response.ready". Esse desacoplamento permite adicionar novos agentes, trocar provedores ou adicionar logging sem mexer no codigo existente.
Dados e Pesquisa
Plataformas event-driven como Kafka processam mais de 10 milhoes de mensagens por segundo em producao. A arquitetura A-tier (application tier) usada por Netflix, Uber e Stripe segue o mesmo principio: separar a camada de aplicacao da camada de dados e da camada de apresentacao. Em plataformas multi-tenant, o isolamento entre clientes nao e opcional. Um bug no agente de um cliente nao pode derrubar ou contaminar o agente de outro.
Dica Pratica
Comece com a estrutura mais simples que funcione, mas com os limites de responsabilidade ja definidos. Um arquivo router.ts que sabe para qual agente enviar, um arquivo por agente em agents/, e um arquivo por tool em tools/. Voce nao precisa de Kafka no dia um, mas precisa que cada peca saiba exatamente o que ela faz e o que ela nao faz.
Fazer
Separar responsabilidades desde o primeiro commit. Cada camada em seu diretorio, cada agente em seu arquivo, cada tool com uma unica funcao. Documentar as fronteiras entre camadas.
Evitar
Colocar tudo num unico arquivo "bot.js" de 3000 linhas. Misturar logica de roteamento com logica de agente. Fazer um agente chamar outro diretamente sem passar pelo orquestrador.
📂 Estrutura de Pastas Profissional
A estrutura de pastas nao e estetica. E a primeira decisao de arquitetura. Ela define como o time navega o codigo, como novas features sao adicionadas e como o sistema cresce sem perder coerencia.
Conceito Principal
A estrutura de referencia para uma plataforma de agentes segue o principio de separacao por dominio funcional, nao por tipo de arquivo. Em vez de ter uma pasta "controllers/", outra "models/" e outra "services/" (que nao dizem nada sobre o que o sistema faz), voce organiza por responsabilidade:
projeto/ ├── app/ # Entrada: servidor, rotas, middleware │ ├── server.ts │ ├── router.ts │ └── middleware/ ├── agents/ # Logica de cada agente │ ├── claude.ts │ ├── ollama.ts │ └── openrouter.ts ├── prompts/ # System prompts e templates │ ├── global.md │ └── agents/ ├── skills/ # Capacidades compostas │ ├── gmail.ts │ └── calendar.ts ├── tools/ # Acoes atomicas │ ├── web-search.ts │ ├── file-read.ts │ └── db-query.ts ├── memory/ # Persistencia de estado │ ├── store.ts │ └── migrations/ ├── config/ # Configuracao centralizada │ ├── env.ts │ └── providers.ts ├── .env ├── .env.example └── .gitignore
Dados e Pesquisa
Estudos de produtividade em grandes codebases mostram que desenvolvedores gastam 60% do tempo lendo e navegando codigo, nao escrevendo. Uma estrutura previsivel reduz esse tempo drasticamente. O padrao de monorepo usado por Google, Meta e Microsoft mantem todo o codigo num unico repositorio com fronteiras internas claras. Feature folders (agrupar por funcionalidade em vez de por tipo) e o padrao recomendado por Angular, Next.js e a maioria dos frameworks modernos.
Dica Pratica
Use barrel exports (index.ts em cada pasta) para controlar o que cada modulo expoe. Se agents/index.ts exporta apenas createAgent() e listAgents(), o resto do sistema nao precisa saber dos detalhes internos de cada agente. Isso permite refatorar a implementacao interna sem quebrar nada de fora.
Fazer
Criar a estrutura completa antes de escrever a primeira linha de logica. Adicionar README curto em cada pasta explicando sua responsabilidade. Usar nomes descritivos: agents/claude.ts, nao agents/a1.ts.
Evitar
Criar pastas "utils/", "helpers/" ou "misc/" que viram lixeira. Ter mais de 10 arquivos numa unica pasta sem subpastas. Nomear arquivos com abreviacoes que so voce entende.
🔑 Configuracao de APIs e Variaveis
Uma plataforma de agentes conversa com o mundo externo o tempo todo. Cada conversa precisa de credenciais, endpoints e configuracoes que mudam entre ambientes. Gerenciar isso de forma profissional e a diferenca entre dormir tranquilo e acordar com uma fatura de $50.000 porque sua chave vazou.
Conceito Principal
O padrao profissional de configuracao usa tres camadas. A primeira e o arquivo .env na raiz do projeto, que contem as variaveis de ambiente locais e nunca entra no git. A segunda e o arquivo .env.example, que contem as mesmas variaveis mas com valores placeholder, servindo de documentacao viva. A terceira e um modulo config/ que carrega, valida e exporta as configuracoes de forma tipada:
// config/env.ts
import { config } from 'dotenv';
config();
export const env = {
// Provedores de IA
OPENAI_API_KEY: requireEnv('OPENAI_API_KEY'),
ANTHROPIC_API_KEY: requireEnv('ANTHROPIC_API_KEY'),
GOOGLE_API_KEY: getEnv('GOOGLE_API_KEY', ''),
// Telegram
TELEGRAM_TOKEN: requireEnv('TELEGRAM_TOKEN'),
ALLOWED_CHAT_ID: requireEnv('ALLOWED_CHAT_ID'),
// Server
PORT: getEnv('PORT', '3000'),
NODE_ENV: getEnv('NODE_ENV', 'development'),
};
function requireEnv(key: string): string {
const value = process.env[key];
if (!value) throw new Error(`Missing: ${key}`);
return value;
}
function getEnv(key: string, fallback: string): string {
return process.env[key] || fallback;
}
Dados e Pesquisa
GitHub reporta que mais de 2 milhoes de secrets sao detectados em repositorios publicos por ano. A rotacao de chaves (trocar a chave periodicamente e invalidar a anterior) e pratica padrao em empresas serias. Para producao, servicos como AWS Secrets Manager, Google Secret Manager ou Vault substituem o .env por um armazenamento criptografado e auditavel. A provider abstraction (uma camada que abstrai qual provedor de IA esta sendo usado) permite trocar entre OpenAI, Anthropic e Google mudando apenas uma variavel de ambiente.
Dica Pratica
Sempre valide todas as variaveis obrigatorias na inicializacao do sistema. Se OPENAI_API_KEY nao esta definida, o sistema deve falhar imediatamente com mensagem clara, nao 20 minutos depois quando alguem tenta usar o agente. Adicione ao .gitignore: .env, *.pem, credentials.json, e qualquer arquivo que tenha "secret" ou "key" no nome.
Fazer
Criar .env.example com todos os campos documentados. Validar variaveis no startup. Usar nomes descritivos: OPENAI_API_KEY, nao KEY1. Ter fallbacks sensiveis para variaveis opcionais.
Evitar
Hardcodar chaves no codigo. Commitar .env no repositorio. Usar a mesma chave de API em desenvolvimento e producao. Ignorar limites de rate limiting dos provedores.
🧠 Contexto Global vs por Agente
Em uma plataforma com multiplos agentes, nem todo agente precisa saber tudo. Um agente de pesquisa nao precisa das regras de formatacao de email. Um agente de comunicacao nao precisa dos detalhes tecnicos de deploy. A hierarquia de contexto define o que cada agente sabe e o que e compartilhado entre todos.
Conceito Principal
O sistema de contexto funciona como uma hierarquia de heranca. No topo esta o contexto global: identidade da plataforma, regras de seguranca, formato de resposta padrao, e restricoes que valem para todos os agentes. Esse contexto normalmente fica em um arquivo como CLAUDE.md ou system-prompt.md na raiz do projeto.
No segundo nivel esta o contexto por agente: dominio de atuacao, tom de voz especifico, ferramentas disponiveis e restricoes locais. Cada agente tem seu arquivo de configuracao (agents/research.yaml, agents/comms.yaml) que define essas instrucoes especificas.
No terceiro nivel esta o contexto por sessao: historico da conversa atual, preferencias do usuario detectadas durante a interacao, e estado temporario. Esse contexto existe apenas durante a execucao e nao persiste entre sessoes (a menos que explicitamente salvo em memory/).
// Hierarquia de contexto
const context = {
global: loadFile('prompts/global.md'), // Regras da plataforma
agent: loadFile('prompts/agents/research.md'), // Instrucoes especificas
session: getSessionHistory(chatId), // Historico da conversa
user: getUserPreferences(userId), // Preferencias do usuario
};
// O system prompt final e a composicao das camadas
const systemPrompt = [
context.global,
context.agent,
context.user,
].join('\n\n');
Dados e Pesquisa
A janela de contexto dos modelos atuais varia de 8K a 200K tokens. Cada token de contexto adicional custa dinheiro e tempo de processamento. Pesquisas mostram que modelos perdem qualidade com contexto excessivo (fenomeno "lost in the middle" documentado por pesquisadores de Stanford). Plataformas de agentes bem projetadas mantendo o contexto enxuto e relevante geram respostas melhores e mais baratas do que as que despejam toda informacao disponivel no prompt.
Dica Pratica
A regra de ouro: se uma instrucao vale para todos os agentes, coloque no global. Se vale so para um agente, coloque no arquivo daquele agente. Se vale so para aquela sessao, monte dinamicamente. Nunca repita a mesma instrucao em multiplos arquivos de agente. Centralize, depois especialize.
Fazer
Criar um prompt global com regras de seguranca e identidade. Criar prompts por agente com dominio e ferramentas. Compor o contexto final em runtime concatenando as camadas relevantes.
Evitar
Dar o contexto inteiro da plataforma para todos os agentes. Copiar e colar instrucoes entre arquivos de agentes diferentes. Deixar o historico de sessao crescer indefinidamente sem compactacao.
⚡ Fluxo Padrao de Execucao
Todo request que entra na plataforma precisa seguir um caminho previsivel. Da mensagem do usuario ate a resposta final, cada etapa tem um papel claro. Sem isso, bugs aparecem em lugares inesperados e diagnosticar problemas vira adivinhacao.
Conceito Principal
O pipeline padrao de execucao tem quatro fases:
1. Entrada: O sistema recebe a mensagem (Telegram, API, webhook), valida o formato, autentica o usuario, e registra o inicio do request com um ID unico para rastreabilidade.
2. Decisao: O roteador analisa a mensagem e decide qual agente deve processar. Isso pode ser baseado em comandos explicitos (/claude, /ollama), classificacao por IA, ou regras fixas. O contexto relevante e montado nesta fase.
3. Execucao: O agente selecionado recebe a mensagem e o contexto, processa usando o provedor de IA correspondente, pode chamar tools durante o processo, e gera uma resposta. Se o provedor falha, o sistema tenta um fallback.
4. Saida: A resposta e formatada para o canal de origem, metricas sao registradas (tokens usados, tempo de resposta, custo), o historico e atualizado, e a resposta e enviada ao usuario.
// Fluxo simplificado
async function handleMessage(msg) {
const requestId = generateId();
log.info({ requestId, user: msg.from }, 'request.start');
try {
// 1. Entrada: validar e autenticar
validateMessage(msg);
authenticate(msg.from.id);
// 2. Decisao: rotear para agente
const agent = router.selectAgent(msg.text);
const context = await buildContext(msg, agent);
// 3. Execucao: processar com fallback
const response = await executeWithFallback(
() => agent.process(msg.text, context),
() => fallbackAgent.process(msg.text, context)
);
// 4. Saida: formatar, registrar, enviar
await trackUsage(requestId, response.usage);
await saveHistory(msg.chat.id, msg.text, response.text);
await sendResponse(msg.chat.id, response.text);
log.info({ requestId, tokens: response.usage }, 'request.done');
} catch (error) {
log.error({ requestId, error }, 'request.failed');
await sendResponse(msg.chat.id, 'Erro no processamento.');
}
}
Dados e Pesquisa
O padrao de middleware (usado por Express, Koa, Fastify) e a forma mais testada de implementar pipelines de processamento. Cada middleware adiciona uma responsabilidade (auth, logging, rate limiting) sem que os outros precisem saber. O circuit breaker pattern (popularizado pelo livro "Release It!" de Michael Nygard) impede que falhas em cascata derrubem o sistema inteiro: se um provedor de IA falha 5 vezes seguidas, o circuito "abre" e redireciona para o fallback automaticamente.
Dica Pratica
Implemente retry com exponential backoff: espere 1s na primeira falha, 2s na segunda, 4s na terceira, e desista apos 3 tentativas. Para producao, adicione um timeout global (60 segundos e um bom padrao) para garantir que requests travados nao acumulem e derrubem o servidor. Sempre registre o tempo total de cada request para identificar gargalos.
Fazer
Definir o pipeline antes de implementar features. Ter error handling em cada etapa. Registrar metricas de tempo e tokens. Ter fallback para pelo menos o provedor principal.
Evitar
Tratar erro com catch vazio que engole a excecao. Nao ter timeout em chamadas de API externas. Deixar o sistema travar silenciosamente quando o provedor nao responde.
🛠️ Exercicio: Criar Estrutura Base
Hora de sair da teoria. Neste exercicio voce vai criar o repositorio, montar a estrutura de pastas, configurar as variaveis de ambiente e construir o esqueleto do primeiro agente. Ao final, voce tera a base funcional que vai receber tudo das proximas trilhas.
Conceito Principal
O exercicio cobre 5 passos concretos:
Passo 1 - Inicializar o repositorio: git init, npm init, instalar dependencias base (dotenv, typescript).
Passo 2 - Criar a estrutura de pastas: Criar todos os diretorios (app/, agents/, prompts/, skills/, tools/, memory/, config/) com seus index files.
Passo 3 - Configurar .env: Criar .env com as chaves de pelo menos um provedor, .env.example como documentacao, e .gitignore para proteger os secrets.
Passo 4 - Modulo de configuracao: Criar config/env.ts que carrega, valida e exporta as variaveis de ambiente de forma tipada.
Passo 5 - Esqueleto do primeiro agente: Criar agents/simple.ts com a interface basica: recebe mensagem, chama provedor de IA, retorna resposta. Testar com um script simples.
# Passo 1: Inicializar mkdir meu-saas-agentes && cd meu-saas-agentes git init npm init -y npm install dotenv typescript @types/node npx tsc --init # Passo 2: Criar estrutura mkdir -p app agents prompts/agents skills tools memory config touch app/server.ts app/router.ts touch agents/simple.ts agents/index.ts touch prompts/global.md touch tools/index.ts skills/index.ts touch memory/store.ts touch config/env.ts # Passo 3: Configurar echo "OPENAI_API_KEY=sk-sua-chave" > .env echo "OPENAI_API_KEY=sk-xxx" > .env.example echo -e ".env\nnode_modules/\ndist/" > .gitignore # Passo 4: Primeiro commit git add . git commit -m "feat: scaffold inicial da plataforma"
Dica Pratica
Nao pule nenhum passo. A tentacao e ir direto para o codigo do agente e "ver funcionando". Mas se a estrutura nao estiver certa agora, voce vai pagar o preco nas proximas trilhas quando precisar adicionar autenticacao, dashboard, multiplos agentes e deploy. Invista 15 minutos na base e economize horas de refactoring depois.
Entregavel
Repositorio git com a estrutura completa de pastas, .env configurado, .gitignore protegendo secrets, modulo de configuracao validando variaveis, e um agente simples que recebe texto e retorna resposta de um provedor de IA. Tudo rodando com um npm start.
Resumo Final
✓ Entendeu a arquitetura event-driven com camadas funcionais separadas.
✓ Montou a estrutura de pastas profissional com separacao por dominio.
✓ Configurou APIs e variaveis de ambiente com seguranca e validacao.
✓ Aprendeu a hierarquia de contexto: global, por agente e por sessao.
✓ Entendeu o pipeline padrao: entrada, decisao, execucao, saida.
✓ Criou a estrutura base do projeto com agente funcional.