Introducción
A fines de 2023, Intuit procesaba $2 billones en facturas anuales y manejaba $100 mil millones en reembolsos de impuestos. Para sostener ese volumen con IA, no bastaba con chatbots: necesitaban un sistema operativo capaz de orquestar agentes autónomos que ejecutaran tareas «done-for-you» para 100 millones de usuarios. Merrin Kurian, Distinguished Engineer en Intuit, presentó en QCon San Francisco los blueprints de GenOS, la plataforma que hoy soporta el 80% de la interacción repetida en QuickBooks y reduce hasta 12 horas mensuales de trabajo contable para sus clientes.
La transición de asistentes conversacionales a agentes autónomos no es trivial. Requiere redefinir flujos de trabajo, APIs «tool-ready», y métricas de evaluación que vayan más allá del prompt engineering. En este artículo, desglosamos cómo Intuit escaló GenOS usando el framework «fixed, flexible, free», los fallos críticos en agentes que descubrieron, y qué deberían replicar —o evitar— equipos de DevOps e infraestructura que ya implementan (o planean hacerlo) con IA generativa en producción.
Qué ocurrió
Intuit apostó por GenOS como capa de abstracción entre sus modelos de lenguaje (LLMs) y los productos finales (QuickBooks, TurboTax, Credit Karma). Según Kurian, el objetivo era pasar de asistentes que responden a agentes que actúan:
- 80% de engagement repetido en los agentes de QuickBooks (frente al 30-50% típico en chatbots genéricos).
- 12 horas/mes ahorradas por usuarios en tareas contables repetitivas.
- 1.7 millones de horas anuales de entrada de datos eliminadas en productos fiscales.
- 110 millones de preguntas resueltas por año en self-help (un orden de magnitud por encima de años anteriores).
El cambio no fue solo técnico, sino organizacional. GenOS se diseñó para escalar 8.000 desarrolladores y 3.500 experimentos mensuales en producción, usando un framework llamado «fixed, flexible, free»:
- Fixed: Estándares estrictos para componentes críticos (ej.: APIs de facturación, autenticación).
- Flexible: Capas de abstracción que permiten personalizar flujos sin romper contratos.
- Free: Autonomía controlada para equipos de producto, con guardrails técnicos.
Kurian destacó que el mayor desafío no fue el LLM-as-a-judge (evaluar respuestas con otro LLM), sino la latencia en orquestación. En pruebas internas, agentes que debían invocar 5+ herramientas secuencialmente superaban los 2 segundos de respuesta en el 40% de los casos. La solución fue implementar un sistema de colas priorizadas (similar a AWS SQS pero con timeout ajustados por SLA) y cachear resultados de herramientas idempotentes (ej.: extracción de datos de facturas).
Impacto para DevOps, Infraestructura y Cloud
El despliegue de GenOS redefine prioridades para equipos técnicos:
| Área | Impacto cuantitativo | Riesgo si no se actúa |
|---|---|---|
| **Infraestructura** | 3x aumento en peticiones a APIs internas (de ~1M/día a ~3M/día) | Fallos en *rate limiting* por saturación de LLMs. |
| **Seguridad** | 70% de los prompts incluyen datos sensibles (facturas, impuestos). | Exposición de PII por *prompt leakage*. |
| **SRE** | 20% de tickets se redujeron al pasar de *chat* a agentes autónomos. | Incremento en *mean time to detect* (MTTD) si no hay observabilidad en flujos. |
| **DevOps** | 8.000 desarrolladores usan GenOS diariamente. | *Technical debt* acumulado por APIs mal diseñadas («tool-ready»). |
Para equipos en la nube (AWS, GCP, Azure), GenOS es un caso de estudio en:
- Costos ocultos de LLM: A 0.03 USD/1K tokens (precio de 2024 para modelos como
gpt-4-turbo), 3M de peticiones/día = 900 USD/día solo en inferencia. Intuit redujo este costo un 40% usando caching de respuestas similares y fine-tuning de modelos pequeños para tareas específicas (ej.: extracción de datos de facturas). - Observabilidad: Implementaron métricas como agent completion rate (tasa de finalización exitosa del flujo) y tool call latency. Un dashboard en Grafana alertaba cuando un agente superaba los 1.5 segundos en invocar una herramienta.
- Seguridad por diseño: Usaron AWS IAM Roles for Services para restringir permisos de agentes a solo los recursos necesarios (principio de least privilege). En un post-mortem de 2024, descubrieron que un agente mal configurado intentó acceder a S3 buckets de impuestos fuera de su scope. La mitigación fue añadir policy conditions basadas en tags (
"IntendedUse": "agent-payment").
Detalles técnicos
Arquitectura de GenOS (versión 2.3, lanzada en Q1 2024)
graph TD
A[Usuario] -->|Prompt| B(GenOS Gateway)
B --> C{Orquestador}
C -->|Fixed Path| D[API Tool-Ready: Facturación]
C -->|Flexible Path| E[API Tool-Ready: Análisis de Margen]
D --> F[LLM: Extracción de Datos]
E --> F
F --> G[Evaluador: LLM-as-a-Judge]
G -->|Aprobado| H[Actualizar Base de Datos]
G -->|Rechazado| I[Registro de Fallo + Retry]
H --> J[Notificación al Usuario]Componentes clave y versiones:- Orquestador: Servicio interno en Kubernetes (versión 1.27) con horizontal pod autoscaler basado en métricas de tool call latency.
- LLM-as-a-Judge: Modelo propio basado en
mistral-7b-instruct(versión v0.2.1), fine-tuneado con 10K ejemplos de pares(prompt, respuesta_correcta). Usa métrica BLEURT para evaluar coherencia. - API Tool-Ready: Estándar de diseño que exige:
POST /invoices/extract debe devolver el mismo resultado para el mismo invoice_id.– Timeouts: Máximo 1 segundo para herramientas internas, 3 segundos para LLMs externos.
– Formato de respuesta: JSON estricto con campos result, confidence, next_actions (array).
- Caché: Usan Redis Cluster (versión 7.0.12) con TTL de 5 minutos para respuestas de herramientas. Redujo latencia en un 60% para consultas repetidas.
Fallos críticos detectados y mitigaciones
| Fallo | Root Cause | Solución implementada | Versión afectada |
|---|---|---|---|
| *Prompt injection* en agente de impuestos | LLMs expuestos a *system prompts* mal sanitizados. | Implementación de **AWS Nitro Enclaves** para aislar inferencia. | 1.0 – 1.8 |
| *Race condition* en actualización de facturas | Dos agentes intentaban modificar el mismo registro. | *Optimistic locking* con BLOCK18 en la DB (PostgreSQL 15). | 2.0 – 2.2 |
| *Timeouts* en OCR de facturas adjuntas | Librería BLOCK19 sin ajustes para PDFs de baja calidad. | Preprocesamiento con BLOCK20 + conversión a PNG antes de OCR. | 2.1 |
customer_id como parámetro, pero el LLM generaba user_id. La solución fue añadir un schema validator en el orquestador usando JSON Schema Draft 2020-12.Qué deberían hacer los administradores y equipos técnicos
1. Diseñar APIs «tool-ready» desde el inicio
No esperes a que el LLM falle para validar tu API. Sigue este checklist para cada endpoint que expongas a agentes:# Ejemplo de especificación OpenAPI 3.1 para una API tool-ready
openapi: 3.1.0
info:
title: InvoiceExtractor
version: 2.0.0
paths:
/invoices/extract:
post:
summary: Extrae datos de una factura adjunta
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExtractInvoiceRequest'
responses:
'200':
description: Datos extraídos exitosamente
content:
application/json:
schema:
$ref: '#/components/schemas/ExtractInvoiceResponse'
components:
schemas:
ExtractInvoiceRequest:
type: object
properties:
attachment_url:
type: string
format: uri
description: URL firmada a un archivo en S3 (máx. 10MB)
invoice_id:
type: string
pattern: '^INV-[0-9]{8}$'
required: [attachment_url, invoice_id]
ExtractInvoiceResponse:
type: object
properties:
result:
type: object
properties:
vendor_name:
type: string
example: "Acme Corp"
total_amount:
type: number
minimum: 0
example: 1250.50
currency:
type: string
enum: [USD, EUR, GBP]
required: [vendor_name, total_amount, currency]
confidence:
type: number
minimum: 0
maximum: 1
example: 0.92
next_actions:
type: array
items:
type: string
enum: ["validate_vendor", "check_duplicate"]
required: [result, confidence]Acciones concretas:- Idempotencia: Usa
PUToPOSTconIdempotency-Key(RFC 9110). Ejemplo:
curl -X POST https://api.intuit.com/invoices/extract \
-H "Idempotency-Key: inv-12345678" \
-H "Content-Type: application/json" \
-d '{"attachment_url": "https://s3...", "invoice_id": "INV-12345678"}'
- Timeouts: Configura client timeouts en 1 segundo para herramientas internas, 3 segundos para LLMs externos. En Python:
import httpx
client = httpx.Client(timeout=httpx.Timeout(1.0, connect=3.0))
- Validación estricta: Usa JSON Schema (como en el ejemplo) y añade un gateway como Kong o Ambassador para validar payloads antes de llegar al servicio.
2. Implementar métricas de agente end-to-end
GenOS usa un dashboard en Grafana con las siguientes métricas (valores de ejemplo):
| Métrica | Valor ideal | Umbral de alerta | Herramienta |
|---|---|---|---|
| *Agent Completion Rate* | >95% | <90% | Prometheus |
| *Tool Call Latency* (P95) | <1.5s | >3s | Datadog |
| *LLM Token Cost* (USD/día) | <500 USD | >1000 USD | AWS Cost Explorer |
| *Prompt Injection Attempts* | 0 | >1/día | SIEM (Splunk) |
- Agent Completion Rate:
% de flujos que terminan con éxito/total de flujos iniciados. - Tool Call Latency: Usa OpenTelemetry para trazar cada invocación de herramienta. Ejemplo de instrumentación en Go:
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
)
func extractInvoice(ctx context.Context, invoiceID string) error {
ctx, span := otel.Tracer("invoice").Start(ctx, "extractInvoice")
defer span.End()
start := time.Now()
defer func() {
metrics.ToolCallLatency.Record(ctx, time.Since(start).Seconds())
}()
// Lógica de extracción...
}
- LLM Token Cost: Integra con la API de tu proveedor (ej.:
openai.completion.costen AWS Bedrock). Ejemplo en Terraform:
resource "aws_cloudwatch_metric_alarm" "llm_cost_alarm" {
alarm_name = "llm-cost-high"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "1"
metric_name = "LLMCost"
namespace = "Intuit/GenAI"
period = "86400" # 1 día
statistic = "Sum"
threshold = "500"
alarm_actions = [aws_sns_topic.alerts.arn]
}
3. Proteger contra prompt injection y fuga de datos
El 70% de los prompts en GenOS incluyen datos sensibles. Usa estas capas de protección:- Aislamiento de inferencia:
– Ollama en modo air-gapped (sin conexión a internet) para modelos locales.
– Azure Confidential Computing para entornos híbridos.
- Sanitización de prompts:
– Lista negra de palabras: Bloquea prompts con patrones como "DROP TABLE" o "--" (SQLi).
– Validación de formato: Rechaza prompts que no cumplan con un schema estricto (ej.: máximo 500 tokens).
- Control de acceso:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["bedrock:InvokeModel"],
"Resource": ["arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-v2"],
"Condition": {
"StringEquals": {
"aws:ResourceTag/IntendedUse": "agent-payment"
}
}
}]
}
– API Gateway con WAF: Bloquea requests con headers sospechosos (ej.: X-Prompt-Injection: 1).
4. Prepararse para el futuro: agentes multi-tool
Intuit ya trabaja en agentes que orquestan múltiples herramientas (ej.: un agente de tax filing que:
- Extrae datos de facturas (herramienta A).
- Consulta el saldo bancario (herramienta B).
- Genera el formulario fiscal (herramienta C).
- Graph de herramientas: Representa dependencias entre herramientas. Ejemplo en Neo4j:
CREATE (a:Tool {name: "extract_invoice"})
CREATE (b:Tool {name: "get_bank_balance"})
CREATE (c:Tool {name: "generate_tax_form"})
CREATE (a)-[:NEXT]->(b)
CREATE (b)-[:NEXT]->(c)
- Planificación dinámica: Usa algoritmos como A* para calcular el camino óptimo. Librería recomendada: LLM Planning (de Microsoft Research).
- Rollback automático: Si una herramienta falla, deshace cambios parciales. Ejemplo con Saga Pattern en Go:
func taxFilingWorkflow(ctx context.Context) error {
saga := saga.NewSaga(ctx)
defer saga.Rollback()
invoiceData, err := extractInvoice(ctx, "INV-12345678")
if err != nil { return err }
saga.AddStep("extract_invoice", invoiceData)
bankBalance, err := getBankBalance(ctx, "ACCT-98765432")
if err != nil { return err }
saga.AddStep("get_bank_balance", bankBalance)
form, err := generateTaxForm(ctx, invoiceData, bankBalance)
if err != nil { return err }
saga.AddStep("generate_tax_form", form)
return saga.Commit()
}
Conclusión
GenOS no es un proyecto de AI research, sino un caso de ingeniería de sistemas a escala. Su éxito se basa en:
- APIs tool-ready: Diseñadas para ser consumidas por agentes, no por humanos.
- Observabilidad end-to-end: Métricas que capturan fallos en orquestación, no solo en el LLM.
- Seguridad por diseño: Aislamiento de inferencia, masking de PII, y control de acceso estricto.
- Equipos empoderados: El framework «fixed, flexible, free» permitió escalar 8.000 desarrolladores sin caer en technical debt.
Para equipos que ya usan (o planean usar) IA generativa en producción, la lección clave es clara: el futuro no son chatbots, sino agentes autónomos. Y esos agentes requieren una infraestructura tan robusta como la que ya exiges para tus servicios tradicionales. Empieza hoy: valida tus APIs, instrumenta métricas, y protege tus datos. El costo de no hacerlo no será solo técnico, sino de negocio.
