Una búsqueda no siempre basta
El RAG clásico tiene una coreografía fija: llega la pregunta, se hace una búsqueda, se meten los fragmentos en el prompt y el modelo redacta. Un solo tiro. Funciona sorprendentemente bien cuando la pregunta es limpia y la respuesta vive en un párrafo concreto de tu índice.
El problema es que muchas preguntas reales no son así. “¿Cómo cambió nuestra política de devoluciones entre 2023 y 2025?” necesita dos búsquedas, no una. “¿Cuál de estos tres proveedores nos sale más barato al año?” necesita recuperar tres cosas y luego comparar. Y “¿por qué me cobrasteis dos veces?” ni siquiera es una pregunta bien formada: hay que aclararla antes de buscar nada.
Ante estos casos, el RAG de un solo paso hace lo único que sabe hacer: recupera lo más parecido a la pregunta tal cual llegó y redacta con eso. Si eso no contiene la respuesta, el modelo rellena el hueco. Vuelves al punto de siempre.
Qué añade el “agéntico”
RAG agéntico es dejar que el modelo controle el bucle de recuperación en lugar de sufrirlo. En vez de “busca una vez y redacta”, el flujo pasa a ser “decide qué necesitas, búscalo, mira si es suficiente y, si no, vuelve a buscar”.
La palabra clave es decide. El modelo deja de ser solo el redactor final y pasa a tomar cuatro tipos de decisión:
- Si buscar o no. No toda pregunta necesita recuperación. “Resume el texto anterior” no toca el índice para nada.
- Qué buscar. Reformular la pregunta del usuario en una o varias consultas mejores. “Devoluciones 2023 vs 2025” se convierte en dos búsquedas separadas.
- Si lo recuperado basta. Leer los fragmentos y juzgar si responden de verdad, en vez de asumir que sí.
- Cuándo parar. Cortar cuando tiene lo necesario, no cuando se acaban los pasos.
Nada de esto es magia nueva. Es el mismo tool calling que ya usas para que un modelo llame a una función, aplicado a la búsqueda: la recuperación se convierte en una herramienta que el modelo invoca las veces que haga falta.
El bucle mínimo
No hace falta un framework. El núcleo cabe en un bucle con una condición de parada. La búsqueda es una herramienta más; el modelo decide en cada vuelta si la llama o si ya puede responder.
def rag_agentico(pregunta, indice, llm, max_pasos=3):
# El historial acumula lo que el modelo va recuperando entre vueltas
contexto = []
for paso in range(max_pasos):
# El modelo ve la pregunta y lo recuperado hasta ahora, y elige:
# o pide otra búsqueda (con SU propia consulta) o ya responde.
decision = llm.decidir(pregunta, contexto)
if decision.accion == "responder":
return decision.respuesta
if decision.accion == "buscar":
# La consulta la redacta el modelo, no es la pregunta literal
resultados = indice.buscar(decision.consulta, k=5)
relevantes = [r for r in resultados if r.score >= 0.75]
if not relevantes:
# Registra el fallo para que la próxima vuelta lo tenga en cuenta
contexto.append(f"Sin resultados para: {decision.consulta}")
else:
contexto.extend(relevantes)
# Red de seguridad: si agota los pasos, responde con lo que tenga
# y admite el límite en vez de inventar.
return llm.responder_o_rendirse(pregunta, contexto)
Tres detalles hacen que esto funcione en producción y no solo en la demo. El
max_pasos evita que el modelo se quede dando vueltas para siempre. El umbral de
score filtra el ruido igual que en el RAG clásico. Y el “rendirse” del final es
lo que separa un sistema honesto de uno que alucina cuando se le acaban las
ideas: si tras tres intentos no hay material, la respuesta correcta es “no lo
sé”, no un párrafo inventado con aplomo.
Clásico vs agéntico, sin humo
No es que uno sea la versión moderna del otro. Resuelven problemas distintos y tienen costes distintos.
| RAG clásico | RAG agéntico | |
|---|---|---|
| Llamadas al modelo | 1 | 2 a N (una por vuelta) |
| Latencia | Baja y predecible | Mayor y variable |
| Preguntas multi-parte | Falla | Su punto fuerte |
| Reformula la consulta | No | Sí |
| Coste por respuesta | Fijo | Variable, difícil de acotar |
| Depuración | Sencilla | Necesitas trazas del bucle |
La conclusión práctica: el agéntico no sustituye al clásico, lo envuelve. Un buen sistema hace primero la decisión barata —¿esta pregunta necesita más de una búsqueda?— y solo entra en el bucle cuando compensa.
Dónde se rompe
Tres cosas se tuercen casi siempre, y conviene anticiparlas.
El coste se dispara sin avisar. Cada vuelta es una llamada al modelo más una búsqueda. Una pregunta que en RAG clásico costaba una llamada puede costar cuatro. Multiplícalo por tu tráfico. Sin un tope de pasos y sin métricas de “vueltas por respuesta”, la factura se te va de las manos antes de que lo notes.
El modelo se enamora de buscar. Si le das una herramienta, la usará de más. Verás bucles que recuperan cinco veces para una pregunta que se respondía a la primera. La cura es un prompt que le recuerde que responder directamente es una opción válida, y un contador que penalice las vueltas innecesarias en tus evaluaciones.
Depurar deja de ser trivial. En el RAG clásico miras los fragmentos y ya. En el agéntico tienes que ver la traza completa: qué consultas generó, qué recuperó en cada vuelta, por qué decidió seguir o parar. Si no registras eso desde el primer día, cada fallo es un misterio.
Cuándo merece la pena
Pásate a agéntico cuando tus preguntas reales sean multi-parte, comparativas o ambiguas, y cuando midas que el RAG de un solo paso falla justo ahí. No lo montes “por si acaso”: añade latencia, coste y complejidad de depuración a cambio de una capacidad que quizá no necesites.
Y hazlo por capas. Empieza con RAG clásico bien afinado —buen troceado, búsqueda híbrida, umbral de relevancia—, porque el agéntico sobre una recuperación mala solo alucina más caro y más despacio. Cuando eso esté sólido, añade un único paso extra: dejar que el modelo reformule la consulta si la primera búsqueda vuelve vacía. Ese cambio, solo ese, ya resuelve buena parte de los casos y te enseña a manejar el bucle antes de complicarlo.
El salto de “buscar una vez” a “saber volver a buscar” es pequeño en código y grande en resultados. Pero como todo en RAG, se gana en la recuperación y en la honestidad del sistema para admitir sus límites, no en lo listo que parezca el bucle.