Resumen
- RAG no es “subir documentos y hacer preguntas”. Un sistema RAG en producción es un sistema de conocimiento: ingesta, chunking, metadatos, recuperación, reranking, síntesis de respuestas, citas, evaluación, monitoreo y corrección.
- El mayor error de diseño es tratar el conocimiento bien estructurado como texto plano. Las políticas, los tickets, las especificaciones, los contratos, los manuales y los documentos de arquitectura suelen necesitar jerarquía, metadatos, IDs estables, chunks padre-hijo y recuperación que tenga en cuenta las relaciones.
- Los benchmarks siguen mostrando la misma verdad incómoda: el RAG básico ayuda, pero no es suficiente. CRAG reporta que los LLMs avanzados por sí solos responden como máximo el 34% de sus preguntas factuales, el RAG sencillo llega al 44% y los sistemas RAG avanzados de la industria alcanzan el 63% sin alucinar.
- Evalúa la cadena, no solo la respuesta final. Mide el recall de recuperación, la precisión del contexto, el sustento o la fidelidad a las fuentes, la relevancia de la respuesta, el comportamiento de rechazo, la calidad de las citas, la latencia, el costo y la deriva en producción.
- El mejor patrón actual es híbrido: ingesta estructurada + recuperación semántica y léxica + filtros de metadatos + reranking + generación que tenga en cuenta las fuentes + evaluaciones automatizadas + revisión humana en casos de alto riesgo.
- Para conocimiento conectado, considera la recuperación jerárquica, los chunks contextualizados, los resúmenes al estilo GraphRAG o la recuperación basada en grafos de conocimiento. Úsalos cuando la pregunta requiera relaciones, agregación, razonamiento multi-hop o síntesis a nivel de corpus.
- Un stack predeterminado sólido incluye Postgres para metadatos y datos de evaluación, Qdrant o pgvector para recuperación híbrida, embeddings de OpenAI o Voyage, un reranker dedicado, LlamaIndex o una capa ligera de orquestación personalizada y evaluaciones al estilo RAGAS/LangSmith/LangWatch.
- Si quieres una implementación full-stack centrada en Python, Agno puede cubrir gran parte de la aplicación: bases de conocimiento, integraciones con bases de datos vectoriales, RAG agéntico, salidas estructuradas, herramientas, APIs de AgentOS, sesiones, trazas, RBAC, integración de UI y evaluaciones integradas.
Qué aprenderás aquí
- Cómo pensar en RAG como una cadena de decisiones y no como una sola llamada de búsqueda vectorial.
- Qué dicen los benchmarks recientes de RAG sobre la recuperación básica, las alucinaciones, los datos dinámicos y las preguntas multi-hop.
- Cómo diseñar chunks para conocimiento estructurado y conectado.
- Qué métricas de evaluación importan a ingenieros y PMs.
- Una arquitectura de referencia práctica que puedes adaptar para aplicaciones en producción.
- Un ejemplo concreto de un asistente de políticas de soporte con IDs de fuente, flujo de recuperación, salida JSON y verificaciones de evaluación.
- Un stack tecnológico RAG recomendado para MVPs, equipos de producto consolidados y sistemas de conocimiento empresariales.
- Cómo armar el mismo tipo de aplicación RAG full-stack con Agno y sus funcionalidades integradas.
- Un pequeño ejemplo al estilo Python para verificar la recuperación y las respuestas sustentadas en las fuentes.
Este artículo está dirigido a ingenieros y PMs que crean aplicaciones de IA sobre documentación de producto, bases de conocimiento internas, historiales de soporte, políticas, especificaciones, contratos, runbooks, registros de clientes u otro conocimiento empresarial.
Una advertencia amistosa: RAG es uno de los patrones de IA más fáciles de demostrar y también uno de los más fáciles de medir mal.
RAG es una cadena, no una funcionalidad
La idea original de RAG es simple: recuperar conocimiento externo, incluirlo en el contexto del modelo y generar una respuesta sustentada en ese conocimiento. Ese sigue siendo el principio central.
Pero, en la práctica, una aplicación RAG es una cadena:
User question
|
v
Intent + query understanding
|
v
Retriever selection + filters
|
v
Hybrid search over structured chunks
|
v
Reranking + deduplication + context packing
|
v
Answer generation with citations
|
v
Post-checks: grounding, policy, format, refusal
|
v
Telemetry + evals + dataset updates
Cada paso puede fallar.
Si el chunking rompe una tabla, la recuperación puede pasar por alto la respuesta. Si la recuperación devuelve la página correcta, pero la sección equivocada, el modelo puede hacer una suposición. Si la respuesta es correcta, pero los IDs de las citas no son estables, nadie puede auditarla. Si las evaluaciones solo califican el estilo de la respuesta final, el equipo podría no notar que el recall de recuperación empeoró después de una actualización del corpus.
Así que la pregunta de diseño no es:
¿Qué base de datos vectorial deberíamos usar?
Es:
¿Cómo preservamos la estructura de conocimiento necesaria para responder las preguntas que realmente hacen los usuarios?
Qué nos dicen los benchmarks
Los benchmarks no son tu producto. Aun así, son útiles porque revelan modos de falla que vuelven a aparecer en producción.
1. El RAG básico mejora las respuestas, pero deja una brecha importante
El benchmark CRAG se diseñó en torno a preguntas y respuestas factuales con datos dinámicos, entidades de larga cola, múltiples dominios y APIs simuladas de web y grafos de conocimiento. Su resultado principal invita a la cautela: los LLMs avanzados por sí solos alcanzan como máximo un 34% de exactitud, el RAG sencillo mejora hasta el 44% y los sistemas RAG avanzados de la industria responden el 63% de las preguntas sin alucinar.
La conclusión no es “RAG falló”. La conclusión es que la recuperación top-k simple es solo el primer escalón. Las preguntas reales suelen requerir datos actualizados, desambiguación de entidades, razonamiento temporal, síntesis de múltiples fuentes y un rechazo cuidadoso cuando falta evidencia.
2. RAG necesita algo más que exactitud en las respuestas
RGB evalúa los sistemas RAG en cuatro capacidades:
| Capacidad | Significado práctico |
|---|---|
| Robustez frente al ruido | ¿Puede el modelo ignorar el texto irrelevante recuperado? |
| Rechazo ante ausencia de evidencia | ¿Puede decir “no lo sé” cuando no hay evidencia? |
| Integración de información | ¿Puede combinar múltiples fragmentos relevantes? |
| Robustez frente a información contrafactual | ¿Puede evitar confiar en información incorrecta recuperada? |
Esto se corresponde casi a la perfección con los incidentes en producción. Muchas aplicaciones RAG no fallan porque la recuperación no haya devuelto nada. Fallan porque devolvió una mezcla confusa de contexto verdadero, desactualizado, parcial e irrelevante.
3. La evaluación debe diagnosticar los componentes
Tanto RAGBench como RAGChecker impulsan una evaluación orientada a la explicabilidad y al diagnóstico por componente. Esto importa porque “mala respuesta” no basta para saber qué hacer.
Una respuesta final puede fallar por diferentes razones:
- El chunk correcto nunca se indexó.
- El chunk existe, pero no se recuperó.
- El chunk se recuperó, pero quedó demasiado abajo en el ranking.
- El contexto recuperado era correcto, pero contenía demasiado ruido.
- El modelo ignoró la evidencia.
- El modelo respondió correctamente, pero citó la fuente equivocada.
- La fuente estaba desactualizada o había sido reemplazada.
Son bugs diferentes. Necesitan soluciones diferentes.
La regla de diseño: preserva los límites que aportan significado
La mayor parte del conocimiento interno no es una secuencia uniforme de párrafos. Tiene estructura.
Ejemplos:
- Una política tiene secciones, excepciones, fechas de entrada en vigor, responsables y estado de aprobación.
- Un artículo de soporte tiene síntomas, causas, soluciones, versiones afectadas y tickets relacionados.
- Un registro de decisión de arquitectura tiene contexto, decisión, consecuencias y sistemas vinculados.
- Un contrato tiene cláusulas, definiciones, dependencias, jurisdicciones e historial de modificaciones.
- Una especificación de producto tiene objetivos, lo que queda fuera de su alcance, requisitos, flujos, analítica y preguntas abiertas.
Si aplanas todo eso en chunks de 800 tokens con superposición, a menudo destruyes justo la estructura que necesita el modelo.
Es mejor que los chunks se comporten como pequeñas fichas de conocimiento:
Chunk ID: policy.refunds.2026.section_4.exception_2
Document: Refund Policy
Version: 2026-04-10
Section path: Refund Policy > Exceptions > Chargebacks
Audience: Support agents
Applies to: US, CA
Status: Approved
Parent: policy.refunds.2026.section_4
Related: policy.payments.chargebacks, macro.support.refund_denied
Text: ...
Este tipo de metadatos permite al sistema recuperar información tanto por significado como por estructura.
Una arquitectura práctica para RAG estructurado
Esta es la arquitectura en la que confío para la mayoría de las aplicaciones RAG en producción:
+-----------------------+
| Source systems |
| Docs, CMS, tickets, DB|
+-----------+-----------+
|
v
+-----------------------+
| Structured ingestion |
| parse, clean, version |
+-----------+-----------+
|
+-----------------+-----------------+
v v
+-----------------------+ +-----------------------+
| Retrieval units | | Source graph / links |
| chunks, parents, refs | | entities, relations |
+-----------+-----------+ +-----------+-----------+
| |
v v
+-----------------------+ +-----------------------+
| Hybrid indexes | | Metadata filters |
| vector + BM25 | | tenant, date, status |
+-----------+-----------+ +-----------+-----------+
+-----------------+-----------------+
v
+-----------------------+
| Rerank + context pack |
| diversify, cite, trim |
+-----------+-----------+
|
v
+-----------------------+
| Grounded generation |
| answer + citations |
+-----------+-----------+
|
v
+-----------------------+
| Evaluation + tracing |
| offline + production |
+-----------------------+
Lo importante no son los bloques del diagrama, sino la separación de responsabilidades. Las unidades de recuperación, el grafo de fuentes, los filtros de metadatos y las trazas de evaluación deben ser conceptos de primera clase, no cadenas de texto incidentales dentro de un prompt.
Chunking: empieza por la pregunta del usuario, no por el tamaño en tokens
El tamaño del chunk importa, pero “¿cuál es el mejor tamaño de chunk?” suele ser la primera pregunta equivocada.
En cambio, pregunta:
- ¿Qué preguntas debería responder este chunk por sí solo?
- ¿Qué contexto del elemento padre necesita?
- ¿Por qué metadatos debe poder filtrarse?
- ¿Qué chunks relacionados deberían ser fáciles de consultar?
- ¿Qué no debería dividirse nunca?
Esta es una regla práctica:
| Tipo de conocimiento | Mejor límite para el chunk |
|---|---|
| FAQ | Un par de pregunta y respuesta |
| Política | Una sección o excepción |
| Documentación de API | Un endpoint, grupo de parámetros, código de error o ejemplo |
| ADR | Una decisión, consecuencia o sistema relacionado |
| Legal/contractual | Una cláusula, definición o modificación |
| Ticket de soporte | Un síntoma, diagnóstico, resolución o entorno |
| Tablas | Un grupo de filas con los encabezados preservados |
| Documentación de código | Una función o clase con su firma y ejemplos |
Para conocimiento bien estructurado, me gusta la recuperación padre-hijo:
Embed small child chunks for precision
|
v
Retrieve child chunks
|
v
Expand to parent section for context
|
v
Rerank parent + child evidence together
Esto te da precisión sin privar al modelo de contexto.
El patrón de recuperación contextual de Anthropic apunta en una dirección similar: enriquecer cada chunk con contexto a nivel de documento antes de generar embeddings y realizar la indexación léxica. La reducción de fallas de recuperación que reportan es lo suficientemente grande como para tomarla en serio, especialmente cuando se combina con reranking. La lección más general es simple: un chunk debe llevar suficiente significado de su entorno para que pueda recuperarse correctamente fuera de su documento original.
Cuando el conocimiento está conectado, recupera la cadena
Algunas preguntas no se responden con un solo chunk.
Ejemplo:
¿Puede un cliente empresarial en Canadá obtener un reembolso si renovó a través de un revendedor e inició un contracargo?
Eso puede requerir:
- la política regional de reembolsos
- los términos del revendedor
- las excepciones del contrato empresarial
- la política de contracargos
- la macro de soporte más reciente
- los metadatos de la cuenta del cliente
Una búsqueda semántica plana podría recuperar una o dos piezas y pasar por alto la cadena.
Una mejor estrategia es la recuperación por etapas:
Question
|
v
Extract entities and constraints
|
+--> country = Canada
+--> customer_type = enterprise
+--> channel = reseller
+--> event = renewal
+--> dispute = chargeback
|
v
Retrieve policy candidates with filters
|
v
Follow related links and parent sections
|
v
Rerank evidence set
|
v
Answer only if the chain supports it
Los enfoques al estilo GraphRAG, la recuperación jerárquica al estilo RAPTOR y los sistemas más recientes basados en grafos, como LightRAG, responden a la misma limitación: los chunks planos no son buenos para responder preguntas sobre conexiones, agregaciones o relaciones multi-hop.
No necesitas un grafo de conocimiento para cada aplicación RAG. Pero deberías considerar uno cuando los usuarios hacen preguntas como:
- “¿Qué cambió entre estas versiones?”
- “¿Qué equipos se ven afectados por esta política?”
- “¿Cuál es la relación entre estos incidentes?”
- “Resume los temas presentes en todas las quejas de clientes”.
- “Encuentra excepciones que dependan de la región, el plan y el tipo de contrato”.
Esas son preguntas sobre relaciones, no solo sobre similitud.
Recuperación: primero lo híbrido, después lo sofisticado
Para muchos sistemas en producción, el stack de recuperación que más impacto aporta es:
metadata filters
+
BM25 / keyword search
+
vector search
+
reranker
+
context packing
¿Por qué híbrido?
La búsqueda vectorial es buena para encontrar similitud semántica. La búsqueda por palabras clave es buena para términos exactos, nombres de productos, IDs, códigos de error, números de cláusula y lenguaje interno peculiar. El conocimiento empresarial tiene mucho lenguaje interno peculiar.
El reranking importa porque la recuperación top-k suele contener ruido. Un cross-encoder o un reranker basado en LLM puede examinar la consulta y los chunks candidatos en conjunto y luego reordenar la lista antes de que la vea el generador.
La organización del contexto importa porque un modelo puede perder la respuesta entre demasiado contexto irrelevante. Más tokens recuperados pueden reducir la calidad si ocultan la evidencia entre el ruido.
Generación: haz que el modelo muestre su evidencia
El prompt de generación debe hacer explícito el contrato de evidencia:
Use only the provided sources.
Answer the user's question directly.
Include citations for every factual claim.
If the sources conflict, name the conflict.
If the sources do not contain the answer, say what is missing.
Do not infer policy from similar but non-applicable sources.
Para los PMs, este es el contrato de producto: los usuarios deben saber si el sistema sabe, no sabe o encontró evidencia contradictoria.
Para los ingenieros, este es el contrato de depuración: cada respuesta debe apuntar a IDs de fuente que puedan recuperarse.
Ejemplo práctico: un asistente de políticas de soporte
Hagamos esto menos abstracto.
Imagina que una empresa SaaS quiere un asistente interno para agentes de soporte. El asistente responde preguntas sobre políticas antes de que un agente responda a un cliente.
Las fuentes de conocimiento son:
- páginas de políticas de reembolso
- términos de revendedores
- plantillas de contratos empresariales
- macros de soporte
- notas de incidentes
- metadatos de planes de producto
La pregunta más difícil no es “¿Cuál es la política de reembolso?”. Es una pregunta que conecta varias políticas:
El cliente ACME tiene el plan Enterprise, renovó a través de un revendedor, está en Canadá e inició un contracargo. ¿Puede soporte emitir un reembolso?
Un flujo RAG práctico se vería así:
User question
|
v
Extract constraints
- customer = ACME
- plan = Enterprise
- region = Canada
- sales_channel = reseller
- event = renewal
- dispute = chargeback
|
v
Fetch account metadata from app DB
|
v
Retrieve policy chunks with metadata filters
- status = approved
- effective_date <= today
- region in [Canada, Global]
- audience = support
|
v
Hybrid search
- vector: "reseller renewal refund chargeback enterprise"
- keyword: reseller, chargeback, renewal, Enterprise
|
v
Rerank top 40 candidates down to top 8
|
v
Expand child chunks to parent sections
|
v
Generate answer with citations and a decision state
El asistente no debería devolver una respuesta vaga como:
Depende. Revisa las políticas de revendedores y contracargos.
Una mejor respuesta es estructurada:
{
"decision": "do_not_refund_without_escalation",
"confidence": "medium",
"answer": "Support should not issue the refund directly. The customer renewed through a reseller, and the chargeback policy requires finance escalation before refund approval.",
"required_escalation": "finance",
"citations": [
"policy.refunds.2026.reseller_terms.section_2",
"policy.payments.2026.chargebacks.section_4",
"macro.support.refund_escalation.2026"
],
"missing_information": [
"The current reseller agreement ID was not available in retrieved sources."
]
}
Observa lo que esto aporta al producto:
- El agente de soporte recibe una recomendación directa.
- La respuesta se sustenta en IDs de fuente estables.
- El sistema expone la información faltante en lugar de ocultar la incertidumbre.
- La decisión puede auditarse más adelante.
- La respuesta puede evaluarse automáticamente.
El modelo de ingesta detrás de esto puede seguir siendo simple:
chunk = {
"id": "policy.payments.2026.chargebacks.section_4",
"text": "Chargeback-related refunds require finance review before approval...",
"parent_id": "policy.payments.2026.chargebacks",
"section_path": "Payments > Chargebacks > Refund approval",
"source_url": "https://internal.example.com/policies/payments#chargebacks",
"status": "approved",
"effective_date": "2026-04-01",
"owner": "finance-ops",
"audience": "support",
"regions": ["global"],
"entities": ["refund", "chargeback", "finance review"],
"related_ids": [
"policy.refunds.2026.reseller_terms.section_2",
"macro.support.refund_escalation.2026"
],
}
Y tu función de recuperación debería devolver evidencia, no solo texto:
def retrieve_policy_evidence(question: str, account: dict) -> list[dict]:
filters = {
"status": "approved",
"audience": "support",
"regions": ["global", account["country"]],
"effective_date_lte": "2026-06-15",
}
dense_hits = vector_search(question, filters=filters, top_k=30)
keyword_hits = keyword_search(question, filters=filters, top_k=30)
fused_hits = reciprocal_rank_fusion([dense_hits, keyword_hits], limit=40)
reranked = rerank(question, fused_hits, top_k=8)
return expand_with_parent_sections(reranked)
La evaluación de este ejemplo debería verificar:
| Verificación | Resultado esperado |
|---|---|
| Recall de recuperación | Los términos del revendedor y la política de contracargos están entre los 8 primeros resultados |
| Cobertura de citas | La respuesta final cita ambas secciones de políticas requeridas |
| Corrección de la decisión | decision = do_not_refund_without_escalation |
| Información faltante | Menciona el ID del acuerdo con el revendedor si no está disponible |
| Sustento en las fuentes | No aparece ninguna afirmación sin respaldo en las fuentes |
| Comportamiento del producto | Escala el caso a finanzas en lugar de inventar una aprobación |
Ese es el ciclo práctico: diseñar los IDs de fuente, recuperar la cadena de evidencia, obligar a que la respuesta tenga una forma auditable y evaluar cada paso.
Un stack tecnológico recomendado
No existe un stack RAG universalmente superior, pero sí hay opciones predeterminadas razonables. Yo elegiría el stack según el tamaño del equipo, la estructura de los datos y el nivel de control operativo que necesites.
Stack predeterminado para la mayoría de los equipos de producto
| Capa | Recomendación | Por qué |
|---|---|---|
| App/API | FastAPI, Node.js o tu backend existente | Mantén RAG cerca de la autenticación, el manejo de tenants y los logs del producto. |
| Ingesta | LlamaIndex o un pipeline personalizado con parsers para contenido no estructurado | Buenas abstracciones para parsing, metadatos, nodos y patrones de recuperación. |
| Almacenamiento | Postgres para metadatos de fuentes y datasets de evaluación | Tu producto ya confía en él; es excelente para IDs, versiones, permisos y registros de auditoría. |
| Índice de recuperación | Qdrant, pgvector, Weaviate, Pinecone u OpenSearch | Elige según la escala y las preferencias operativas del equipo; exige filtros de metadatos. |
| Búsqueda híbrida | Vectores densos + BM25/vectores dispersos | Mejor para nombres de productos, IDs, números de cláusula y preguntas en lenguaje natural. |
| Embeddings | OpenAI text-embedding-3-small por costo, text-embedding-3-large para búsquedas donde la calidad es prioritaria | La documentación oficial indica 1536 dimensiones para small y 3072 para large, con reducción de dimensiones disponible. |
| Reranking | Cohere Rerank, rerankers de Voyage, bge-reranker o rerank nativo del proveedor | Los rerankers suelen mejorar la precisión antes de que el LLM vea el contexto. |
| Generación | Un modelo de la clase GPT-4.1/GPT-5, de la clase Claude Sonnet o tu modelo empresarial aprobado | Elige según los resultados de las evaluaciones, no por preferencia de marca. |
| Evaluación | RAGAS o DeepEval localmente; LangSmith, LangWatch, TruLens o Arize Phoenix para trazas gestionadas | Necesitas métricas de recuperación y generación, además de depuración de trazas. |
| Observabilidad | OpenTelemetry + analítica de producto + dashboards de evaluación | Conecta la calidad del modelo con los resultados para el usuario, la latencia y el costo. |
Mi implementación predeterminada para un producto consolidado, pero no enorme, sería:
Backend: FastAPI or existing Node.js service
Metadata DB: Postgres
Vector search: Qdrant with dense + sparse hybrid search
Embeddings: text-embedding-3-large for quality, small for cost-sensitive paths
Reranker: Cohere Rerank or Voyage reranker
Orchestration: LlamaIndex for ingestion/retrieval, thin custom app logic
Evaluation: RAGAS + LangSmith/LangWatch traces
Monitoring: OpenTelemetry + dashboards for latency, cost, retrieval recall, faithfulness
¿Por qué este stack?
- Qdrant tiene consultas híbridas de primera clase con recuperación densa, dispersa y multivectorial, además de fusión de puntuaciones.
- pgvector es excelente cuando quieres menos componentes y ya usas Postgres; combínalo con la búsqueda de texto completo de Postgres y reciprocal rank fusion para obtener búsqueda híbrida.
- LlamaIndex es útil para la ingesta estructurada, la recuperación basada en metadatos y los patrones RAG para producción.
- LangSmith, LangWatch, TruLens, RAGAS y DeepEval ayudan a separar la calidad de la recuperación de la calidad de la respuesta.
- La API de rerank de Cohere y otros rerankers similares están diseñados para reordenar los documentos candidatos por relevancia antes de la generación.
Stack ligero para un MVP
Úsalo cuando necesites aprender rápido:
Postgres + pgvector
Postgres full-text search
OpenAI embeddings
One reranker
RAGAS or DeepEval test set
Simple trace table in Postgres
Esto es aburrido en el mejor sentido. Mantiene el sistema comprensible. La principal compensación es que tendrás que construir más lógica de integración para la recuperación por tu cuenta.
Stack más robusto para conocimiento empresarial
Úsalo cuando el conocimiento es extenso, está sujeto a permisos, tiene vínculos cruzados y se audita:
Document pipeline: LlamaParse, Unstructured, or custom parsers
Metadata system: Postgres
Search: OpenSearch/Elasticsearch + vector DB, or Qdrant/Weaviate with hybrid search
Graph layer: Neo4j, Kuzu, or graph tables in Postgres
Reranking: dedicated reranker
LLM gateway: LiteLLM or internal provider gateway
Eval/observability: LangSmith, LangWatch, Arize Phoenix, TruLens, OpenTelemetry
Human review: annotation queue for failed and high-risk answers
Este stack es más robusto porque el RAG empresarial rara vez es solo búsqueda. Son permisos, actualización, responsables, auditabilidad y respuesta a incidentes disfrazados de búsqueda.
RAG full-stack con funcionalidades integradas de Agno
Si tu equipo trabaja principalmente con Python y quiere lanzar un producto RAG sin ensamblar a mano cada pieza del runtime, Agno es una opción sólida.
Al June 15, 2026, la documentación actual de Agno describe tres capas útiles:
| Capa | Funcionalidad de Agno | Qué te ofrece |
|---|---|---|
| Conocimiento | Knowledge, integraciones con bases de datos vectoriales, base de datos de contenido | Documentos, metadatos, embeddings y conocimiento que se puede consultar. |
| Runtime de agentes | Agent, herramientas, salida estructurada, equipos, workflows | La capa de razonamiento y acción que responde o delega. |
| Runtime de producto | AgentOS, Agent API, AG-UI, AgentUI, trazas, evaluaciones, RBAC | La API, la UI, las sesiones, las trazas, la autenticación y la superficie operativa. |
Una decisión de diseño importante de Agno es que el conocimiento puede asociarse directamente a un agente. Cuando tiene conocimiento asociado, Agno usa RAG agéntico por defecto: el agente puede decidir cuándo buscar en la base de conocimiento. Si quieres RAG clásico, donde las referencias relevantes siempre se agregan al contexto según el mensaje del usuario, Agno también ofrece ese modo.
Así implementaría con Agno el asistente de políticas de soporte de la sección anterior.
1. Almacena el conocimiento en Postgres + PgVector
Para un producto consolidado, empieza con Postgres porque puede almacenar metadatos de fuentes, sesiones, trazas, datasets de evaluación y vectores mediante PgVector.
from agno.db.postgres.postgres import PostgresDb
from agno.knowledge.embedder.openai import OpenAIEmbedder
from agno.knowledge.knowledge import Knowledge
from agno.vectordb.pgvector import PgVector, SearchType
db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai"
db = PostgresDb(db_url=db_url)
policy_knowledge = Knowledge(
name="support_policy_knowledge",
description="Approved support policies, reseller terms, chargeback rules, and support macros.",
contents_db=db,
vector_db=PgVector(
table_name="support_policy_vectors",
db_url=db_url,
embedder=OpenAIEmbedder(),
search_type=SearchType.hybrid,
),
)
Las piezas importantes:
contents_dble da a AgentOS un lugar para gestionar el contenido subido y los metadatos.PgVectoralmacena embeddings y admite operaciones de Postgres adecuadas para producción.SearchType.hybridmantiene los términos exactos de las políticas, los IDs y el significado semántico en la misma ruta de recuperación.- Puedes cambiar PgVector por Qdrant, Weaviate, Pinecone, LanceDB, Chroma, Redis u otros almacenes vectoriales compatibles sin reescribir la lógica del agente.
2. Inserta documentos con metadatos
Agno puede incorporar contenido a la base de conocimiento, pero aún necesitas tratar los metadatos como parte del diseño del producto.
await policy_knowledge.ainsert(
name="Refund Policy 2026",
url="https://internal.example.com/policies/refunds-2026.pdf",
metadata={
"status": "approved",
"audience": "support",
"owner": "finance-ops",
"effective_date": "2026-04-01",
"regions": ["global", "CA", "US"],
"source_type": "policy",
},
)
No te quedes en “subir un PDF”. Agrega los metadatos que necesita tu política de recuperación: estado, responsable, región, producto, plan, fecha de entrada en vigor, tipo de fuente y alcance de los permisos.
3. Agrega herramientas de producto alrededor de la base de conocimiento
El conocimiento responde preguntas sobre políticas. Las herramientas responden preguntas sobre el estado del producto.
from agno.tools import tool
@tool
def get_customer_account(customer_name: str) -> dict:
"""Fetch account facts needed for policy decisions."""
return {
"customer": customer_name,
"plan": "Enterprise",
"country": "CA",
"sales_channel": "reseller",
"renewal_date": "2026-05-12",
"chargeback_open": True,
}
Esta es la separación correcta:
Knowledge base -> "What do the policies say?"
Product tools -> "What is true about this customer right now?"
Agent -> "Given both, what decision is supported?"
4. Exige una salida de decisión estructurada
Para los workflows de producto, no devuelvas prosa sin una estructura definida. Usa una salida estructurada para que el frontend, el registro de auditoría y las evaluaciones puedan depender de campos estables.
from pydantic import BaseModel, Field
class PolicyDecision(BaseModel):
decision: str = Field(description="refund_allowed, deny, or escalate")
confidence: str = Field(description="low, medium, or high")
answer: str
required_escalation: str | None = None
citations: list[str]
missing_information: list[str] = []
Agno admite salidas estructuradas respaldadas por Pydantic, así que esto se convierte en un contrato de API en lugar de un ejercicio de parsing.
5. Construye el agente RAG
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
policy_agent = Agent(
name="support_policy_agent",
model=OpenAIResponses(id="gpt-5.2"),
knowledge=policy_knowledge,
tools=[get_customer_account],
output_schema=PolicyDecision,
instructions=[
"Answer only from approved policy knowledge and account tool data.",
"Search the knowledge base before making policy claims.",
"Cite source IDs for every policy claim.",
"If required sources are missing or conflict, escalate instead of guessing.",
"Never approve a refund when chargeback rules require finance review.",
],
)
Esto ya te da el comportamiento central de la aplicación:
- búsqueda en el conocimiento
- uso de herramientas
- generación de respuestas sustentadas en las fuentes
- salida tipada
- uso trazable de fuentes
6. Publícalo con AgentOS
AgentOS convierte el agente en una API para producción. La documentación actual de Agno describe REST y SSE como interfaces de API predeterminadas, con opciones para AG-UI, WebSocket, MCP, A2A, Slack y otras interfaces.
from agno.os import AgentOS
from agno.os.interfaces.agui import AGUI
agent_os = AgentOS(
name="Support Policy OS",
agents=[policy_agent],
interfaces=[AGUI(agent=policy_agent)],
tracing=True,
)
app = agent_os.get_app()
if __name__ == "__main__":
agent_os.serve(app="support_policy_os:app", reload=True)
Eso te da:
- runtime de FastAPI
- endpoints REST
- streaming compatible con SSE
- APIs de sesión
- APIs de ejecución
- captura de trazas
- conectividad con AgentOS UI
- integración de frontend compatible con AG-UI
En otras palabras, tu frontend puede ser una aplicación Astro/React/Next.js, pero no necesitas construir el runtime RAG desde cero.
7. Usa las evaluaciones integradas antes del lanzamiento
Agno tiene dimensiones de evaluación integradas para exactitud, criterios de agente como juez, rendimiento y confiabilidad. Para este asistente RAG, ejecutaría al menos dos tipos de evaluación:
Accuracy eval:
Input: "ACME renewed through reseller in Canada and has an open chargeback. Can support refund?"
Expected: decision = escalate, required_escalation = finance
Reliability eval:
Expected tool calls:
- get_customer_account
- search_knowledge_base
El criterio de lanzamiento no debería ser “la respuesta se vio bien una vez”. Debería ser:
Golden set passes
+
required tool calls happen
+
citations are present
+
structured output validates
+
trace shows the right knowledge was retrieved
8. Usa AgentOS para el ciclo operativo
Una vez desplegada la aplicación, usa las funcionalidades de runtime respaldadas por la base de datos de Agno como tu ciclo de mejora:
Production run
|
v
AgentOS stores session + trace + tool calls
|
v
Review bad or low-confidence answers
|
v
Promote failures into eval examples
|
v
Improve metadata, policies, tools, prompt, or model
|
v
Rerun evals before release
Aquí es donde más importan las funcionalidades “integradas” de Agno. AgentOS no es solo una forma de exponer un agente como API. Te da los registros del runtime necesarios para depurar, evaluar y mejorar continuamente la aplicación RAG.
Cuándo Agno es una buena opción
Usa Agno para RAG cuando:
- tu equipo de backend se siente cómodo con Python
- quieres RAG agéntico sin escribir desde cero el contrato de la herramienta de búsqueda
- quieres sesiones, trazas, memoria, conocimiento, evaluaciones y APIs en un solo runtime
- necesitas exponer el mismo agente mediante REST, streaming, AG-UI u otras interfaces
- quieres mantener el control de tus datos, con sesiones, conocimiento y trazas en tu base de datos
Ten más cautela cuando:
- tu empresa ya tiene un runtime de IA maduro que usa solo TypeScript
- necesitas una orquestación de recuperación muy personalizada que no encaja bien con el framework
- tu principal desafío es la infraestructura de búsqueda, no el runtime de agentes
Mi recomendación práctica: usa Agno para gestionar la capa de agente y runtime, pero mantén explícito el modelo de conocimiento. Los IDs estables, los metadatos, las pruebas de recuperación y la asignación de responsables de las fuentes siguen siendo tu responsabilidad.
Evaluación: mide toda la cadena RAG
Una buena evaluación de RAG tiene al menos cuatro capas.
| Capa | Pregunta | Ejemplo de métrica |
|---|---|---|
| Recuperación | ¿Recuperamos la evidencia correcta? | recall@k, precisión del contexto, MRR |
| Contexto | ¿Pasamos contexto útil y sin ruido? | relevancia del contexto, redundancia, actualización |
| Generación | ¿La respuesta usó correctamente la evidencia? | fidelidad a las fuentes, sustento en las fuentes, relevancia de la respuesta |
| Producto | ¿Esto satisfizo al usuario de forma segura? | éxito de la tarea, tasa de escalamiento, CSAT, revisión humana |
RAGAS, TruLens, DeepEval, LangSmith y herramientas similares giran en torno a la misma idea central: evaluar la recuperación y la generación por separado y luego evaluar la experiencia de extremo a extremo.
Aquí hay un pequeño esquema de evaluador:
from dataclasses import dataclass
@dataclass
class RagExample:
question: str
required_source_ids: set[str]
expected_answer_facts: set[str]
@dataclass
class RagRun:
retrieved_source_ids: list[str]
answer: str
cited_source_ids: set[str]
def recall_at_k(example: RagExample, run: RagRun, k: int = 5) -> float:
retrieved = set(run.retrieved_source_ids[:k])
if not example.required_source_ids:
return 1.0
return len(example.required_source_ids & retrieved) / len(example.required_source_ids)
def citation_coverage(example: RagExample, run: RagRun) -> float:
if not example.required_source_ids:
return 1.0
return len(example.required_source_ids & run.cited_source_ids) / len(example.required_source_ids)
def unsupported_fact_count(answer_claims: set[str], supported_claims: set[str]) -> int:
return len(answer_claims - supported_claims)
Esto es intencionalmente simple. En un sistema real, answer_claims y supported_claims podrían provenir de un LLM que actúe como juez, un extractor de afirmaciones o etiquetas humanas. El punto es que no solo debes preguntar: “¿La respuesta fue agradable?”. Pregunta si se recuperaron, citaron y usaron las fuentes requeridas.
El conjunto de evaluación que PMs e ingenieros pueden compartir
Un conjunto de evaluación RAG útil debe incluir más que preguntas del caso ideal.
| Tipo de caso | Por qué importa |
|---|---|
| Respuesta conocida | Corrección básica |
| Respuesta ausente | Rechazo e incertidumbre |
| Fuentes contradictorias | Manejo de conflictos |
| Fuente desactualizada | Actualización y control de versiones |
| Pregunta multi-hop | Cadena de evidencia |
| Ambigüedad de entidad | Desambiguación |
| Identificador exacto | Recuperación por palabras clave y metadatos |
| Respuesta con muchas tablas | Calidad del parser y de los chunks |
| Excepción de política | Lógica para casos límite |
| Error tipográfico o consulta vaga del usuario | Reformulación de consultas |
Un conjunto inicial práctico es de 50 a 100 ejemplos:
- 30 preguntas comunes de usuarios
- 20 casos límite de logs de producción o tickets de soporte
- 20 casos adversariales o con fuentes desactualizadas
- 10 casos sin respuesta disponible
- 10 preguntas multi-hop o sobre relaciones
Luego agrega fallas de producción cada semana.
Cómo diagnosticar fallas
Cuando falle una respuesta RAG, no empieces cambiando el prompt. Usa la traza.
Bad answer
|
v
Was the needed source indexed?
| no -> ingestion/parser/versioning bug
v yes
Was it retrieved in top-k?
| no -> query, embeddings, filters, chunking, hybrid search
v yes
Was it ranked high enough?
| no -> reranker, scoring, metadata boost
v yes
Was it included in final context?
| no -> context packing, dedupe, token budget
v yes
Did the model use it correctly?
| no -> prompt, model, citation rules, post-check
v yes
Is the expected label wrong?
-> update dataset
Aquí es donde los PMs pueden ayudar mucho. Muchas fallas no son fallas del modelo. Son fallas en la gestión del conocimiento: documentos desactualizados, políticas poco claras, ausencia de una fuente de verdad o páginas contradictorias.
Mejores prácticas que usaría en 2026
Esta es la versión breve que incluiría en una lista de verificación para el equipo.
- Diseña el corpus antes de ajustar el modelo.
- Mantén IDs de fuente estables y fáciles de citar.
- Preserva la jerarquía de documentos y las rutas de las secciones.
- Agrega metadatos de tenant, producto, región, versión, estado, responsable y fecha de entrada en vigor.
- Usa recuperación híbrida en producción, a menos que tengas evidencia de que solo con vectores es suficiente.
- Aplica reranking antes de la generación.
- Recupera chunks pequeños y responde con el contexto del elemento padre.
- Agrega reformulación de consultas solo después de poder ver las trazas de recuperación.
- Trata las tablas, imágenes, diagramas y bloques de código como casos especiales de ingesta.
- Exige respuestas sustentadas en las fuentes y con citas.
- Enseña al sistema a decir “no se encontró” y “las fuentes están en conflicto”.
- Evalúa por separado la recuperación, el contexto, la generación y el éxito del producto.
- Mantén actualizado un conjunto de evaluación a partir de fallas reales.
- Monitorea la deriva en producción a medida que cambian los documentos, las preguntas de los usuarios y los modelos.
- Incluye revisión humana en decisiones sobre políticas, asuntos legales, médicos, financieros o de alto impacto.
Una guía sencilla para decidir
Usa RAG simple cuando:
- las preguntas son principalmente de un solo salto
- los documentos están limpios y ya estructurados
- las necesidades de actualización son moderadas
- las citas son útiles, pero no críticas desde el punto de vista legal
Usa RAG estructurado o jerárquico cuando:
- los usuarios preguntan sobre políticas, especificaciones, procedimientos, contratos o manuales
- los chunks necesitan el contexto del elemento padre
- las secciones, versiones, responsables y excepciones importan
- los límites de tablas y código importan
Usa GraphRAG o recuperación que tenga en cuenta las relaciones cuando:
- las preguntas requieren razonamiento multi-hop
- las respuestas agregan información de muchos documentos
- las relaciones entre entidades importan
- el corpus es narrativo, desordenado o tiene vínculos cruzados
- los usuarios preguntan “por qué”, “qué cambió”, “qué depende de esto” o “qué temas aparecen en todo el corpus”
Usa fine-tuning cuando:
- el modelo tiene el contexto correcto, pero usa repetidamente el estilo, formato o política de decisión equivocados
- necesitas un comportamiento consistente más que conocimiento nuevo
- tienes un conjunto de entrenamiento representativo y de alta calidad
No uses RAG como sustituto de corregir la base de conocimiento. Si el material de origen es contradictorio, está desactualizado o no tiene responsables, la recuperación principalmente hará que esos problemas sean visibles más rápido.
Brechas pendientes y temas para profundizar
Este artículo se centra en el diseño y la evaluación. Hay tres áreas que merecen un tratamiento más profundo:
- Seguridad: prompt injection a través de documentos recuperados, permisos de las fuentes, aislamiento de tenants y registros de auditoría.
- RAG multimodal: PDFs con tablas, capturas de pantalla, diagramas, manuales con muchas imágenes y confianza del OCR.
- Ingeniería de costos: estrategia de actualización de embeddings, caché, costo de los rerankers, presupuestos de contexto y SLOs de latencia.
No son temas secundarios. Suelen ser lo que determina si una aplicación RAG sobrevive al tráfico en producción.
Lista de fuentes
- Generación aumentada por recuperación para tareas de NLP intensivas en conocimiento, Lewis et al., 2020.
- CRAG: benchmark integral de RAG, Meta y colaboradores, 2024.
- RGB: evaluación comparativa de modelos de lenguaje grandes en generación aumentada por recuperación, Chen et al., 2023.
- RAGBench: benchmark explicable para sistemas de generación aumentada por recuperación, Friel et al., 2024.
- RAGChecker: un framework de diagnóstico detallado para generación aumentada por recuperación, Ru et al., 2024.
- OpenAI: optimización de la exactitud de los LLMs, especialmente la orientación sobre cuándo ayuda RAG y por qué debe evaluarse la recuperación.
- OpenAI: mejores prácticas de evaluación, especialmente el diseño de datasets y la calificación según criterios específicos.
- OpenAI: embeddings vectoriales, incluidas las dimensiones de los embeddings y sus casos de uso.
- Anthropic: recuperación contextual, 2024.
- LangChain: evaluación de una aplicación RAG.
- LangChain: deconstrucción de RAG.
- Descripción general de la evaluación en LangSmith, especialmente la separación entre la calidad de la recuperación y la de la generación.
- LlamaIndex: estrategias de chunking de documentos.
- LlamaIndex: creación de aplicaciones RAG de alto rendimiento para producción.
- Qdrant: consultas híbridas.
- pgvector: búsqueda híbrida.
- Cohere: API de Rerank.
- Agno: bienvenida, descripción general del SDK y AgentOS.
- Agno: descripción general de Knowledge, incluidos los modos de RAG agéntico y RAG tradicional.
- Agno: agentes con conocimiento, incluidos
search_knowledgeyadd_knowledge_to_context. - Agno: bases de datos vectoriales, incluida la búsqueda híbrida de PgVector y la compatibilidad con Qdrant.
- Agno: Content DB, para la compatibilidad con Knowledge UI de AgentOS.
- Agno: introducción a AgentOS, para APIs de producción, sesiones, conocimiento, trazas, RBAC y gobernanza.
- Agno: Agent API, para REST, SSE, sesiones, memoria y APIs de ejecución.
- Agno: salida estructurada para agentes, para contratos de respuesta respaldados por Pydantic.
- Agno: descripción general de las evaluaciones, para evaluaciones de exactitud, confiabilidad, rendimiento y agente como juez.
- Agno: AgentUI, para una UI autoalojable sobre datos de AgentOS.
- Documentación de Microsoft GraphRAG.
- RAPTOR: procesamiento abstractivo recursivo para recuperación organizada en árboles, Sarthi et al., 2024.
- LightRAG: generación aumentada por recuperación simple y rápida, Guo et al., 2024.
- Documentación de métricas de Ragas.
- Tríada RAG de TruLens.