Ir al contenido

Referencia de Tools

mcp-memory expone 19 tools vía el protocolo MCP. Las primeras 8 son 100% compatibles con la API de MCP Memory de Anthropic — úsalo como reemplazo drop-in. Las 11 restantes extienden la funcionalidad con búsqueda semántica, recuperación híbrida, gestión de entidades y operaciones de mantenimiento.

ToolDescripciónAnthropicNueva
create_entitiesCrea o actualiza entidades (fusiona observaciones)
create_relationsCrea relaciones tipadas entre entidades
add_observationsAñade observaciones a una entidad existente
delete_entitiesElimina entidades (cascada a observaciones + relaciones)
delete_observationsElimina observaciones específicas de una entidad
delete_relationsElimina relaciones específicas
search_nodesBúsqueda por substring (nombre, tipo, contenido de observaciones)
open_nodesRecupera entidades por nombre exacto
search_semanticBúsqueda semántica vía embeddings vectoriales + re-ranking límbico🆕
migrateImporta desde formato JSONL de Anthropic (idempotente)🆕
analyze_entity_splitAnaliza una entidad para determinar si necesita splitting (umbrales: Sesion=15, Proyecto=25, otras=20)🆕
propose_entity_splitAnaliza y propone un split si la entidad lo necesita🆕
execute_entity_splitEjecuta un split aprobado (crea nuevas entidades, mueve observaciones)🆕
find_split_candidatesEncuentra todas las entidades candidatas para splitting🆕
find_duplicate_observationsEncuentra observaciones semánticamente duplicadas dentro de una entidad (coseno + containment)🆕
consolidation_reportGenera un reporte de consolidación de solo lectura (candidatas a split, obs marcadas, entidades estancadas)🆕
end_relationExpira una relación activa estableciendo active=0 y ended_at=now🆕
add_reflectionAñade una reflexión narrativa a una entidad, sesión, relación o global🆕
search_reflectionsBusca reflexiones vía búsqueda híbrida semántica (KNN) y texto (FTS5) con RRF🆕

Crea o actualiza entidades en el knowledge graph. Si una entidad ya existe, las observaciones se fusionan — los datos existentes nunca se sobrescriben.

Signature: create_entities(entities: list[dict[str, Any]]) → dict[str, Any]

ParámetroTipoRequeridoDescripción
entitieslist[dict]Lista de entidades a crear o actualizar

Cada diccionario de entidad se valida contra el modelo Pydantic EntityInput:

CampoTipoRequeridoDefaultDescripción
namestrNombre de la entidad (mínimo 1 carácter). Actúa como identificador único.
entityTypestrNo"Generic"Categoría de la entidad (ej: "Project", "Task", "Component").
observationslist[str]No[]Observaciones a adjuntar a la entidad.
{
"entities": [
{
"name": "CachorroSpace",
"entityType": "Project",
"observations": [
"Stack: Astro 6.x + Starlight 0.38.x",
"Deployed on Vercel at cachorro.space"
]
}
]
}
{
"entities": [
{
"name": "CachorroSpace",
"entityType": "Project",
"observations": [
"Stack: Astro 6.x + Starlight 0.38.x",
"Deployed on Vercel at cachorro.space"
]
}
]
}
{
"error": "1 validation error for EntityInput\nname\n Field required [type=missing, input_value={'entityType': 'Project'}, input_type=dict]"
}
  • Implementa upsert vía INSERT … ON CONFLICT(name) DO UPDATE. Si la entidad ya existe, actualiza entity_type y updated_at sin eliminar las observaciones previas.
  • Las observaciones se fusionan: las nuevas se añaden y los duplicados exactos se descartan silenciosamente.
  • Genera un embedding con el snapshot completo de la entidad (nombre + tipo + todas las observaciones). Si el motor de embeddings no está disponible, la operación se completa sin error.
  • Se pueden crear múltiples entidades en una sola llamada pasando varios diccionarios en el array entities.

Crea relaciones entre entidades. Ambas entidades — origen y destino — deben existir en el knowledge graph antes de crear una relación.

