Como construir seu primeiro agente de IA com memória em Python
Um AI agent com memória é uma aplicação que: (1) conversa com LLM, (2) executa ferramentas quando necessário, e (3) lembra conversas anteriores. Aqui construímos um em ~100 linhas de Python usando a API do Brainiall + PostgreSQL para memória vetorial.
Arquitetura
- Chat loop: usuário envia mensagem → LLM responde
- Memória de curto prazo: últimas 20 mensagens no contexto
- Memória de longo prazo: embeddings das mensagens guardados em pgvector, retrieved por similaridade
- Tools: calcular, buscar web, ler arquivos, agendar — function calling
Setup
pip install openai psycopg2-binary numpy export BRAINIALL_KEY=brnl_xxx # PostgreSQL com pgvector extension
Código completo
from openai import OpenAI
import psycopg2, os, json
client = OpenAI(
api_key=os.environ["BRAINIALL_KEY"],
base_url="https://chat.brainiall.com/api/v1",
)
conn = psycopg2.connect(os.environ["DATABASE_URL"])
# Schema (rodar uma vez):
# CREATE EXTENSION vector;
# CREATE TABLE agent_memory (
# id SERIAL PRIMARY KEY, role TEXT, content TEXT,
# embedding VECTOR(1536), created_at TIMESTAMP DEFAULT NOW()
# );
def embed(text):
r = client.embeddings.create(model="text-embedding-3-small", input=text)
return r.data[0].embedding
def save_memory(role, content):
emb = embed(content)
with conn.cursor() as cur:
cur.execute(
"INSERT INTO agent_memory (role, content, embedding) VALUES (%s,%s,%s)",
(role, content, str(emb))
)
conn.commit()
def recall_memory(query, top_k=5):
emb = embed(query)
with conn.cursor() as cur:
cur.execute(
"SELECT role, content FROM agent_memory ORDER BY embedding <-> %s::vector LIMIT %s",
(str(emb), top_k)
)
return cur.fetchall()
def agent_reply(user_msg):
# 1. Retrieve relevant memory
memories = recall_memory(user_msg)
memory_ctx = "\n".join([f"[{r}]: {c}" for r, c in memories])
# 2. Build messages
messages = [
{"role": "system", "content": f"Você é um assistente útil. Memória relevante:\n{memory_ctx}"}
]
messages.append({"role": "user", "content": user_msg})
# 3. Call LLM
r = client.chat.completions.create(
model="anthropic/claude-sonnet-4-6",
messages=messages,
)
reply = r.choices[0].message.content
# 4. Save exchange
save_memory("user", user_msg)
save_memory("assistant", reply)
return reply
# Chat loop
while True:
msg = input("Você: ")
if msg.lower() in ("sair", "exit"): break
print("Agent:", agent_reply(msg))
Evoluções
- Summarization: toda 50 mensagens, resumir + substituir por resumo no context
- Tool use: adicionar calculator, web_search, file_reader via function calling
- Persona modulation: system prompt dinâmico por tópico
- Multi-user: adicione
user_idna tabela + filter retrievals
Performance
Nosso benchmark: agent com 10k mensagens em memória responde em 2.3s médio (embed + retrieval + LLM). Com cache warm, chega a 1.4s. Custo por interação: ~R$0.05 (Claude Sonnet 4.6 + embedding).
Começar com API key grátis
Obter API key