Este post es el acompañamiento de mi charla en el AWS Summit CDMX 2026 (DEV302). No es un truco de free tier ni una demo de juguete: son 8 o 9 decisiones de ingeniería, cada una medida, que convierten el camino default (unos 250 dólares al mes) en algo que cabe en dos pizzas. Voy a mostrarte los números y el código.
Para que sea concreto uso un caso ficticio llamado Aula, una plataforma de cursos en línea con unos 1,000 estudiantes. El conocimiento ya existe: dudas resueltas, material de cada lección, ejercicios. Diez agentes convierten ese conocimiento en respuestas fundamentadas en el historial. Aula no es un producto real, pero los números sí salen de un sistema real.
El caso: qué hacen los diez agentes
Cinco flujos que ve el estudiante:
- Una duda ("no entiendo los closures"), que devuelve una explicación fundamentada en el historial.
- Una entrega (sube un ejercicio), que devuelve feedback editable, no la respuesta.
- Qué sigue ("¿qué estudio después?"), que devuelve la siguiente lección más un plan de 3 pasos.
- Buscar ("¿ya lo preguntaron?"), que devuelve dudas similares ya resueltas.
- Resumen de un hilo largo, que devuelve los puntos clave.
Diez agentes en total: classifier, extractor, retriever, enricher, synthesizer, drafter, summarizer, recommender, action_plan y quality_judge. Cada uno es una clase, no un framework. Ahí empieza la historia de costo.
El camino default cuesta 22 pizzas
Si sigues el tutorial que la mayoría encuentra, armas esto: Amazon Bedrock Agents, AgentCore, Amazon OpenSearch Serverless, un NAT Gateway, un Application Load Balancer, Amazon RDS Proxy y AWS X-Ray. Suma unos 250 dólares al mes. Diecisiete pizzas solo de piso fijo, antes de la primera petición.
El reto no es recortar. Recortar es fácil. El reto es sostener el mismo sistema, en producción, seguro, manejable y escalable, gastando lo que dos pizzas. Voy a cotizar cada decisión en pizzas que se comería de tu factura. Una rebanada son unos 1.75 dólares (unos 30 pesos). Una pizza son 8 rebanadas, unos 14 dólares. El tope: dos pizzas, 16 rebanadas, unos 28 dólares al mes.
Decisión 1: un modelo por tarea (el 90/10)
La palanca más grande, y la que no te vende nadie, es el tier por agente. No todos los pasos necesitan el modelo premium.
- 7 agentes en Amazon Nova Lite (clasificar, extraer, condensar, recomendar, evaluar).
- 2 agentes en Amazon Nova Pro, solo los que producen lo que LEE el estudiante (synthesizer y drafter).
- 1 agente con Amazon Titan Embeddings (el retriever, que no es un LLM de chat).
El resultado medido: el 90% de las llamadas al modelo van al tier económico, y el costo baja a unos 0.004 dólares por duda. Si todo corriera en Nova Pro, sería cerca de 10 veces más.
¿Y la calidad? No es fe. Un shadow run midió que Nova Lite clasifica con un 98.5% de acuerdo contra Nova Pro en esa tarea. El tier se elige por dificultad, no por default.
# El tier lo fija el agente, no el framework.
MODEL_LITE = "amazon.nova-lite-v1:0" # 7 agentes
MODEL_PRO = "amazon.nova-pro-v1:0" # 2 agentes: lo que LEE el estudiante
MODEL_EMB = "amazon.titan-embed-text-v2:0" # 1 agente: retrieval
class DrafterAgent(BaseAgent):
name, default_model = "drafter", MODEL_PRO
Ver code/base_agent.py y code/tier_routing.py.
Decisión 2: mata el piso fijo (ingreso y red)
Dos ausencias que casi nadie cuestiona, y que juntas valen casi 5 pizzas que no pago.
Amazon API Gateway, no Application Load Balancer. El ALB cuesta unos 16 dólares al mes fijos, pizza y media, llegue 1 persona o un millón. Amazon API Gateway HTTP API cobra por request: a 1,000 usuarios con tráfico modesto, cerca de 1.5 dólares al mes. Llega al contenedor por VPC Link y service discovery, sin ALB de por medio. ¿Cuándo sí ALB? Routing L7 sofisticado, WebSockets, o miles de peticiones por segundo.
AWS Fargate en subnet pública, no NAT Gateway. El NAT cuesta unos 33 dólares al mes fijos (3 pizzas) aunque el tráfico sea cero. Lo mío: subnet pública con IP pública y un security group que solo deja entrar al VPC Link. La IP es pública pero funcionalmente inalcanzable. Cuidado con el consejo de "usa VPC endpoints": 4 o 5 endpoints a 7 dólares cada uno salen más caros que el NAT. Valen por compliance, no por ahorro.
Decisión 3: usa lo que ya pagas
pgvector, no Amazon OpenSearch Service. A escala de miles de embeddings, pgvector basta y sobra. El menú arranca en OpenSearch a 174 dólares o más, entre 8 y 15 veces mi presupuesto, en una sola línea. Lo mío: CREATE EXTENSION vector en la misma Amazon RDS que ya pago. La pregunta correcta no es si pgvector es tan bueno, es si necesito lo que OpenSearch hace de más. A 3,000 vectores, no.
-- El retriever: distancia coseno con índice HNSW, prefiltrando por curso.
SELECT contenido, resolucion
FROM dudas_embedding
WHERE curso_id = :curso
ORDER BY embedding <=> :q
LIMIT :k;
Tus filas ya son la memoria. AgentCore Memory ofrece memoria semántica gestionada. Pero la memoria de Aula, qué respuestas sirvieron por tema, ya está en filas de Postgres. Leer 20 filas, agruparlas y meterlas al prompt como un bloque de historial son unas 120 líneas y 50 milisegundos. No gana por económico, gana por simplicidad y por no necesitar código nuevo.
Workers asyncio, no AWS Lambda por tarea. Los trabajos programados (reindex, resumen semanal, barrido de evaluaciones, recordatorios) corren como tareas asyncio dentro del contenedor de AWS Fargate que ya está prendido para la API. El break point honesto: con más de una réplica, un cron in process dispara doble, y ahí sí subes a Amazon EventBridge Scheduler apuntando a ECS RunTask (cerca de 0 dólares). Managed cuando el patrón lo justifica, no por default.
Decisión 4: observabilidad por log, no por traza
Latencia, tokens y costo por agente salen de una línea de log en formato EMF (Embedded Metric Format), que Amazon CloudWatch convierte en métrica sin ninguna llamada a la API en el hot path. AWS X-Ray a bajo volumen es casi gratis (unos 0.40 dólares), así que aquí el argumento no es el costo, es el acoplamiento: EMF no necesita SDK ni escala por traza, y tú decides qué métricas existen.
La trampa que sí cuesta dinero: meter un ID de alta cardinalidad (como student_id) como dimensión son miles de métricas custom, cientos de dólares al mes. Los IDs van al cuerpo del log, nunca a la dimensión.
# 1 línea EMF -> métrica en CloudWatch, sin PutMetricData.
def emit_emf(agent: str, model: str, latency_ms: float, cost_usd: float):
print(json.dumps({
"_aws": {"CloudWatchMetrics": [{
"Namespace": "aula/Agents",
"Dimensions": [["AgentName", "ModelUsed"]],
"Metrics": [{"Name": "LatencyMs"}, {"Name": "CostUsd"}],
}]},
"AgentName": agent, "ModelUsed": model,
"LatencyMs": latency_ms, "CostUsd": cost_usd,
}))
Ver code/emf.py.
Decisión 5: seguridad y resiliencia sin inflar la factura
Seguridad. El input del usuario entra a un LLM, así que va como dato delimitado, no como instrucción. Salida estructurada más el juez como respaldo. IAM al mínimo: bedrock:InvokeModel solo sobre los ARNs de mis 2 modelos, no un comodín. Guardrails gestionados solo a escala (PII, toxicidad) o por compliance.
Resiliencia. El estudiante espera unos 2 segundos. Amazon Bedrock puede responder 429 en picos. La respuesta: retry con backoff acotado por el presupuesto de latencia (2 intentos máximo) y fallback de tier. Si Nova Pro está throttled, degrada a Nova Lite con la confianza más baja. Degrada, no revienta. Provisioned Throughput solo si el 429 es crónico, no para un pico.
async def invoke_resilient(prompt, primary=MODEL_PRO, fallback=MODEL_LITE, budget_ms=2500):
for attempt in range(2):
try:
return await invoke(prompt, model=primary, timeout_ms=budget_ms)
except ThrottlingException:
await asyncio.sleep(min(0.2 * 2 ** attempt + jitter(), 0.6))
# sigue throttled: degrada, no revienta
return await invoke(prompt, model=fallback, confidence_penalty=0.15)
Ver code/resilience.py.
Dónde se va el costo, de verdad
Aquí está lo bonito de medir con EMF: puedes ver dónde vive cada dólar sin instrumentar nada extra.
| Concepto | Rebanadas | Costo aprox |
|---|---|---|
| AWS Fargate ×2, 24/7 | 12 | 22 dólares |
| Amazon Bedrock (10 agentes) | 2 | 3 dólares |
| EMF (métricas por log) | 1 | 2 dólares |
| Amazon API Gateway | 1 | 1 dólar |
| Total | 16 | ~28 dólares |
El 72% de la factura son los dos contenedores de AWS Fargate prendidos todo el tiempo. Todo lo demás junto son 5 rebanadas. La lección: el costo fijo que no usas es tu mayor fuga, y aquí ya está exprimido.
La parte honesta
- Redondeo a 2 pizzas, pero son unos 2 y cuarto. El redondeo lo absorbe.
- Las cifras del core (AWS Fargate, Amazon Bedrock, EMF) son medidas. Las de tool use en Aula son estimadas.
- El costo real de este sistema no es dinero, es tiempo de ingeniería y seguridad. Medir cada decisión toma más trabajo que aceptar el default.
Lo contraintuitivo: baja al crecer
Costo por estudiante al mes, a 1,000 estudiantes: unos 2 centavos.
Como la factura es costo fijo (los contenedores no escalan con el uso), se reparte. Más estudiantes, menos por cabeza. Es lo opuesto a una arquitectura lineal por request. A 10 usuarios sale carísimo por cabeza; a 1,000 sale a 2 centavos, y sigue bajando.
Para llevar
- El piso fijo que no usas es tu mayor fuga: NAT, ALB, OCU.
- Usa lo que ya pagas: pgvector, asyncio, filas como memoria.
- Haz coincidir el tier del modelo con la dificultad de la tarea (el 90/10).
- El patrón de uso elige la herramienta, no el default.
- La pregunta correcta no es "¿uso managed?", es "¿qué NO quiero mantener?".
Las slides, el código y las notas están en el repositorio. Si vas a construir agentes sobre Amazon Bedrock y el presupuesto importa, empieza por medir dónde se va cada dólar. Casi siempre es una sola cosa.
Demo: https://awssummitcdmx2026.elches.co/
elchesco
/
diez-agentes-dos-pizzas
Diez agentes en producción sobre Amazon Bedrock por el costo de dos pizzas al mes. Código de acompañamiento (AWS Summit CDMX 2026, DEV302).
Diez agentes en producción por el costo de dos pizzas al mes
Código de acompañamiento de la charla AWS Summit CDMX 2026 (DEV302): un sistema multi agente en producción sobre Amazon Bedrock, con Q&A, feedback de ejercicios, recomendaciones, búsqueda y resumen, para unos 1,000 usuarios, por unos 28 dólares al mes.
El caso es ficticio: Aula, una plataforma de cursos en línea con ~1,000 estudiantes. No es un producto real. Los números (latencia, costo por duda, picos de conexiones) salen de un sistema real. Los snippets son ilustrativos: muestran cada decisión de costo, no son un proyecto ejecutable completo.
Las decisiones, en código
Cada archivo es una decisión de la charla. Los marcados con 🔒 estaban en slides que oculté por tiempo, pero el código va aquí completo.
Archivo
Decisión
Gracias por leer. Preguntas y correcciones son bienvenidas.
Top comments (0)