Signature: create_relations(relations: list[dict[str, Any]]) → dict[str, Any]

ParámetroTipoRequeridoDescripción
relationslist[dict]Lista de relaciones a crear

Cada diccionario de relación se valida contra el modelo Pydantic RelationInput:

CampoTipoRequeridoDescripción
fromstrNombre de la entidad origen. Debe existir en el grafo.
tostrNombre de la entidad destino. Debe existir en el grafo.
relationTypestrTipo de relación (ej: "contains", "depends_on", "uses").
{
"relations": [
{
"from": "CachorroSpace",
"to": "Astro",
"relationType": "uses"
}
]
}
{
"relations": [
{
"from": "CachorroSpace",
"to": "Astro",
"relationType": "uses"
}
]
}
{
"relations": [
{ "error": "Entity not found: NonExistentEntity" }
],
"errors": [
"Entity not found: NonExistentEntity"
]
}
{
"relations": [
{
"from": "CachorroSpace",
"to": "Astro",
"relationType": "uses",
"error": "Relation already exists"
}
]
}
  • Ambas entidades (from y to) deben existir antes de crear la relación. Si falta alguna, la relación no se crea y se retorna un error.
  • La tabla relations tiene una restricción UNIQUE(from_entity, to_entity, relation_type). Si la relación ya existe, el diccionario se retorna con una clave "error".
  • No modifica embeddings — las relaciones son metadatos estructurales y no participan en la búsqueda semántica.

Añade observaciones a una entidad existente. La entidad debe existir previamente — usa create_entities para crear nuevas entidades.

Signature: add_observations(name: str, observations: list[str]) → dict[str, Any]

ParámetroTipoRequeridoDescripción
namestrNombre exacto de la entidad. Debe existir.
observationslist[str]Observaciones a añadir. Los duplicados exactos se descartan.
{
"name": "CachorroSpace",
"observations": [
"ECharts 6.x chosen for visualizations",
"Accent color: teal (#2dd4bf)"
]
}
{
"entity": {
"name": "CachorroSpace",
"entityType": "Project",
"observations": [
"Stack: Astro 6.x + Starlight 0.38.x",
"Deployed on Vercel at cachorro.space",
"ECharts 6.x chosen for visualizations",
"Accent color: teal (#2dd4bf)"
]
}
}
{
"error": "Entity not found: NonExistentEntity"
}
  • La entidad debe existir. Esta tool nunca crea entidades nuevas.
  • Los duplicados exactos de observaciones se descartan silenciosamente — no se genera error por duplicados.
  • Regenera el embedding con el snapshot actualizado de la entidad (todas las observaciones existentes + las nuevas).
  • Usa esta tool cuando quieras añadir datos a una entidad sin reespecificar su tipo u observaciones existentes.

Elimina entidades y todas sus observaciones y relaciones asociadas.

Signature: delete_entities(entityNames: list[str]) → dict[str, Any]

ParámetroTipoRequeridoDescripción
entityNameslist[str]Nombres de entidades a eliminar.
{
"entityNames": ["Old Project", "Deprecated Component"]
}
{
"deleted": ["Old Project", "Deprecated Component"]
}
{
"deleted": ["Old Project"],
"errors": ["Entity not found: Already Deleted Entity"]
}
  • Eliminación en cascada: eliminar una entidad remueve automáticamente todas sus observaciones y relaciones vía ON DELETE CASCADE en SQLite.
  • Crítico — embeddings: la tabla virtual vec0 de sqlite-vec no soporta CASCADE. El código elimina manualmente los embeddings antes de eliminar entidades: (1) busca los rowids de la entidad, (2) elimina de entity_embeddings por rowid, (3) elimina de entities. Todo dentro de una transacción implícita de SQLite.
  • Puede fallar intermitentemente con "cannot start a transaction" bajo alta concurrencia en modo WAL. Reintentar normalmente lo resuelve.
  • Las entidades que no existen se reportan en el array errors pero no impiden otras eliminaciones válidas.

Elimina observaciones específicas de una entidad. La entidad se preserva — solo se remueven las observaciones coincidentes.

