Un sistema de archivos virtual para agentes: cómo lo hizo Mintlify

Un sistema de archivos virtual para agentes: cómo lo hizo Mintlify
46 s → 100 mspara crear una sesión, en el percentil 90
+70.000 $al año en sandbox, con sesiones de 5 minutos
0 $de cómputo extra por conversación con ChromaFs
30.000+conversaciones al día en su asistente
Tu agente no necesita un disco: el sistema de archivos virtual de Mintlify
También lo cuento en este vídeo de unos nueve minutos, en mi canal Articulator ES.

Cuando RAG se queda cortoenlace

El asistente de Mintlify funcionaba con RAG, la generación aumentada por recuperación: buscaba los trozos de texto más parecidos a la pregunta y respondía con ellos. El artículo arranca con una frase que lo resume todo: RAG funciona muy bien… hasta que deja de funcionar.

Falla en dos casos. Cuando la respuesta está repartida entre varias páginas. Y cuando el usuario necesita la sintaxis exacta de algo, y ese trozo no aparece entre los primeros resultados de la búsqueda (el famoso top-K). En los dos, el asistente se quedaba atascado.

Tres páginas con un trozo de la respuesta en cada una y una lista de resultados donde el trozo exacto queda fuera del top K: el asistente, atascado.
Los dos casos en los que RAG se atasca.

La documentación, como un repositorioenlace

Querían que el asistente se moviera por la documentación como se mueve un agente por un repositorio de código. Y los agentes ya tienen una interfaz favorita para eso: el sistema de archivos. Según el artículo, están convergiendo en él porque grep, cat, ls y find es todo lo que necesitan.

La idea es sencilla: cada página de la documentación es un archivo y cada sección, una carpeta. Así el agente busca textos exactos, lee páginas enteras y recorre la estructura por su cuenta. Solo les faltaba un sistema de archivos que reflejara, en vivo, la web de documentación.

Una web de documentación a la izquierda y su árbol de carpetas a la derecha, unidos por flechas: un sistema de archivos que refleje la web.
Cada página, un archivo; cada sección, una carpeta.

El cuello de botella del contenedorenlace

Lo obvio es darle al agente un sistema de archivos de verdad. Es lo que hacen casi todos los arneses: levantan un entorno aislado, un sandbox, y clonan dentro el repositorio. Mintlify ya lo hace con sus agentes en segundo plano, donde la latencia da igual. Pero este asistente vive en la web, con un usuario mirando cómo gira el icono de carga.

Una grúa baja un contenedor en un puerto de noche, con el rótulo sandbox, entorno aislado, y una terminal haciendo git clone.
Un sandbox por conversación: hay que levantarlo y clonar dentro el repositorio.

Crear cada sesión, con el clon de GitHub incluido, tardaba unos 46 segundos en el percentil 90. Es decir, nueve de cada diez sesiones tardaban menos, pero el resto, todavía más: casi un minuto mirando una ruedita, solo para empezar a leer documentación.

Una web con el asistente cargando y un cronómetro que marca 46 segundos con la etiqueta P90.
Crear una sesión: 46 s en el percentil 90.

Además está la factura. El artículo hace la cuenta: 850.000 conversaciones al mes, cada una con su propia micro máquina virtual. Aunque sea mínima (1 vCPU, 2 GiB de memoria y 5 minutos de vida), con los precios por segundo de Daytona (0,0504 $/h por vCPU y 0,0162 $/h por GiB) sale a unos 0,0069 $ por conversación: más de 70.000 $ al año. Con sesiones más largas, el doble: unos 0,0137 $ por conversación, la cifra de su tabla comparativa.

La cuenta: la tarifa de Daytona, 0,0069 dólares por conversación y 70.380 dólares al año, con un sello de por dos.
La cuenta del artículo, paso a paso.

