Configura las fuentes de sincronización¶
Las fuentes de sincronización traen documentos de servicios externos (Google Drive, S3/MinIO, un sitio web público, un repositorio Git, un sitio de SharePoint o un OneDrive) a las colecciones de conocimiento por su cuenta. Cada fuente guarda un tipo de connector, una colección de destino, opciones propias del connector, un modo de sincronización, un horario opcional y el id del secreto del vault que la autentica - un sitio web no necesita ninguno.
Cuando se ejecuta una sincronización, el connector lista los archivos remotos,
los descarga a un directorio temporal y los pasa por la cadena de ingesta
habitual (parsear, trocear, embeber, almacenar). Cuando el listado está completo,
se eliminan los documentos que la fuente trajo antes y ya no lista. Una entrada
de SyncLog deja constancia del resultado de cada operación de sincronización.
La arquitectura de un vistazo¶
| Componente | Ubicación | Función |
|---|---|---|
BaseSyncConnector |
app/services/rag/connectors/__init__.py |
Base abstracta de todos los connectores |
RemoteFile |
app/services/rag/connectors/__init__.py |
Modelo de Pydantic que describe un archivo remoto |
CONNECTOR_REGISTRY |
app/services/rag/connectors/__init__.py |
Asocia las cadenas de tipo de connector con sus clases |
SyncSource (modelo de BD) |
app/db/models/sync_source.py |
Persiste la configuración de las fuentes |
SyncLog (modelo de BD) |
app/db/models/sync_log.py |
Registra cada operación de sincronización |
SyncSourceService |
app/services/sync_source.py |
Lógica de negocio del CRUD y del disparo manual |
| Comandos CLI de RAG | app/commands/rag.py |
Interfaz de línea de comandos para gestionar fuentes |
| Rutas de la API de RAG | app/api/routes/v1/rag.py |
API REST para gestionar fuentes |
Inicio rápido -- CLI¶
Listar los tipos de connector disponibles¶
# Shows all registered connectors (e.g. gdrive, s3, git, sharepoint)
uv run agenticos cmd rag-sources
Añadir una fuente de Google Drive -- sincronización cada 2 horas¶
uv run agenticos cmd rag-source-add \
--name "Legal docs" \
--type gdrive \
--org 0c8f2b1e-... \
--collection legal \
--config '{"folder_id": "1abc123def", "include_subfolders": true}' \
--sync-mode new_only \
--schedule 120
Añadir una fuente de S3 -- solo sincronización manual¶
uv run agenticos cmd rag-source-add \
--name "Marketing" \
--type s3 \
--org 0c8f2b1e-... \
--collection marketing \
--config '{"bucket": "my-docs", "prefix": "marketing/"}' \
--sync-mode full \
--schedule 0
Añadir una fuente de Git -- la documentación de un repositorio, cada noche¶
uv run agenticos cmd rag-source-add \
--name "Handbook" \
--type git \
--org 0c8f2b1e-... \
--collection handbook \
--config '{"repository_url": "https://github.com/acme/handbook.git", "branch": "main", "path_prefix": "docs"}' \
--sync-mode new_only \
--schedule 1440
Después elige su token de acceso como credencial de la fuente en la interfaz, o
envía secret_id con un PATCH — consulta
Configurar un repositorio Git.
Añadir una fuente de SharePoint -- una carpeta de una biblioteca, cada 6 horas¶
uv run agenticos cmd rag-source-add \
--name "HR policies" \
--type sharepoint \
--org 0c8f2b1e-... \
--collection hr \
--secret-id <vault-secret-id> \
--config '{"site_url": "https://contoso.sharepoint.com/sites/HR", "folder_path": "Policies"}' \
--sync-mode new_only \
--schedule 360
--secret-id es la app de Microsoft Entra en el vault de la organización —
consulta Configurar SharePoint y OneDrive.
Lanzar una sincronización a mano¶
# Sync a single source by ID
uv run agenticos cmd rag-source-sync <source-id>
# Sync all active sources
uv run agenticos cmd rag-source-sync --all
Eliminar una fuente¶
El <source-id> es un UUID que se imprime al crear la fuente y que aparece en
el listado de rag-sources.
Inicio rápido -- interfaz¶
- Ve a Knowledge Base y abre la pestaña Sync.
- Pulsa "+ Add Source".
- Elige un tipo de connector (Google Drive, S3, Website, Git
repository, SharePoint & OneDrive). Los campos del
formulario se generan a partir del JSON Schema del
CONFIG_MODELdel connector. Un sitio web no tiene paso de credencial. - Rellena los campos de configuración propios del connector (por ejemplo, el ID de la carpeta o el nombre del bucket).
- Elige una colección de destino, un modo de sincronización y un intervalo de ejecución.
- Pulsa "Create Source".
- Usa el botón "Sync Now" para lanzar una sincronización inmediata, o espera a que el horario la dispare por sí solo.
Para cambiar una fuente más adelante, pulsa el lápiz de su fila. Se abre el mismo asistente con los valores de la fuente ya rellenados. El connector no se puede cambiar, y "Save Changes" envía solo los campos que hayas cambiado. La fuente sigue en la base de conocimiento en la que está.
La interfaz llama a la misma API REST que se documenta más abajo, así que todo
lo que puedes hacer desde ella lo puedes hacer también con curl o con
cualquier cliente HTTP.
Modos de sincronización¶
| Modo | Comportamiento |
|---|---|
full |
Sincroniza todo de nuevo. Todos los archivos se (re)ingestan y los documentos existentes se reemplazan. |
new_only |
Añade los archivos nuevos y actualiza los que han cambiado. Usa un hash SHA-256 para detectar cambios: los archivos sin cambios se omiten. |
update_only |
Solo actualiza archivos que ya están en la colección. Los archivos nuevos se omiten. Usa un hash SHA-256 para omitir los archivos sin cambios. |
new_only para casi todos los flujos
Añade los archivos nuevos y actualiza los modificados mientras omite los que
no han cambiado, que es la sincronización incremental más rápida.
update_only refresca los documentos existentes sin añadir ninguno nuevo;
full es una reimportación limpia cada vez.
Qué elimina una sincronización¶
En todos los modos, una sincronización elimina los documentos que su fuente trajo
antes y ya no lista: una página retirada del sitio, un archivo borrado de la
carpeta de Drive, un objeto quitado del bucket. El registro de sincronización los
cuenta en removed.
No elimina nada salvo que el listado estuviera completo. Un crawl que se detuvo en su límite de páginas, o que no pudo leer una de ellas, no ha visto lo que no lista. Ese run conserva todos los documentos y lo indica en el mensaje del registro de sincronización. La siguiente sincronización con un listado completo elimina lo que ya no está. Un documento que no se pudo eliminar cuenta como un archivo fallido, y la siguiente sincronización lo vuelve a intentar.
Cada fuente ejecuta una sola sincronización a la vez. Una sincronización iniciada mientras otra de la misma fuente sigue en marcha no arranca, y su registro lo indica.
Solo se eliminan los documentos de la propia fuente. Una subida, o un documento que otra fuente trajo a la misma colección, no se toca nunca. Cuando dos fuentes de una colección listan el mismo documento, este se conserva hasta que ambas dejan de listarlo. Un documento ingestado antes de que su fuente registrara esto (septiembre de 2026) se conserva hasta que una sincronización de la fuente vuelva a listarlo.
Qué hace una segunda sincronización¶
Una sincronización posterior a la primera hace tan poco como la fuente le permite:
- Un archivo sin cambios cuesta una descarga, no un embedding. Su SHA-256
coincide con el del documento almacenado, así que se cuenta como
skippedy no se vuelve a parsear ni a embeber. - Una fuente sin cambios cuesta una petición. Un connector capaz de decir en
qué punto está todo su contenido —el commit de cabeza de una rama de Git, el
feed de cambios de una biblioteca de SharePoint— lo registra después de cada ejecución que termina sin ningún fallo. La siguiente
ejecución
new_onlyoupdate_onlyque encuentra el mismo valor, con la misma configuración, se detiene antes de listar nada: su registro no muestra ningún archivo procesado, y no elimina nada. Cambiar la configuración, la colección o el modo hace que la siguiente ejecución lo vuelva a leer todo, yfullnunca se detiene antes. - Un archivo que una sincronización interrumpida dejó a medias se corrige. Un worker detenido después de guardar los vectores de un archivo y antes de registrarlos los deja sin ninguna fila que los siga. La siguiente sincronización de esa fuente borra lo que nada sigue y vuelve a ingerir el archivo; mientras un archivo así espera, no se detiene antes.
Una ejecución con un archivo fallido no registra ningún estado, así que la siguiente lee la fuente entera y vuelve a intentarlo.
Horario¶
El campo schedule_minutes controla con qué frecuencia se sincroniza la fuente
por sí sola:
| Valor | Significado |
|---|---|
0 (o null) |
Solo manual -- se lanza desde la CLI o la interfaz |
30 |
Cada 30 minutos |
120 |
Cada 2 horas |
1440 |
Una vez al día |
Un horario necesita el worker
La programación dispatch-due-syncs despierta cada 60 segundos y encola una
sincronización por cada fuente que toque, así que schedule_minutes no hace
nada sin el contenedor worker que arranca make dev. Sin él, un disparo
manual (CLI, API o la interfaz) también encola su sincronización, que
igualmente espera a un worker. Una fuente nunca tiene dos sincronizaciones a
la vez.
Configurar Google Drive¶
1. Crea una cuenta de servicio¶
- Entra en la Google Cloud Console.
- Crea un proyecto nuevo (o selecciona uno existente).
- Activa la Google Drive API.
- Ve a IAM & Admin > Service Accounts y crea una cuenta de servicio nueva.
- Crea una clave JSON para la cuenta de servicio y descárgala.
2. Comparte tu carpeta de Drive¶
- Abre Google Drive y ve a la carpeta que quieres sincronizar.
- Pulsa Share y añade la dirección de correo de la cuenta de servicio
(tiene la forma
name@project.iam.gserviceaccount.com). - Concédele al menos acceso Viewer.
3. Dale la clave a la fuente¶
Pega el contenido del archivo de clave JSON en el campo Service Account JSON
de la fuente. Una fuente gdrive funciona con la credencial que lleva su propia
configuración y con nada más: no hay un valor de respaldo para todo el
despliegue, porque uno así dejaría que el folder_id de una fuente decidiera qué
se lista bajo la cuenta de servicio del operador.
GOOGLE_DRIVE_CREDENTIALS_FILE en .env sirve únicamente para el comando de
CLI rag-sync-gdrive.
4. Averigua el ID de la carpeta¶
El ID de la carpeta es el último segmento de la URL de la carpeta de Google Drive:
5. Campos de configuración del connector de Google Drive¶
| Campo | Tipo | Obligatorio | Valor por defecto | Descripción |
|---|---|---|---|---|
folder_id |
string | Sí | -- | El ID de la carpeta de Google Drive, tomado de la URL |
include_subfolders |
boolean | No | true |
Incluir de forma recursiva los archivos de las subcarpetas |
La cuenta de servicio en sí no es un campo de configuración. Guárdala en el
vault como credencial de tipo gcp_service_account y apunta la fuente hacia ella
con secret_id: así se almacena una sola vez y la referencia cada fuente que la
necesite, en lugar de pegarla en cada una
(#937). Enviarla bajo
config se rechaza.
Un folder_id solo puede contener lo que Google emite: letras, dígitos, - y
_. Cualquier otra cosa se rechaza al crear la fuente, porque el id se
interpola en la consulta de Drive y una comilla simple dentro de él amplía lo
que esa consulta lista.
Los archivos de Google Docs, Sheets y Slides se exportan por sí solos a formatos portables (PDF, XLSX, PPTX) durante la descarga. Un archivo cuyo nombre en Drive contiene separadores de ruta se escribe como un único archivo dentro del directorio de sincronización, nunca en la ruta que deletrea su nombre.
Configurar S3 / MinIO¶
1. Configura el entorno¶
Añade estas variables a tu .env:
S3_RAG_ENDPOINT=https://s3.amazonaws.com # or your MinIO URL, e.g. http://localhost:9000
S3_RAG_ACCESS_KEY=your-access-key
S3_RAG_SECRET_KEY=your-secret-key
S3_RAG_REGION=us-east-1 # required for AWS, optional for MinIO
En MinIO, el endpoint suele ser http://minio:9000 (Docker) o
http://localhost:9000 (local).
2. Campos de configuración del connector de S3¶
| Campo | Tipo | Obligatorio | Valor por defecto | Descripción |
|---|---|---|---|---|
bucket |
string | Sí | -- | Nombre del bucket de S3 |
prefix |
string | No | "" |
Prefijo de clave que acota el alcance de la sincronización (por ejemplo, documents/legal/). Déjalo vacío para el bucket entero. |
Configurar un sitio web¶
Una fuente web lee un sitio web público, normalmente el sitio de documentación
de un producto. No necesita credencial ni entrada en el vault. Dale una URL de
inicio y, o bien sigue los enlaces desde esa página, o bien lee las páginas que
lista un sitemap.
uv run agenticos cmd rag-source-add \
--name "Product docs" \
--type web \
--org 0c8f2b1e-... \
--collection product-docs \
--config '{"root_url": "https://docs.example.com/guide/", "max_depth": 3}' \
--sync-mode new_only \
--schedule 1440
Campos de configuración del connector de sitio web¶
| Campo | Tipo | Obligatorio | Valor por defecto | Descripción |
|---|---|---|---|---|
root_url |
string | Sí | -- | La página desde la que empieza el crawl. Su host es el único host que lee la fuente. |
max_depth |
integer | No | 2 |
A cuántos enlaces de distancia de la URL de inicio seguir, de 0 a 10. 0 lee solo la página de inicio. |
path_prefix |
string | No | la carpeta de la URL de inicio | Solo se leen las páginas cuya ruta empieza por esto. https://docs.example.com/guide/intro lee /guide/ por defecto; pon / para el host entero. |
sitemap_url |
string | No | -- | Lee las páginas que lista este sitemap en lugar de seguir enlaces. Tiene que estar en el host de la URL de inicio y usar https:// cuando la URL de inicio lo usa. Un índice de sitemaps se sigue hasta sus sitemaps. |
max_pages |
integer | No | 500 |
El crawl se detiene tras leer este número de páginas, de 1 a 5000. |
Qué acota un crawl¶
- Un host y una ruta. Los enlaces a otros hosts, y a rutas fuera de
path_prefix, no se siguen. Una redirección que salga de ellos tampoco se sigue. Una URL de inicio enhttps://nunca se abandona porhttp://: no se sigue un enlace ni una redirección a una página sin cifrar. - La red del deployment queda fuera de alcance. Cada petición - robots.txt, el sitemap, cada página y cada redirección - se comprueba contra la misma política SSRF que los webhooks y los servidores MCP. Se envía a la dirección que pasó la comprobación. Una URL de inicio que resuelve a una dirección privada, de loopback, link-local o de metadatos de la nube se rechaza al guardar la fuente.
- Se respeta robots.txt para sitemaps y páginas, incluido
Crawl-delayde hasta diez segundos. El crawler se identifica comoAgenticOS-Crawler. Espera al menos medio segundo entre peticiones, y se respeta una página que diganoindexonofollow. Una página que un sitemap sigue listando después de decirnoindex, o de desaparecer, se elimina de la colección. - Tamaño y tiempo. Una página de más de 5 MB no se lee. El crawl se detiene en
max_pages. Una sincronización deja de leer el sitio al cabo de seis horas, y una sincronización que se detuvo no elimina nada.
Cada página se guarda como un documento Markdown que contiene su texto y la URL de la que procede, sin su query string. La navegación, las cabeceras, los pies de página y los scripts se dejan fuera. Una página solo se vuelve a embeber cuando cambia su texto. Un nuevo sello de build o un script de seguimiento en el marcado no cuentan como cambio.
Quién puede leer lo que importa¶
Una fuente de sitio web no tiene credencial, así que su alcance es lo que el sitio muestra a cualquiera en internet. Nunca pasa de un login. Todo lo que importa lo puede buscar cualquiera que pueda buscar en la colección que alimenta, como con cualquier otra fuente. Consulta quién acaba pudiendo leer lo que ingirió una fuente.
Solo se importan páginas HTML. Un PDF u otro archivo enlazado desde una página no se descarga.
Configurar un repositorio Git¶
Una fuente git lee la documentación de un repositorio por HTTPS: GitHub, GitLab
o cualquier otro host que sirva git por HTTPS. Necesita la URL de clonado y un
token de acceso, no la API de ninguna de las dos plataformas.
1. Emite un token para ese único repositorio¶
El alcance del token es el alcance de la fuente. Todo lo que la fuente ingiere pasa a poder buscarlo cualquiera que pueda leer la colección, así que un token capaz de leer todos los repositorios privados que puede leer su dueño es un token capaz de publicarlos todos para ese público. Consulta quién acaba pudiendo leer lo que ingirió una fuente.
- GitHub: un personal access token de tipo fine-grained, con Only select repositories, ese único repositorio y Contents: Read-only como único permiso.
- GitLab: un project access token en ese único proyecto, con el rol
Reporter y solo el scope
read_repository.
Ponle una fecha de caducidad. Cuando caduque, la siguiente sincronización de la fuente falla con the repository refused the source's token, y la solución es un token nuevo en el mismo secreto del vault.
2. Añádelo al vault¶
Añade el token al vault como Git access token, con el host al que
pertenece: github.com, gitlab.com o tu propio servidor, como
git.example.com:8443. Un host con letras que no son ASCII se escribe en su forma
codificada, por ejemplo xn--bcher-kva.example para bücher.example. Después
elige el token en el paso de credencial de la fuente. Se
envía en una cabecera HTTP Authorization, nunca en la URL ni en una línea de
comandos que otro proceso pueda leer.
El host es del token, no de la fuente. Quien edita una fuente elige la URL de su repositorio, y un token solo se envía al host con el que se añadió. Así que editar una fuente no puede dirigir el token de la organización a otro servidor, y ningún otro tipo de clave, como la API key de un provider de modelos, puede elegirse para una fuente de Git.
3. Campos de configuración del connector de Git¶
| Campo | Tipo | Obligatorio | Valor por defecto | Descripción |
|---|---|---|---|---|
repository_url |
string | Sí | -- | La URL de clonado HTTPS, por ejemplo https://github.com/acme/handbook.git. Sin nombre de usuario ni token. |
branch |
string | No | main |
La rama que se lee. |
path_prefix |
string | No | -- | Un directorio dentro del repositorio, por ejemplo docs. Déjalo vacío para el repositorio entero. |
include |
lista de strings | No | **/*.md, **/*.txt |
Qué archivos se ingieren, como patrones al estilo de .gitignore relativos a path_prefix. |
El valor por defecto es la documentación, no el árbol entero: el código fuente de
un repositorio no es un corpus, e ingerirlo llena la base de conocimiento de
código que nadie ha pedido buscar. Añade un patrón como **/*.pdf para otro
formato que lea el parser de la colección. Un patrón no puede empezar por !.
Cada archivo es un documento cuya dirección es
git://<host>/<owner>/<repo>@<branch>/<path>, con :<port> tras el host cuando
el puerto no es 443. La rama forma parte de la dirección, así que dos fuentes que leen dos ramas de un mismo repositorio en una
misma colección mantienen documentos separados.
4. Qué transfiere una sincronización¶
La primera petición de cada sincronización es git ls-remote para la rama: más o
menos un kilobyte. Si el commit de cabeza no se ha movido desde la última
ejecución limpia, la sincronización se detiene ahí. Si se ha movido, el connector
hace un clonado superficial, parcial y disperso (shallow, partial, sparse): un
solo commit, y solo los archivos que casan con los patrones de inclusión. Por eso
la documentación de un monorepo cuesta lo que su documentación, no lo que su
árbol de código.
Antes de que el clonado escriba nada en el disco del worker, el connector mide
cada archivo que escribiría. Un archivo que supera el límite de documento de la
base de conocimiento (MAX_UPLOAD_SIZE_MB, 50 MB por defecto), o más de 512 MB
de archivos en total, se rechaza, y no se escribe nada.
Los enlaces simbólicos y los submódulos no se siguen, y un enlace no se ingiere como documento.
Reglas de red¶
La URL tiene que ser https://. Su host se resuelve una sola vez y se comprueba
como cualquier otra dirección que elige un inquilino: un host que resuelve a una
dirección privada, de loopback o link-local se rechaza al guardar la fuente y de
nuevo al sincronizar, y git solo se conecta a las direcciones que esa
comprobación aprobó. Las redirecciones no se siguen. Un deployment detrás de un
proxy de salida (HTTPS_PROXY) lo sigue usando; en ese caso el proxy resuelve el
host por su cuenta.
La imagen del worker incluye git. Un worker construido a partir de otra imagen
necesita git 2.37 o posterior en su PATH.
Configurar SharePoint y OneDrive¶
Una fuente sharepoint lee una biblioteca de documentos a través de Microsoft
Graph: la biblioteca de un sitio de SharePoint, o el OneDrive de una persona, que
Microsoft 365 guarda como un sitio propio. Puede leer la biblioteca entera o una
carpeta dentro de ella. Inicia sesión como un registro de aplicación de Microsoft
Entra que un administrador de tu tenant crea una sola vez.
1. Registra una app en Microsoft Entra¶
En el Microsoft Entra admin center, abre App registrations → New registration. Dale un nombre como AgenticOS sync, deja Accounts in this organizational directory only y deja vacío el redirect URI. La fuente inicia sesión como la propia app, no como una persona.
En la Overview de la app, anota el Application (client) ID y el Directory (tenant) ID. En Certificates & secrets, añade un client secret y copia su Value. El valor se muestra una sola vez. El ID del secreto no es lo que necesita la fuente.
2. Concédele un sitio, no el tenant¶
El alcance de la app es el alcance de la fuente. Todo lo que la fuente ingiere pasa a poder buscarlo cualquiera que pueda leer la colección que alimenta. Consulta quién acaba pudiendo leer lo que ingirió una fuente.
En API permissions, añade el permiso de aplicación de Microsoft Graph
Sites.Selected y concede el consentimiento de administrador para él. Por sí
solo, Sites.Selected no lee nada. Después, un administrador concede a la app
acceso de lectura al único sitio que lee la fuente:
POST https://graph.microsoft.com/v1.0/sites/{site-id}/permissions
Content-Type: application/json
{
"roles": ["read"],
"grantedToIdentities": [
{"application": {"id": "<client-id>", "displayName": "AgenticOS sync"}}
]
}
Esa llamada necesita Sites.FullControl.All, así que un administrador la hace
desde Graph Explorer o con Grant-PnPAzureADAppSitePermission de PnP PowerShell,
y no con la propia app.
GET https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/HR?$select=id
devuelve el id del sitio. Un OneDrive se concede de la misma forma, a través de su
sitio: contoso-my.sharepoint.com:/personal/jane_contoso_com.
Files.Read.All o Sites.Read.All hacen legibles todas las bibliotecas del tenant
Esos permisos se consienten para todo el tenant. Una fuente que los tiene
sigue leyendo solo la biblioteca que nombra. Pero quien puede editar la
fuente puede apuntar su URL de sitio a cualquier sitio u OneDrive de la
organización, y la siguiente sincronización hace que esa biblioteca pueda
buscarla cualquiera que pueda leer la colección. Nada en este producto puede
saber qué permiso se dio a la app, porque un token no lo dice. Usa
Sites.Selected y concede una app por cada público.
3. Añádela al vault¶
Añade la app al vault como Microsoft Entra app: el id del tenant (o el
dominio del tenant, como contoso.onmicrosoft.com), el client id y el valor del
client secret. Después elígela en el paso de credencial de la fuente. El secreto
solo se envía a login.microsoftonline.com, para iniciar sesión.
Un client secret caduca, como mucho a los dos años. Cuando ha caducado, la siguiente sincronización falla con Microsoft Entra refused the app registration's credentials (invalid_client). Añade un secreto nuevo a la app y sustituye el valor en el mismo secreto del vault. Todas las fuentes que lo usan recogen el valor nuevo en su siguiente sincronización.
4. Campos de configuración del connector de SharePoint¶
| Campo | Tipo | Obligatorio | Valor por defecto | Descripción |
|---|---|---|---|---|
site_url |
string | Sí | -- | El sitio, por ejemplo https://contoso.sharepoint.com/sites/HR, o un OneDrive, por ejemplo https://contoso-my.sharepoint.com/personal/jane_contoso_com. Solo el sitio: una URL de biblioteca o de página copiada del navegador se rechaza. |
library |
string | No | la biblioteca por defecto del sitio | El nombre de la biblioteca tal como lo muestra SharePoint, por ejemplo Documents. Un OneDrive solo tiene su biblioteca por defecto. |
folder_path |
string | No | -- | Una carpeta dentro de la biblioteca, por ejemplo Policies/HR. Déjalo vacío para la biblioteca entera. |
include_subfolders |
boolean | No | true |
Si se leen las carpetas que hay bajo folder_path. |
extensions |
lista de strings | No | .pdf, .docx, .md, .txt |
Qué tipos de archivo se ingieren. Añade .pptx, .xlsx u otro tipo solo si el parser de la colección lo lee: un archivo que el parser no puede leer cuenta como archivo fallido en cada sincronización. |
Cada archivo es un documento cuya dirección es sharepoint://<drive-id>/<item-id>.
La dirección sigue al archivo, no a su ruta, así que un archivo que se renombra o
se mueve dentro de la biblioteca conserva su documento. El documento conserva el
nombre de archivo con el que se ingirió hasta que cambia el contenido del archivo.
Los blocs de notas de OneNote y los archivos de otros tipos no se ingieren.
5. Qué transfiere una sincronización¶
Cada sincronización empieza por el feed de cambios de Microsoft Graph para la biblioteca. Cuando nada en la biblioteca ha cambiado desde la última ejecución limpia, la sincronización se detiene ahí: una petición y ningún listado. El feed cubre la biblioteca entera, porque Graph solo lo ofrece para la raíz de una biblioteca. Por eso un cambio en otra carpeta de la misma biblioteca hace que la siguiente sincronización vuelva a listar la carpeta de la fuente.
Cuando algo ha cambiado, la sincronización lista la carpeta y descarga todos los
archivos de los tipos configurados. Un archivo cuyo contenido no ha cambiado se
omite entonces antes de embeberlo, así que solo los archivos nuevos y modificados
cuestan un embedding. Un archivo se descarga desde la dirección que Graph da para
él, sin el token de la app. Un archivo que supera el límite de documento de la
base de conocimiento (MAX_UPLOAD_SIZE_MB, 50 MB por defecto) no se descarga y
cuenta como archivo fallido.
Graph frena a un cliente que lee deprisa. Una petición que Graph limita (HTTP
429) o que falla con un 5xx o un error de red se intenta cuatro veces en total, y
la sincronización espera lo que pida el Retry-After de Graph, hasta un minuto.
Una carpeta que aun así no se puede listar se nombra en el registro de
sincronización, y esa sincronización no elimina nada, porque no se vieron los
archivos de esa carpeta. Los archivos de las demás carpetas se ingieren igualmente.
Un archivo borrado después del listado y antes de su descarga se elimina como un archivo que el listado no nombró.
Red¶
El worker necesita HTTPS de salida hacia login.microsoftonline.com,
graph.microsoft.com y los hosts *.sharepoint.com de tu tenant. Nada de lo que
escribe quien edita una fuente se convierte en una dirección a la que se conecte
el worker: la URL del sitio es solo un nombre que Graph busca. Las nubes
nacionales de Microsoft, como US Government y China, usan otros hosts y no están
soportadas.
Referencia de la API¶
Todos los endpoints de las fuentes de sincronización viven bajo
/api/v1/rag/sync/. Listar exige collections:view y todo lo que modifica una
fuente exige collections:edit, en ambos casos sobre la colección a la que
pertenece la fuente: no interviene ningún rol de administrador. Consulta
quién puede llegar a una colección.
CRUD de fuentes de sincronización¶
| Método | Endpoint | Descripción |
|---|---|---|
GET |
/api/v1/rag/sync/sources |
Lista todas las fuentes de sincronización configuradas |
POST |
/api/v1/rag/sync/sources |
Crea una fuente de sincronización nueva |
PATCH |
/api/v1/rag/sync/sources/{id} |
Modifica una fuente de sincronización existente |
DELETE |
/api/v1/rag/sync/sources/{id} |
Borra una fuente de sincronización |
POST |
/api/v1/rag/sync/sources/{id}/trigger |
Lanza una sincronización a mano |
Connectores y registros¶
| Método | Endpoint | Descripción |
|---|---|---|
GET |
/api/v1/rag/sync/connectors |
Lista los tipos de connector disponibles con sus esquemas de configuración |
GET |
/api/v1/rag/sync/logs |
Lista el historial de sincronizaciones (se puede filtrar por collection_name) |
Ejemplo: crear una fuente con la API¶
curl -X POST http://localhost:8000/api/v1/rag/sync/sources \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Legal Drive",
"connector_type": "gdrive",
"collection_name": "legal",
"config": {
"folder_id": "1abc123def",
"include_subfolders": true
},
"sync_mode": "new_only",
"schedule_minutes": 120
}'
Ejemplo: lanzar una sincronización con la API¶
curl -X POST http://localhost:8000/api/v1/rag/sync/sources/{source_id}/trigger \
-H "Authorization: Bearer $TOKEN"
Ejemplo: consultar el historial de sincronizaciones¶
Ejemplo: descubrir los connectores disponibles¶
La respuesta incluye el config_schema de cada connector, que el frontend usa
para renderizar formularios dinámicos. También resulta útil para construir
integraciones de forma programática.
Modificar una fuente¶
Puedes actualizar cualquier subconjunto de campos de una fuente existente con
PATCH:
curl -X PATCH http://localhost:8000/api/v1/rag/sync/sources/{source_id} \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sync_mode": "full",
"schedule_minutes": 60,
"is_active": false
}'
Campos modificables: name, config, sync_mode, schedule_minutes,
is_active, collection_name.
Pon is_active en false para pausar una fuente sin borrarla.
Supervisar las sincronizaciones¶
Cada sincronización crea una entrada de SyncLog con estos campos:
| Campo | Descripción |
|---|---|
source |
El tipo de connector, o "local" para la ingesta desde la CLI |
collection_name |
La colección de destino |
status |
running, done o error |
mode |
full, new_only o update_only |
total_files |
Número de archivos encontrados |
ingested |
Ingestados correctamente (nuevos) |
updated |
Reingestados correctamente (reemplazados) |
skipped |
Omitidos (ya presentes o sin cambios) |
failed |
No se pudieron ingestar, incluidas las páginas o archivos que el listado no pudo leer y los documentos que no se pudieron eliminar |
removed |
Eliminados porque la fuente ya no los lista (consulta qué elimina una sincronización) |
error_message |
Qué salió mal, o por qué no se eliminó nada. Un run puede estar en done y aun así tener un mensaje, por ejemplo cuando un crawl se detuvo en su límite de páginas |
started_at |
Cuándo empezó la sincronización |
completed_at |
Cuándo terminó la sincronización |
Consulta los registros desde la salida de la CLI o desde la API:
curl http://localhost:8000/api/v1/rag/sync/logs?collection_name=legal&limit=5 \
-H "Authorization: Bearer $TOKEN"
Añadir connectores propios¶
Para añadir un tipo de connector nuevo (por ejemplo, Notion, Confluence o Dropbox), consulta Añade un connector de sincronización.
La versión corta:
- Crea una clase que herede de
BaseSyncConnectorenapp/services/rag/connectors/. - Implementa
list_files(),_fetch()y, opcionalmente,validate_config(). - Declara
SECRET_KIND—qué tipo de secreto del vault lo autentica— y unCONFIG_MODEL, un modelo de Pydantic que dice cómo encontrar los documentos. La credencial nunca es uno de sus campos. - Regístralo en
CONNECTOR_REGISTRY, enapp/services/rag/connectors/__init__.py.
Una vez registrado, el connector aparece por sí solo en la CLI, en la API y en la interfaz.
Resolución de problemas¶
"No sync sources configured"¶
Todavía no has creado ninguna fuente. Crea una con rag-source-add (CLI) o con
POST /api/v1/rag/sync/sources (API).
"Unknown connector type"¶
El tipo de connector que has indicado no está en CONNECTOR_REGISTRY. Consulta
los tipos disponibles con rag-sources o con
GET /api/v1/rag/sync/connectors.
Google Drive (gdrive) está disponible.
S3 (s3) está disponible.
Website (web) está disponible.
Git (git) está disponible.
Google Drive: "this source has no credential"¶
El secret_id de la fuente está vacío, o el secreto del vault que nombraba ha
sido borrado. Guarda el JSON de la cuenta de servicio en el vault y elígelo en el
paso de credencial de la fuente: GOOGLE_DRIVE_CREDENTIALS_FILE no lo sustituye,
y solo el comando de CLI rag-sync-gdrive lee ese ajuste.
"A Google Drive source needs a service account credential"¶
El secret_id nombra una credencial del tipo equivocado: un par de claves de
AWS, por ejemplo. Una fuente de Drive toma un gcp_service_account y una fuente
de S3 un par aws_credentials; el asistente solo ofrece las que corresponden,
así que a esto se llega a través de la API.
Google Drive: "folder ID may contain only letters, digits, '-' and '_'"¶
El valor no es un id de carpeta de Drive. Tómalo de la URL de la carpeta: es el último segmento, y nada más de esa URL pertenece al campo.
Google Drive: "Cannot access folder"¶
Asegúrate de haber compartido la carpeta con el correo de la cuenta de servicio. La cuenta de servicio necesita al menos acceso Viewer.
S3: "Cannot access bucket"¶
Comprueba que S3_RAG_ACCESS_KEY, S3_RAG_SECRET_KEY y S3_RAG_ENDPOINT están
bien puestos en el .env. En MinIO, asegúrate de que el endpoint incluye el
puerto (por ejemplo, http://localhost:9000).
Sitio web: "resolves to private/internal address"¶
La URL de inicio, o el sitemap, apunta dentro de la red del deployment, o su nombre resuelve ahí. Una fuente de sitio web solo lee direcciones públicas. Para indexar un sitio interno, publica sus páginas en algún lugar público o sube los archivos directamente.
Sitio web: "The site's robots.txt could not be read, so it was not crawled"¶
/robots.txt en el host de la URL de inicio agotó el tiempo de espera o
respondió con un error del servidor (5xx) tres veces seguidas. El crawler no
adivina qué permitiría un robots.txt inaccesible, así que el run se detiene. Un
robots.txt que falta (404) o que está prohibido (403) significa que no hay
reglas, y el crawl sigue adelante.
Sitio web: "The start URL … did not lead to an HTML page"¶
La URL de inicio respondió 404, redirigió a otro host o fuera de path_prefix,
o sirvió algo que no es HTML. Ábrela en un navegador y usa como root_url la
dirección en la que acaba.
Sitio web: "robots.txt does not allow the start URL"¶
El sitio pide a los crawlers que no entren en esa ruta. Elige una URL de inicio
que el sitio permita, o pide al propietario del sitio que permita
AgenticOS-Crawler.
Sitio web: "… answered HTTP 403" o "… could not be reached"¶
La página necesita un login, o el sitio rechazó al crawler. Falló tras tres intentos si la respuesta fue un timeout, un 429 o un 5xx. Cada página así cuenta como un archivo fallido. En ese run no se elimina nada, porque no se vieron las páginas que había detrás.
"The source could not be listed completely, so documents it may no longer hold were kept"¶
El listado se quedó corto: un crawl alcanzó max_pages, algunas páginas no se
pudieron leer, o una carpeta de SharePoint no se pudo listar. Lo que se encontró
se ingestó, y no se eliminó nada. Para un sitio web, sube max_pages, o acota el
crawl con path_prefix, hasta que un run termine sin este mensaje. Para
SharePoint, consulta más abajo la entrada de esa carpeta.
Git: "The repository refused the source's token"¶
El token ha caducado, se ha revocado o no puede leer este repositorio. Emite uno nuevo como se describe en Configurar un repositorio Git y sustituye el valor del secreto del vault que usa la fuente; todas las fuentes que usan ese secreto lo recogen en su siguiente sincronización.
Git: "The repository was not found, or the source's token cannot see it"¶
Comprueba primero la URL de clonado. Un repositorio privado responde not found en lugar de forbidden a un token que no puede leerlo, así que un token fine-grained emitido para otro repositorio se ve así.
Git: "The repository has no branch named …"¶
El campo branch nombra una rama que el repositorio no tiene. Su valor por
defecto es main; la rama por defecto de un repositorio más antiguo puede ser
master.
Git: "… is … MB, and a synced file may be at most … MB"¶
Un archivo que casa con los patrones de inclusión supera el límite de documento
de la base de conocimiento. Acota include o path_prefix para que ese archivo
quede fuera. En esta sincronización no se escribió nada.
Git: "… over the … MB one sync may check out"¶
Todos los archivos que casan con los patrones de inclusión suman más de 512 MB.
Acota include o path_prefix, o divide el repositorio en varias fuentes, cada
una con su propio prefijo.
Git: "This token was added for …, and the repository is on …"¶
El repositorio de la fuente está en un host distinto de aquel con el que se añadió su token. O la URL es incorrecta, o la fuente necesita un token añadido para ese host. No se envió nada al host del repositorio.
Git: "A Git source needs a Git access token"¶
La fuente nombra un secreto de otro kind, como una API key. Añade el token como Git access token, con su host, y elige ese.
"Another sync of this source is still running"¶
Se lanzó una ejecución mientras había otra de la misma fuente en curso, así que no arrancó. La ejecución en curso termina con normalidad; vuelve a lanzarla después si la fuente ha cambiado entretanto.
Git: "… resolves to a private address"¶
El host del repositorio resuelve dentro de la red del deployment, así que la fuente se rechaza. Una fuente de sincronización no puede llegar a un servidor Git autoalojado en una dirección interna.
Git: "git is not installed on this worker"¶
El worker se ejecuta desde una imagen sin git. El backend/Dockerfile que se
distribuye lo instala; a una imagen propia hay que añadírselo.
Git: una sincronización terminó sin ningún archivo procesado¶
El commit de cabeza de la rama es el mismo que leyó la última ejecución limpia,
con la misma configuración, así que no había nada que hacer. Cambia la fuente a
full durante una ejecución para volver a leerlo todo de todos modos.
SharePoint: "Microsoft Entra refused the app registration's credentials (…)"¶
Microsoft Entra no inició la sesión de la app. invalid_client suele significar
que el client secret ha caducado o que el vault guarda el ID del secreto en lugar
de su valor. unauthorized_client o invalid_request suele significar que el id
del tenant o el client id son incorrectos. Comprueba los tres valores con la
Overview y Certificates & secrets de la app, y sustitúyelos en el secreto
del vault.
SharePoint: "Microsoft Graph did not accept the app's token for …"¶
La app inició sesión, pero su token no lleva ningún permiso de Microsoft Graph.
Añade el permiso de aplicación Sites.Selected, no uno delegado, y concede el
consentimiento de administrador, como se describe en el
paso 2.
SharePoint: "Microsoft Graph denied the app access to … (accessDenied)"¶
La app tiene Sites.Selected pero ninguna concesión sobre este sitio. Concédele
read sobre el sitio, como se describe en el
paso 2. Si el mensaje nombra una carpeta
bajo la carpeta de la fuente, esa carpeta tiene permisos propios que excluyen a la
app. El resto de la biblioteca se ingirió y no se eliminó nada.
SharePoint: "There is no SharePoint site at …, or the app cannot see it"¶
Comprueba primero la URL del sitio: es la dirección del propio sitio, como
https://contoso.sharepoint.com/sites/HR, no una biblioteca ni una página dentro
de él. Con Sites.Selected, un sitio sobre el que la app no tiene concesión
también puede responder así.
SharePoint: "The site has no document library named …"¶
El mensaje lista las bibliotecas que la app puede ver. Copia uno de esos nombres
en library, o deja library vacío para la biblioteca por defecto del sitio. La
biblioteca por defecto lleva el nombre en el idioma del sitio, como Documents o
Dokumente.
SharePoint: "The library has no folder …" o "… is a file, not a folder"¶
folder_path no nombra una carpeta de la biblioteca. Es relativo al nivel
superior de la biblioteca, por ejemplo Policies/HR, y no repite el nombre de la
biblioteca.
SharePoint: "The folder … could not be listed: …"¶
No se pudo leer una carpeta bajo la carpeta de la fuente. El motivo va detrás de los dos puntos. Las demás carpetas se ingirieron, y en ese run no se eliminó nada.
SharePoint: "Microsoft 365 stayed unavailable or kept throttling … after 4 attempts"¶
Graph seguía limitando o fallando tras cuatro intentos. La siguiente
sincronización vuelve a empezar. Si ocurre en cada sincronización, programa la
fuente con menos frecuencia, o divide una biblioteca muy grande en varias fuentes,
cada una con su propio folder_path.
SharePoint: "A SharePoint source needs a Microsoft Entra app credential"¶
La fuente nombra un secreto de otro kind, como una API key. Añade la app al vault como Microsoft Entra app y elige esa.
SharePoint: una sincronización terminó sin ningún archivo procesado¶
Nada en la biblioteca ha cambiado desde la última ejecución limpia con la misma
configuración, así que no había nada que hacer. Cambia la fuente a full durante
una ejecución para volver a leerlo todo de todos modos.
Las sincronizaciones programadas no se ejecutan¶
Tiene que haber un sistema de tareas en segundo plano en marcha. Comprueba que tu proceso worker está activo:
Sin un worker, solo funcionan los disparos manuales desde la CLI o la API.