Signature: delete_observations(name: str, observations: list[str]) → dict[str, Any]

ParámetroTipoRequeridoDescripción
namestrNombre exacto de la entidad. Debe existir.
observationslist[str]Observaciones a eliminar (coincidencia de contenido exacto).
{
"name": "CachorroSpace",
"observations": [
"Accent color: teal (#2dd4bf)"
]
}
{
"entity": {
"name": "CachorroSpace",
"entityType": "Project",
"observations": [
"Stack: Astro 6.x + Starlight 0.38.x",
"Deployed on Vercel at cachorro.space",
"ECharts 6.x chosen for visualizations"
]
}
}
{
"error": "Entity not found: NonExistentEntity"
}
  • La eliminación es por coincidencia de contenido exacto. No hay patrones, wildcards ni coincidencia por substring.
  • Si una observación no existe para esa entidad, no ocurre nada — no se genera error por observaciones no encontradas.
  • Regenera el embedding con las observaciones restantes después de la eliminación.
  • Útil para remover observaciones obsoletas o incorrectas sin recrear la entidad completa.

Elimina relaciones entre entidades. Requiere el triple completo para identificar la relación.

Signature: delete_relations(relations: list[dict[str, Any]]) → dict[str, Any]

ParámetroTipoRequeridoDescripción
relationslist[dict]Relaciones a eliminar (mismo formato que create_relations)

Cada diccionario de relación:

CampoTipoRequeridoDescripción
fromstrNombre de la entidad origen
tostrNombre de la entidad destino
relationTypestrTipo de relación
{
"relations": [
{
"from": "CachorroSpace",
"to": "Astro",
"relationType": "uses"
}
]
}
{
"deleted": [
{
"from": "CachorroSpace",
"to": "Astro",
"relationType": "uses"
}
]
}
{
"deleted": [],
"errors": [
"Relation not found: A -> B (contains)"
]
}
  • Requiere el triple completo (from + to + relationType) para identificar la relación. Las coincidencias parciales no funcionan.
  • Si alguna entidad no existe: "Entity not found: X or Y".
  • Si la relación no existe: "Relation not found: X -> Y (relationType)".
  • No modifica embeddings — las relaciones no forman parte del índice semántico.

Busca entidades por nombre, tipo de entidad o contenido de observaciones usando coincidencia de substring. Es una búsqueda ligera que no requiere el modelo de embeddings.

Signature: search_nodes(query: str) → dict[str, Any]

ParámetroTipoRequeridoDescripción
querystrTérmino de búsqueda. Se aplica como patrón LIKE en múltiples campos.
{ "query": "astro" }
{
"entities": [
{
"name": "CachorroSpace",
"entityType": "Project",
"observations": [
"Stack: Astro 6.x + Starlight 0.38.x",
"Deployed on Vercel at cachorro.space"
]
},
{
"name": "CachorroInk",
"entityType": "Project",
"observations": [
"Blog built with Astro 5.x"
]
}
]
}
  • Usa LIKE con el patrón %query% aplicado simultáneamente en tres campos: name, entity_type y content de observaciones.
  • Usa SELECT DISTINCT para evitar retornar la misma entidad múltiples veces cuando coincide en varios campos.
  • No requiere el modelo de embeddings ONNX — funciona de inmediato sin configuración adicional.
  • La búsqueda es sensible a mayúsculas por defecto (comportamiento estándar de LIKE en SQLite). Para búsqueda insensible a mayúsculas, usa la búsqueda semántica.
  • Para consultas dirigidas en grafos grandes, prefiere search_nodes o la búsqueda semántica sobre open_nodes.

Recupera entidades específicas por nombre exacto. Retorna los datos completos de la entidad con todas sus observaciones.

Signature: open_nodes(names: list[str]) → dict[str, Any]

