Arquitecto de automatización con IA: Día 84
Índice de contenido
Resumen:
Don Ernesto repite la pregunta que hizo el Día 12, “¿cuánto nos cuesta esto al mes? Y no me diga ‘depende’”, y hoy la respuesta es una factura. Valeria suma rubro por rubro las piezas que midió cada día de la serie: el ecosistema de Trigo Lento cuesta $40.53$ USD al mes con todo encendido, $4.18$ más de lo que estimó el plan de la serie y $4.47$ por debajo del tope de $45$. Reparte ese coste entre los $23$ flujos del inventario, mide cuánto se desvió cada rubro de la Tabla E del Día 12, calcula qué pasa con la factura si las tarifas de WhatsApp en México se mueven dentro del rango que publican las fuentes, proyecta el gasto con un crecimiento del $5%$ mensual (el presupuesto se rompe en el cuarto mes si no se hace nada) y acciona tres palancas con evidencia que dejan mayo en $38.44$ USD. El retorno cierra la cuenta: $68.24$ horas ahorradas al mes valen $276.64$ USD, casi siete veces el gasto. Al terminar, usted sabrá construir la factura de un ecosistema de automatizaciones a partir de sus piezas, repartirla por flujo, proyectarla con crecimiento y decidir qué palanca accionar con números y no con entusiasmo.
¿Cómo citar el presente artículo?
Romero, J. (25 de abril de 2026). Arquitecto de automatización con IA: Día 84. python-data-engineer. https://www.python-data-engineer.com/post/aai/dia_84/.
Arquitecto de automatización con IA: Día 84 by Jeshua Romero Guadarrama, available under Attribution 4.0 International (CC BY 4.0) at https://www.python-data-engineer.com/post/aai/dia_84/.
Precios, límites y políticas revisados en octubre de 2026: planes, precios y límites de Make, n8n, Zapier, WhatsApp (Meta, Twilio, Wati) y de la API de Claude. Los precios por millón de tokens de Claude Opus 5.5 ($4$ y $20$ USD), Sonnet 5.5 ($2$ y $10$), Haiku 5.5 ($0.10$ y $0.50$ hasta $100,000$ tokens de entrada), las lecturas de caché ($0.20$, $0.10$ y $0.01$) y el descuento del $50%$ de la API de lotes se contrastaron con la página oficial de precios de la plataforma de Claude. La página de precios de Meta confirma que desde el 1 de octubre de 2026 los mensajes de servicio se cobran a partir de los $1,000$ gratuitos al mes por número y que México tiene tarifa propia; las cifras de México ($0.0085$ USD de utilidad y $0.0397$ de marketing) siguen saliendo de fuentes secundarias que no coinciden entre sí, y por eso la entrada calcula la factura con el rango completo. La página de precios de Make no publica el precio del plan Core, que la serie mantiene en $10.59$ USD en pago mensual según las fuentes consultadas; Looker Studio sigue siendo gratuito y su versión Pro cuesta $9$ USD por usuario y proyecto al mes según fuentes secundarias. Los dos puntos de la API de administración de Claude que usa el Bloque 10, el informe de costes (/v1/organizations/cost_report, en centavos como cadena decimal, solo diario) y el de uso (/v1/organizations/usage_report/messages), se contrastaron con su referencia oficial; ese bloque requiere una clave de administración, no se ejecutó y su salida es un ejemplo. Los otros nueve bloques son Python que se ejecuta sin red sobre las cifras que dejó cada día y sus salidas son las reales.
Día 84. Proyecto integrador V: costes finales frente a los 45 USD
Introducción
Ayer, en el Día 83 (Proyecto integrador IV: pruebas de punta a punta y de caos), Valeria sometió el ecosistema a pruebas de punta a punta con los mensajes reales de un día y a pruebas de caos con el servidor apagado y el token caducado, y Trigo Lento ganó la certeza de que sus flujos se degradan como dicen los manuales y no como quiere el azar. Hoy toca la pregunta que no se puede responder con una prueba, porque su respuesta es una factura.
Es viernes 24 de abril, a las seis de la tarde. Valeria tiene abiertas cuatro pestañas: la consola de Claude con el gasto del mes, la página de facturación de Make, el recibo del proveedor del servidor y el panel de WhatsApp Business con los mensajes entregados por categoría. Al lado, el cuaderno de Python con el que ha medido el coste de cada pieza desde el Día 12 (Costes y límites: créditos, tareas, ejecuciones y cuotas). Cada día de la serie dejó una cifra, y el Día 77 dejó además una deuda: la reserva del presupuesto estaba en $4.02$ USD y la decisión sobre qué hacer con ella quedó aplazada “para el Día 84, el día del coste total”. Ese día es hoy.
Don Ernesto llega con la misma libreta de compras del Día 12, la de la harina y la mantequilla, y hace la misma pregunta de entonces, palabra por palabra: "¿Cuánto nos cuesta esto al mes? Y no me diga ‘depende’. Hace ochenta días me dijo que primero había que saber qué cuenta cada plataforma como un bulto. Ya lo sabe. Ahora quiero el total, y quiero saber si el total va a seguir siendo el total cuando vendamos más." Son tres preguntas en una: cuánto cuesta hoy, cuánto costará si el negocio crece y qué se puede hacer al respecto. Las tres tienen respuesta numérica, y la última además tiene una decisión que le toca a él.
En la presente entrada, descubrirá cómo se construye la factura mensual de un ecosistema de automatizaciones a partir de las piezas que midió cada día, con los precios revisados en octubre de 2026 y con el día que respalda cada cifra. Repartirá esa factura entre los $23$ flujos del inventario del Día 79, con una regla explícita para los costes fijos; medirá la desviación de cada rubro frente al reparto inicial de la Tabla E y explicará cada una con su causa; calculará la sensibilidad de la factura a las tarifas de WhatsApp en México, que las fuentes no publican igual, y al tipo de cambio; proyectará el gasto a $18$ meses con un crecimiento del $5%$ mensual y encontrará el mes en que se rompe el presupuesto; ordenará ocho palancas de ahorro por efecto, evidencia y riesgo; y cerrará con el retorno: cuántas horas ahorra el ecosistema cada mes, cuánto valen y cuántas de ellas bastan para pagarlo. Al final, Don Ernesto tendrá su cifra, y usted el método para calcular la suya.
Objetivos de aprendizaje
Al terminar esta entrada, usted podrá:
- Calcular el coste mensual final del ecosistema por rubro y por flujo con los precios revisados en octubre de 2026.
- Compararlo con el presupuesto de $45$ USD y con el reparto inicial de la Tabla E, y explicar cada desviación con su causa.
- Proyectar el coste con un crecimiento del $5%$ mensual y encontrar el mes en que se rompe el presupuesto.
- Calcular el retorno, horas ahorradas frente a gasto, y definir las palancas de ahorro si el negocio crece.
La factura del mes
Una factura mensual de automatizaciones tiene una propiedad que la distingue de la de la harina: ningún proveedor la emite completa. Make cobra su plan; el proveedor del servidor cobra el servidor; Meta cobra los mensajes entregados; la consola de Claude cobra los tokens; y Slack, Notion y Looker Studio no cobran nada mientras Trigo Lento quepa en sus planes gratuitos. Lo que Don Ernesto quiere ver no existe en ninguna de esas páginas: hay que construirlo. Y la forma honesta de construirlo no es sumar cuatro recibos, sino sumar las piezas que la serie fue midiendo, cada una con el día que la midió, para que cualquier cifra se pueda rastrear hasta el cálculo que la produjo.
El coste total del mes se escribe como la suma de una parte fija y una variable:
$$ C = F + V = \underbrace{P_{M} + P_{S}}{F} + \underbrace{\sum{m} \frac{t^{e}{m}, p^{e}{m} + t^{s}{m}, p^{s}{m} + t^{c}{m}, p^{c}{m}}{10^{6}} + \sum_{j} n_{j}, r_{j}}_{V} $$
La lógica detrás de la fórmula es la siguiente:
- $P_M$ y $P_S$ son el plan de Make y el servidor de n8n: se pagan el primer día del mes, se usen o no, y por eso forman la parte fija $F$. El Día 12 ya advirtió que proyectar lo fijo como si se gastara poco a poco hace saltar las alarmas el día 1.
- Para cada modelo $m$, $t^e$, $t^s$ y $t^c$ son los tokens de entrada sin caché, de salida y leídos de la caché, y $p^e$, $p^s$ y $p^c$ sus precios por millón; la serie midió cada pieza por separado, de modo que hoy la suma no vuelve a contar tokens, sino que recoge el resultado de cada día.
- $n_j$ y $r_j$ son los mensajes de WhatsApp de cada categoría $j$ (servicio por encima de la franquicia, utilidad y marketing) y su tarifa por mensaje entregado.
- En conclusión, la parte variable $V$ es la única que crece con el negocio, y por eso es la que se proyecta más adelante; la parte fija solo cambia si cambia el plan.
El primer bloque fija las importaciones, la semilla de la serie (hoy casi todo es aritmética, pero la regla se cumple), la fecha del cierre y los tipos de cambio didácticos:
# Importaciones base, semilla de la serie, fecha del cierre y carpeta del día en Python:
import warnings
warnings.filterwarnings('ignore')
import json
import math
import re
from datetime import date
from pathlib import Path
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# Generador aleatorio con la semilla global de la serie (hoy casi todo es aritmética, pero la regla se cumple):
rng = np.random.default_rng(2026)
pd.set_option('display.width', 170)
pd.set_option('display.max_colwidth', 60)
carpeta = Path('trigo_lento') / 'dia_84'
carpeta.mkdir(parents = True, exist_ok = True)
hoy = date(2026, 4, 24)
PRESUPUESTO, TC, USD_POR_EUR = 45.00, 18.50, 1.08 # tope mensual y tipos de cambio didácticos de la serie
DIAS = ['lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado', 'domingo']
print('numpy', np.__version__, '| pandas', pd.__version__)
print(f'Cierre de costes: {DIAS[hoy.weekday()]} {hoy:%d/%m/%Y} | tope: {PRESUPUESTO:.2f} USD = {PRESUPUESTO * TC:,.2f} MXN al mes')
numpy 2.4.6 | pandas 3.0.3
Cierre de costes: viernes 24/04/2026 | tope: 45.00 USD = 832.50 MXN al mes
Los precios son la materia prima de todo el día, y por eso van en un bloque propio, con su fecha de revisión y con el rango que publican las fuentes cuando no coinciden. El siguiente bloque los reúne desde las Tablas A, B y C de la serie:
# Precios de las Tablas A, B y C de la serie con su fecha de revisión en Python:
REVISION = 'octubre de 2026'
MODELOS = pd.DataFrame({ # USD por millón de tokens
'claude-opus-5-5': {'entrada': 4.00, 'salida': 20.00, 'lectura de caché': 0.20, 'lote entrada': 2.00, 'lote salida': 10.00},
'claude-sonnet-5-5': {'entrada': 2.00, 'salida': 10.00, 'lectura de caché': 0.10, 'lote entrada': 1.00, 'lote salida': 5.00},
'claude-haiku-5-5': {'entrada': 0.10, 'salida': 0.50, 'lectura de caché': 0.01, 'lote entrada': 0.05, 'lote salida': 0.25}}).T
PLATAFORMAS = {'Make Core, 10 000 créditos (pago mensual)': 10.59,
'Servidor de n8n: 5.99 EUR al mes, presupuestado en la Tabla E a': 6.00,
'Slack Free, Notion Free, Looker Studio, Google Sheets y Drive': 0.00}
WHATSAPP = pd.DataFrame({ # USD por mensaje entregado en México
'utilidad': {'usado': 0.0085, 'mínimo publicado': 0.0040, 'máximo publicado': 0.0150},
'servicio': {'usado': 0.0085, 'mínimo publicado': 0.0000, 'máximo publicado': 0.0085}, # 0 en el régimen anterior
'marketing': {'usado': 0.0397, 'mínimo publicado': 0.0305, 'máximo publicado': 0.0436}}).T
FRANQUICIA = 1_000 # mensajes de servicio gratis al mes por número desde el 1-oct-2026
VOLUMEN_WA = {'respuestas de servicio': 1_408, 'recordatorios de recogida': 327.6, 'mensajes de marketing': 80}
print(f'Precios revisados en {REVISION}. Modelos (USD por millón de tokens):')
print(MODELOS.to_string())
for nombre, usd in PLATAFORMAS.items():
print(f' {nombre}: {usd:.2f} USD al mes')
print('WhatsApp, Cloud API de Meta (USD por mensaje entregado):')
print(WHATSAPP.to_string())
print(f'Servidor al tipo didáctico: {5.99 * USD_POR_EUR:.2f} USD; diferencia frente a la Tabla E: {5.99 * USD_POR_EUR - 6.00:+.2f}')
Precios revisados en octubre de 2026. Modelos (USD por millón de tokens):
entrada salida lectura de caché lote entrada lote salida
claude-opus-5-5 4.0 20.0 0.20 2.00 10.00
claude-sonnet-5-5 2.0 10.0 0.10 1.00 5.00
claude-haiku-5-5 0.1 0.5 0.01 0.05 0.25
Make Core, 10 000 créditos (pago mensual): 10.59 USD al mes
Servidor de n8n: 5.99 EUR al mes, presupuestado en la Tabla E a: 6.00 USD al mes
Slack Free, Notion Free, Looker Studio, Google Sheets y Drive: 0.00 USD al mes
WhatsApp, Cloud API de Meta (USD por mensaje entregado):
usado mínimo publicado máximo publicado
utilidad 0.0085 0.0040 0.0150
servicio 0.0085 0.0000 0.0085
marketing 0.0397 0.0305 0.0436
Servidor al tipo didáctico: 6.47 USD; diferencia frente a la Tabla E: +0.47
Tres detalles de la salida importan para lo que sigue. El primero es que los precios de los tres modelos guardan proporciones exactas: Sonnet 5.5 cuesta la mitad de Opus 5.5 en entrada, salida y lote, y Haiku 5.5 cuesta cuarenta veces menos que Opus 5.5 en entrada; esa aritmética es la que hace que “cambiar de modelo” sea la palanca más grande y la más peligrosa a la vez. El segundo es que las tarifas de WhatsApp en México llevan un rango: la de utilidad va de $0.0040$ a $0.0150$ USD según la fuente y la de marketing de $0.0305$ a $0.0436$, y la serie usa $0.0085$ y $0.0397$; la sección de sensibilidad mide cuánto importa esa incertidumbre. El tercero es el servidor: cuesta $5.99$ EUR, que al tipo didáctico de $1.08$ son $6.47$ USD, pero la Tabla E del Día 12 lo presupuestó en $6.00$ y la serie lo ha contabilizado así desde entonces; los $0.47$ de diferencia se anotan en la sensibilidad y no se esconden.
Con los precios en su sitio, el siguiente bloque construye la factura: una lista de $22$ piezas con su rubro, su descripción, el día que la midió y su coste mensual, agrupada por rubro, comparada con lo que estimó el plan de la serie y dibujada como el puente que va del tope de $45$ USD a lo que queda:
# Factura del mes rubro por rubro, con la pieza y el día que la midió, en Python:
u, m = WHATSAPP.loc['utilidad', 'usado'], WHATSAPP.loc['marketing', 'usado']
PIEZAS = [ # (rubro, pieza, día que la midió, USD al mes)
('Make Core', 'Plan Core: 4 escenarios activos, 2 430 de 10 000 créditos', 12, 10.59),
('Servidor de n8n', 'VPS de 2 vCPU y 4 GB para n8n, Postgres y el servidor MCP', 34, 6.00),
('WhatsApp (Cloud API)', f'Respuestas de servicio que pasan de {FRANQUICIA:,}: 408 x {u}', 46, 408 * u),
('WhatsApp (Cloud API)', f'Recordatorios de recogida (utilidad): 327.6 x {u}', 46, 327.6 * u),
('WhatsApp (Cloud API)', f'Secuencia de bienvenida (marketing): 80 x {m}', 48, 80 * m),
('Claude y embeddings', 'Cascada de clasificación de mensajes', 30, 1.470),
('Claude y embeddings', 'Agente de pedidos v3 con caché', 61, 2.570),
('Claude y embeddings', 'Gmail: clasificación y borradores (con caché)', 47, 1.287),
('Claude y embeddings', 'Chatbot y traducción de WhatsApp', 48, 0.360),
('Claude y embeddings', 'Plan de horneado semanal (esfuerzo medium)', 57, 0.470),
('Claude y embeddings', 'Facturas y remisiones en PDF (lote)', 58, 0.417),
('Claude y embeddings', 'Lote nocturno: etiquetas y resumen', 60, 1.664),
('Claude y embeddings', 'Consulta de inventario por MCP', 63, 0.705),
('Claude y embeddings', 'Batería de 30 ataques, 2 corridas', 64, 0.840),
('Claude y embeddings', 'Remisiones de proveedores', 66, 0.440),
('Claude y embeddings', 'Informe del lunes con comprobador', 67, 0.337),
('Claude y embeddings', 'Embeddings de la sincronización con Notion', 68, 0.0002),
('Claude y embeddings', 'Preguntas frecuentes con recuperación (escalado a Opus 5.5)', 69, 3.166),
('Claude y embeddings', 'Evaluación semanal del agente', 70, 0.372),
('Claude y embeddings', 'Calendario editorial, visión y textos alternativos', 71, 0.299),
('Claude y embeddings', 'Campaña de primavera, 4 al año', 77, 0.1169),
('Gratuitos', 'Slack Free, Notion Free, Looker Studio, Google Sheets y Drive (copias)', 50, 0.0),
]
piezas = pd.DataFrame(PIEZAS, columns = ['rubro', 'pieza', 'dia', 'usd'])
ORDEN = ['Make Core', 'Servidor de n8n', 'WhatsApp (Cloud API)', 'Claude y embeddings', 'Gratuitos']
factura = piezas.groupby('rubro').agg(piezas = ('pieza', 'size'), usd = ('usd', 'sum')).reindex(ORDEN)
factura['mxn'] = factura.usd * TC
factura['porcentaje'] = 100 * factura.usd / factura.usd.sum()
total = factura.usd.sum()
libre = PRESUPUESTO - total
PLAN_SERIE = {'Make Core': 10.59, 'Servidor de n8n': 6.00, 'WhatsApp (Cloud API)': 11.18, 'Claude y embeddings': 8.58, 'Gratuitos': 0.0}
factura['plan de la serie'] = pd.Series(PLAN_SERIE)
factura.round(2).to_csv(carpeta / 'factura_2026-04.csv')
print(factura.round(2).to_string())
print(f'Total: {total:.2f} USD = {total * TC:,.2f} MXN | libres frente al tope: {libre:.2f} USD ({100 * libre / PRESUPUESTO:.1f} %)')
print(f'El plan de la serie estimó {sum(PLAN_SERIE.values()):.2f} USD; la cuenta con todo encendido es {total:.2f}: {total - sum(PLAN_SERIE.values()):+.2f}')
# Cascada del presupuesto: del tope de 45 USD a lo que queda, rubro por rubro:
pasos = [('Tope', PRESUPUESTO)] + [(r, -factura.loc[r, 'usd']) for r in ORDEN if factura.loc[r, 'usd'] > 0] + [('Libres', libre)]
fig, ax = plt.subplots(figsize = (9, 4.6))
nivel = 0.0
for i, (nombre, valor) in enumerate(pasos):
if i == 0 or nombre == 'Libres':
ax.bar(i, valor, color = '#4472C4' if i == 0 else '#70AD47', width = 0.6)
ax.text(i, valor + 0.6, f'{valor:.2f}', ha = 'center', fontsize = 10)
nivel = valor
else:
ax.bar(i, -valor, bottom = nivel + valor, color = '#eb6834', width = 0.6)
ax.text(i, nivel + 0.6, f'{valor:.2f}', ha = 'center', fontsize = 10)
ax.plot([i - 0.8, i + 0.3], [nivel, nivel], color = '#8a8986', lw = 0.8, ls = ':')
nivel += valor
ax.axhline(sum(PLAN_SERIE.values()), color = '#7b4fc9', lw = 1.2, ls = '--')
ax.text(len(pasos) - 0.6, sum(PLAN_SERIE.values()) + 0.5, 'plan de la serie: 36.35', color = '#7b4fc9', ha = 'right', fontsize = 9)
ax.set_xticks(range(len(pasos)), [p[0].replace(' (Cloud API)', '').replace(' y embeddings', '') for p in pasos], fontsize = 9)
ax.set_ylabel('USD al mes')
ax.set_ylim(0, 50)
ax.set_title('El puente del presupuesto: de 45 USD a lo que queda', fontsize = 13)
ax.spines[['top', 'right']].set_visible(False)
plt.tight_layout()
plt.show()
piezas usd mxn porcentaje plan de la serie
rubro
Make Core 1 10.59 195.92 26.13 10.59
Servidor de n8n 1 6.00 111.00 14.80 6.00
WhatsApp (Cloud API) 3 9.43 174.43 23.26 11.18
Claude y embeddings 16 14.51 268.51 35.81 8.58
Gratuitos 1 0.00 0.00 0.00 0.00
Total: 40.53 USD = 749.85 MXN | libres frente al tope: 4.47 USD (9.9 %)
El plan de la serie estimó 36.35 USD; la cuenta con todo encendido es 40.53: +4.18