Ellos mismos reconocen que es una cuenta ingenua: en producción habría máquinas precalentadas y contenedores compartidos. Pero la idea se mantiene. Para leer documentación estática, una máquina por conversación es lento y caro. Necesitaban algo instantáneo y barato, y eso obligaba a repensar el propio sistema de archivos.

Fingir una shell: ChromaFsenlace

La clave es esta: el agente no necesita un sistema de archivos de verdad, le basta con la ilusión de uno. Y Mintlify ya tenía toda su documentación troceada, indexada y guardada en Chroma, la base de datos que usa su buscador.

Un decorado de cine de noche: la fachada de un edificio iluminado, con el rótulo la ilusión de uno.
En el vídeo lo cuento con un decorado de cine: por delante, una fachada; por detrás, solo unos puntales.

Así nació ChromaFs: un sistema de archivos virtual que intercepta los comandos de Unix que escribe el agente y los traduce a consultas sobre esa misma base de datos. El agente cree que está leyendo archivos; en realidad, le está preguntando a Chroma.

La terminal del agente hace cat de una página; ChromaFs la intercepta y manda una consulta a Chroma.
El agente cree que lee archivos; en realidad, pregunta a Chroma.

El resultado: crear una sesión pasó de unos 46 segundos a unos 100 milisegundos, unas 460 veces más rápido (esta cuenta es mía). Y como reutiliza una base de datos que ya pagaban, cada conversación nueva no añade coste de cómputo. Cara a cara:

Sandbox
  • Arranque (p90): ~46 s
  • Coste: ~0,0137 $ por conversación
  • Búsqueda: recorre el disco archivo a archivo
  • Infraestructura: Daytona o similar
ChromaFs
  • Arranque (p90): ~100 ms
  • Coste: ~0 $, reutiliza la base de datos
  • Búsqueda: una consulta a los metadatos
  • Infraestructura: la base de datos que ya tenían
La tabla del artículo: arranque, coste por conversación, búsqueda e infraestructura, del sandbox frente a ChromaFs.
La tabla del artículo.

just-bash y las capasenlace

Por debajo, ChromaFs se apoya en just-bash, de Vercel Labs: una reimplementación de bash en TypeScript que entiende grep, cat, ls, find y cd. Se encarga de todo lo difícil: interpretar los comandos, las tuberías y las opciones.

Y lo mejor: deja enchufar tu propio sistema de archivos a través de una interfaz, IFileSystem. ChromaFs la implementa, y cada llamada al disco se convierte en una consulta a Chroma. Por arriba, una shell normal; por abajo, una base de datos. En el código que enseña el artículo, readFile pide a Chroma todos los trozos de la página y los une, y writeFile, appendFile, mkdir y rm lanzan un error de solo lectura.

just-bash arriba, la interfaz IFileSystem y ChromaFs enchufado debajo, conectado a la base de datos: una shell normal por arriba y una base de datos por abajo.
Por arriba, una shell normal; por abajo, una base de datos.

El diagrama del artículo lo resume en cuatro capas. Arriba, el agente escribe comandos de bash. Debajo, just-bash los interpreta. Después, ChromaFs los traduce. Y al fondo están los datos: Chroma, una caché en Redis y archivos en S3.

El diagrama de capas: agente, shell, ChromaFs con el optimizador de grep y el árbol de rutas, y la capa de datos con Redis, Chroma y S3.
El diagrama del artículo, redibujado.

El árbol de carpetasenlace

ChromaFs tiene que saber qué archivos existen antes de que el agente escriba un solo comando. Por eso guardan el árbol entero como un único documento JSON comprimido, __path_tree__, dentro de la propia colección de Chroma. Cada ruta lleva dos datos más: si es pública (isPublic) y a qué grupos pertenece (groups).

Al arrancar, el servidor lo descarga, lo descomprime y monta dos estructuras en memoria: un conjunto (Set<string>) con la ruta de cada archivo y un mapa (Map<string, string[]>) que dice qué hijos tiene cada carpeta. A partir de ahí, ls, cd y find se resuelven en la memoria local, sin tocar la red. Y como el árbol queda en caché, las siguientes sesiones del mismo sitio ni siquiera tienen que pedírselo a Chroma.