ParámetroTipoRequeridoDescripción
nameslist[str]Nombres de entidades a recuperar.
{ "names": ["CachorroSpace", "Astro"] }
{
"entities": [
{
"name": "CachorroSpace",
"entityType": "Project",
"observations": [
"Stack: Astro 6.x + Starlight 0.38.x",
"Deployed on Vercel at cachorro.space"
]
}
]
}
  • Búsqueda por nombre exacto (WHERE name = ?). Sin patrones, wildcards ni coincidencia LIKE.
  • Si un nombre no coincide con ninguna entidad, se omite silenciosamente de los resultados — no se genera error. En el ejemplo anterior, si "Astro" no existe, solo se retorna "CachorroSpace".
  • No incluye relaciones en la respuesta. Para obtener relaciones, usa search_nodes con una consulta relevante a relaciones o search_semantic.
  • Ideal para consultas rápidas cuando se conoce el nombre exacto de la entidad.

Búsqueda semántica usando embeddings vectoriales con búsqueda híbrida de texto completo opcional. Combina resultados semánticos (KNN) y de texto (FTS5) vía Reciprocal Rank Fusion, y luego aplica re-ranking límbico basado en patrones de acceso y co-ocurrencia.

Requiere el modelo de embeddings — ejecuta download_model.py primero. Consulta Búsqueda Semántica para los detalles completos del pipeline y Búsqueda Híbrida para el mecanismo de fusión RRF.

Signature: search_semantic(query: str, limit: int = 10) → dict[str, Any]

ParámetroTipoRequeridoDefaultDescripción
querystrTexto de consulta. Se codifica como embedding y se compara contra los vectores almacenados.
limitintNo10Número máximo de resultados a retornar.
{
"query": "web framework for documentation sites",
"limit": 5
}
{
"results": [
{
"name": "CachorroSpace",
"entityType": "Project",
"observations": [
"Stack: Astro 6.x + Starlight 0.38.x",
"Documentation site for open-source repos"
],
"limbic_score": 0.6742,
"scoring": {
"importance": 0.8512,
"temporal_factor": 0.9923,
"cooc_boost": 1.2341
},
"distance": 0.1234,
"rrf_score": 0.018542
},
{
"name": "CachorroInk",
"entityType": "Project",
"observations": [
"Blog built with Astro 5.x"
],
"limbic_score": 0.4521,
"scoring": {
"importance": 0.6234,
"temporal_factor": 0.8756,
"cooc_boost": 0.5123
},
"distance": 0.3591,
"rrf_score": 0.012341
}
]
}
{
"error": "Embedding model not available. Run 'python scripts/download_model.py' to download the model first."
}
  • Requiere que el modelo de embeddings ONNX esté descargado. Si no está disponible, retorna un error descriptivo. Todas las demás tools funcionan sin él.
  • Usa búsqueda híbrida: KNN (distancia coseno de sqlite-vec) se ejecuta en paralelo con FTS5 (texto completo BM25). Los resultados se fusionan vía Reciprocal Rank Fusion (k=60).
  • Si FTS5 no retorna resultados o no está disponible, recurre al modo semántico puro (solo KNN + re-ranking límbico).
  • Cada resultado incluye:
    • limbic_score — score de ranking final (consulta Sistema Límbico)
    • scoring — desglose de importancia, decay temporal y boost de co-ocurrencia
    • distance — distancia coseno desde el vector de consulta
    • rrf_score — score de Reciprocal Rank Fusion (solo presente en modo híbrido; ausente en modo semántico puro)
  • Tracking post-respuesta: después de retornar resultados, el motor registra eventos de acceso y co-ocurrencias para las entidades top-K. Esto mejora los rankings futuros. Es best-effort — no afecta la respuesta actual.
  • Menor distancia = mayor similitud. Fórmula: d = 1 - cos(A, B), rango [0, 2].
  • El texto de la entidad se codifica usando una estrategia de selección Head+Tail+Diversity con un presupuesto de 480 tokens (no es concatenación simple). Consulta Búsqueda Semántica para más detalles.

Importa datos desde el formato JSONL de Anthropic MCP Memory a SQLite. Idempotente — ejecutarlo múltiples veces no duplica datos. Consulta Migración para una guía paso a paso.

Signature: migrate(source_path: str = "") → dict[str, Any]

