MÓDULO 1.2

🧠 Identidade e Memória

Sem identidade, o agente responde como um chatbot genérico. Sem memória, ele esquece tudo. Aqui você dá voz e três camadas de lembrança que fazem toda a diferença.

6
Tópicos
~45
Minutos
Básico
Nível
Conceito
Tipo
1

🎭 Personalidade (soul.md)

A soul.md é um arquivo Markdown que define quem o agente é: tom, regras, formato de resposta, o que ele recusa fazer. Ela é injetada como system prompt em toda chamada do LLM. Versionar como Markdown deixa você editar como qualquer outro arquivo do projeto e ver diff no git.

📋 O que sempre vai na soul

  • Identidade: nome do agente, propósito, pra quem trabalha (você).
  • Tom: formal? casual? direto? bem-humorado? exemplos curtos do estilo.
  • Regras: sempre responder em PT-BR, mensagens curtas no Telegram, código em bloco, etc.
  • Recusas: o que não fazer (mandar dados sensíveis em texto puro, ações destrutivas sem confirmar).
  • Fatos sobre você: nome, fuso, profissão, contexto familiar mínimo.

💡 Como evoluir a soul

Comece com 30 linhas. Use o agente uma semana. Toda vez que ele errar tom ou estilo, abra a soul e adicione a regra ("nunca usar emoji no início da resposta", "preferir bullets sobre parágrafo longo"). Em duas semanas ela está afiada e o agente "soa como você espera".

2

⚙️ Configuração centralizada

Em vez de espalhar process.env.ALGUMA_COISA por todo o código, você cria um único módulo que lê o .env, valida tipos com Zod, e exporta um objeto config tipado. Todo o resto do código importa de lá.

🎯 Por que vale a pena

  • Validação na inicialização: se faltou .env ou tem valor inválido, falha logo no boot — não 3 horas depois numa request real.
  • Refactor sem dor: renomeou uma variável? Muda em um lugar, TypeScript te aponta todas as referências.
  • Defaults seguros: MAX_ITER default 15, TZ default America/Sao_Paulo — sem precisar lembrar.

📊 Anatomia mínima

import { z } from 'zod';
import 'dotenv/config';

const Schema = z.object({
  TELEGRAM_BOT_TOKEN: z.string().min(20),
  ALLOWED_CHAT_IDS: z.string().transform(s => s.split(',').map(Number)),
  LLM_PROVIDER: z.enum(['openrouter','anthropic','openai','ollama']),
  LLM_MODEL: z.string(),
  LLM_API_KEY: z.string().min(10),
  DATABASE_PATH: z.string().default('./data/agente.db'),
  TIMEZONE: z.string().default('America/Sao_Paulo'),
  MAX_ITER: z.coerce.number().default(15),
});

export const config = Schema.parse(process.env);
export type Config = typeof config;
3

💭 Memória de curto prazo

É o histórico recente da conversa: as últimas N mensagens guardadas em SQLite e re-enviadas a cada chamada do LLM. Sem isso, cada mensagem sua é uma conversa nova — ele esquece o que vocês acabaram de falar.

📐 Como dimensionar

  • Buffer de 40-60 mensagens serve a maioria dos casos — equivale a uma conversa de uma hora.
  • Mensagens antigas não somem: ficam no banco e podem ser recuperadas pela memória semântica (tópico 5).
  • Quando o buffer estoura, descarta o mais velho. Em produção, antes de descartar, summariza num "highlight" de uma linha.

💡 Dica

Use better-sqlite3 em vez do sqlite3 antigo. É síncrono (mais simples), mais rápido, e funciona com TypeScript sem dor. Crie índice em (chat_id, created_at) — buscar últimas N fica instantâneo mesmo com 10k mensagens.

4

📌 Memória central de fatos

Uma tabela chave-valor com fatos centrais sobre você, que sempre entram no system prompt. Diferente do buffer (que rola e descarta), esses fatos são permanentes até você mudar.

🔑 Exemplos de fatos centrais

  • nome: "Nei"
  • fuso: "America/Sao_Paulo"
  • profissão: "consultor de tecnologia, foco em automação"
  • família: "esposa Ana, filhos Pedro (8) e Mariana (5)"
  • meta_q2: "lançar curso de agentes em junho"
  • preferência_resposta: "bullets curtos, sem emoji no início"

✓ Bons candidatos

  • • Fatos estáveis (nome, fuso)
  • • Preferências de longo prazo
  • • Contexto de família/trabalho
  • • Metas trimestrais

✗ Não é pra cá

  • • Detalhe de uma conversa única
  • • Estado temporário ("estou no aeroporto")
  • • Histórico transacional (vai pra buffer)
  • • Documentos longos (vai pra semântica)

💡 Budget

Mantenha total da memória central abaixo de ~2.000 caracteres (~500 tokens). Tudo isso vai a cada mensagem — se inflar demais, queima tokens à toa e dilui o foco do agente. Quando passar do limite, é hora de mover fatos antigos pra arquivo histórico.

5

🔍 Memória semântica

Cada mensagem que vocês trocam é convertida em um embedding (vetor numérico que representa o significado) e indexada num banco vetorial. Quando você pergunta algo, o agente busca os trechos mais parecidos em significado — não em palavras exatas.

🎯 Por que muda o jogo

Você diz: "Lembra daquele cliente que reclamou de prazo lá no início do ano?"

Sem memória semântica: ele só vê as últimas 40 mensagens, não acha nada, responde "qual?".

Com memória semântica: busca por similaridade (não pela palavra "prazo"), encontra a conversa de fevereiro com o cliente Marcelo, e responde com o contexto certo.

🔧 Opções de banco vetorial

  • Pinecone: serverless, free tier de 100k vetores, configura em 2 minutos. Bom pra começar.
  • sqlite-vec: extensão SQLite, roda local, sem custo, sem internet. Bom se já usa SQLite.
  • Qdrant: open-source, roda em Docker, escalável. Bom pra depois de 100k vetores.
  • Modelo de embedding: text-embedding-3-small (OpenAI, $0.02/M tokens) ou nomic-embed via Ollama (grátis local).
6

🪜 Estratégia das 3 camadas

A regra prática é simples: cada camada tem um custo e um benefício. Você usa camadas 1 e 2 sempre, e camada 3 sob demanda via tool call.

🎯 Resumo decisório

Camada 1 — Central

Sempre vai. ~500 tokens. Fatos sobre você. Mudança rara.

Camada 2 — Buffer recente

Sempre vai. ~2.000-5.000 tokens. Últimas 40-60 mensagens. Continuidade.

Camada 3 — Semântica

Só quando o agente decide chamar a tool buscar_memoria(query). Pode trazer 5-10 trechos relevantes.

💰 Impacto no custo

Mandar tudo a cada mensagem (sem essa hierarquia) facilmente triplica seu gasto mensal de tokens. A diferença entre $5/mês e $50/mês vem de onde você corta — e cortar inteligentemente é exatamente isso aqui.

Resumo do módulo

soul.md no lugar — agente tem voz, regras e recusas claras
Config validada — Zod garante que o boot só sobe com tudo certo
Buffer de curto prazo — SQLite com últimas 40-60 mensagens
Memória central — fatos chave-valor sempre injetados
Memória semântica — busca por significado quando precisa
Estratégia das 3 camadas — uso eficiente de tokens, custo controlado

Próximo módulo:

1.3 — Cérebro e Ferramentas (camada de LLM, sistema de tools, e o loop que junta tudo)