El ecosistema de Trigo Lento cuesta $40.53$ USD al mes con todo encendido, $749.85$ MXN al tipo didáctico, y deja $4.47$ USD libres frente al tope de $45$. La Tabla 1 la presenta rubro por rubro, con las piezas que suma cada uno y con la cifra que el plan de la serie estimó el Día 1 para este mismo día.
Tabla 1. Coste mensual final del ecosistema de Trigo Lento, abril de 2026 (USD, precios revisados en octubre de 2026).
| Rubro | Piezas que suma | USD al mes | MXN al mes | Porcentaje | Plan de la serie | Día que lo midió |
|---|---|---|---|---|---|---|
| Make Core (pago mensual) | 1: cuatro escenarios, 2 430 créditos | 10.59 | 195.92 | 26.1 % | 10.59 | 12 |
| Servidor de n8n | 1: VPS de 2 vCPU y 4 GB | 6.00 | 111.00 | 14.8 % | 6.00 | 34 |
| WhatsApp (Cloud API directa) | 3: servicio, recordatorios y bienvenida | 9.43 | 174.43 | 23.3 % | 11.18 | 46 y 48 |
| Claude y embeddings | 16: de la cascada del Día 30 a la campaña del Día 77 | 14.51 | 268.51 | 35.8 % | 8.58 | 30 a 77 |
| Slack, Notion, Looker Studio, Sheets y Drive | 1: planes gratuitos | 0.00 | 0.00 | 0.0 % | 0.00 | 50 y 75 |
| Total | 22 | 40.53 | 749.85 | 100 % | 36.35 | 84 |
| Libres frente al tope | 4.47 | 82.65 | 9.9 % | 8.65 |
La tabla cuenta dos historias a la vez. La primera es la del total: $40.53$ frente a los $36.35$ que el plan de la serie escribió antes de construir nada, $4.18$ USD de diferencia, un $11.5%$. La segunda es la del reparto, y es más interesante que la primera: el plan acertó los dos rubros fijos al centavo, se equivocó a favor en WhatsApp ($9.43$ frente a $11.18$, porque el Día 46 eligió la Cloud API directa y no pagó recargo de proveedor) y se equivocó en contra en Claude ($14.51$ frente a $8.58$). El plan subestimó la inteligencia en un $69%$ y sobrestimó la mensajería en un $16%$; los dos errores no se cancelan, y la factura queda por encima del plan y por debajo del tope.
La Figura 1 la dibuja como el ticket que Don Ernesto recibe del molino cada semana: un renglón por rubro, con su cantidad, su precio y su día, el total, lo pagado y el cambio.
Figura 1. La factura del mes como ticket de la panadería: cada rubro es un renglón con su cantidad y su precio (Make Core 10.59, servidor 6.00, WhatsApp 9.43 y Claude con embeddings 14.51 USD), los servicios gratuitos van a 0.00, el total es 40.53 USD, se pagan 45 y el cambio son 4.47 USD.
La gráfica del bloque es la misma idea en forma de puente: cada rubro es un tramo que baja desde los $45$ USD, y lo que queda al final es la reserva real, no la que dice una tabla. La línea punteada del plan de la serie, en $36.35$, queda justo por encima del tramo de Claude: ahí está toda la diferencia. Y conviene decir desde ahora lo que la factura no incluye, porque el Día 76 (Anatomía de un fallo real IV: la publicación que salió sin aprobación) dejó claro que el coste de una automatización no es solo su recibo: no incluye las dos horas mensuales de mantenimiento del servidor que el Día 34 valoró en $8.11$ USD, porque son horas de Valeria y no dinero que sale; no incluye los créditos de servicio del acuerdo con Brújula del Día 82, porque tienen tope y no se han pagado nunca; y no incluye ningún coste de fallo, porque hoy se cuenta lo que se paga, no lo que se arriesga.
Coste por flujo
La Tabla 1 le dice a Don Ernesto cuánto cuesta el ecosistema; no le dice cuánto cuesta cada cosa que el ecosistema hace. Para eso hace falta repartir la factura entre los flujos, y el reparto tiene una dificultad que el Día 75 (Cuadros de mando de las automatizaciones: métricas, costes y errores) ya encontró al construir el registro común: los costes variables se asignan solos, porque cada llamada a Claude y cada plantilla de WhatsApp sale de un flujo concreto, pero los costes fijos no son de nadie. Make Core cuesta $10.59$ USD tanto si sus cuatro escenarios corren una vez como mil, y el servidor cuesta $6.00$ tanto si n8n ejecuta un flujo como veinte.
La regla de reparto que usa Valeria es explícita, y por eso discutible, que es lo que debe ser una regla de reparto:
$$ c_i = v_i + P_{M} \cdot \frac{cr_i}{\sum_{k \in \text{Make}} cr_k} + \frac{P_{S}}{n_{\text{n8n}}} $$
La lógica detrás del reparto es la siguiente:
- $v_i$ es el coste variable del flujo $i$: sus llamadas a Claude y sus mensajes de WhatsApp, que el registro común del Día 75 atribuye ejecución por ejecución.
- $cr_i$ son los créditos de Make que consume el flujo al mes; el plan Core se reparte entre los cuatro escenarios en proporción a los créditos, porque los créditos son lo que el plan vende y lo que, si se agotan, obliga a cambiar de plan.
- El servidor se reparte a partes iguales entre los $n_{\text{n8n}}$ flujos activos de n8n, y no en proporción a sus ejecuciones, porque un flujo que corre $4,320$ veces al mes durante dos segundos (las alertas cada diez minutos) no le cuesta más al servidor que uno que corre treinta veces durante dos minutos; el Día 12 lo llamó “la línea horizontal”: el coste del servidor no depende del volumen mientras el servidor aguante.
- En conclusión, el coste por flujo mezcla una medida (lo variable) con una convención (lo fijo), y la convención se declara para que otra persona pueda cambiarla.
El siguiente bloque lee los $23$ flujos activos directamente del inventario que el Día 79 (Proyecto integrador II: inventario de flujos y gobierno) generó desde las exportaciones, les añade las ejecuciones, los créditos y los costes variables que midió cada día, aplica la regla de reparto y comprueba con una aserción que la suma por flujo cuadra con la factura:
# Coste por flujo: los 23 flujos del inventario del Día 79 con su gasto variable y su parte de los fijos en Python:
texto = Path('trigo_lento/dia_79/inventario_flujos.md').read_text(encoding = 'utf-8')
filas = re.findall(r'^\| (TL [^|]+?) \| (Make|n8n) \| (\w+) \| (\w+) \| ([^|]+?) \|', texto, flags = re.M)
inventario = pd.DataFrame(filas, columns = ['flujo', 'plataforma', 'dominio', 'criticidad', 'dueno']).set_index('flujo')
USO = { # flujo: (ejecuciones al mes, créditos de Make por ejecución, USD de Claude al mes, USD de mensajes al mes)
'TL Pastel con alergias v1': (40, 9, 0.0, 0.0),
'TL Pedidos WhatsApp n8n v2.1': (1_560, 0, 1.470, 408 * u),
'TL Agente de pedidos v4': (1_068, 0, 2.570 + 3.166 + 0.0002, 0.0),
'TL Brújula diario v1': (26, 13, 0.0, 0.0),
'TL Orquestador v1': (2_000, 0, 0.360, 0.0),
'TL Facturación': (60, 0, 0.417 + 0.440, 0.0),
'TL Recordatorio de recogida v1': (328, 4, 0.0, 327.6 * u),
'TL Aprobaciones v2': (150, 0, 0.0, 0.0),
'TL Gmail mayoristas v1': (300, 0, 1.287, 0.0),
'TL Formulario v2': (70, 6, 0.0, 0.0),
'TL WhatsApp secuencias v1': (80, 0, 0.0, 80 * m),
'TL Campaña primavera v1': (8, 0, 0.1169, 0.0),
'TL Monitor de plantillas v1': (30, 0, 0.0, 0.0),
'TL Publicación multired v2': (36, 0, 0.299, 0.0),
'TL Slack operaciones v1': (400, 0, 0.0, 0.0),
'TL Clasificador IA v1': (0, 0, 0.0, 0.0), # huérfano desde el Día 79: nadie lo llama
'TL Consulta de inventario v1': (120, 0, 0.705, 0.0),
'TL Lote nocturno v1': (30, 0, 1.664, 0.0),
'TL Evaluación del agente v1': (4, 0, 0.372 + 0.840, 0.0),
'TL Informe del lunes v1': (4, 0, 0.337 + 0.470, 0.0),
'TL Métricas de atención v1': (30, 0, 0.0, 0.0),
'TL Alertas de flujos v1': (4_320, 0, 0.0, 0.0), # cada diez minutos
'TL Prueba de humo v1': (30, 0, 0.0, 0.0),
}
uso = pd.DataFrame(USO, index = ['ejecuciones', 'creditos_por_ejecucion', 'claude', 'mensajes']).T
flujos = inventario.join(uso)
assert flujos.claude.isna().sum() == 0, 'Hay flujos del inventario sin datos de uso'
flujos['creditos'] = flujos.ejecuciones * flujos.creditos_por_ejecucion
es_make = flujos.plataforma == 'Make'
activos_n8n = (~es_make) & (flujos.ejecuciones > 0)
# Reparto de los fijos: Make Core en proporción a los créditos; el servidor a partes iguales entre los flujos activos de n8n:
flujos['plataforma_usd'] = np.where(es_make, 10.59 * flujos.creditos / flujos.creditos[es_make].sum(),
np.where(activos_n8n, 6.00 / activos_n8n.sum(), 0.0))
flujos['total'] = flujos[['claude', 'mensajes', 'plataforma_usd']].sum(axis = 1)
flujos['por_ejecucion'] = flujos.total / flujos.ejecuciones.replace(0, np.nan)
flujos = flujos.sort_values('total', ascending = False)
assert abs(flujos.total.sum() - total) < 0.01, 'El reparto por flujo no cuadra con la factura'
flujos.round(4).to_csv(carpeta / 'coste_por_flujo.csv')
columnas = ['plataforma', 'criticidad', 'ejecuciones', 'creditos', 'claude', 'mensajes', 'plataforma_usd', 'total', 'por_ejecucion']
print(flujos[columnas].head(10).round(4).to_string())
diez = flujos.total.head(10).sum()
print(f'Flujos: {len(flujos)} | créditos de Make usados: {int(flujos.creditos.sum()):,} de 10 000 | '
f'flujos activos de n8n: {int(activos_n8n.sum())} ({6.00 / activos_n8n.sum():.3f} USD de servidor cada uno)')
print(f'Los diez flujos más caros suman {diez:.2f} USD, el {100 * diez / total:.1f} % de la factura; '
f'{int((flujos.claude + flujos.mensajes == 0).sum())} flujos no tienen gasto variable')
print(f'Flujo más caro por ejecución: {flujos.por_ejecucion.idxmax()} ({flujos.por_ejecucion.max():.4f} USD); '
f'más barato: {flujos.por_ejecucion.idxmin()} ({flujos.por_ejecucion.min():.5f} USD)')
plataforma criticidad ejecuciones creditos claude mensajes plataforma_usd total por_ejecucion
flujo
TL Recordatorio de recogida v1 Make crítica 328.0 1312.0 0.0000 2.7846 5.7177 8.5023 0.0259
TL Agente de pedidos v4 n8n crítica 1068.0 0.0 5.7362 0.0000 0.3333 6.0695 0.0057
TL Pedidos WhatsApp n8n v2.1 n8n crítica 1560.0 0.0 1.4700 3.4680 0.3333 5.2713 0.0034
TL WhatsApp secuencias v1 n8n media 80.0 0.0 0.0000 3.1760 0.3333 3.5093 0.0439
TL Lote nocturno v1 n8n baja 30.0 0.0 1.6640 0.0000 0.3333 1.9973 0.0666
TL Formulario v2 Make media 70.0 420.0 0.0000 0.0000 1.8304 1.8304 0.0261
TL Gmail mayoristas v1 n8n crítica 300.0 0.0 1.2870 0.0000 0.3333 1.6203 0.0054
TL Pastel con alergias v1 Make crítica 40.0 360.0 0.0000 0.0000 1.5689 1.5689 0.0392
TL Evaluación del agente v1 n8n baja 4.0 0.0 1.2120 0.0000 0.3333 1.5453 0.3863
TL Brújula diario v1 Make crítica 26.0 338.0 0.0000 0.0000 1.4730 1.4730 0.0567
Flujos: 23 | créditos de Make usados: 2,430 de 10 000 | flujos activos de n8n: 18 (0.333 USD de servidor cada uno)
Los diez flujos más caros suman 33.39 USD, el 82.4 % de la factura; 10 flujos no tienen gasto variable
Flujo más caro por ejecución: TL Evaluación del agente v1 (0.3863 USD); más barato: TL Alertas de flujos v1 (0.00008 USD)
La salida da una sorpresa que vale la entrada entera: el flujo más caro de Trigo Lento no usa inteligencia artificial. TL Recordatorio de recogida v1 cuesta $8.50$ USD al mes, y solo $2.78$ son los $327.6$ recordatorios que envía por WhatsApp; los otros $5.72$ son su parte del plan de Make, porque consume $1,312$ de los $2,430$ créditos del mes (cuatro módulos por cada recordatorio). El agente de pedidos, que es la pieza con más inteligencia del ecosistema, queda segundo con $6.07$ USD, y el flujo de pedidos de WhatsApp tercero con $5.27$, de los que $3.47$ son las $408$ respuestas de servicio que pasan de la franquicia de $1,000$. Los diez flujos más caros suman $33.39$ USD, el $82.4%$ de la factura, y diez flujos no tienen ningún gasto variable: cuestan exactamente su parte del servidor, $0.333$ USD cada uno. TL Clasificador IA v1, el huérfano que el Día 79 encontró sin que nadie lo llamara, cuesta $0.00$ y sigue teniendo credenciales, como anotó el Día 80.
La cifra de coste por ejecución ordena las cosas de otra manera. La evaluación semanal del agente cuesta $0.3863$ USD cada vez que corre, porque son cuatro corridas al mes de una batería larga con Opus 5.5; las alertas de flujos cuestan $0.00008$ USD por ejecución, porque corren $4,320$ veces sobre un servidor que ya está pagado. Ninguna de las dos cifras es “cara” o “barata” por sí sola: la evaluación vale lo que cuesta un fallo del agente que no se detecta (el Día 76 lo tasó en $184.86$ USD), y las alertas valen las horas de afectación que el Día 81 midió. El coste por ejecución sirve para una cosa concreta: saber cuánto sube la factura si el volumen de ese flujo se duplica.
El siguiente bloque dibuja los $23$ flujos ordenados, con el coste apilado por su origen, para que se vea de un vistazo dónde está el dinero:
# Gráfica del coste mensual por flujo, apilado por origen del gasto, en Python:
orden = flujos.sort_values('total')
fig, ax = plt.subplots(figsize = (9.5, 7.2))
izquierda = np.zeros(len(orden))
for columna, color, etiqueta in [('claude', '#7b4fc9', 'Claude y embeddings'), ('mensajes', '#25a35a', 'WhatsApp'),
('plataforma_usd', '#8a8986', 'Make o servidor (fijo repartido)')]:
ax.barh(orden.index, orden[columna], left = izquierda, color = color, label = etiqueta, height = 0.65)
izquierda += orden[columna].to_numpy()
for i, (v, c) in enumerate(zip(orden.total, orden.criticidad)):
ax.text(v + 0.08, i, f'{v:.2f}' + (' *' if c == 'crítica' else ''), va = 'center', fontsize = 8.5)
ax.set_xlabel('USD al mes (* flujo crítico)')
ax.set_xlim(0, orden.total.max() * 1.18)
ax.tick_params(axis = 'y', labelsize = 8.5)
ax.legend(frameon = False, fontsize = 9, loc = 'lower right')
ax.set_title('Coste mensual de los 23 flujos de Trigo Lento', fontsize = 13)
ax.spines[['top', 'right']].set_visible(False)
plt.tight_layout()
plt.show()