ParámetroTipoRequeridoDefaultDescripción
source_pathstr""Ruta al archivo JSONL fuente de Anthropic. Debe existir.
{
"source_path": "~/.config/opencode/mcp-memory.jsonl"
}
{
"entities_imported": 32,
"relations_imported": 37,
"errors": 0,
"skipped": 2
}
  • Idempotente: las entidades se insertan o actualizan (upsert), las relaciones se crean solo si no existen ya, y las observaciones duplicadas se descartan. Seguro para ejecutar repetidamente.
  • Las relaciones se importan solo si ambas entidades ya existen en el grafo al momento de procesar la línea. Esto significa que el archivo JSONL debería listar entidades antes que sus relaciones.
  • Generación de embeddings en batch: si el motor de embeddings está disponible, se generan embeddings para todas las entidades importadas al final del proceso de migración.
  • El contador skipped incluye líneas que no se pudieron procesar (JSON malformado, campos requeridos faltantes, etc.).
  • También disponible como script independiente — consulta Primeros Pasos para la invocación por CLI.

Signature: analyze_entity_split(entity_name: str) → dict[str, Any]

ParámetroTipoRequeridoDescripción
entity_namestrNombre de la entidad a analizar
{
"entity_name": "Proyecto cachorrites"
}
{
"analysis": {
"entity_name": "Proyecto cachorrites",
"entity_type": "Proyecto",
"observation_count": 28,
"threshold": 25,
"needs_split": true,
"topics": {
"Arquitectura": ["Stack: FastMCP + SQLite", "MCP Memory v2"],
"Implementacion": ["97 tests passing", "Query routing implementado"],
"Despliegue": ["Deploy: Vercel", "URL: cachorro.space"]
},
"split_score": 1.12
}
}
  • Analiza si una entidad excede su umbral específico por tipo (Sesion=15, Proyecto=25, otras=20)
  • Usa TF-IDF para agrupar observaciones en tópicos
  • needs_split: true cuando split_score > 1.0 Y observation_count > threshold
  • NO modifica la entidad — solo analiza

Signature: propose_entity_split_tool(entity_name: str) → dict[str, Any]

ParámetroTipoRequeridoDescripción
entity_namestrNombre de la entidad a analizar y dividir
{
"proposal": {
"original_entity": {
"name": "Proyecto cachorrites",
"entity_type": "Proyecto"
},
"suggested_splits": [
{
"name": "Proyecto cachorrites - Arquitectura",
"entity_type": "Proyecto",
"observations": ["Stack: FastMCP + SQLite", "MCP Memory v2"]
},
{
"name": "Proyecto cachorrites - Implementacion",
"entity_type": "Proyecto",
"observations": ["97 tests passing", "Query routing implementado"]
}
],
"relations_to_create": [
{"from": "Proyecto cachorrites", "to": "Proyecto cachorrites - Arquitectura", "type": "contiene"},
{"from": "Proyecto cachorrites - Arquitectura", "to": "Proyecto cachorrites", "type": "parte_de"},
{"from": "Proyecto cachorrites", "to": "Proyecto cachorrites - Implementacion", "type": "contiene"},
{"from": "Proyecto cachorrites - Implementacion", "to": "Proyecto cachorrites", "type": "parte_de"}
],
"analysis": {
"observation_count": 28,
"threshold": 25,
"split_score": 1.12,
"num_topics": 3
}
}
}
  • Retorna proposal: null si la entidad no necesita splitting
  • Crea relaciones contiene (parent→child) y parte_de (child→parent)
  • Usa TF-IDF con stop words en español para extraer tópicos
  • Los nombres de entidades preservan acentos, entityType no tiene acentos

Signature: execute_entity_split_tool(entity_name: str, approved_splits: list[dict[str, Any]], parent_entity_name: str | None = None) → dict[str, Any]

ParámetroTipoRequeridoDescripción
entity_namestrNombre de la entidad original a dividir
approved_splitslist[dict]Lista de definiciones de splits aprobadas
parent_entity_namestrNoNombre opcional del parent explícito

Cada approved_split debe tener:

