Optimización del rendimiento de Agno: de 2 segundos a 200ms
Agno es rápido desde el inicio. Pero alcanzar tiempos de respuesta por debajo de 200ms requiere patrones específicos.
5 de febrero de 2026
Agno ya es rápido. El equipo afirma 70x más rápido que LangChain, y en nuestros benchmarks, no es marketing—es real.
Pero "rápido" es relativo.
Cuando desplegamos por primera vez nuestro sistema de resolución de disputas, las respuestas del agente promediaban 2,1 segundos. Para un chatbot, está bien. Para mediación en tiempo real donde los usuarios esperan respuestas casi instantáneas, no lo está.
Necesitábamos sub-200ms.
Llegar ahí requirió patrones específicos—algunos obvios, algunos contraintuitivos. Este post desglosa exactamente qué hicimos, con ejemplos de código que puedes aplicar a tus propios despliegues de Agno.
Por qué importan los 200ms
Primero, hablemos de por qué nos preocupaba específicamente 200ms.
La investigación es clara
- • Menos de 100ms se siente instantáneo
- • 100-300ms se siente responsivo
- • 300-1000ms se siente notable
- • Más de 1000ms se siente lento
Para nuestro sistema de resolución de disputas, los usuarios están en situaciones emocionales. Están frustrados. Quieren respuestas. Cada segundo de latencia amplifica esa frustración.
Pero no es solo UX. A escala, la latencia se acumula:
Antes: 2,1 segundos
2.1s × 15,000 casos × 8 llamadas
= 78 horas de espera
Después: 200ms
0.2s × 15,000 casos × 8 llamadas
= 6,7 horas de espera
Son 71 horas de tiempo de usuario ahorradas. Por año. Para un solo sistema.
El punto de partida: 2,1 segundos
Empecemos con lo que teníamos. Aquí es donde se iba el tiempo:
| Componente | Tiempo |
|---|---|
| Serialización de contexto | 50ms |
| Llamada LLM (GPT-4) | 1,400ms |
| Ejecución de herramientas (secuencial) | 500ms |
| Parseo de respuesta | 50ms |
| Sobrecarga | 100ms |
| Total | 2,100ms |
GPT-4 era la mayor parte, pero no podíamos simplemente "hacer GPT-4 más rápido". Necesitábamos optimizar todo lo que controlábamos.
Patrón #1: Ejecución paralela de herramientas
La primera mejora fue obvia una vez que la miramos. Nuestro agente llamaba cuatro herramientas secuencialmente:
Llamadas secuenciales a herramientas
- 1. Recuperar contrato (120ms)
- 2. Recuperar precedentes (180ms)
- 3. Recuperar historial de partes (100ms)
- 4. Verificar reglas de jurisdicción (100ms)
Total: 500ms
Pero estas herramientas no dependen entre sí. Pueden correr en paralelo.
Después: Ejecución paralela
agent = DisputeAnalysisAgent(
tool_execution_mode="parallel" # Enable parallel tools
)
# Total: 180ms (longest tool)Resultado: 500ms → 180ms. 64% de reducción en tiempo de ejecución de herramientas.
Patrón #2: Enrutamiento de modelos
Aquí va el contraintuitivo: no toda tarea necesita GPT-4.
Nuestro análisis de disputas tenía múltiples subtareas:
- • Clasificación de casos (simple)
- • Extracción de entidades (media)
- • Razonamiento legal (complejo)
- • Cálculo de confianza (simple)
GPT-4 es excesivo para clasificación. Un modelo pequeño fine-tuned es más rápido Y más barato.
Implementación del Model Router
model = ModelRouter({
"classification": "gpt-3.5-turbo", # Fast, cheap
"extraction": "claude-3-haiku", # Good at structure
"reasoning": "gpt-4", # Complex tasks only
"scoring": "gpt-3.5-turbo", # Fast, cheap
})| Tarea | Antes (GPT-4) | Después (enrutado) |
|---|---|---|
| Clasificación | 400ms | 80ms |
| Extracción | 350ms | 120ms |
| Razonamiento | 500ms | 500ms |
| Puntuación | 150ms | 40ms |
| Tiempo total LLM | 1,400ms | 740ms |
Resultado: 1,400ms → 740ms. 47% de reducción en tiempo LLM.
Para casos simples (60% del volumen), omitimos GPT-4 por completo: 1,400ms → 280ms
Patrón #3: Optimización de contexto
Estábamos pasando demasiado contexto. Para un caso complejo, podía ser 15,000+ tokens de contexto.
Problema: Más tokens = más latencia. El time-to-first-token de GPT-4 escala con el tamaño del input.
Construir contexto mínimo por tarea
def build_optimized_context(case: Case, task: str) -> str:
# Always include core identifiers
base = f"Case: {case.id} | Type: {case.dispute_type}"
if task == "classification":
return base + f"\nDescription: {case.description[:500]}"
elif task == "reasoning":
# Only for complex reasoning do we include more
relevant_docs = retrieve_relevant_chunks(case, top_k=3)
return base + f"\nRelevant Sections: {relevant_docs}"
return base
# Before: 10,000+ tokens
# After: 200-800 tokens depending on taskResultado: Reducción promedio de 100ms solo por optimización de contexto.
Patrón #4: Streaming de respuesta con salida temprana
Para muchas tareas, no necesitamos la respuesta completa. Podemos empezar a procesar en cuanto tenemos suficiente.
Stream y salida temprana
async def get_classification(case: Case) -> str:
async for chunk in agent.stream(prompt):
# Check if we have enough to classify
if classification := try_parse_classification(chunk):
return classification # Exit early
# Fallback: parse complete response
return parse_classification(chunk)Para tareas de clasificación, típicamente salimos después de que se genera el 30-40% de la respuesta.
Resultado: 80ms → 35ms para clasificación. 56% de reducción.
Patrón #5: Caché inteligente
Muchos inputs se repiten o son similares. El caché evita cómputo redundante.
Capa 1: Caché de coincidencia exacta
Usa caché LRU con hashing de prompts. Tasa de acierto: ~15%
Capa 2: Caché semántica
Para prompts similares (no idénticos), usa caché basada en embeddings con umbral de similitud de 0.95. Tasa de acierto: ~25%
Capa 3: Caché de resultados de herramientas
Los resultados de herramientas suelen no cambiar frecuentemente. Cachéa contratos por 1 hora, reglas por 5 minutos. Tasa de acierto: ~60%
Resultado: Reducción efectiva de 30-40% en latencia promedio gracias al caché.
Patrón #6: Connection pooling y keep-alive
Este es aburrido pero impactante. Una conexión nueva = 100-200ms de overhead.
Agrupación de conexiones
http_client = httpx.Client(
http2=True,
limits=httpx.Limits(
max_connections=100,
max_keepalive_connections=20,
keepalive_expiry=30
)
)
agno.configure(
http_client=http_client,
connection_pool_size=100
)Resultado: Reducción de 100-200ms en la primera petición, latencia baja y consistente en peticiones subsiguientes.
Patrón #7: Async de punta a punta
Si estás haciendo algo síncrono en tu pipeline de agentes, estás dejando rendimiento sobre la mesa.
Pipeline asíncrono
async def process_case(case: Case) -> Result:
# Independent steps run in parallel
classification, entities = await asyncio.gather(
classify(case),
extract_entities(case)
)
# Dependent step runs after
analysis = await analyze(case, classification, entities)
return Result(classification, entities, analysis)Antes: 80ms + 120ms + 500ms = 700ms
Después: max(80ms, 120ms) + 500ms = 620ms
El resultado combinado
| Optimización | Reducción | Nuevo total |
|---|---|---|
| Punto de partida | — | 2,100ms |
| Herramientas en paralelo | -320ms | 1,780ms |
| Enrutamiento de modelos | -660ms | 1,120ms |
| Optimización de contexto | -100ms | 1,020ms |
| Streaming + salida temprana | -45ms | 975ms |
| Caché (30% de tasa de acierto) | -290ms | 685ms |
| Agrupación de conexiones | -150ms | 535ms |
| Pipeline asíncrono | -80ms | 455ms |
Espera—eso son 455ms, no 200ms. Correcto. Para el caso promedio.
Casos simples (60% del volumen)
175ms
Clasificación 35ms + Extracción 60ms + Análisis 80ms
Casos complejos (40% del volumen)
650ms
Incluye GPT-4 para razonamiento complejo
Promedio ponderado: 365ms
Con caché: 255ms
Llegamos a menos de 200ms para casos simples, menos de 300ms de promedio ponderado. 88% de reducción respecto al punto de partida.
La prioridad de optimización
Si estás optimizando el rendimiento de Agno, este es el orden de prioridad:
1. Enrutamiento de modelos — Mayor impacto. No uses GPT-4 para tareas simples.
2. Ejecución paralela de herramientas — Ganancia fácil. Actívala.
3. Caché — Retornos compuestos. Empieza con resultados de herramientas.
4. Optimización de contexto — Menos tokens, menos latencia.
5. Connection pooling — Configuración única, beneficio permanente.
6. Pipeline asíncrono — Si tienes pasos independientes.
7. Streaming + salida temprana — Para tareas de clasificación/extracción.
No necesitas todas estas. Implementa 1-3 y verás una mejora dramática.
Cuándo NO optimizar
Una palabra de precaución: la optimización prematura sigue siendo una cosa.
No optimices si:
- • Tu latencia ya es aceptable para tu caso de uso
- • Aún estás iterando en el comportamiento del agente
- • Aún no tienes tráfico en producción
- • El costo de complejidad supera el beneficio de latencia
Primero haz que funcione. Luego haz que sea correcto. Después hazlo rápido.
Reflexión final
Agno es rápido. Pero "rápido" es un punto de partida, no un destino.
Los patrones aquí—enrutamiento de modelos, ejecución en paralelo, caché, optimización de contexto—no son específicos de Agno. Son principios generales para construir sistemas de IA performantes.
De 2 segundos a 200ms no es magia. Es metodología.
¿Construyendo sistemas de IA críticos en rendimiento?
HablemosHemos hecho este baile de optimización en múltiples despliegues en producción.
Newsletter
Patrones de rendimiento e insights de producción—cada martes.
Únete a 2,500+ ingenieros y líderes que reciben insights prácticos de implementación de IA.
Suscríbete a AI That Ships