La gráfica confirma lo que la tabla decía y añade un matiz de color. El morado (Claude) se concentra en cinco flujos: el agente de pedidos, el de pedidos de WhatsApp, el lote nocturno, la evaluación y Gmail. El verde (WhatsApp) está en tres, y uno de ellos, la secuencia de bienvenida, es el único flujo de marketing del ecosistema y cuesta $3.51$ USD. El gris (fijos repartidos) es el que más engaña: parece que los escenarios de Make son caros, pero lo que es caro es el plan, y el plan se paga igual con $2,430$ créditos que con $9,999$. Si Valeria migrara dos escenarios a n8n, los dos que quedaran en Make no costarían menos: seguirían repartiéndose los mismos $10.59$ USD. Ese razonamiento es el que convierte el gris en una palanca con nombre propio, más adelante.
Atención aquí: un coste por flujo con fijos repartidos es una asignación, no una medida, y las dos se confunden con facilidad en una reunión. Si alguien propone “apagar el recordatorio de recogida porque es el flujo más caro”, la factura no bajaría $8.50$ USD sino $2.78$: los $5.72$ de Make se redistribuirían entre los otros tres escenarios. Para decidir qué apagar o qué migrar se usa el coste marginal (lo que de verdad deja de pagarse), y para explicar en qué se gasta el presupuesto se usa el coste asignado. Las decisiones de hoy, en la sección de palancas, se toman con el primero. Y ninguna de ellas consiste en apagar un flujo crítico para ahorrar: los nueve flujos marcados con asterisco en la gráfica atienden a clientes, y su valor se mide en el Día 82 con el acuerdo de servicio, no aquí.
Frente a la Tabla E
El Día 12 repartió los $45$ USD en cinco rubros antes de construir nada, y la serie los ha revisado en cada cierre de módulo: el Día 46 rehízo WhatsApp al elegir la Cloud API, el Día 55 consolidó la comunicación en $32.19$ USD, el Día 67 (Sesión práctica de consolidación: el informe de negocio del lunes) subió el rubro de Claude de $8.00$ a $10.50$ con dinero de WhatsApp y de la reserva, y el Día 77 (Sesión práctica: la campaña de primavera, de la idea a la publicación) cargó el módulo 7 a la reserva y la dejó en $4.02$. Hoy la comparación se hace contra la Tabla E original, no contra sus revisiones, porque la pregunta de Don Ernesto es qué tan bien se adivinó el reparto antes de empezar.
El siguiente bloque calcula la desviación de cada rubro en USD y en porcentaje, le pone su causa, y después mide la sensibilidad de la factura al rango de tarifas de WhatsApp y al régimen de cobro de los mensajes de servicio:
# Desviaciones frente a la Tabla E y sensibilidad de la factura a las tarifas de WhatsApp y al tipo de cambio en Python:
TABLA_E = {'Make Core': 10.59, 'Servidor de n8n': 6.00, 'API de Claude': 8.00, 'WhatsApp': 12.00, 'Reserva': 8.41}
GASTO = {'Make Core': factura.loc['Make Core', 'usd'], 'Servidor de n8n': factura.loc['Servidor de n8n', 'usd'],
'API de Claude': factura.loc['Claude y embeddings', 'usd'], 'WhatsApp': factura.loc['WhatsApp (Cloud API)', 'usd'], 'Reserva': 0.0}
CAUSA = {'Make Core': 'sin cambio: el plan es fijo aunque solo se usen 2 430 créditos',
'Servidor de n8n': 'sin cambio en USD; 5.99 EUR valen 6.47 al tipo didáctico',
'API de Claude': 'piezas del M6 (10.12), remisiones (0.44) y M7 (3.95); el rubro subió a 10.50 el Día 67',
'WhatsApp': 'Cloud API directa (Día 46): sin recargo de proveedor',
'Reserva': 'absorbió 4.39 del M7 y el exceso de Claude'}
desvios = pd.DataFrame({'asignado': TABLA_E, 'gasto': GASTO})
desvios['desviacion'] = desvios.gasto - desvios.asignado
desvios['porcentaje'] = np.where(desvios.asignado > 0, 100 * desvios.desviacion / desvios.asignado, 0)
desvios['causa'] = pd.Series(CAUSA)
print(desvios.round(2).to_string())
print(f'Suma asignada: {desvios.asignado.sum():.2f} | gastada: {desvios.gasto.sum():.2f} | libres: {PRESUPUESTO - desvios.gasto.sum():.2f}')
# Sensibilidad: 3 tarifas de utilidad x 3 de marketing x 2 regímenes de los mensajes de servicio:
def coste_whatsapp(utilidad, marketing, cobra_servicio):
servicio = utilidad * max(VOLUMEN_WA['respuestas de servicio'] - FRANQUICIA, 0) if cobra_servicio else 0.0
return servicio + utilidad * VOLUMEN_WA['recordatorios de recogida'] + marketing * VOLUMEN_WA['mensajes de marketing']
escenarios = []
for nu, tu in WHATSAPP.loc['utilidad'].items():
for nm, tm in WHATSAPP.loc['marketing'].items():
for regimen, cobra in [('anterior', False), ('vigente', True)]:
escenarios.append({'utilidad': nu, 'marketing': nm, 'regimen': regimen, 'whatsapp': coste_whatsapp(tu, tm, cobra)})
sensibilidad = pd.DataFrame(escenarios)
sensibilidad['factura'] = total - GASTO['WhatsApp'] + sensibilidad.whatsapp
peor, mejor = sensibilidad.loc[sensibilidad.factura.idxmax()], sensibilidad.loc[sensibilidad.factura.idxmin()]
print(sensibilidad.pivot_table(index = ['utilidad', 'marketing'], columns = 'regimen', values = 'whatsapp').round(2).to_string())
print(f'WhatsApp: de {mejor.whatsapp:.2f} a {peor.whatsapp:.2f} USD | factura: de {mejor.factura:.2f} a {peor.factura:.2f} USD; '
f'con el servidor a 6.47 USD, hasta {peor.factura + 0.47:.2f}')
print(f'Tipo de cambio: la factura de {total:.2f} USD son {total * TC:,.2f} MXN a 18.50 y {total * 20.00:,.2f} MXN a 20.00')
asignado gasto desviacion porcentaje causa
Make Core 10.59 10.59 0.00 0.00 sin cambio: el plan es fijo aunque solo se usen 2 430 créditos
Servidor de n8n 6.00 6.00 0.00 0.00 sin cambio en USD; 5.99 EUR valen 6.47 al tipo didáctico
API de Claude 8.00 14.51 6.51 81.43 piezas del M6 (10.12), remisiones (0.44) y M7 (3.95); el rubro subió a 10.50 el Día 67
WhatsApp 12.00 9.43 -2.57 -21.43 Cloud API directa (Día 46): sin recargo de proveedor
Reserva 8.41 0.00 -8.41 -100.00 absorbió 4.39 del M7 y el exceso de Claude
Suma asignada: 45.00 | gastada: 40.53 | libres: 4.47
regimen anterior vigente
utilidad marketing
máximo publicado máximo publicado 8.40 14.52
mínimo publicado 7.35 13.47
usado 8.09 14.21
mínimo publicado máximo publicado 4.80 6.43
mínimo publicado 3.75 5.38
usado 4.49 6.12
usado máximo publicado 6.27 9.74
mínimo publicado 5.22 8.69
usado 5.96 9.43
WhatsApp: de 3.75 a 14.52 USD | factura: de 34.85 a 45.63 USD; con el servidor a 6.47 USD, hasta 46.10
Tipo de cambio: la factura de 40.53 USD son 749.85 MXN a 18.50 y 810.65 MXN a 20.00
La Tabla 2 resume las desviaciones. La lectura es la de un presupuesto que acertó en lo fijo y falló en lo variable, en las dos direcciones.
Tabla 2. Desviaciones del gasto de abril frente al reparto inicial de la Tabla E (USD al mes).
| Rubro | Asignado (Día 12) | Gasto de abril | Desviación | Porcentaje | Causa |
|---|---|---|---|---|---|
| Make Core | 10.59 | 10.59 | 0.00 | 0 % | El plan es fijo aunque solo se usen 2 430 de 10 000 créditos |
| Servidor de n8n | 6.00 | 6.00 | 0.00 | 0 % | Sin cambio en USD; los 5.99 EUR valen 6.47 al tipo didáctico |
| API de Claude | 8.00 | 14.51 | +6.51 | +81.4 % | Piezas del M6 (10.12), remisiones del Día 66 (0.44) y M7 (3.95); el rubro ya había subido a 10.50 el Día 67 |
| 12.00 | 9.43 | -2.57 | -21.4 % | Cloud API directa desde el Día 46: sin recargo de proveedor | |
| Reserva | 8.41 | 0.00 | -8.41 | -100 % | Absorbió los 4.39 del módulo 7 y el exceso de Claude; lo que queda libre son 4.47 |
| Total | 45.00 | 40.53 | -4.47 | -9.9 % | Libres frente al tope |
Claude se desvió $6.51$ USD, un $81%$ por encima de su rubro inicial, y la causa no es un error de cálculo sino una decisión repetida: cada módulo añadió piezas que valían lo que costaban, y cada día lo escribió. El Día 61 llevó el agente a $2.57$ con caché; el Día 60 dejó el lote nocturno en $1.664$; el Día 69 escaló las preguntas frecuentes a Opus 5.5 por $3.166$ USD, la pieza más cara de todo el ecosistema, con la variante de Sonnet 5.5 calculada en $1.681$ y guardada “por si el módulo 7 necesitaba más reserva”. La necesitó. WhatsApp, en cambio, gasta $2.57$ menos de lo asignado desde que no paga recargo de proveedor, y esa diferencia es exactamente la que el Día 67 propuso mover al rubro de Claude. Y la reserva, que la Tabla E fijó en $8.41$ como un rubro más, resultó ser lo que una reserva es: el dinero que se gasta cuando lo demás no alcanza.
La segunda parte de la salida es la sensibilidad, y responde a una objeción razonable: si las tarifas de México no se conocen con certeza, ¿de qué sirve una factura al centavo? Sirve si se sabe cuánto se mueve. El coste de WhatsApp con la Cloud API es:
$$ W = \delta \cdot r_u \cdot \max(n_s - F_s,, 0) + r_u \cdot n_r + r_m \cdot n_m $$
La lógica detrás de la fórmula es la siguiente:
- $n_s = 1,408$ son las respuestas de servicio del mes, $F_s = 1,000$ la franquicia mensual por número y $\delta$ vale $1$ en el régimen vigente desde el 1 de octubre de 2026 y $0$ en el anterior, en el que las respuestas dentro de la ventana no se cobraban.
- $n_r = 327.6$ son los recordatorios de recogida, plantillas de utilidad a la tarifa $r_u$; $n_m = 80$ los mensajes de la secuencia de bienvenida, a la tarifa de marketing $r_m$.
- Con los valores usados, $W = 0.0085 \cdot 408 + 0.0085 \cdot 327.6 + 0.0397 \cdot 80 = 3.47 + 2.78 + 3.18 = 9.43$ USD.
- En conclusión, la factura de WhatsApp es lineal en cada tarifa, y por eso el rango de las fuentes se traslada directamente al rango de la factura.
Con las tres tarifas de utilidad y las tres de marketing que publican las fuentes, y los dos regímenes, WhatsApp va de $3.75$ a $14.52$ USD al mes y la factura completa de $34.85$ a $45.63$; con el servidor a $6.47$ en lugar de $6.00$, hasta $46.10$. El peor caso rompe el tope por $1.10$ USD. No es el caso más probable: la tarifa de utilidad de $0.0150$ la publica una sola guía sin fecha y la de marketing de $0.0436$ una fuente que la serie no pudo contrastar con la tarjeta de Meta. Pero existe, y por eso el presupuesto revisado de mayo, más adelante, conserva una reserva de verdad en lugar de repartirla. El tipo de cambio es la otra fuente de incertidumbre, y para Don Ernesto la más tangible: los $40.53$ USD son $749.85$ MXN a $18.50$ y $810.65$ a $20.00$, sesenta pesos de diferencia que ninguna palanca técnica controla.
La Figura 2 pone el puente completo en un solo dibujo: lo que queda libre después de cada rubro, lo que el plan de la serie esperaba y, como anticipo de la sección de palancas, el tramo de mayo con lo que las decisiones de hoy devuelven.
Figura 2. El puente del presupuesto: de los 45 USD del tope a los 4.47 libres, rubro por rubro; la línea punteada marca los 36.35 USD que estimó el plan de la serie y el último tramo, los 38.44 USD de mayo con las tres palancas aplicadas hoy.
Cuando el negocio crece
Hasta aquí la factura es una fotografía. Don Ernesto preguntó otra cosa: si el total seguirá siendo el total cuando vendan más. La respuesta es que no, y la pregunta útil es cuándo deja de caber en los $45$ USD. El Día 12 dedujo que el mes de ruptura depende del cociente entre el margen de hoy y la parte variable, no del precio, y hoy ese cociente se calcula con la factura real.
Con una parte fija $F$ y una variable $V$ que crece a una tasa mensual $g$, el coste del mes $k$ y el mes de ruptura son:
$$ C_k = F + V \cdot (1 + g)^{k}, \qquad k^{*} = \frac{\ln!\left(\dfrac{P - F}{V}\right)}{\ln(1 + g)} $$
La lógica detrás de la proyección es la siguiente:
- $F = 16.59$ USD es Make más el servidor, que no crecen con las ventas; $V = 23.94$ es Claude más WhatsApp, que crecen con cada encargo y cada mensaje; $P = 45$ es el tope.
- El supuesto de $g = 5%$ al mes es el de la ficha de la serie: es un crecimiento alto para una panadería (un $80%$ al año compuesto), elegido a propósito para que la proyección sea exigente y no cómoda.
- $k^$ es el mes exacto en que $C_k = P$; como los meses son enteros, el presupuesto se rompe en el primer mes mayor que $k^$. Despejando al revés, la tasa que cabe durante $12$ meses es $g^* = ((P - F) / V)^{1/12} - 1$.
- En conclusión, cuanto mayor es la parte fija, menos crecimiento cabe: con los mismos $45$ USD, bajar $F$ compra más meses que bajar $V$ en la misma cantidad, porque el margen se mide contra lo que queda después de lo fijo.
El siguiente bloque proyecta tres escenarios a $18$ meses: todo encendido como está hoy, con la opción que el Día 77 dejó medida (Sonnet 5.5 en las preguntas frecuentes) y, además de eso, con Make en plan gratuito después de migrar dos escenarios a n8n:
# Proyección a 18 meses con crecimiento del 5 % mensual de la parte variable y mes de ruptura en Python:
F = GASTO['Make Core'] + GASTO['Servidor de n8n'] # fijos: se pagan se use o no se use
V = GASTO['API de Claude'] + GASTO['WhatsApp'] # variables: crecen con los mensajes y los encargos
g = 0.05
ESCENARIOS = {'Todo encendido (hoy)': (F, V),
'Con Sonnet 5.5 en las preguntas frecuentes (opción del Día 77)': (F, V - (3.166 - 1.681)),
'Lo anterior y Make en plan gratuito (dos escenarios migrados)': (F - 10.59, V - (3.166 - 1.681))}
def mes_de_ruptura(fijo, variable, tope = PRESUPUESTO, tasa = g):
# k* = ln((P - F) / V) / ln(1 + g); el presupuesto se rompe en el primer mes entero mayor que k*:
if variable <= 0 or tope <= fijo:
return math.inf, math.inf
k = math.log((tope - fijo) / variable) / math.log(1 + tasa)
return k, math.floor(k) + 1
meses = np.arange(0, 19)
proyeccion = pd.DataFrame({nombre: fijo + variable * (1 + g) ** meses for nombre, (fijo, variable) in ESCENARIOS.items()}, index = meses)
for nombre, (fijo, variable) in ESCENARIOS.items():
k, mes = mes_de_ruptura(fijo, variable)
g_12 = ((PRESUPUESTO - fijo) / variable) ** (1 / 12) - 1 # crecimiento mensual que cabe 12 meses
print(f'{nombre}: F = {fijo:.2f}, V = {variable:.2f} | k* = {k:.2f} -> se rompe en el mes {mes} | '
f'mes 12: {proyeccion.loc[12, nombre]:.2f} USD | crecimiento sostenible 12 meses: {100 * g_12:.2f} % al mes')
fig, ax = plt.subplots(figsize = (9, 4.8))
for (nombre, serie), color in zip(proyeccion.items(), ['#c0392b', '#4472C4', '#70AD47']):
ax.plot(meses, serie, marker = 'o', ms = 3.5, color = color, label = nombre)
k, mes = mes_de_ruptura(*ESCENARIOS[nombre])
if mes <= 18:
ax.annotate(f'mes {mes}', (mes, serie[mes]), textcoords = 'offset points', xytext = (-6, 10), color = color, fontsize = 9, ha = 'right')
ax.axhline(PRESUPUESTO, color = '#333333', lw = 1.4, ls = '--')
ax.text(18, PRESUPUESTO + 0.6, 'tope de 45 USD', ha = 'right', fontsize = 9)
ax.set_xlabel('meses desde el cierre de abril de 2026')
ax.set_ylabel('USD al mes')
ax.set_xticks(meses)
ax.legend(frameon = False, fontsize = 8.5, loc = 'upper left')
ax.set_title('Si el negocio crece un 5 % al mes: cuándo se rompe el presupuesto', fontsize = 13)
ax.spines[['top', 'right']].set_visible(False)
plt.tight_layout()
plt.show()
Todo encendido (hoy): F = 16.59, V = 23.94 | k* = 3.51 -> se rompe en el mes 4 | mes 12: 59.59 USD | crecimiento sostenible 12 meses: 1.44 % al mes
Con Sonnet 5.5 en las preguntas frecuentes (opción del Día 77): F = 16.59, V = 22.46 | k* = 4.82 -> se rompe en el mes 5 | mes 12: 56.92 USD | crecimiento sostenible 12 meses: 1.98 % al mes
Lo anterior y Make en plan gratuito (dos escenarios migrados): F = 6.00, V = 22.46 | k* = 11.31 -> se rompe en el mes 12 | mes 12: 46.33 USD | crecimiento sostenible 12 meses: 4.71 % al mes

