Cómo hacer que Claude tenga memoria persistente
Implementa memoria conversacional en Claude usando la API de Anthropic con historial y resúmenes.
- Python 3.9+ instalado
- Cuenta en Anthropic con API key (console.anthropic.com)
- Conocimientos básicos de Python y APIs REST
- Terminal y editor de código
- Por qué Claude no recuerda conversaciones por defecto y cómo solucionarlo
- Cómo mantener historial de mensajes entre llamadas a la API
- Cómo persistir la memoria en disco con JSON para sobrevivir reinicios
- Cómo resumir conversaciones largas para no exceder el límite de tokens
- Cómo implementar memoria de largo plazo con hechos clave sobre el usuario
Instalar el SDK y configurar la API key
Claude es stateless por diseño: cada llamada a la API es independiente y el modelo no recuerda nada de interacciones previas. La 'memoria' es responsabilidad tuya como desarrollador: consiste en reenviar el contexto relevante en cada petición. Empecemos instalando el SDK oficial de Anthropic y configurando tu clave. En España y LATAM puedes pagar la API con tarjeta normal desde la consola. Guarda tu API key como variable de entorno para no exponerla en el código (nunca la subas a Git). Este primer paso deja lista la base sobre la que construiremos toda la lógica de memoria.
pip install anthropic
# En Linux/macOS
export ANTHROPIC_API_KEY='sk-ant-tu-clave-aqui'
# En Windows PowerShell
$env:ANTHROPIC_API_KEY='sk-ant-tu-clave-aqui'Crear una conversación con historial en memoria
El mecanismo básico de memoria es mantener una lista de mensajes y reenviarla completa en cada llamada. La API acepta un array 'messages' con roles 'user' y 'assistant' alternados. Cada vez que Claude responde, añades su respuesta al historial; en la siguiente pregunta envías todo el historial acumulado. Así el modelo 've' toda la conversación previa y responde con contexto. Este ejemplo crea una clase sencilla que gestiona el historial en RAM durante la sesión. Fíjate en que usamos claude-opus-4-8 como modelo por defecto y un system prompt para dar personalidad. El historial vive solo mientras el programa corre.
import anthropic
client = anthropic.Anthropic()
class ClaudeConMemoria:
def __init__(self, system="Eres un asistente útil y conciso."):
self.system = system
self.historial = []
def preguntar(self, mensaje):
self.historial.append({"role": "user", "content": mensaje})
resp = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
system=self.system,
messages=self.historial,
)
texto = resp.content[0].text
self.historial.append({"role": "assistant", "content": texto})
return texto
bot = ClaudeConMemoria()
print(bot.preguntar("Me llamo Lucía y vivo en Madrid."))
print(bot.preguntar("¿Recuerdas cómo me llamo y dónde vivo?"))Persistir la memoria en disco con JSON
Para que Claude 'recuerde' entre sesiones distintas necesitas guardar el historial en almacenamiento persistente. La opción más simple es serializar la lista de mensajes a un archivo JSON al terminar y cargarla al iniciar. Así, aunque cierres el programa o reinicies el servidor, la conversación continúa donde la dejaste. Ampliamos la clase anterior con métodos guardar() y cargar(). En producción usarías una base de datos (SQLite, Postgres, Redis) con una fila por usuario, pero JSON es perfecto para prototipar y entender el concepto. Cada usuario tendría su propio archivo identificado por su ID.
import json, os
class ClaudeMemoriaPersistente(ClaudeConMemoria):
def __init__(self, user_id, system="Eres un asistente útil."):
super().__init__(system)
self.ruta = f"memoria_{user_id}.json"
self.cargar()
def cargar(self):
if os.path.exists(self.ruta):
with open(self.ruta, encoding="utf-8") as f:
self.historial = json.load(f)
def guardar(self):
with open(self.ruta, "w", encoding="utf-8") as f:
json.dump(self.historial, f, ensure_ascii=False, indent=2)
def preguntar(self, mensaje):
respuesta = super().preguntar(mensaje)
self.guardar()
return respuesta
bot = ClaudeMemoriaPersistente(user_id="lucia_42")
print(bot.preguntar("Mi color favorito es el verde."))
# Cierra y vuelve a ejecutar: seguirá recordándoloResumir conversaciones largas para no reventar el límite
Reenviar todo el historial funciona hasta que la conversación crece tanto que supera la ventana de contexto (o dispara los costes, ya que pagas por tokens de entrada). La solución profesional es la compactación: cuando el historial supera cierto número de mensajes, pides a Claude que resuma la parte más antigua en un párrafo y sustituyes esos mensajes por el resumen. Así conservas la esencia sin arrastrar cada palabra. Este patrón, llamado 'memoria de ventana deslizante con resumen', mantiene el coste acotado y la relevancia alta. Aquí resumimos cuando pasamos de 20 mensajes, conservando los 6 más recientes intactos.
def compactar_si_necesario(self, umbral=20, conservar=6):
if len(self.historial) <= umbral:
return
antiguos = self.historial[:-conservar]
recientes = self.historial[-conservar:]
texto_antiguo = "\n".join(
f"{m['role']}: {m['content']}" for m in antiguos
)
resumen = client.messages.create(
model="claude-opus-4-8",
max_tokens=512,
messages=[{"role": "user", "content":
f"Resume esta conversación en un párrafo, "
f"conservando datos clave del usuario:\n\n{texto_antiguo}"}],
).content[0].text
self.historial = [
{"role": "user", "content": f"[Resumen previo]: {resumen}"},
{"role": "assistant", "content": "Entendido, tengo el contexto."},
] + recientesAñadir memoria de largo plazo con hechos clave
El historial resume la conversación, pero a menudo quieres recordar hechos permanentes sobre el usuario aunque pasen meses: su nombre, preferencias, idioma, zona horaria. Esto es la 'memoria de largo plazo'. La estrategia consiste en extraer hechos relevantes tras cada intercambio y almacenarlos por separado, inyectándolos en el system prompt de cada nueva sesión. Así Claude arranca ya sabiendo quién eres, independientemente del historial de mensajes. Combinamos ambos: hechos permanentes en el system, conversación reciente en messages. Este es el patrón que usan asistentes reales en producción.
def extraer_hechos(mensaje_usuario):
r = client.messages.create(
model="claude-opus-4-8",
max_tokens=256,
system="Extrae hechos permanentes sobre el usuario "
"(nombre, gustos, ubicación). Devuelve una lista corta "
"o 'NINGUNO' si no hay hechos nuevos.",
messages=[{"role": "user", "content": mensaje_usuario}],
).content[0].text
return r if "NINGUNO" not in r else None
# Uso: acumular hechos y meterlos en el system prompt
hechos = []
nuevo = extraer_hechos("Soy vegetariana y hablo español de Argentina")
if nuevo:
hechos.append(nuevo)
system = "Eres un asistente útil.\nHechos conocidos del usuario:\n" + \
"\n".join(hechos)
print(system)Unir todo en un asistente con memoria completa
Ahora integramos las tres capas: hechos de largo plazo en el system prompt, historial reciente persistido en disco, y compactación automática cuando crece. El resultado es un asistente que recuerda quién eres entre sesiones, mantiene el hilo de la conversación actual y no revienta el límite de tokens. Este es el esqueleto que puedes desplegar en un backend con FastAPI o similar, usando un identificador por usuario. Prueba a ejecutarlo, cerrar el programa, y volver a abrirlo: Claude seguirá recordándote. Desde aquí puedes migrar el almacenamiento a una base de datos y añadir búsqueda semántica con embeddings para memoria a gran escala.
class AsistenteCompleto(ClaudeMemoriaPersistente):
def __init__(self, user_id):
self.hechos = []
super().__init__(user_id)
def construir_system(self):
base = "Eres un asistente cercano que responde en español."
if self.hechos:
base += "\nDatos del usuario:\n" + "\n".join(self.hechos)
return base
def preguntar(self, mensaje):
nuevo = extraer_hechos(mensaje)
if nuevo:
self.hechos.append(nuevo)
self.system = self.construir_system()
self.compactar_si_necesario()
return super().preguntar(mensaje)
bot = AsistenteCompleto("lucia_42")
print(bot.preguntar("Hola, ¿qué recuerdas de mí?"))Has construido un asistente basado en Claude con memoria real de tres niveles: historial conversacional que persiste en disco entre sesiones, compactación automática mediante resúmenes para no exceder el límite de tokens, y memoria de largo plazo con hechos permanentes sobre el usuario inyectados en el system prompt. Ahora entiendes que Claude es stateless y que la memoria la implementas tú controlando qué contexto reenvías en cada llamada. Tienes un esqueleto listo para escalar a producción cambiando el almacenamiento a una base de datos.
Los cursos de certificación en español de Partners Academy te llevan de principiante a builder profesional con Claude y su API.
Ver programas de Partners Academy →