CampoTipoRequeridoDescripción
namestrNombre para la nueva sub-entidad
entity_typestrTipo de entidad (típicamente igual al original)
observationslist[str]Observaciones a mover a esta sub-entidad
{
"entity_name": "Proyecto cachorrites",
"approved_splits": [
{
"name": "Proyecto cachorrites - Arquitectura",
"entity_type": "Proyecto",
"observations": ["Stack: FastMCP + SQLite", "MCP Memory v2"]
}
]
}
{
"result": {
"new_entities": ["Proyecto cachorrites - Arquitectura"],
"moved_observations": 2,
"relations_created": 2,
"original_observations_remaining": 26
}
}
  • Crea nuevas entidades a partir de los splits aprobados
  • Mueve las observaciones especificadas de la entidad original a las nuevas
  • Establece relaciones contiene/parte_de
  • Usa transacción atómica (todo o nada)
  • Regenera embeddings para las nuevas entidades

Signature: find_split_candidates() → dict[str, Any]

{
"candidates": [
{
"entity_name": "Proyecto cachorrites",
"entity_type": "Proyecto",
"observation_count": 28,
"threshold": 25,
"needs_split": true,
"topics": {...},
"split_score": 1.12
},
{
"entity_name": "Sesión 2026-03-31",
"entity_type": "Sesion",
"observation_count": 18,
"threshold": 15,
"needs_split": true,
"topics": {...},
"split_score": 1.2
}
]
}
  • Escanea TODAS las entidades en el knowledge graph
  • Retorna lista vacía si no encuentra candidatas
  • NO modifica ninguna entidad — solo analiza

Encuentra observaciones que pueden estar semánticamente duplicadas dentro de una entidad. Retorna pares de observaciones con scores de similitud y tipo de match.

Requiere el modelo de embeddings — ejecuta download_model.py primero.

Signature: find_duplicate_observations(entity_name: str, threshold: float = 0.85, containment_threshold: float = 0.7) → dict[str, Any]

ParámetroTipoRequeridoDefaultDescripción
entity_namestrNombre de la entidad a revisar
thresholdfloatNo0.85Similitud coseno mínima para considerar dos observaciones como duplicadas
containment_thresholdfloatNo0.7Score de containment mínimo para pares de texto asimétricos (ratio de longitud >= 2.0)
{
"entity_name": "Mi Proyecto",
"threshold": 0.85
}
{
"entity_name": "Mi Proyecto",
"total_observations": 12,
"duplicate_pairs": [
{
"obs_text_a": "Desplegado en Vercel con dominio personalizado",
"obs_text_b": "Deployment: Vercel, dominio personalizado configurado",
"similarity_score": 0.91,
"match_type": "cosine"
},
{
"obs_text_a": "Stack: FastMCP + SQLite + ONNX Runtime para embeddings",
"obs_text_b": "FastMCP",
"similarity_score": 0.73,
"match_type": "containment"
}
]
}
  • Usa similitud combinada: similitud coseno >= threshold OR score de containment >= containment_threshold cuando un texto es 2x+ más largo que el otro (longitud asimétrica).
  • Clustering Union-Find agrupa observaciones en clusters de duplicados — cada par aparece una sola vez.
  • El campo match_type indica qué métrica de similitud disparó el match: "cosine" para similitud coseno estándar, "containment" para pares de texto asimétricos.
  • Solo lectura — no se realizan modificaciones al knowledge graph. Revisa los resultados y usa delete_observations para consolidar manualmente.
  • Requiere el modelo de embeddings. Retorna un error si el modelo no está disponible.
  • Consulta Mantenimiento & Operaciones para el workflow completo de deduplicación.

Genera un reporte de consolidación de solo lectura que analiza la salud del knowledge graph en cuatro dimensiones: candidatas a split, observaciones marcadas, entidades estancadas y entidades grandes.

Signature: consolidation_report(stale_days: float = 90.0) → dict[str, Any]