Con todo encendido y un crecimiento del $5%$ mensual, el presupuesto se rompe en el cuarto mes ($k^* = 3.51$): en agosto de 2026 la factura sería de $45.69$ USD y en abril de 2027 de $59.59$. Es una cifra peor que la del plan de la serie, que esperaba aguantar hasta el octavo mes con una parte variable de $19.76$ USD; la diferencia la explica el rubro de Claude, que es $4.18$ mayor de lo previsto, y la fórmula la amplifica: con $V = 23.94$ el margen de hoy, $28.41$ USD, es solo $1.19$ veces la parte variable, y $1.05^k$ llega a $1.19$ en tres meses y medio. Dicho de otra forma, el crecimiento sostenible durante un año con la factura de hoy es del $1.44%$ mensual, un $19%$ anual: bastante para una panadería, poco para la ambición de Don Ernesto.
La opción del Día 77 compra un mes: con Sonnet 5.5 en el escalado de las preguntas frecuentes, $V$ baja a $22.46$ y la ruptura pasa al quinto mes, con un crecimiento sostenible del $1.98%$. Lo que cambia la curva de verdad es la parte fija: con Make en plan gratuito, $F$ baja a $6.00$, la ruptura se va al duodécimo mes y el crecimiento sostenible sube al $4.71%$ mensual, casi el supuesto completo. La gráfica lo enseña con tres curvas que tienen la misma forma y distinta altura: la tasa de crecimiento les da la curvatura y la parte fija las desplaza. Por eso la palanca más grande de la tabla siguiente es una palanca de Make y no de Claude, aunque Claude sea el rubro que más se desvió.
Palancas de ahorro
Una palanca de ahorro es una decisión que baja la factura, y la serie ha acumulado ocho candidatas. La regla para ordenarlas la fijó el Día 67 y hoy se aplica sin excepciones: una palanca se acciona si tiene efecto medido y riesgo aceptable; se mide si tiene efecto calculado y riesgo de calidad; y no se acciona si su riesgo no se puede medir todavía. “Calculado” y “medido” no son lo mismo: el ahorro de pasar una pieza a Sonnet 5.5 se calcula con los precios, pero solo se mide cuando una evaluación con casos propios, con el protocolo del Día 65 (OpenAI frente a Claude: una elección de arquitecto), demuestra que la calidad no empeora.
El siguiente bloque reúne las ocho palancas con su efecto, su evidencia, su riesgo y la decisión de hoy, aplica las que se accionan, calcula la factura de mayo y escribe el presupuesto revisado con sus rubros y sus avisos al $80%$:
# Palancas de ahorro con efecto medido o estimado, riesgo y decisión, y presupuesto revisado para mayo en Python:
PALANCAS = [ # (palanca, USD de ahorro al mes, evidencia, riesgo, decisión de hoy)
('Preguntas frecuentes: escalado a Sonnet 5.5 en lugar de Opus 5.5', 3.166 - 1.681, 'medido el Día 69', 'medio: políticas mal citadas', 'sí, tras evaluar con las 30 preguntas del Día 69'),
('Batería de ataques del Día 64 por lotes', 0.840 / 2, 'descuento del 50 % de la API de lotes', 'ninguno: corre de noche', 'sí'),
('Evaluación semanal del agente por lotes', 0.372 / 2, 'descuento del 50 % de la API de lotes', 'bajo: el resultado llega en horas', 'sí'),
('Resumen nocturno con Sonnet 5.5 por lotes', 1.43 - 0.715, 'calculado el Día 67, sin medir calidad', 'medio: resumen para Don Ernesto', 'medir primero'),
('Cascada de clasificación: escalado a Sonnet 5.5', 1.26 - 0.63, 'calculado el Día 67, sin medir calidad', 'medio: 234 mensajes dudosos al mes', 'medir primero'),
('Esfuerzo low en la consulta de inventario por MCP', 0.705 * 0.25, 'estimado: la salida domina el coste', 'bajo: respuestas de solo lectura', 'medir primero'),
('Secuencia de bienvenida de 2 mensajes de marketing a 1', 40 * m, 'aritmética sobre el Día 48', 'alto: efecto de la secuencia sin medir', 'no'),
('Migrar dos escenarios a n8n y bajar Make a plan gratuito', 10.59, 'Día 45: migración medida; 698 créditos quedarían', 'alto: 2 escenarios y 1 000 créditos de tope', 'hoja de ruta (Día 89)'),
]
palancas = pd.DataFrame(PALANCAS, columns = ['palanca', 'ahorro', 'evidencia', 'riesgo', 'decision'])
palancas.to_csv(carpeta / 'palancas.csv', index = False)
print(palancas[['palanca', 'ahorro', 'riesgo', 'decision']].round(3).to_string(index = False))
aplicadas = palancas[palancas.decision.str.startswith('sí')]
ahorro_hoy = aplicadas.ahorro.sum()
claude_mayo = GASTO['API de Claude'] - ahorro_hoy
total_mayo = total - ahorro_hoy
print(f'Palancas aplicadas hoy: {len(aplicadas)} | ahorro: {ahorro_hoy:.3f} USD | Claude: {GASTO["API de Claude"]:.2f} -> {claude_mayo:.2f} | '
f'factura: {total:.2f} -> {total_mayo:.2f} | todas las palancas juntas: {palancas.ahorro.sum():.2f}')
# Presupuesto revisado: el rubro de Claude recibe 2.00 USD del de WhatsApp; la reserva vuelve a ser un rubro:
RUBROS_MAYO = {'Make Core': 10.59, 'Servidor de n8n': 6.00, 'API de Claude': 12.50, 'WhatsApp': 10.00}
RUBROS_MAYO['Reserva'] = round(PRESUPUESTO - sum(RUBROS_MAYO.values()), 2)
GASTO_MAYO = {'Make Core': 10.59, 'Servidor de n8n': 6.00, 'API de Claude': claude_mayo, 'WhatsApp': GASTO['WhatsApp'], 'Reserva': 0.0}
mayo = pd.DataFrame({'rubro': RUBROS_MAYO, 'gasto previsto': GASTO_MAYO})
mayo['margen'] = mayo.rubro - mayo['gasto previsto']
mayo['aviso al 80 %'] = 0.8 * mayo.rubro
print(mayo.round(2).to_string())
k, mes = mes_de_ruptura(F, claude_mayo + GASTO['WhatsApp'])
k2, mes2 = mes_de_ruptura(F - 10.59, claude_mayo + GASTO['WhatsApp'])
print(f'Mayo: {total_mayo:.2f} de {PRESUPUESTO:.2f} USD, {PRESUPUESTO - total_mayo:.2f} libres | con 5 % de crecimiento se rompe en el mes {mes} '
f'(k* = {k:.2f}); con Make en plan gratuito, en el mes {mes2} (k* = {k2:.2f})')
json.dump({'mes': '2026-05', 'tope_usd': PRESUPUESTO, 'rubros': RUBROS_MAYO, 'gasto_previsto': {k_: round(v, 2) for k_, v in GASTO_MAYO.items()},
'palancas_aplicadas': aplicadas.palanca.tolist(), 'revision_precios': REVISION, 'proxima_revision': '2026-06-01'},
open(carpeta / 'presupuesto_2026-05.json', 'w', encoding = 'utf-8'), ensure_ascii = False, indent = 1)
palanca ahorro riesgo decision
Preguntas frecuentes: escalado a Sonnet 5.5 en lugar de Opus 5.5 1.485 medio: políticas mal citadas sí, tras evaluar con las 30 preguntas del Día 69
Batería de ataques del Día 64 por lotes 0.420 ninguno: corre de noche sí
Evaluación semanal del agente por lotes 0.186 bajo: el resultado llega en horas sí
Resumen nocturno con Sonnet 5.5 por lotes 0.715 medio: resumen para Don Ernesto medir primero
Cascada de clasificación: escalado a Sonnet 5.5 0.630 medio: 234 mensajes dudosos al mes medir primero
Esfuerzo low en la consulta de inventario por MCP 0.176 bajo: respuestas de solo lectura medir primero
Secuencia de bienvenida de 2 mensajes de marketing a 1 1.588 alto: efecto de la secuencia sin medir no
Migrar dos escenarios a n8n y bajar Make a plan gratuito 10.590 alto: 2 escenarios y 1 000 créditos de tope hoja de ruta (Día 89)
Palancas aplicadas hoy: 3 | ahorro: 2.091 USD | Claude: 14.51 -> 12.42 | factura: 40.53 -> 38.44 | todas las palancas juntas: 15.79
rubro gasto previsto margen aviso al 80 %
Make Core 10.59 10.59 0.00 8.47
Servidor de n8n 6.00 6.00 0.00 4.80
API de Claude 12.50 12.42 0.08 10.00
WhatsApp 10.00 9.43 0.57 8.00
Reserva 5.91 0.00 5.91 4.73
Mayo: 38.44 de 45.00 USD, 6.56 libres | con 5 % de crecimiento se rompe en el mes 6 (k* = 5.38); con Make en plan gratuito, en el mes 12 (k* = 11.87)
La Tabla 3 presenta las ocho palancas en el orden en que Valeria las puso delante de Don Ernesto: primero las que se accionan hoy, después las que se miden, y al final las dos que no.
Tabla 3. Palancas de ahorro del ecosistema: efecto mensual, evidencia, riesgo y decisión (USD al mes).
| Palanca | Ahorro | Evidencia | Riesgo | Decisión |
|---|---|---|---|---|
| Preguntas frecuentes: escalado a Sonnet 5.5 en lugar de Opus 5.5 | 1.485 | Medido el Día 69 (de 3.166 a 1.681) | Medio: una política mal citada a un cliente | Sí, tras la evaluación con las 30 preguntas del Día 69 |
| Batería de ataques del Día 64 por lotes | 0.420 | Descuento del 50 % de la API de lotes | Ninguno: corre de noche y nadie la espera | Sí, desde hoy |
| Evaluación semanal del agente por lotes | 0.186 | Descuento del 50 % de la API de lotes | Bajo: el resultado llega en horas, no al instante | Sí, desde hoy |
| Resumen nocturno con Sonnet 5.5 por lotes | 0.715 | Calculado el Día 67, sin medir calidad | Medio: es el resumen que lee Don Ernesto | Medir primero |
| Cascada de clasificación: escalado a Sonnet 5.5 | 0.630 | Calculado el Día 67, sin medir calidad | Medio: 234 mensajes dudosos al mes | Medir primero |
Esfuerzo low en la consulta de inventario por MCP | 0.176 | Estimado: la salida domina el coste | Bajo: respuestas de solo lectura | Medir primero |
| Secuencia de bienvenida: de 2 mensajes de marketing a 1 | 1.588 | Aritmética sobre el Día 48 | Alto: el efecto de la secuencia en recompra no se midió | No |
| Migrar dos escenarios a n8n y bajar Make al plan gratuito | 10.590 | Día 45: migración medida; quedarían 698 créditos | Alto: 2 escenarios activos y 1 000 créditos de tope | Hoja de ruta (Día 89) |
| Accionadas hoy | 2.091 | 3 de 8 |
Las tres palancas de hoy ahorran $2.091$ USD y dejan Claude en $12.42$ y la factura de mayo en $38.44$ USD, con $6.56$ libres. Dos de ellas no tienen discusión: la batería de ataques del Día 64 y la evaluación semanal del Día 70 son trabajo que nadie espera al instante, y la API de lotes lo cobra a la mitad sin cambiar una sola respuesta; el Día 60 (Message Batches: grandes volúmenes a mitad de precio) ya enseñó que el lote divide el coste entre dos y el modelo correcto entre cuarenta. La tercera, la de las preguntas frecuentes, es la opción que el Día 77 dejó medida y es la única con condición: Valeria pasa la variante de Sonnet 5.5 por las $30$ preguntas etiquetadas del Día 69 la semana del 27 de abril, y solo si el recall@3 y las abstenciones no empeoran se cambia el modelo. Si empeoran, la palanca no se acciona y Claude queda en $13.91$, por encima del rubro: la tabla lo dice antes de que pase.
Las tres que se miden suman $1.52$ USD y comparten el mismo riesgo, la calidad de una respuesta que lee una persona; el Día 67 ya avisó de que ninguna de las dos primeras se puede hacer sin el protocolo del Día 65. La del esfuerzo low en la consulta de inventario es una estimación, no un cálculo: la serie no midió cuántos tokens de pensamiento gasta esa consulta, y una estimación no entra en una decisión de presupuesto. Las dos que no se accionan son las más grandes, y por razones distintas. Recortar la secuencia de bienvenida ahorraría $1.59$ USD, pero el Día 48 (WhatsApp Business API: plantillas, ventana de 24 horas, secuencias y chatbots) dejó pendiente medir si la secuencia trae recompras, y tocar el único flujo de marketing sin saber lo que produce es ahorrar a ciegas. Y migrar dos escenarios a n8n para bajar Make al plan gratuito ahorraría $10.59$ USD, más que todas las demás juntas, con un riesgo que el plan gratuito escribe en su página: dos escenarios activos, $1,000$ créditos y un intervalo mínimo de quince minutos; con TL Pastel con alergias v1 y TL Brújula diario v1 quedarían $698$ créditos, un margen del $30%$ que un mes bueno se come. Esa palanca es la primera línea de la hoja de ruta del Día 89, con la migración medida del Día 45 (Sesión práctica de consolidación: migrar el escenario de Make a n8n) como método, no una decisión de viernes por la tarde.
La Figura 3 resume las ocho palancas como lo que son: barras de distinta longitud y distinto color, donde la más larga es también la que más cuidado pide.
Figura 3. Las palancas de ahorro: la longitud de cada palanca es su efecto en USD al mes y el color su riesgo (verde ninguno o bajo, amarillo medio, gris alto); tres se accionan hoy (2.09 USD), tres se miden antes, una se descarta y la de Make, la más larga, pasa a la hoja de ruta.
El presupuesto revisado para mayo cierra la deuda del Día 77 con la primera de sus dos opciones: el rubro de Claude recibe $2.00$ USD del de WhatsApp, que baja a $10.00$ y sigue cubriendo los $9.43$ con margen, y queda en $12.50$ frente a un gasto previsto de $12.42$. Cabe por ocho centavos, y Valeria lo escribe así, porque un rubro que se llena es un aviso, no un éxito: el aviso al $80%$ de Claude sonará a los $10.00$ USD, es decir, todos los meses, y eso es exactamente lo que quiere, que el gasto de modelos se mire cada mes. La reserva vuelve a ser un rubro de $5.91$ USD con una regla nueva: no se asigna a nada por adelantado y absorbe solo el peor caso de la sensibilidad de WhatsApp. Con esa factura, el crecimiento del $5%$ rompe el presupuesto en el sexto mes, y con Make en plan gratuito, en el duodécimo.
El retorno
Falta la mitad de la cuenta. Un gasto de $40.53$ USD al mes es caro o barato según lo que devuelve, y lo que devuelve el ecosistema de Trigo Lento no son ventas que nadie midió, sino horas que sí se midieron: las del proceso de encargos el Día 1 (Qué es la automatización de procesos y cómo piensa un arquitecto), las del buzón de mayoristas el Día 47 (Gmail con criterio: OAuth, etiquetas y borradores contextuales con Claude), las del contenido de redes el Día 71 (De la idea al calendario editorial: textos e imágenes con IA) y las del informe del lunes el Día 67. El retorno se calcula con la definición de siempre:
$$ \text{ROI} = \frac{B - C}{C}, \qquad B = \sum_{p} h_p \cdot \frac{w}{\tau} $$
La lógica detrás del retorno es la siguiente:
- $h_p$ son las horas ahorradas al mes en el proceso $p$, $w = 75$ MXN el valor didáctico de la hora de Valeria y $\tau = 18.50$ el tipo de cambio; $B$ es el valor en USD de todas las horas y $C$ el gasto del mes.
- Un ROI de $1$ significa que cada dólar devuelve dos (el propio y uno más); el cociente $B / C$ dice directamente cuántos dólares devuelve cada dólar.
- La cuenta inversa, $C \cdot \tau / w$, dice cuántas horas ahorradas bastan para pagar el gasto; el resto son horas que el negocio gana limpias.
- En conclusión, el retorno solo incluye horas medidas: la conciliación contable del Día 59 ahorró $34.3$ horas, pero al despacho Ledesma y no a Trigo Lento, y no se cuenta; las horas de afectación que evitan los manuales del Día 81 son esperanzas de una simulación, y tampoco.
El siguiente bloque reúne las cuatro mediciones, las convierte a pesos y a dólares, calcula el retorno con el gasto de abril, con el de mayo y con el tope, y dibuja el valor de cada proceso frente al gasto:
# Retorno: horas ahorradas al mes por proceso, su valor a 75 MXN la hora y la comparación con el gasto en Python:
VALOR_HORA = 75 # MXN, supuesto didáctico de la serie
HORAS = { # proceso: (horas ahorradas al mes, día que las midió)
'Encargos: de 6 a 1.5 minutos por encargo': (46.8 - 11.7, 1),
'Correos de mayoristas con borradores': (20.00 - 5.03, 47),
'Contenido de redes con calendario y borradores': (14.0 - 4.5, 71),
'Informe del lunes: 2 horas por semana': (2 * 52 / 12, 67),
}
retorno = pd.DataFrame(HORAS, index = ['horas', 'dia']).T
retorno['mxn'] = retorno.horas * VALOR_HORA
retorno['usd'] = retorno.mxn / TC
retorno.loc['Total'] = [retorno.horas.sum(), '', retorno.mxn.sum(), retorno.usd.sum()]
retorno.round(2).to_csv(carpeta / 'retorno.csv')
print(retorno.round(2).to_string())
beneficio = retorno.loc['Total', 'usd']
for nombre, gasto in [('abril, todo encendido', total), ('mayo, con las palancas', total_mayo), ('tope del presupuesto', PRESUPUESTO)]:
roi = (beneficio - gasto) / gasto
print(f'{nombre}: gasto {gasto:.2f} USD | retorno (B - C) / C = {roi:.2f} | cada dólar devuelve {beneficio / gasto:.2f} USD | '
f'horas que pagan el gasto: {gasto * TC / VALOR_HORA:.1f} de {retorno.loc["Total", "horas"]:.1f}')
fig, ax = plt.subplots(figsize = (9, 4.6))
procesos = retorno.drop('Total')
ax.bar(range(len(procesos)), procesos.usd, color = '#70AD47', width = 0.6)
for i, (h, v) in enumerate(zip(procesos.horas, procesos.usd)):
ax.text(i, v + 4, f'{h:.2f} h\n{v:.2f} USD', ha = 'center', fontsize = 9)
ax.axhline(total, color = '#c0392b', lw = 1.4, ls = '--', label = f'gasto de abril: {total:.2f} USD')
ax.axhline(beneficio, color = '#4472C4', lw = 1.2, ls = ':', label = f'valor de las horas: {beneficio:.2f} USD')
ax.set_xticks(range(len(procesos)), ['Encargos', 'Correos', 'Contenido', 'Informe'], fontsize = 10)
ax.set_ylabel('USD al mes')
ax.set_ylim(0, beneficio * 1.25)
ax.legend(frameon = False, fontsize = 9, loc = 'upper right')
ax.set_title('Retorno mensual: valor de las horas ahorradas frente al gasto', fontsize = 13)
ax.spines[['top', 'right']].set_visible(False)
plt.tight_layout()
plt.show()
horas dia mxn usd
Encargos: de 6 a 1.5 minutos por encargo 35.10 1.0 2632.50 142.30
Correos de mayoristas con borradores 14.97 47.0 1122.75 60.69
Contenido de redes con calendario y borradores 9.50 71.0 712.50 38.51
Informe del lunes: 2 horas por semana 8.67 67.0 650.00 35.14
Total 68.24 5117.75 276.64
abril, todo encendido: gasto 40.53 USD | retorno (B - C) / C = 5.82 | cada dólar devuelve 6.82 USD | horas que pagan el gasto: 10.0 de 68.2
mayo, con las palancas: gasto 38.44 USD | retorno (B - C) / C = 6.20 | cada dólar devuelve 7.20 USD | horas que pagan el gasto: 9.5 de 68.2
tope del presupuesto: gasto 45.00 USD | retorno (B - C) / C = 5.15 | cada dólar devuelve 6.15 USD | horas que pagan el gasto: 11.1 de 68.2