El árbol descargado de Chroma se convierte en dos estructuras en memoria: un conjunto con cada ruta y un mapa de carpeta a hijos.
Un conjunto con las rutas y un mapa con los hijos de cada carpeta.

Control de accesoenlace

Antes de construir el árbol, ChromaFs poda las rutas según el token de sesión del usuario, y aplica el mismo filtro a todas las consultas que vengan después. Si no tienes acceso a un archivo, ese archivo no existe: desaparece del árbol, y el agente no puede leerlo ni tampoco mencionarlo, porque para él esa ruta nunca ha estado ahí.

El árbol de carpetas sin las rutas restringidas y una terminal donde cat de una página interna devuelve No such file or directory.
Si no tienes acceso, no existe.

En un sandbox de verdad, esto obligaría a gestionar grupos de usuarios de Linux, permisos con chmod o una imagen de contenedor distinta para cada tipo de cliente. En ChromaFs son unas pocas líneas de filtro antes de construir el árbol.

Páginas en trozos, caché y solo lecturaenlace

Las páginas están guardadas en Chroma en trozos, porque así se indexan para la búsqueda. Cuando el agente hace cat de una página, ChromaFs trae todos sus fragmentos, los ordena por su número (chunk_index) y los une. Además guarda el resultado en caché, así que varios grep seguidos sobre las mismas páginas nunca van dos veces a la base de datos.

Los fragmentos de una página salen de Chroma desordenados, se ordenan y se unen en la página entera.
Trae los fragmentos, los ordena y los une.

No todo tiene que estar en Chroma. Algunos clientes tienen especificaciones OpenAPI enormes guardadas en su propio S3. Para ellas hay punteros perezosos: el agente ve v2.json al listar /api-specs/, pero el contenido solo se descarga cuando hace cat.

El archivo v2.json en el árbol, con un enlace punteado al S3 del cliente: se descarga solo al hacer cat.
Un puntero perezoso a S3.

Y una última regla: cualquier escritura devuelve EROFS, el error de sistema de archivos de solo lectura. El agente explora con total libertad, pero nunca puede cambiar la documentación. Así todo funciona sin estado: no hay que limpiar nada al cerrar la sesión, y ningún agente estropea lo que ve otro.

Una terminal donde echo, rm y mkdir devuelven EROFS, junto a un escudo con el rótulo solo lectura.
Leer y buscar, sí; escribir, no.

Optimizar grepenlace

cat y ls son fáciles de virtualizar. El difícil es grep: un grep -r que leyera todos los archivos uno a uno, por la red, sería lentísimo. Así que lo interceptan: leen sus opciones con un analizador de argumentos (yargs-parser) y las convierten en una consulta de Chroma, $contains para un texto exacto o $regex para un patrón. Después trabaja en dos pasadas:

  1. Filtro grueso. Chroma señala qué archivos podrían contener lo que se busca.
  2. Precarga. Los fragmentos de esos archivos se descargan a la vez (bulkPrefetch) a una caché de Redis.
  3. Filtro fino. Reescriben el grep para que mire solo esos archivos y se lo devuelven a just-bash, que lo ejecuta en memoria.
Chroma deja caer los archivos en un embudo, salen tres, y sus fragmentos van a la vez a una caché de Redis.
Filtro grueso y precarga.

El resultado son búsquedas recursivas enormes que terminan en milisegundos.

Unas manos baten oro en una batea, con el rótulo filtro fino, en memoria.
El filtro fino, como el oro que queda en la batea.

En resumenenlace

Hoy ChromaFs mueve el asistente de documentación de cientos de miles de usuarios, en más de 30.000 conversaciones al día. Al cambiar los sandbox por un sistema de archivos virtual sobre su base de datos de siempre, Mintlify consiguió tres cosas: sesiones instantáneas, coste marginal de cómputo cero y control de acceso por roles de serie, sin montar infraestructura nueva.

