Memoria, recursos y skills organizados como un filesystem bajo el protocolo viking://
Los agentes de IA se olvidan. OpenViking (30K+ estrellas, trending de GitHub) resuelve la gestión de contexto convirtiéndolo en un sistema de archivos virtual: tu agente explora su propia memoria con ls, tree y find en vez de consultar un vector store de caja negra. Aprende a instalar el servidor, alimentar recursos, crear skills, usar las capas L0/L1/L2 para recortar tokens, convertir sesiones en memoria a largo plazo e integrarlo con Claude Code, Codex, MCP y LangChain.
Cuando construyes agentes de IA te topas con cinco dolores constantes:
| Problema | Qué significa |
|---|---|
| Fragmentación | Memoria en código, recursos en vectordb, skills dispersas. Imposible gestionar de forma unificada. |
| Explosión de contexto | Tareas largas generan contexto en cada ejecución; truncar o comprimir pierde información. |
| RAG pobre | El RAG tradicional usa almacenamiento plano, sin visión global del contexto. |
| Opacidad | El pipeline de recuperación es una caja negra imposible de depurar. |
| Memoria sin iterar | Los sistemas de memoria solo guardan preferencias del usuario, no experiencia de tareas del agente. |
OpenViking ataca exactamente estos puntos con un cambio de paradigma: en lugar de una base de datos plana, todo el contexto se organiza como un sistema de archivos virtual con URIs deterministas (viking://), capas de resumen L0/L1/L2 y recuperación por directorios que deja una trayectoria auditable.
No necesitas migrar tu stack de golpe. OpenViking funciona como servicio HTTP independiente y se conecta a tus agentes existentes por plugins o MCP.
OpenViking es una base de datos de contexto: unifica memoria, recursos y skills bajo un mismo árbol viking://.
viking://
├── resources/ # Recursos: docs de proyecto, repos, webs
│ └── my_project/
├── user/
│ └── {user_id}/ # Contexto privado del usuario
│ ├── memories/ # Memorias del usuario
│ ├── resources/ # Recursos privados
│ ├── skills/ # Skills privadas
│ └── peers/
└── agent/
└── skills/ # Skills compartidas de la cuenta
La arquitectura interna separa la lógica en módulos claros:
| Módulo | Responsabilidad |
|---|---|
| Client | Entrada unificada; delega en la capa de servicio. |
| Service | Lógica de negocio: FSService, SearchService, SessionService, ResourceService… |
| Retrieve | Análisis de intención, recuperación jerárquica y rerank. |
| Session | Mensajes, uso de contexto, compresión y commit de memoria. |
| Parse | Parseo de documentos (PDF/MD/HTML), construcción de árbol y generación semántica L0/L1/L2. |
| Compressor | Extracción de memoria con esquemas y deduplicación por LLM. |
| Storage | Almacenamiento dual: AGFS (contenido) + índice vectorial. |
El flujo de escritura es Input → Parser → TreeBuilder → AGFS → SemanticQueue → Vector Index. El flujo de lectura es Query → Intent Analysis → Hierarchical Retrieval → Rerank → Results.
No pienses en OpenViking como "otro vector store". El índice vectorial solo guarda referencias; el contenido vive en AGFS. La recuperación empieza por directorios, no por fragmentos sueltos.
Requisitos: Python 3.10+. Puedes instalarlo como paquete Python o levantarlo con Docker.
pip install openviking --upgrade
# o con uv (recomendado)
uv tool install openviking --upgrade
Tras instalar, tienes dos comandos: ov (cliente) y openviking-server (servidor).
mkdir -p ~/.openviking && touch ~/.openviking/ov.conf
# docker-compose.yml
services:
openviking:
image: ghcr.io/volcengine/openviking:latest
ports:
- "1933:1933"
volumes:
- ~/.openviking:/app/.openviking
restart: unless-stopped
openviking-server init te guía por proveedores, modelos y escribe ~/.openviking/ov.conf. Soporta Volcengine, OpenAI, Codex OAuth, Kimi, GLM y Ollama local.
openviking-server doctor comprueba el config, la versión de Python, la conectividad de los proveedores y el espacio en disco.
openviking-server escucha por defecto en 127.0.0.1:1933. En otro terminal ya puedes usar ov.
Necesitas dos capacidades de modelo: un VLM (para entender imágenes y contenido) y un embedding (para vectorización). El config mínimo es:
{
"embedding": {
"dense": {
"provider": "volcengine",
"model": "doubao-embedding-vision-251215",
"api_base": "https://ark.cn-beijing.volces.com/api/v3",
"api_key": "<tu-ark-api-key>",
"dimension": 1024,
"input": "multimodal"
}
},
"vlm": {
"provider": "volcengine",
"model": "doubao-seed-2-0-code-preview-260215",
"api_base": "https://ark.cn-beijing.volces.com/api/v3",
"api_key": "<tu-ark-api-key>",
"temperature": 0
},
"storage": { "workspace": "./data" },
"server": { "host": "127.0.0.1", "port": 1933 }
}
Para probar sin APIs de pago, Ollama local puede servir tanto el embedding como el VLM. El asistente init detecta e instala el runtime si es necesario.
Con el servidor corriendo, la CLI ov te da control total del contexto:
$ ov status # servidor conectado, health OK $ ov add-resource https://github.com/volcengine/OpenViking --wait $ ov ls viking://resources/ $ ov tree viking://resources/volcengine -L 2 $ ov find "what is openviking" $ ov grep "openviking" --uri viking://resources/volcengine/OpenViking/docs/en
El árbol de comandos cubre todo el ciclo de vida:
| Grupo | Comandos |
|---|---|
| Escritura | add-resource, add-skill, write, mkdir, rm, mv, add-memory |
| Lectura | ls, tree, stat, read, abstract, overview, find, search, grep, glob |
| Skills | skills add/list/find/show/update/remove/validate |
| Sesiones | session new/list/get/delete/commit/add-message(s) |
| Import/export | export, backup, import, restore, snapshot |
| Observabilidad | health, status, observer, task status/watch |
add-resource acepta URLs, ficheros locales, directorios, repos Git, sitemaps y RSS. El parámetro --wait espera a que termine el procesamiento semántico antes de devolver el control.
Prueba ov tui para un explorador de archivos a pantalla completa con previsualización de imágenes y vista vectorial.
OpenViking abstrae todo el contexto en tres tipos básicos:
| Tipo | Propósito | Ciclo de vida | Iniciativa |
|---|---|---|---|
| Resource | Conocimiento y reglas (docs, repos, FAQs) | Largo plazo, estático | El usuario lo añade |
| Memory | Cognición del agente (preferencias, experiencia) | Largo plazo, se actualiza | El agente lo registra |
| Skill | Capacidades invocables (herramientas, MCP) | Largo plazo, estático | Usuario o sistema |
Las memorias tienen tipos integrados que se escriben en el namespace del usuario:
| Tipo | Ubicación | Descripción |
|---|---|---|
profile | memories/profile.md | Información básica del usuario |
preferences | memories/preferences/ | Preferencias por tema |
entities | memories/entities/ | Personas, proyectos, organizaciones |
events | memories/events/ | Decisiones e hitos |
identity | memories/identity.md | Nombre, persona y temperamento del asistente |
soul | memories/soul.md | Principios, límites y estilo |
cases / trajectories / experiences | memories/cases|trajectories|experiences/ | Aprendizaje de tareas y experiencia reutilizable |
Una skill se guarda como directorio con su SKILL.md:
viking://user/skills/search-web/
├── .abstract.md # L0: descripción corta
├── .overview.md # L1: resumen del directorio
├── SKILL.md # L2: definición de la skill
└── scripts # L2: implementación
No confundas el tipo Skill con las memorias skills/ deshabilitadas. Las skills vivas viven en viking://user/skills/{name}/SKILL.md y son independientes de la extracción de memoria.
Meter todo el contexto en el prompt es caro y ruidoso. OpenViking procesa cada directorio en tres niveles:
| Nivel | Nombre | Límite por defecto | Propósito |
|---|---|---|---|
| L0 | Abstract | 256 caracteres | Búsqueda vectorial y filtrado rápido |
| L1 | Overview | 4000 caracteres | Rerank y navegación de contenido |
| L2 | Detail | Sin límite | Contenido completo, carga bajo demanda |
viking://resources/docs/auth/
├── .abstract.md # L0: "Guía de autenticación: OAuth 2.0, JWT y API keys"
├── .overview.md # L1: estructura y puntos clave del directorio
├── oauth.md # L2: contenido completo
├── jwt.md # L2: contenido completo
└── api-keys.md # L2: contenido completo
L0 y L1 son sidecars de directorio (no por archivo). El generador semántico procesa de abajo arriba: resúmenes de archivos → L1 hoja → L0 hoja → directorios padre. El ls normal los oculta, pero los accessors los leen:
ov abstract viking://resources/docs/auth
ov overview viking://resources/docs/auth
ov read viking://resources/docs/auth/oauth.md
La estrategia recomendada: para comprobar relevancia usa L0; para entender el alcance de un directorio, L1; y solo cuando haga falta, carga L2. Así construyes el contexto inicial del LLM con L1 y profundizas bajo demanda.
Los benchmarks de OpenViking muestran caídas de tokens de entrada del 34–91% frente a la memoria nativa de los agentes, manteniendo precisión de memoria del 80%+.
OpenViking usa recuperación en dos fases: análisis de intención + recuperación jerárquica + rerank. Tiene dos APIs principales:
| Feature | find() | search() |
|---|---|---|
| Contexto de sesión | No necesario | Requerido |
| Análisis de intención | No | Sí (LLM) |
| Consultas generadas | Una | 0–5 TypedQueries |
| Latencia | Baja | Mayor |
| Caso de uso | Consultas simples | Tareas complejas |
El análisis de intención convierte la consulta en TypedQueries tipadas por contexto:
# Skill: verbo primero → "Crear documento RFC", "Extraer tablas de PDF"
# Resource: sintagma nominal → "Plantilla de documento RFC"
# Memory: "preferencias de X del usuario" → "Preferencias de estilo de código del usuario"
La recuperación jerárquica funciona con una cola de prioridad: primero localiza los directorios con mayor score, luego desciende recursivamente propagando el score del padre (parámetro score_propagation_alpha), y converge cuando el top-k no cambia en 3 rondas.
# find(): consulta simple
ov find "OAuth authentication" --uri viking://resources/
# search(): tarea compleja con contexto de sesión
ov search "Ayúdame a crear un documento RFC" --session-id chat_001
El rerank se activa en modo THINKING (por defecto en search()) cuando hay credenciales configuradas; si falla, cae a los scores vectoriales. La gran ventaja: cada consulta conserva su trayectoria de navegación, así que cuando un resultado es raro puedes ver exactamente qué camino lo produjo.
0 consultas generadas no es un fallo: para chitchat o saludos que no necesitan recuperación, el planificador devuelve vacío a propósito.
El ciclo de vida de una sesión es Create → Interact → Commit. Al hacer commit, OpenViking comprime, archiva y extrae memoria a largo plazo en segundo plano.
from openviking_sdk import SyncHTTPClient, TextPart, ContextPart
client = SyncHTTPClient(url="http://localhost:1933")
client.initialize()
session = client.session(session_id="chat_001")
session.add_message("user", [TextPart("Prefiero el modo oscuro")])
session.add_message("assistant", [
TextPart("Entendido, lo recordaré."),
ContextPart(uri="viking://user/memories/profile.md"),
])
session.used(contexts=["viking://user/memories/profile.md"])
result = session.commit() # devuelve task_id, archiva al momento
task = client.get_task(result["task_id"]) # poll hasta "completed"
El commit tiene dos fases:
Incrementa el índice de compresión, escribe los mensajes en messages.jsonl del archivo y devuelve el task_id.
Genera el resumen estructurado (L0/L1), extrae memorias a largo plazo, escribe memory_diff.json (auditoría de cambios) y marca .done.
El flujo de extracción de memoria es: Mensajes → LLM Extract → Candidatos → Pre-filtro vectorial → Decisión de deduplicación → Write AGFS + vectorizar. La deduplicación decide entre skip, create, merge o delete de memorias existentes, así que no se acumulan duplicados.
Cada commit genera un memory_diff.json con adds/updates/deletes. Úsalo como auditoría y para hacer rollback de cambios de memoria si un commit extrajo algo incorrecto.
OpenViking se conecta a casi cualquier agente. La vía más universal es su endpoint MCP integrado (/mcp), compatible con Cursor, Trae, Claude Desktop, ChatGPT y más:
{
"mcpServers": {
"openviking": {
"url": "https://tu-servidor.com/mcp",
"headers": { "Authorization": "Bearer tu-api-key" }
}
}
}
Para Claude Code, el plugin de memoria inyecta recuerdo automático en cada prompt y hace commit de la sesión antes de la compactación:
bash <(curl -fsSL https://raw.githubusercontent.com/volcengine/OpenViking/main/examples/memory-plugin-shared/install.sh)
El plugin conecta además el /mcp de OpenViking, exponiendo herramientas como find, search, read y remember. Con LangChain/LangGraph, usa el paquete independiente:
pip install langchain-openviking # adaptadores LangChain
pip install "langchain-openviking[langgraph]" # middleware LangGraph
from langchain_openviking import create_openviking_tools, OpenVikingRetriever, with_openviking_context
# Herramientas explícitas para el agente
tools = create_openviking_tools(url="http://localhost:1933", profile="agent")
# viking_find, viking_search, viking_browse, viking_read, viking_grep, viking_store...
# Retriever RAG
retriever = OpenVikingRetriever(url="http://localhost:1933")
docs = retriever.invoke("¿Qué decidió el usuario sobre el despliegue?")
# Backend de contexto con ciclo de vida completo
with with_openviking_context(runnable, url="http://localhost:1933") as chain:
result = chain.invoke({"messages": [...]})
Otras integraciones nativas: Hermes Agent (hermes memory setup openviking), Codex (plugin de memoria con hooks), OpenClaw, Cursor, OpenCode y TRAE.
Si usas Hermes, no instales OpenViking dentro del entorno de Hermes con --force-reinstall: las versiones de dependencias pueden chocar. Corre el servidor en su propio venv o contenedor y conéctate por HTTP.
VikingBot es un framework de agente construido sobre OpenViking. Con un comando tienes un agente que chatea con memoria persistente:
pip install "openviking[bot]"
openviking-server --with-bot
# en otro terminal
ov chat
La imagen Docker oficial incluye VikingBot y arranca el servidor + consola por defecto (desactívalo con command: ["--without-bot"] si no lo necesitas).
Corre openviking-server como proceso standalone; los clientes se conectan por HTTP en cualquier lenguaje.
Modo dev para local, api_key para producción, trusted si un gateway inyecta identidad. Define root_api_key y activa cifrado AES con encryption.enabled si es necesario.
ov observer queue, ov observer vikingdb y ov observer models te dan colas, colecciones vectoriales y salud de modelos.
Formato .ovpack para export/import y backup/restore, más snapshot para versionado del workspace.
La edición open-source no está limitada: AGPLv3 sin feature gates, sin cuenta y sin claves de activación. Los benchmarks oficiales (LoCoMo y tau2-bench) muestran que con OpenViking la precisión de memoria de agentes como OpenClaw, Hermes o Claude Code sube de 24–57% a 80–83%, con menos tokens.
Antes de ir a producción, revisa server.workers, los límites de semantic.abstract_max_chars/overview_max_chars y el backend de vectordb (local, cuvs, vikingdb…). Cambiar modelo o dimensión de embedding puede exigir reindexar.
No exactamente: lo envuelve. OpenViking usa un índice vectorial internamente (local, cuvs, vikingdb…), pero añade la capa de filesystem, las capas L0/L1/L2 y la recuperación por directorios que un vector store plano no tiene.
No. Los modelos se configuran por proveedor: OpenAI, Kimi, GLM, Ollama local o cualquier servicio compatible con la API de OpenAI.
Sí, toda la funcionalidad está en la CLI ov y en el SDK Python (openviking_sdk). La UI Web Studio en /studio es opcional.
El proyecto principal es AGPLv3; la CLI (ov_cli) y los ejemplos son Apache 2.0. La edición open-source no tiene gates de funcionalidad.