La Tabla 4 recoge las horas y su valor. Son $68.24$ horas al mes, unas ocho jornadas y media.
Tabla 4. Horas ahorradas al mes por proceso y su valor a 75 MXN la hora (tipo de cambio didáctico de 18.50).
| Proceso | Día que lo midió | Horas al mes | MXN al mes | USD al mes |
|---|---|---|---|---|
| Encargos: de 6 a 1.5 minutos por encargo | 1 | 35.10 | 2 632.50 | 142.30 |
| Correos de mayoristas con borradores: de 20.00 a 5.03 horas | 47 | 14.97 | 1 122.75 | 60.69 |
| Contenido de redes con calendario y borradores: de 14.0 a 4.5 horas | 71 | 9.50 | 712.50 | 38.51 |
| Informe del lunes: 2 horas por semana | 67 | 8.67 | 650.00 | 35.14 |
| Total | 68.24 | 5 117.75 | 276.64 |
Las horas ahorradas valen $276.64$ USD al mes, $5,117.75$ MXN, frente a un gasto de $40.53$: el retorno es de $5.82$ y cada dólar devuelve $6.82$. Con la factura de mayo sube a $6.20$, y aun gastando el tope completo de $45$ USD sería de $5.15$. La cuenta inversa es la que Don Ernesto entiende mejor: diez de las $68$ horas pagan todo el ecosistema, y las otras $58$ son del negocio. El Día 1 calculó que cada dólar devolvería $3.16$ USD contando solo los encargos y el presupuesto completo; hoy, con cuatro procesos medidos y la factura real, la cifra es más del doble, y la razón no es que las automatizaciones sean más baratas de lo previsto (son más caras), sino que ahorran más horas de las que el Día 1 podía contar.
La gráfica del bloque deja claro dónde está el retorno: en los encargos, que valen $142.30$ USD ellos solos, más de tres veces el gasto. Los otros tres procesos juntos valen $134.34$. Conviene leerla con la honestidad que la serie se exige: las $35.1$ horas de los encargos salen del objetivo de $1.5$ minutos por encargo del Día 1, que el Día 83 comprobó con mensajes reales, pero no de un cronómetro durante un mes completo con los flujos encendidos; el Día 75 construyó el panel con un mes simulado por la misma razón. El retorno de $5.82$ es una estimación con todas sus piezas medidas por separado, no una medición del conjunto, y así se le dice a Don Ernesto.
Lo que dijo Don Ernesto
Valeria le enseña la Tabla 1 y la Tabla 4 en la misma hoja, una encima de la otra, y espera. Don Ernesto lee la primera dos veces, como lee las facturas del molino, y pregunta por el renglón más caro antes que por el total: "¿Catorce y medio en el robot que piensa? Hace tres semanas eran diez." Valeria le explica los $3.166$ de las preguntas frecuentes y la palanca de Sonnet 5.5 con su condición, y él la acepta sin discutir la condición, porque la evaluación es la misma que le enseñaron el Día 70. Después lee la Tabla 4 y hace la cuenta que ella esperaba que hiciera: “Sesenta y ocho horas son dos semanas de Itzel en el mostrador. Y me cuesta setecientos cincuenta pesos. Un bulto de harina de calidad cuesta más.” Y luego la pregunta que nadie había hecho: "¿Y si un mes se pasa de los cuarenta y cinco? ¿Quién lo ve, y cuándo?"
La respuesta a esa pregunta no es una cifra sino un proceso, y es el último bloque del día. El registro propio dice lo que Valeria cree que gastó; la consola de Claude dice lo que cobró; y los dos tienen que coincidir cada mes, porque una diferencia que crece es una pieza que gasta sin escribir su fila, el síntoma que el manual M05 del Día 81 (Proyecto integrador III: manuales de operación (runbooks) y continuidad) convierte en acción. La API de administración de Claude expone el informe de costes del mes, agrupado por descripción (modelo, nivel de servicio y tipo de token), con los importes en centavos como cadena decimal y solo con granularidad diaria, y el informe de uso con los tokens leídos de la caché. Las dos consultas requieren una clave de administración (con el prefijo sk-ant-admin01), distinta de la clave de producción que el Día 80 inventarió: se guarda aparte, la usa este cuaderno el primer lunes de cada mes y nunca viaja en un workflow:
# Conciliación del gasto real de la consola de Claude con el registro propio por la API de uso y costes en Python:
import os
from collections import defaultdict
import requests
ADMIN = {'x-api-key': os.environ['ANTHROPIC_ADMIN_KEY'], # clave de administración (prefijo sk-ant-admin01), nunca en un flujo
'anthropic-version': '2023-06-01'}
BASE = 'https://api.anthropic.com/v1/organizations'
PERIODO = {'starting_at': '2026-04-01T06:00:00Z', 'ending_at': '2026-05-01T06:00:00Z'} # abril en hora de Ciudad de México
def cubetas(ruta, params):
# Recorre todas las páginas: has_more y next_page, como documenta la API de administración:
while True:
r = requests.get(BASE + ruta, headers = ADMIN, params = params, timeout = 30)
r.raise_for_status()
cuerpo = r.json()
yield from cuerpo['data']
if not cuerpo['has_more']:
return
params = {**params, 'page': cuerpo['next_page']}
# 1. Informe de costes del mes agrupado por descripción: cada resultado trae modelo, nivel de servicio y tipo de token:
por_modelo, por_tipo = defaultdict(float), defaultdict(float)
for cubeta in cubetas('/cost_report', {**PERIODO, 'group_by[]': 'description', 'limit': 31}):
for x in cubeta['results']:
usd = float(x['amount']) / 100 # amount llega en centavos, como cadena decimal
por_modelo[x['model'] or x['cost_type']] += usd
por_tipo[(x['service_tier'] or '-', x['token_type'] or '-')] += usd
consola = sum(por_modelo.values())
# 2. Uso del mes por modelo: cuánta entrada vino de la caché y cuánta salida se pagó:
tokens = defaultdict(lambda: defaultdict(int))
for cubeta in cubetas('/usage_report/messages', {**PERIODO, 'group_by[]': 'model', 'bucket_width': '1d', 'limit': 31}):
for x in cubeta['results']:
t = tokens[x['model']]
t['sin_cache'] += x['uncached_input_tokens']
t['cache'] += x['cache_read_input_tokens']
t['escritura'] += x['cache_creation']['ephemeral_5m_input_tokens'] + x['cache_creation']['ephemeral_1h_input_tokens']
t['salida'] += x['output_tokens']
# 3. Conciliación con el registro propio: las piezas de Claude de la factura (Bloque 3) y el aviso al 10 %:
registro = piezas.loc[piezas.rubro == 'Claude y embeddings', 'usd'].sum()
diferencia = consola - registro
print(f'Consola: {consola:.2f} USD | registro propio: {registro:.2f} USD | diferencia: {diferencia:+.2f} ({100 * diferencia / registro:+.1f} %)')
for modelo, usd in sorted(por_modelo.items(), key = lambda kv: -kv[1]):
t = tokens.get(modelo, {})
entrada = t.get('sin_cache', 0) + t.get('cache', 0)
print(f' {modelo}: {usd:.2f} USD | caché: {100 * t.get("cache", 0) / max(entrada, 1):.0f} % de la entrada | salida: {t.get("salida", 0):,} tokens')
lote = sum(v for (nivel, _), v in por_tipo.items() if nivel == 'batch')
print(f'Por lotes: {lote:.2f} USD ({100 * lote / consola:.0f} % de la consola)')
if abs(diferencia) > 0.10 * registro:
print('AVISO: hay una pieza que gasta sin escribir su fila; revisar con el manual M05 del Día 81')
# Salida de ejemplo (puede variar):
# Consola: 14.83 USD | registro propio: 14.51 USD | diferencia: +0.32 (+2.2 %)
# claude-opus-5-5: 12.06 USD | caché: 61 % de la entrada | salida: 418,350 tokens
# claude-sonnet-5-5: 1.93 USD | caché: 44 % de la entrada | salida: 131,900 tokens
# claude-haiku-5-5: 0.84 USD | caché: 12 % de la entrada | salida: 402,110 tokens
# Por lotes: 2.09 USD (14 % de la consola)
La conciliación cierra el círculo que abrió el Día 75: la consola cobró $14.83$ USD en el ejemplo y el registro explica $14.51$, una diferencia del $2.2%$ que son las pruebas del Día 83 y alguna llamada desde el cuaderno; el aviso salta al $10%$, el mismo umbral con el que el Día 81 detecta un bucle. Las dos cifras que Don Ernesto pidió ver cada mes están en la salida: el porcentaje de entrada que viene de la caché, que mide si la arquitectura del Día 61 sigue funcionando, y la parte del gasto que va por lotes, que subirá del $14%$ cuando las dos palancas de hoy entren en mayo. Y hay una respuesta directa a su pregunta: lo ve Valeria, el primer lunes de cada mes, en la cita mensual de costes que el calendario de gobierno del Día 79 ya tenía apuntada; si el total pasa del $80%$ del tope, lo ve también él, por Slack, el mismo día.
La decisión del Día 77 queda tomada y escrita en el registro de decisiones con la fecha de hoy: la primera opción (ampliar el rubro de Claude con dinero de WhatsApp) se adopta; la segunda (Sonnet 5.5 en las preguntas frecuentes) se adopta con condición; y la reserva de $5.91$ USD no se reparte. Don Ernesto firma debajo con la misma letra con la que firma los pedidos de harina.
Consideraciones finales
El coste de un ecosistema de automatizaciones no es un número que alguien le da, sino una tabla que usted construye con las piezas que midió, y la calidad de la tabla depende de que cada pieza tenga un día, un cálculo y un precio con fecha. La serie pudo escribir hoy “$40.53$ USD” porque ochenta y tres días antes empezó a anotar cada cifra; sin ese hábito, la pregunta de Don Ernesto se habría contestado con la cómoda estimación de $36.35$ del plan, y en agosto la factura habría roto el tope sin que nadie supiera por qué. Esa es la primera lección: el presupuesto se controla con el registro, no con el tope.
La segunda es que las desviaciones no son culpas. Claude costó un $81%$ más de lo asignado porque cada módulo añadió piezas que valían lo que costaban, y cada día lo documentó con su coste y su decisión; WhatsApp costó un $21%$ menos porque una decisión de arquitectura, la Cloud API directa, eliminó un recargo. Un presupuesto que no se desvía nunca es un presupuesto que nadie usó para decidir. Lo que sí es una falla es una desviación sin causa escrita, y hoy no queda ninguna.
La tercera es la más incómoda y la que la proyección enseña con tres curvas: la palanca más grande no está en el rubro que más creció. Claude es el rubro que más se desvió y el que más atención recibe, pero las palancas de Claude suman $3.61$ USD entre todas, mientras que una sola decisión sobre Make vale $10.59$ y multiplica por tres los meses de crecimiento que caben en el presupuesto. Los costes fijos son invisibles en una reunión porque no cambian; por eso hay que ir a buscarlos.
Hay una pregunta ética que la factura no responde y que la serie no deja pasar. Las $68$ horas ahorradas se contaron como valor, y lo son, pero el Día 1 fijó a qué se dedican: a la atención en el mostrador y al obrador, no a recortar personas; Don Ernesto lo dijo hoy a su manera al traducirlas a “dos semanas de Itzel en el mostrador”, y lo dijo como ganancia de tiempo, no como ahorro de sueldo. Y el retorno no incluye ventas adicionales que nadie midió: la campaña de primavera del Día 77 se publicará entre el 27 de abril y el 8 de mayo, y si vende más se sabrá en junio, no hoy. Un retorno que incluye lo que se desea en lugar de lo que se midió no es un retorno, es una ilusión con decimales.
Un gran libro sobre esta disciplina es Cloud FinOps (segunda edición, 2023), en el que J. R. Storment y Mike Fuller recogen la práctica de cientos de equipos para que el gasto en la nube sea una decisión de valor y no una sorpresa de fin de mes; sus tres fases (informar, optimizar y operar) son, a escala de empresa, lo que hoy hizo Valeria a escala de panadería: primero la factura con sus piezas, después las palancas con su evidencia y por último la cita mensual que vuelve a cruzar el puente.
Un presupuesto no es un tope que se cumple, sino una cuenta que se entiende: cada renglón con su día, cada desviación con su causa y cada palanca con su riesgo. Trigo Lento cuesta $40.53$ USD al mes y mañana costará $38.44$; devuelve $276.64$ en horas; se rompería en el cuarto mes si creciera un $5%$ sin hacer nada y en el duodécimo si hace lo que la hoja de ruta dice. Don Ernesto tiene su cifra, y no fue “depende”.
Conclusiones clave
Factura
- El ecosistema cuesta $40.53$ USD al mes con todo encendido ($749.85$ MXN): Make Core $10.59$, servidor $6.00$, WhatsApp $9.43$ y Claude con embeddings $14.51$ en $16$ piezas; quedan $4.47$ libres frente a los $45$, y el plan de la serie había estimado $36.35$.
- El coste por flujo mezcla una medida (lo variable) con una convención declarada (Make por créditos, servidor a partes iguales): el flujo más caro es el recordatorio de recogida ($8.50$, de los que $5.72$ son Make) y no el agente ($6.07$); los diez primeros suman el $82.4%$ y diez flujos cuestan solo su parte del servidor.
- Claude se desvió $+6.51$ USD ($81%$) y WhatsApp $-2.57$ ($-21%$) frente a la Tabla E, cada uno con su causa escrita; con el rango de tarifas de México y los dos regímenes de cobro, la factura va de $34.85$ a $45.63$ USD, y el peor caso rompe el tope por $1.10$.
Crecimiento
- Con $F = 16.59$ y $V = 23.94$, un crecimiento del $5%$ mensual rompe el presupuesto en el cuarto mes ($k^* = 3.51$); el crecimiento sostenible durante un año es del $1.44%$ al mes, y la parte fija pesa más que la variable: con Make en plan gratuito la ruptura se va al duodécimo mes.
- De ocho palancas, tres se accionan hoy ($2.09$ USD: preguntas frecuentes a Sonnet 5.5 tras evaluar, y dos piezas por lotes), tres se miden antes ($1.52$), una se descarta por riesgo sin medir y la de Make ($10.59$, más que todas las demás juntas) pasa a la hoja de ruta.
- Mayo queda en $38.44$ USD con un presupuesto revisado que cierra la deuda del Día 77: Claude $12.50$ (cabe por ocho centavos y avisará cada mes), WhatsApp $10.00$ y una reserva de $5.91$ que no se reparte; la conciliación mensual con la API de costes de Claude vigila que el registro y la consola coincidan al $10%$.
Retorno
- Las horas medidas suman $68.24$ al mes (encargos $35.1$, correos $14.97$, contenido $9.5$ e informe $8.67$) y valen $276.64$ USD: el retorno es de $5.82$, cada dólar devuelve $6.82$ y diez horas pagan todo el ecosistema.
- El retorno solo incluye lo medido: ni las horas del despacho Ledesma, ni las de afectación evitada de los manuales, ni ventas de una campaña que todavía no se publicó; y las horas ahorradas se dedican al mostrador y al obrador, como fijó el Día 1.
Mañana, en el Día 85: Caso comparado: el mismo método en la clínica dental, la tienda en línea y el despacho contable. Trigo Lento ya tiene su factura y su retorno; mañana Valeria aplicará las mismas preguntas, el mismo registro y las mismas palancas a los tres negocios ficticios que la serie visitó por el camino, para comprobar que el método de la panadería no depende del pan.
Referencias
- Anthropic (2026). Pricing. Claude Platform Documentation. https://platform.claude.com/docs/en/about-claude/pricing
- Anthropic (2026). Usage and Cost API; Get Cost Report; Get Messages Usage Report. Claude Platform Documentation. https://platform.claude.com/docs/en/manage-claude/usage-cost-api
- Meta (2026). Pricing on the WhatsApp Business Platform. Meta for Developers. https://developers.facebook.com/documentation/business-messaging/whatsapp/pricing
- Make (2026). Pricing and credits. https://www.make.com/en/pricing
- Storment, J. R. y Fuller, M. (2023). Cloud FinOps: Collaborative, Real-Time Cloud Value Decision Making (2.ª ed.). O’Reilly Media.
- Phillips, J. J. y Phillips, P. P. (2007). Show Me the Money: How to Determine ROI in People, Projects, and Programs. Berrett-Koehler Publishers.