ParámetroTipoRequeridoDefaultDescripción
stale_daysfloatNo90.0Días de inactividad para considerar una entidad como estancada
{
"stale_days": 90
}
{
"summary": {
"total_entities": 47,
"total_observations": 312,
"split_candidates_count": 3,
"flagged_observations_count": 8,
"stale_entities_count": 12,
"large_entities_count": 5
},
"split_candidates": [
{
"entity_name": "Sesión 2026-03-31",
"entity_type": "Sesion",
"observation_count": 18,
"threshold": 15,
"split_score": 1.2
}
],
"flagged_observations": [
{
"entity_name": "Mi Proyecto",
"observation_text": "Desplegado en Vercel",
"similarity_flag": 1
}
],
"stale_entities": [
{
"entity_name": "Experimento Antiguo",
"entity_type": "Generic",
"last_accessed_days_ago": 145,
"access_count": 2,
"observation_count": 3
}
],
"large_entities": [
{
"entity_name": "Proyecto cachorritos",
"entity_type": "Proyecto",
"observation_count": 35
}
]
}
  • Solo lectura — genera un reporte sin modificar datos. sofia revisa el reporte y decide qué acciones tomar.
  • Verifica 4 áreas:
    1. Candidatas a split: entidades que exceden umbrales de observaciones por tipo (Sesion=15, Proyecto=25, otras=20) con diversidad temática suficiente
    2. Observaciones marcadas: observaciones con similarity_flag=1 (posibles duplicados semánticos detectados por add_observations)
    3. Entidades estancadas: entidades no accedidas en stale_days días con bajo count de acceso
    4. Entidades grandes: entidades que exceden umbrales de tamaño y pueden necesitar split
  • No requiere el modelo de embeddings para la mayoría de verificaciones (solo el análisis de candidatas a split usa TF-IDF, que está integrado).
  • Consulta Mantenimiento & Operaciones para el workflow completo de consolidación.

Expira una relación activa estableciendo active=0 y ended_at=now. Para pares inversos (contiene/parte_de), también expira la relación inversa.

Signature: end_relation(relation_id: int) → dict[str, Any]

ParámetroTipoRequeridoDescripción
relation_idintEl ID de la relación a expirar
{
"relation_id": 42
}
{
"result": "Relation 42 expired successfully"
}
  • Establece active=0 y ended_at=now en la relación especificada
  • Para pares contiene/parte_de, ambas direcciones se expiran automáticamente
  • La relación no se elimina — permanece en la base de datos con active=0 como referencia histórica
  • Si la relación ya está expirada (active=0), la operación es un no-op
  • Usa esta tool en lugar de delete_relations cuando quieras preservar el hecho histórico de que existió una relación

Añade una reflexión narrativa para dar contexto y significado a un recuerdo. Las reflexiones son prosa libre adjunta a entidades, sesiones, relaciones o de forma global, con metadatos de autor y mood.

Signature: add_reflection(target_type: str, content: str, author: str = "sofia", mood: str | None = None, target_id: int | None = None) → dict[str, Any]

ParámetroTipoRequeridoDefaultDescripción
target_typestrQué objetivo tiene esta reflexión — 'entity', 'session', 'relation' o 'global'
contentstrEl texto de la reflexión (prosa libre, sin prefijos)
authorstrNo"sofia"Quién la escribió — 'nolan' o 'sofia'
moodstr o nullNonullMood opcional — 'frustracion', 'satisfaccion', 'curiosidad', 'duda', 'insight'
target_idint o nullNonullID de la entidad/relación objetivo. Requerido para tipos entity y relation. null para session y global.
{
"target_type": "entity",
"target_id": 15,
"content": "Esta entidad representa la decisión arquitectónica central que dio forma a todo el proyecto.",
"author": "nolan",
"mood": "insight"
}
{
"result": {
"id": 5,
"target_type": "entity",
"target_id": 15,
"author": "nolan",
"content": "Esta entidad representa la decisión arquitectónica central que dio forma a todo el proyecto.",
"mood": "insight",
"created_at": "2026-04-14 22:47:23"
}
}
  • Las reflexiones se almacenan en una tabla reflections separada — independiente de las observaciones
  • Cada reflexión se indexa con FTS5 paralelo (reflection_fts) y embeddings vectoriales (reflection_embeddings) para búsqueda híbrida
  • target_type='entity' o 'relation' requiere un target_id válido. target_type='session' o 'global' usa target_id=null
  • El campo content es prosa libre — no requiere formato estructurado
  • El campo mood es opcional y usa términos en español (consistente con las convenciones del proyecto)
  • Los embeddings de reflexiones usan el mismo modelo ONNX que las entidades, almacenados en una tabla vec0 separada

