# API del RAG **Proyecto:** Workspace de tools IA para empresas **Modulo:** RAG **Ultima actualizacion:** 2026-09-11 **Ultima modificacion por:** Subagente Implementacion ciclo de vida del conocimiento **Estado:** Punto 2 desplegado; pendiente de preparar PostgreSQL, migrar el corpus y validar en produccion Esta guia explica como descubrir y consumir la API. El contrato tecnico completo y canonico se publica en OpenAPI 3.1.1; este documento prioriza el camino rapido, las decisiones de uso y los ejemplos habituales. ## Acceso rapido Base URL de produccion: ```text https://rag.por-correo.com ``` | Recurso | URL | Uso | |---|---|---| | Ayuda resumida | `GET /help` | Descubrimiento rapido para personas y agentes | | Contrato OpenAPI | `GET /openapi.json` | Esquemas, parametros, respuestas y errores | | Playground | `GET /playground` | Pruebas manuales desde navegador | `GET /help` indica expresamente que debe consultarse `/openapi.json` para obtener los parametros, cuerpos, respuestas, errores y ejemplos completos de cada endpoint. La API general sigue sin autenticacion completa. Las operaciones administrativas del ciclo de vida usan una proteccion acotada con `Authorization: Bearer `; esto no sustituye la autenticacion general pendiente. ## Elegir la operacion correcta | Necesidad | Endpoint recomendado | |---|---| | Comprobar servicio y capacidades | `GET /health` | | Ver scopes ingeridos | `GET /sources` | | Ver versiones de una fuente | `GET /sources/{sourceId}/versions` | | Activar, rollback o purgar versiones | `/sources/*` con token administrativo | | Recuperar contexto para otro agente | `POST /retrieve` | | Obtener una respuesta final con citas | `POST /answer` | | Comparar una respuesta sin RAG | `POST /answer/direct` | | Conversar con bootstrap e historial | `POST /chat` | | Ingerir una ruta accesible por el servidor | `POST /ingest` | | Subir un archivo o carpeta ZIP | `POST /ingest/upload` | | Eliminar una fuente antes de reingestar | `POST /cleanup` legacy, o purga de version no activa | | Consultar o actualizar evaluaciones | `/logs/*` | ## Catalogo completo La API queda formada por las operaciones de descubrimiento, ingesta, retrieval, evaluacion y ciclo de vida: | Metodo | Ruta | Descripcion | |---|---|---| | `GET` | `/help` | Catalogo resumido derivado de OpenAPI | | `GET` | `/openapi.json` | Contrato OpenAPI 3.1.1 | | `GET` | `/playground` | Interfaz web de prueba | | `GET` | `/health` | Estado, proveedores, parsers y chunking | | `GET` | `/sources` | Scopes disponibles en Qdrant | | `GET` | `/sources/{sourceId}` | Fuente registrada en el catalogo | | `GET` | `/sources/{sourceId}/versions` | Versiones de una fuente | | `GET` | `/sources/{sourceId}/versions/{versionId}` | Detalle de una version | | `POST` | `/sources/{sourceId}/versions/{versionId}/activate` | Activacion administrativa con precondicion | | `POST` | `/sources/{sourceId}/rollback` | Rollback administrativo sin recalcular embeddings | | `POST` | `/sources/{sourceId}/versions/{versionId}/retry` | Reintento explicito de version fallida o huerfana con fuente durable | | `DELETE` | `/sources/{sourceId}/versions/{versionId}` | Purga administrativa de una version no activa | | `GET` | `/models/answer` | Modelo por defecto y modelos seleccionables | | `POST` | `/ingest` | Ingesta desde una ruta del servidor | | `POST` | `/ingest/upload` | Upload `multipart/form-data` | | `POST` | `/cleanup` | Borrado controlado por scope | | `POST` | `/retrieve` | Recuperacion de contexto | | `POST` | `/answer` | Respuesta apoyada en retrieval | | `POST` | `/answer/direct` | Respuesta del modelo sin retrieval | | `POST` | `/chat` | Conversacion con contexto opcional | | `GET` | `/logs/recent` | Logs recientes de evaluacion | | `POST` | `/logs/manual` | Registro manual de una evaluacion | | `PATCH` | `/logs/{id}` | Seguimiento y resolucion de un log | ## Contratos comunes ### Scope Permite limitar una consulta o una operacion a fuentes concretas: ```json { "sourceId": "customer-a:manual:v1", "sourceRef": "customer-a-errors.md", "tags": ["customer-a", "support"] } ``` Todos los campos son opcionales en consultas. Para `POST /cleanup` es obligatorio enviar al menos `sourceId` o `sourceRef`; las etiquetas solas no autorizan un borrado. ### Modos e intents | Campo | Valores | Default | |---|---|---| | `mode` en retrieval y answer | `documental`, `codigo`, `auto` | `auto` | | `mode` en chat | `documental`, `codigo`, `auto` | `documental` | | `intent` | `specific`, `bootstrap` | `specific` | | `mode` en ingesta | `mechanical`, `interactive` | `mechanical` | ### Errores Los errores JSON siguen esta forma: ```json { "ok": false, "error": "Description of the error" } ``` Actualmente la mayoria de fallos de validacion o de proveedores se devuelven como `500`. `POST /cleanup` y `POST /ingest/upload` tambien pueden devolver `400`, y `PATCH /logs/{id}` devuelve `404` si no encuentra el log. Mejorar la validacion queda fuera de este bloque para no cambiar silenciosamente el comportamiento existente. Con `KNOWLEDGE_LIFECYCLE_ENFORCED=true`, la API devuelve errores mas especificos para el catalogo: | Codigo HTTP | Caso | |---|---| | `400` | Falta `expectedActiveVersionId` cuando `activate=true` | | `409` | Cambio concurrente de version activa, version en curso o intento de purgar una activa | | `422` | Fuente vacia, sin documentos soportados o sin contenido util | | `503` | PostgreSQL, Qdrant, embeddings o version activa inconsistente | ## Recuperar contexto `POST /retrieve` es la operacion recomendada cuando otro agente o flujo generara la respuesta final. ```bash curl -sS -X POST "https://rag.por-correo.com/retrieve" \ -H "Content-Type: application/json" \ -d '{ "mode": "documental", "intent": "specific", "query": "What does error FAT07 mean?", "scope": { "sourceId": "customer-a:manual:v1" }, "useModelInRetrieve": false }' ``` Campos principales: | Campo | Requerido | Funcion | |---|---|---| | `query` | Si | Consulta de recuperacion | | `mode` | No | Tipo de conocimiento | | `intent` | No | Consulta concreta o mapa bootstrap | | `scope` | No | Limita las fuentes | | `useModelInRetrieve` | No | Añade `modelSummary` generado por un modelo | | `model` | No | Override usado solo para `modelSummary` | | `bootstrapMeta` | No | Trazabilidad del bootstrap en logs | Respuesta resumida: ```json { "mode": "documental", "intent": "specific", "summary": "Retrieved 5 relevant chunks.", "topics": ["support-errors.md"], "criticalPoints": [], "items": [ { "chunkId": "chk:example", "documentId": "doc:example", "sourceId": "customer-a:manual:v1", "title": "support-errors.md", "content": "...", "score": 0.87 } ], "followUpRefs": ["doc:example"], "scope": { "sourceId": "customer-a:manual:v1" } } ``` ## Obtener una respuesta `POST /answer` ejecuta retrieval y genera una respuesta final con citas. ```json { "mode": "documental", "intent": "specific", "query": "Explain the documented resolution for FAT07", "scope": { "sourceId": "customer-a:manual:v1" }, "model": "openai/gpt-4.1-mini" } ``` Tambien acepta `preloadedContext` y `bootstrapMeta`. La respuesta incluye `model`, `answer`, resumen del retrieval, temas, puntos criticos, citas y scope. `POST /answer/direct` no consulta el vector store: ```json { "query": "Explain what a RAG service is", "model": "openai/gpt-4.1-mini", "preloadedContext": "Optional context supplied by the caller" } ``` Su respuesta real solo contiene: ```json { "model": "openai/gpt-4.1-mini", "answer": "..." } ``` ## Chat con bootstrap `POST /chat` reutiliza contexto precargado, historial reciente y, opcionalmente, una nueva consulta al RAG: ```json { "message": "What should I check next?", "history": [ { "role": "user", "content": "Give me an initial map of this project" }, { "role": "assistant", "content": "The project contains..." } ], "mode": "documental", "preloadedContext": "Previously loaded bootstrap", "allowAdditionalRetrieve": true, "scope": { "sourceId": "project-docs" } } ``` Respuesta: ```json { "model": "openai/gpt-4.1-mini", "answer": "...", "usedBootstrapContext": true, "usedAdditionalRetrieve": true, "retrieved": { "summary": "...", "items": [] } } ``` ## Ingesta ### Ruta del servidor `POST /ingest` requiere `sourceType` y `sourceRef`: ```json { "sourceId": "project-docs", "sourceType": "folder", "sourceRef": "/data/project-docs", "mode": "mechanical", "tags": ["project", "documentation"], "activate": true, "expectedActiveVersionId": null } ``` `readPath` es un campo interno para separar la ruta fisica de lectura de la referencia logica. Los consumidores normales no deben enviarlo. Con ciclo de vida activo: - `activate` por defecto es `true`. - si `activate=true`, `expectedActiveVersionId` es obligatorio: `null` para primera activacion y UUID para reemplazar una version existente. - una ingesta identica a la version activa responde `noOp: true` y no escribe nuevos puntos. - `activate=false` deja la version en `ready` para activarla despues con una operacion administrativa. - la respuesta exitosa cambia a `201 Created` e incluye `sourceId`, `versionId`, `versionNumber`, `state`, `previousVersionId`, `activated` y `noOp`. ### Upload `POST /ingest/upload` usa `multipart/form-data`: | Campo | Requerido | Formato | |---|---|---| | `file` | Si | Archivo binario o ZIP | | `sourceId` | No | Identificador logico | | `mode` | No | `mechanical` o `interactive` | | `tags` | No | Lista separada por comas | | `isZipFolder` | No | Texto `true` o `false` | | `activate` | No | Texto `true` o `false` | | `expectedActiveVersionId` | Si activa | UUID o texto `null` | ```bash curl -sS -X POST "https://rag.por-correo.com/ingest/upload" \ -F "file=@./support-errors.md" \ -F "sourceId=customer-a:manual:v1" \ -F "mode=mechanical" \ -F "tags=customer-a,support" ``` Con enforcement desactivado, ambas variantes conservan `202`. Con enforcement activado, responden `201` y usan el catalogo PostgreSQL como autoridad de version activa. El upload añade `uploadedResource`. ## Ciclo de vida de fuentes El catalogo PostgreSQL es la autoridad para saber que fuentes existen, que versiones tienen y cual es la version activa. Qdrant conserva los puntos fisicos versionados, pero retrieval solo consulta versiones activas resueltas desde PostgreSQL. ### Listado y detalle ```text GET /sources GET /sources/{sourceId} GET /sources/{sourceId}/versions GET /sources/{sourceId}/versions/{versionId} ``` `GET /sources` mantiene los campos usados por el playground (`sourceId`, `sourceRef`, `chunkModes`, `tags`) y añade `activeVersionId`, `activeVersionNumber`, `state`, `needsReingest` y `updatedAt`. ### Activacion y rollback ```bash curl -sS -X POST "https://rag.por-correo.com/sources/src:default:folder:docs/versions//activate" \ -H "Authorization: Bearer $LIFECYCLE_ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"expectedActiveVersionId":""}' ``` Rollback usa la misma activacion atomica del puntero PostgreSQL: ```json { "targetVersionId": "uuid-version-anterior", "expectedActiveVersionId": "uuid-version-activa-actual" } ``` ### Purga `DELETE /sources/{sourceId}/versions/{versionId}` exige token administrativo y solo acepta versiones no activas. La purga marca la version como `purging`, borra puntos Qdrant con `wait=true`, verifica que no quedan puntos y finalmente deja la version como `purged`. ### Reintento explicito `POST /sources/{sourceId}/versions/{versionId}/retry` acepta versiones `failed`, `pending` o `indexing`. Si recibe una fuente durable (`sourceType`, `sourceRef` y opcionalmente `readPath`) cierra versiones huerfanas como fallidas y crea una version nueva mediante `/ingest`. Si no recibe fuente durable, devuelve `202` con instrucciones: los uploads temporales no se reintentan en sitio porque el original ya no esta garantizado. ## Limpieza controlada `POST /cleanup` elimina los chunks que coinciden con un scope solo en modo legacy y con `INGEST_WRITES_ENABLED=true`: ```json { "scope": { "sourceId": "customer-a:manual:v1" } } ``` Respuesta: ```json { "ok": true, "deleted": 36 } ``` Esta operacion es destructiva. Verifica primero el scope con `GET /sources`. ## Evaluacion `GET /logs/recent?limit=20` devuelve los logs recientes. Si no se indica `limit`, usa 20. `POST /logs/manual` registra una observacion humana: ```json { "operation": "retrieve", "reason": "manual_review_requested", "query": "What does error FAT07 mean?", "mode": "documental", "intent": "specific", "scope": { "sourceId": "customer-a:manual:v1" }, "note": "The first result is too generic" } ``` `PATCH /logs/{id}` actualiza su seguimiento: ```json { "reviewStatus": "resolved", "severity": "high", "reviewedBy": "maintainer", "resolutionNote": "Retrieval ranking adjusted and validated.", "fixReference": "commit-or-ticket-reference" } ``` Valores admitidos: | Campo | Valores | |---|---| | `reviewStatus` | `pending`, `in_progress`, `resolved`, `ignored` | | `severity` | `low`, `medium`, `high` | ## Integracion recomendada con n8n Para una `HTTP Request Tool` conectada a un AI Agent: 1. Usa `POST /retrieve`. 2. Fija `mode`, `intent` y `scope` en el nodo. 3. Permite que el agente complete solo `query`. 4. Mantiene `useModelInRetrieve=false` para evitar procesar la consulta con dos modelos. 5. Entrega `items[].content` y sus metadatos al agente final. Usa `POST /answer` solamente cuando el propio RAG deba generar la respuesta final. ## Fuente de verdad y mantenimiento - `GET /openapi.json` es el contrato publico para integraciones y herramientas. - `GET /help` es el indice rapido derivado del mismo contrato. - Este documento explica flujos y decisiones de uso. - `src/app.ts` contiene la implementacion efectiva. - Cualquier cambio de endpoint debe actualizar OpenAPI y esta guia en el mismo bloque de trabajo.