Tres insignias: sesiones instantáneas, coste marginal cero y control de acceso por roles, y debajo, sin infraestructura nueva.
Lo que ganaron.
En una frase

El agente no necesita un disco de verdad: le basta con la ilusión de uno.

¿Qué más convertirías en carpetas para que lo explore un agente?

Fuentesenlace

Seguir leyendo

Últimos posts -->

¿Has visto estos proyectos?

Gymnasia

Gymnasia Gymnasia
Expo
React Native
TypeScript
OpenAI
Anthropic

App de fitness con dos agentes que se ejecutan íntegramente en el dispositivo, sin backend, de forma que los datos del usuario nunca salen del móvil. Un coach conversacional BYOK con tools locales y system prompt remoto con fallback offline, y un estimador de comidas que saca los macronutrientes de una foto del plato, con lectura de códigos de barras contra OpenFoodFacts.

LangGraph Deep Researcher

LangGraph Deep Researcher LangGraph Deep Researcher
Python
LangGraph
FastAPI
React
TypeScript
Docker

Sistema multiagente de investigación construido con LangGraph. Un supervisor descompone tu pregunta en temas y lanza subagentes de búsqueda en paralelo; cada uno comprime sus hallazgos antes de pasarlos a un agente redactor que escribe el informe final en markdown con sus fuentes. Streaming en vivo por WebSockets, modelo configurable por rol y claves de API propias que nunca se guardan en el servidor.

Tau

Tau Tau
Python
LangChain

Sistema multiagente de tutoría para estudiantes de secundaria, con un agente por asignatura y material de curso elaborado y validado por un equipo de profesores. Llegó a usarse con alumnos reales en un colegio privado en España y en un instituto en Colombia.

Ver todos los proyectos -->
>_ Disponible para proyectos

¿Tienes un proyecto con IA?

Hablemos.

maximofn@gmail.com

Especialista en Machine Learning e Inteligencia Artificial. Desarrollo soluciones con IA generativa, agentes inteligentes y modelos personalizados.

¿Quieres ver alguna charla?

Últimas charlas -->

¿Quieres mejorar con estos tips?

Últimos tips -->

Usa esto en local

Los espacios de Hugging Face nos permite ejecutar modelos con demos muy sencillas, pero ¿qué pasa si la demo se rompe? O si el usuario la elimina? Por ello he creado contenedores docker con algunos espacios interesantes, para poder usarlos de manera local, pase lo que pase. De hecho, es posible que si pinchas en alún botón de ver proyecto te lleve a un espacio que no funciona.

Flow edit

Flow edit Flow edit

Edita imágenes con este modelo de Flow. Basándose en SD3 o FLUX puedes editar cualquier imagen y generar nuevas

FLUX.1-RealismLora

FLUX.1-RealismLora FLUX.1-RealismLora
Ver todos los contenedores -->
>_ Disponible para proyectos

¿Tienes un proyecto con IA?

Hablemos.

maximofn@gmail.com

Especialista en Machine Learning e Inteligencia Artificial. Desarrollo soluciones con IA generativa, agentes inteligentes y modelos personalizados.

¿Quieres entrenar tu modelo con estos datasets?

short-jokes-dataset

HuggingFace

Dataset de chistes en inglés

Uso: Fine-tuning de modelos de generación de texto humorístico

231K filas 2 columnas 45 MB
Ver en HuggingFace →

opus100

HuggingFace

Dataset con traducciones de inglés a español

Uso: Entrenamiento de modelos de traducción inglés-español

1M filas 2 columnas 210 MB
Ver en HuggingFace →

netflix_titles

HuggingFace

Dataset con películas y series de Netflix

Uso: Análisis de catálogo de Netflix y sistemas de recomendación

8.8K filas 12 columnas 3.5 MB
Ver en HuggingFace →
Ver más datasets -->