Busca reflexiones por similitud semántica y filtros opcionales. Combina resultados semánticos (KNN) y de texto (FTS5) vía Reciprocal Rank Fusion — el mismo pipeline híbrido usado para la búsqueda de entidades.

Signature: search_reflections(query: str, author: str | None = None, mood: str | None = None, target_type: str | None = None, limit: int = 10) → dict[str, Any]

ParámetroTipoRequeridoDefaultDescripción
querystrTexto de búsqueda
authorstr o nullNonullFiltrar por autor ('nolan' o 'sofia')
moodstr o nullNonullFiltrar por mood
target_typestr o nullNonullFiltrar por tipo de objetivo ('entity', 'session', 'relation', 'global')
limitintNo10Máximo de resultados (default 10)
{
"query": "decisiones de arquitectura que formaron el proyecto",
"author": "nolan",
"limit": 5
}
{
"results": [
{
"id": 5,
"target_type": "entity",
"target_id": 15,
"author": "nolan",
"content": "Esta entidad representa la decisión arquitectónica central que dio forma a todo el proyecto.",
"mood": "insight",
"created_at": "2026-04-14 22:47:23",
"score": 0.8456
}
]
}
  • Usa el mismo pipeline híbrido RRF que la búsqueda de entidades: KNN (semántico) + FTS5 (texto) fusionados vía Reciprocal Rank Fusion
  • Busca solo en el índice de reflexiones — no busca observaciones de entidades
  • Todos los filtros (author, mood, target_type) son opcionales — combínalos para consultas dirigidas
  • Requiere el modelo de embeddings (igual que search_semantic)
  • Retorna un campo score que representa la similitud semántica combinada con RRF

Toda operación de escritura que cambia el contenido de una entidad dispara una actualización del embedding. La siguiente tabla resume cómo interactúa cada tool con el sistema de embeddings:

OperaciónAcción sobre EmbeddingDetalle
create_entities✅ Genera/ActualizaSnapshot completo: nombre + tipo + todas las observaciones
add_observations✅ RegeneraRegenera con todas las observaciones (antiguas + nuevas)
delete_observations✅ RegeneraRegenera sin las observaciones eliminadas
delete_entities🗑️ EliminaEliminación manual antes de CASCADE (limitación de vec0)
create_relations❌ NingunaLas relaciones no participan en la búsqueda semántica
delete_relations❌ NingunaÍdem
search_nodes❌ NingunaBúsqueda basada en LIKE, no requiere embeddings
open_nodes❌ NingunaBúsqueda directa por nombre exacto
search_semantic📖 Solo lecturaCodifica la consulta, busca por distancia coseno, re-ranke con Limbic Scoring. Registra accesos + co-ocurrencias post-respuesta.
migrate✅ BatchGenera embeddings para todas las entidades importadas al final de la migración
analyze_entity_split❌ NingunaSolo análisis, no modifica
propose_entity_split❌ NingunaRetorna propuesta, no modifica
execute_entity_split✅ RegeneraCrea nuevas entidades con embeddings frescos
find_split_candidates❌ NingunaEscanea sin modificar
find_duplicate_observations📖 Solo lecturaCodifica observaciones, calcula similitud coseno + containment por pares. Requiere modelo de embeddings.
consolidation_report❌ NingunaSolo análisis, no modifica
end_relation❌ NingunaSolo actualiza metadatos de la relación
add_reflection✅ GeneraEmbedding almacenado en tabla vec0 paralela reflection_embeddings
search_reflections📖 Solo lecturaCodifica la consulta, busca embeddings de reflexiones vía KNN + FTS5 RRF