Arquitecto de automatización con IA: Día 13
Índice de contenido
Resumen:
Comparar plataformas de automatización por sus anuncios es comparar promesas; compararlas con el mismo flujo es comparar hechos. En esta entrada, Valeria construye cuatro veces el recordatorio de recogida de Trigo Lento (en Zapier, en un blueprint de Make, en un workflow de n8n y en una definición de Power Automate), cuenta lo que cobra cada una a 468 encargos al mes (962 créditos, 962 tareas, 26 ejecuciones o una licencia por usuario), simula 10 000 meses para medir el riesgo de pasarse de cuota, revisa conectores, gobierno y puertas de salida, y decide con una matriz ponderada (Make 3.60, n8n 3.30, Zapier 3.25 y Power Automate 2.90) cuya sensibilidad pone a prueba con 5 000 vectores de pesos. Al terminar, usted sabrá traducir un flujo entre plataformas pieza por pieza, calcular su consumo en cada unidad de cobro y defender una elección en una sola hoja.
¿Cómo citar el presente artículo?
Romero, J. (13 de febrero de 2026). Arquitecto de automatización con IA: Día 13. python-data-engineer. https://www.python-data-engineer.com/post/aai/dia_13/.
Arquitecto de automatización con IA: Día 13 by Jeshua Romero Guadarrama, available under Attribution 4.0 International (CC BY 4.0) at https://www.python-data-engineer.com/post/aai/dia_13/.
Precios, límites y políticas de Zapier, Make, n8n, Power Automate, WhatsApp (Meta y Twilio) y de la API de Claude revisados en octubre de 2026; las fuentes secundarias discrepan en algunos valores y se indica cuáles. El precio de Power Automate Premium (15 USD por usuario al mes, pago anual) se contrastó en la página oficial de Microsoft. Este día no llama a ningún servicio: los bloques de Python se ejecutan sin red y sus salidas son las reales. Los tres archivos JSON de flujo (Bloques 3, 4 y 5) tienen la estructura verificada contra la documentación de Make, de n8n y del lenguaje de definición de flujos de trabajo de Microsoft, revisado en octubre de 2026; no son exportaciones de una cuenta real, y sus identificadores son valores de ejemplo.
Día 13. Comparativa de herramientas I: Zapier, Make, n8n y Power Automate con el mismo flujo
Introducción
Ayer, en el Día 12 (Costes y límites: créditos, tareas, ejecuciones y cuotas), Valeria tradujo el flujo de mensajes a la unidad de cobro de cada plataforma ($7,644$ créditos de Make, $6,084$ tareas de Zapier y $1,560$ ejecuciones de n8n al mes), midió el riesgo de exceder una cuota y Trigo Lento ganó su reparto del presupuesto de $45$ USD con una alerta al $80%$. Hoy toca la otra mitad de la pregunta: no cuánto cobra cada plataforma por un flujo cualquiera, sino cómo se construye el mismo flujo en cada una y qué se gana o se pierde en el camino.
Es viernes 13 de febrero y mañana es el día de más trabajo del año en la panadería: el 14 de febrero los pasteles de chocolate y los pays de queso salen por docenas. Esta semana, además, tres clientes olvidaron recoger su encargo. Uno de ellos era un pastel de zanahoria de $420$ MXN que terminó repartido entre el personal al cierre del sábado. Valeria quiere que, cada mañana, cada persona que recoge ese día reciba un mensaje breve por WhatsApp: “Hola, su pedido está listo para recogerse hoy a partir de las 13:00”. Un amigo de la familia, que trabaja en una oficina, le recomienda Power Automate “porque ya pagan Microsoft 365”, y en la libreta de Valeria ya hay tres nombres más del Día 11: Zapier, Make y n8n.
Don Ernesto escucha la conversación mientras enharina la mesa y corta por lo sano: “Cuatro marcas para mandar un mensaje. Dígame cuál y por qué, en una hoja.” La petición es justa y tiene trampa. Justa, porque una decisión que no cabe en una hoja todavía no está pensada; con trampa, porque la matriz general del Día 11 ya puntuó las plataformas en abstracto, y un flujo concreto puede contar otra historia. El recordatorio es corto, se ejecuta una vez al día, recorre una lista y envía un mensaje por cada fila: justo el tipo de flujo en el que las unidades de cobro se separan.
En la presente entrada, descubrirá cómo se escribe el mismo flujo en cuatro plataformas: las piezas equivalentes (disparador, lectura, iteración, filtro, petición HTTP, registro y manejo de errores), el blueprint de Make, el workflow de n8n y la definición de Power Automate, leídos y dibujados con Python con las mismas formas. Contará el consumo en la unidad de cobro de cada una, simulará $10,000$ meses para ver con qué frecuencia se rompe una cuota y dibujará el coste frente al volumen de encargos. Después comparará conectores, autoalojamiento, gobierno y puertas de salida, y terminará con una matriz ponderada de seis criterios, puesta a prueba con $5,000$ vectores de pesos, y con la hoja que Don Ernesto pidió.
Objetivos de aprendizaje
Al terminar esta entrada, usted podrá:
- Modelar un mismo flujo (el recordatorio de recogida) en Zapier, Make, n8n y Power Automate e identificar las piezas equivalentes en cada uno.
- Contar el consumo del flujo en la unidad de cobro de cada plataforma a $468$ encargos al mes y su riesgo de exceder una cuota.
- Comparar conectores, autoalojamiento, gobierno y dependencia del proveedor con criterios explícitos.
- Decidir con una matriz ponderada y comprobar cuánto depende la decisión de los pesos.
El flujo de referencia
Una comparación honesta empieza por fijar qué se compara. Si cada plataforma construyera “un recordatorio” a su manera, una con reintentos y otra sin ellos, una con registro y otra sin él, la comparación mediría el cuidado de quien construye y no la herramienta. Por eso Valeria escribe primero la especificación del flujo, independiente de cualquier plataforma, y solo después lo traduce. Es la misma disciplina del contrato de datos del Día 4: primero se acuerda qué entra y qué sale; después se decide quién lo hace.
El recordatorio funciona así: cada día, de lunes a sábado a las 9:00, el flujo lee en la hoja de cálculo de encargos las filas cuya fecha de recogida es hoy; descarta a quien no dio consentimiento para recibir mensajes por WhatsApp; envía a cada persona restante una plantilla de utilidad aprobada por Meta, a través de Twilio, con su nombre y la hora de recogida; y anota cada envío en una segunda hoja, con el identificador del mensaje que devuelve Twilio y su estado. Con los datos fijos de la serie, son $18$ encargos al día y $26$ días de trabajo al mes: $468$ recordatorios como máximo.
El primer bloque prepara las importaciones, la semilla global $2026$, la carpeta del día y los dos números que gobiernan toda la entrada: los encargos por día y los días de trabajo al mes:
# Importaciones base, semilla de la serie y supuestos del día en Python:
import warnings
warnings.filterwarnings('ignore')
import json
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:
rng = np.random.default_rng(2026)
pd.set_option('display.width', 120)
pd.set_option('display.max_columns', 12)
carpeta = Path('trigo_lento') / 'dia_13'
carpeta.mkdir(parents = True, exist_ok = True)
# Volumen del recordatorio y supuestos didácticos de la serie:
ENCARGOS_DIA, DIAS = 18, 26 # lunes a sábado
ENCARGOS_MES = ENCARGOS_DIA * DIAS # 468
USD_POR_EUR = 1.08 # tipo didáctico (supuesto)
print('numpy', np.__version__, '| pandas', pd.__version__)
print('Encargos al mes:', ENCARGOS_MES, '| corridas del flujo al mes:', DIAS)
numpy 2.4.6 | pandas 3.0.3
Encargos al mes: 468 | corridas del flujo al mes: 26
El flujo se ejecuta $26$ veces al mes y atiende $468$ encargos. Esa diferencia entre corridas y encargos es la que va a separar a las plataformas: unas cobran por corrida, otras por cada paso que se ejecuta dentro de la corrida, y otras no cobran ni lo uno ni lo otro, sino por la persona que usa la herramienta.
El siguiente bloque escribe la especificación como un diccionario y la traducción de cada pieza a las cuatro plataformas como un DataFrame. La especificación es lo que Valeria le entregaría a cualquier persona que tuviera que construir el flujo; la tabla de piezas es el diccionario bilingüe, o mejor dicho cuatrilingüe, que permite pasar de una plataforma a otra:
# Especificación del recordatorio de recogida y piezas equivalentes por plataforma en Python:
especificacion = {
'disparador': 'Programado: lunes a sábado a las 9:00 (America/Mexico_City)',
'entrada': 'Hoja Encargos: id_pedido, nombre, telefono, fecha_recogida, hora_recogida, whatsapp_ok',
'filtro': 'fecha_recogida = hoy y whatsapp_ok = "sí"',
'mensaje': 'Plantilla de utilidad aprobada por Meta con nombre y hora; ofrece responder BAJA',
'registro': 'Hoja Envios: id_pedido, tipo, sid, estado, enviado',
'errores': '3 reintentos ante 429 o 5xx; si persiste, estado "fallido" y aviso a Valeria',
'responsable': 'Valeria (dueña del flujo); Don Ernesto recibe el resumen semanal',
}
for campo, valor in especificacion.items():
print(f'{campo:<12} {valor}')
piezas = pd.DataFrame({
'Zapier': ['Schedule by Zapier', 'Lookup Spreadsheet Rows', 'Looping by Zapier',
'Filter by Zapier', 'Webhooks by Zapier (POST)', 'Create Spreadsheet Row', 'Autoreplay y aviso'],
'Make': ['Programación del escenario', 'google-sheets:filterRows', 'Un paquete por fila',
'Filtro en la conexión', 'http:ActionSendData', 'google-sheets:addRow', 'onerror con builtin:Break'],
'n8n': ['scheduleTrigger', 'googleSheets (leer)', 'Items sin bucle explícito',
'filter', 'httpRequest', 'googleSheets (append)', 'retryOnFail en el nodo'],
'Power Automate': ['Recurrence', 'Listar filas (GetItems)', 'Apply to each',
'Filter array (Query)', 'HTTP (premium)', 'Insertar fila (PostItem)', 'retryPolicy y runAfter'],
}, index = ['disparador', 'lectura', 'iteración', 'filtro', 'petición HTTP', 'registro', 'error'])
print()
print(piezas.to_string())
print('Piezas por plataforma:', len(piezas), '| plataformas:', len(piezas.columns))
disparador Programado: lunes a sábado a las 9:00 (America/Mexico_City)
entrada Hoja Encargos: id_pedido, nombre, telefono, fecha_recogida, hora_recogida, whatsapp_ok
filtro fecha_recogida = hoy y whatsapp_ok = "sí"
mensaje Plantilla de utilidad aprobada por Meta con nombre y hora; ofrece responder BAJA
registro Hoja Envios: id_pedido, tipo, sid, estado, enviado
errores 3 reintentos ante 429 o 5xx; si persiste, estado "fallido" y aviso a Valeria
responsable Valeria (dueña del flujo); Don Ernesto recibe el resumen semanal
Zapier Make n8n Power Automate
disparador Schedule by Zapier Programación del escenario scheduleTrigger Recurrence
lectura Lookup Spreadsheet Rows google-sheets:filterRows googleSheets (leer) Listar filas (GetItems)
iteración Looping by Zapier Un paquete por fila Items sin bucle explícito Apply to each
filtro Filter by Zapier Filtro en la conexión filter Filter array (Query)
petición HTTP Webhooks by Zapier (POST) http:ActionSendData httpRequest HTTP (premium)
registro Create Spreadsheet Row google-sheets:addRow googleSheets (append) Insertar fila (PostItem)
error Autoreplay y aviso onerror con builtin:Break retryOnFail en el nodo retryPolicy y runAfter
Piezas por plataforma: 7 | plataformas: 4
La primera parte de la salida es la Tabla 1, la especificación con siete campos. Ninguno menciona una plataforma: dicen qué debe pasar, no con qué botón.
Tabla 1. Especificación del recordatorio de recogida de Trigo Lento, independiente de la plataforma.
| Campo | Especificación |
|---|---|
| Disparador | Programado: de lunes a sábado a las 9:00, hora de la Ciudad de México |
| Entrada | Hoja Encargos: id_pedido, nombre, telefono, fecha_recogida, hora_recogida, whatsapp_ok |
| Filtro de consentimiento | fecha_recogida igual a hoy y whatsapp_ok igual a “sí” |
| Mensaje | Plantilla de utilidad aprobada por Meta con nombre y hora; ofrece responder BAJA |
| Registro | Hoja Envios: id_pedido, tipo, sid, estado y momento del envío |
| Errores | Tres reintentos ante un 429 o un 5xx; si el fallo persiste, estado “fallido” y aviso a Valeria |
| Responsable | Valeria es la dueña del flujo; Don Ernesto recibe el resumen semanal |
Tres campos merecen una explicación:
- El filtro va antes del mensaje, no después. El consentimiento no es un adorno ético: es una condición técnica para enviar una plantilla por WhatsApp y una obligación de la ley de datos personales que el Día 6 puso en el código de honor. Un flujo que envía y luego comprueba ya incumplió.
- El mensaje es una plantilla de utilidad, no de marketing. Avisa de un pedido en curso, se cobra a $0.0085$ USD por mensaje entregado en México según la Tabla C del plan de la serie, y no se puede usar para ofrecer el pastel de la semana. Una plantilla de marketing costaría casi cuatro veces más y exigiría otro consentimiento.
- El registro guarda el identificador del mensaje, no el texto. Con el
sidde Twilio se puede consultar el estado de entrega más tarde; guardar el texto completo duplicaría datos personales sin necesidad.
La segunda parte de la salida es la Tabla 2: las siete piezas del flujo y su nombre en cada plataforma.
Tabla 2. Piezas equivalentes del recordatorio en Zapier, Make, n8n y Power Automate.
| Pieza | Zapier | Make | n8n | Power Automate |
|---|---|---|---|---|
| Disparador programado | Schedule by Zapier | Programación del escenario | scheduleTrigger | Recurrence |
| Lectura de filas | Lookup Spreadsheet Rows | google-sheets:filterRows | googleSheets (leer) | Listar filas (GetItems) |
| Iteración | Looping by Zapier | Un paquete por fila, sin módulo | Los items fluyen sin bucle | Apply to each |
| Filtro de consentimiento | Filter by Zapier | Filtro en la conexión entre módulos | filter | Filter array (Query) |
| Petición HTTP a Twilio | Webhooks by Zapier (POST) | http:ActionSendData | httpRequest | HTTP (conector premium) |
| Escritura del registro | Create Spreadsheet Row | google-sheets:addRow | googleSheets (append) | Insertar fila (PostItem) |
| Manejo de error | Repetición automática y aviso | onerror con builtin:Break | retryOnFail en el nodo | retryPolicy y runAfter |
La fila más instructiva es la de la iteración. Zapier y Power Automate necesitan una pieza explícita para recorrer la lista (Looping by Zapier y Apply to each); en Make y en n8n la iteración es implícita: cuando un módulo de Make devuelve varias filas, cada fila se convierte en un paquete (en inglés, bundle) que recorre los módulos siguientes; en n8n, cada fila es un item y todos los nodos procesan todos los items que reciben. La consecuencia no es solo estética: la pieza explícita de iteración aparece en el dibujo, a veces en la factura y siempre en la mente de quien mantiene el flujo.
El mismo flujo cuatro veces
Con la especificación fija y el diccionario de piezas en la mano, Valeria construye el recordatorio en las cuatro plataformas. En las cuatro conserva los mismos nombres de columnas, la misma plantilla de Twilio y los mismos identificadores de ejemplo, de modo que las diferencias que aparezcan sean de la herramienta y no del diseño.
Zapier
En Zapier, el flujo es un Zap de seis pasos. El disparador Schedule by Zapier se configura “cada día”, de lunes a sábado, a las 9:00. El segundo paso, Lookup Spreadsheet Rows de Google Sheets en su variante que devuelve varias filas, busca las de la fecha de hoy. El tercero, Looping by Zapier, convierte la lista en iteraciones: todo lo que viene después se repite una vez por fila. Dentro del bucle, Filter by Zapier deja pasar solo a quien tiene whatsapp_ok igual a “sí”; Webhooks by Zapier envía el POST a la API de Twilio con la plantilla; y Create Spreadsheet Row escribe el registro.
Zapier tiene un conector propio de Twilio, pero su acción de enviar mensajes está pensada para texto libre; una plantilla de WhatsApp aprobada se identifica con un ContentSid y unas ContentVariables, y el camino más directo para enviarla es la petición HTTP. Este detalle se repetirá en las cuatro plataformas: el conector con el nombre del servicio no siempre expone la operación que usted necesita, y entonces el conector genérico HTTP pasa a ser una pieza crítica.
Zapier no ofrece una exportación de Zaps en un formato que otra herramienta pueda importar, así que el Zap de Valeria se describe a mano, como una lista de pasos, en el Bloque 6. Esa ausencia es, en sí misma, un dato para la sección de dependencia del proveedor.
Make
En Make, el recordatorio es un escenario de tres módulos más un manejador de errores. La programación diaria no es un módulo: vive en los ajustes del escenario (“cada día”, con días y hora), y por eso el blueprint exportado no la contiene. El primer módulo, google-sheets:filterRows (la acción “Search Rows”), busca las filas cuya columna E, la fecha de recogida, coincide con la fecha de hoy; cada fila encontrada sale como un paquete. El segundo, http:ActionSendData (“Make a request”), envía la plantilla a Twilio, pero solo para los paquetes que pasan el filtro “Con consentimiento de WhatsApp”, que en Make se coloca en la conexión entre dos módulos y no cuesta créditos. El tercero, google-sheets:addRow, escribe el registro con el sid y el status que devuelve Twilio. El módulo HTTP lleva un manejador onerror con la directiva builtin:Break, configurada para reintentar tres veces con $15$ minutos de intervalo.
Este es el archivo trigo_lento/dia_13/flujos/make/recordatorio_recogida_v0.blueprint.json:
{
"name": "TL Recordatorio de recogida v0",
"flow": [
{
"id": 1,
"module": "google-sheets:filterRows",
"version": 2,
"parameters": {"__IMTCONN__": 0},
"mapper": {
"from": "drive",
"spreadsheetId": "/ID_DE_EJEMPLO",
"sheetId": "Encargos",
"includesHeaders": true,
"tableFirstRow": "A1:Z1",
"filter": [[{"a": "E", "b": "{{formatDate(now; \"YYYY-MM-DD\")}}", "o": "text:equal"}]],
"sortOrder": "asc",
"limit": 100
},
"metadata": {"designer": {"x": 0, "y": 0}}
},
{
"id": 2,
"module": "http:ActionSendData",
"version": 3,
"parameters": {"handleErrors": true},
"filter": {
"name": "Con consentimiento de WhatsApp",
"conditions": [[{"a": "{{1.`6`}}", "b": "sí", "o": "text:equal"}]]
},
"mapper": {
"url": "https://api.twilio.com/2010-04-01/Accounts/AC_DE_EJEMPLO/Messages.json",
"method": "post",
"bodyType": "x_www_form_urlencoded",
"fields": [
{"key": "From", "value": "whatsapp:+5255000000XX"},
{"key": "To", "value": "whatsapp:{{1.`3`}}"},
{"key": "ContentSid", "value": "HX_PLANTILLA_DE_EJEMPLO"},
{"key": "ContentVariables", "value": "{\"1\": \"{{1.`1`}}\", \"2\": \"{{1.`5`}}\"}"}
],
"parseResponse": true,
"timeout": 30
},
"metadata": {"designer": {"x": 300, "y": 0}},
"onerror": [
{
"id": 4,
"module": "builtin:Break",
"version": 1,
"parameters": {},
"mapper": {"retry": true, "count": 3, "interval": 15},
"metadata": {"designer": {"x": 300, "y": 300}}
}
]
},
{
"id": 3,
"module": "google-sheets:addRow",
"version": 2,
"parameters": {"__IMTCONN__": 0},
"mapper": {
"mode": "select",
"spreadsheetId": "/ID_DE_EJEMPLO",
"sheetId": "Envios",
"includesHeaders": true,
"insertDataOption": "INSERT_ROWS",
"valueInputOption": "USER_ENTERED",
"values": {
"0": "{{1.`0`}}",
"1": "recordatorio_recogida",
"2": "{{2.data.sid}}",
"3": "{{2.data.status}}",
"4": "{{now}}"
}
},
"metadata": {"designer": {"x": 600, "y": 0}}
}
],
"metadata": {
"instant": false,
"version": 1,
"scenario": {"roundtrips": 1, "maxErrors": 3, "autoCommit": true, "autoCommitTriggerLast": true, "sequential": false, "confidential": false, "dataloss": false, "dlq": true, "freshVariables": false},
"designer": {"orphans": []}
}
}
Cuatro detalles del blueprint conviene leerlos con calma:
"instant": falseenmetadataindica que el escenario no arranca con un webhook instantáneo, sino por programación. En el Día 11, el formulario web tenía"instant": true."dlq": trueenmetadata.scenarioactiva el almacenamiento de ejecuciones incompletas, que la directivabuiltin:Breaknecesita para guardar el paquete fallido y reintentarlo; sin esa casilla, el reintento no tiene dónde esperar.- El mapeo usa índices de columna:
{{1.3}}es la cuarta columna (el teléfono) del paquete que entregó el módulo $1$. Es frágil: si alguien inserta una columna en la hoja, el flujo envía el mensaje al número equivocado. El Día 14 volverá sobre este riesgo al hablar de tablas con encabezados. - El identificador
google-sheets:filterRowsde la búsqueda de filas, como los demás de la serie, debe contrastarse exportando un escenario real antes de usarlo, porque los nombres internos cambian con las versiones de las aplicaciones.
n8n
En n8n, el recordatorio es un workflow de cinco nodos en línea: el disparador scheduleTrigger con la expresión cron 0 9 * * 1-6 (minuto $0$, hora $9$, cualquier día del mes, cualquier mes, días de la semana del $1$ al $6$, es decir, de lunes a sábado); la lectura de Google Sheets con un filtro por la columna fecha_recogida; un nodo filter para el consentimiento; un httpRequest a Twilio con la credencial predefinida twilioApi; y la escritura del registro. No hay bucle: el nodo de lectura devuelve $18$ items y los nodos siguientes procesan los $18$. La zona horaria se fija en settings.timezone, para que las 9:00 sean las de la Ciudad de México y no las del servidor.
Este es trigo_lento/dia_13/flujos/n8n/recordatorio_recogida_v0.json:
{
"name": "TL Recordatorio de recogida v0",
"nodes": [
{
"parameters": {"rule": {"interval": [{"field": "cronExpression", "expression": "0 9 * * 1-6"}]}},
"id": "0b1c0000-0000-4000-8000-000000000001",
"name": "Cada día a las 9",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [0, 0]
},
{
"parameters": {
"documentId": {"__rl": true, "value": "ID_DE_EJEMPLO", "mode": "id"},
"sheetName": {"__rl": true, "value": "Encargos", "mode": "name"},
"filtersUI": {"values": [{"lookupColumn": "fecha_recogida", "lookupValue": "={{ $today.toFormat('yyyy-MM-dd') }}"}]},
"options": {}
},
"id": "7f3a0000-0000-4000-8000-000000000002",
"name": "Encargos de hoy",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [220, 0],
"credentials": {"googleSheetsOAuth2Api": {"id": "CREDENCIAL_DE_EJEMPLO", "name": "Hoja de Trigo Lento"}}
},
{
"parameters": {
"conditions": {
"options": {"caseSensitive": false, "typeValidation": "strict"},
"conditions": [{"leftValue": "={{ $json.whatsapp_ok }}", "rightValue": "sí", "operator": {"type": "string", "operation": "equals"}}],
"combinator": "and"
},
"options": {}
},
"id": "7f3a0000-0000-4000-8000-000000000003",
"name": "¿Consentimiento?",
"type": "n8n-nodes-base.filter",
"typeVersion": 2,
"position": [440, 0]
},
{
"parameters": {
"method": "POST",
"url": "https://api.twilio.com/2010-04-01/Accounts/AC_DE_EJEMPLO/Messages.json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "twilioApi",
"sendBody": true,
"contentType": "form-urlencoded",
"bodyParameters": {"parameters": [
{"name": "From", "value": "whatsapp:+5255000000XX"},
{"name": "To", "value": "=whatsapp:{{ $json.telefono }}"},
{"name": "ContentSid", "value": "HX_PLANTILLA_DE_EJEMPLO"},
{"name": "ContentVariables", "value": "={{ JSON.stringify({ 1: $json.nombre, 2: $json.hora_recogida }) }}"}
]},
"options": {}
},
"id": "7f3a0000-0000-4000-8000-000000000004",
"name": "Enviar plantilla",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [660, 0],
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 5000,
"credentials": {"twilioApi": {"id": "CREDENCIAL_DE_EJEMPLO", "name": "Twilio de Trigo Lento"}}
},
{
"parameters": {
"operation": "append",
"documentId": {"__rl": true, "value": "ID_DE_EJEMPLO", "mode": "id"},
"sheetName": {"__rl": true, "value": "Envios", "mode": "name"},
"columns": {
"mappingMode": "defineBelow",
"value": {
"id_pedido": "={{ $('¿Consentimiento?').item.json.id_pedido }}",
"tipo": "recordatorio_recogida",
"sid": "={{ $json.sid }}",
"estado": "={{ $json.status }}",
"enviado": "={{ $now.toISO() }}"
}
},
"options": {}
},
"id": "7f3a0000-0000-4000-8000-000000000005",
"name": "Registrar envío",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [880, 0],
"credentials": {"googleSheetsOAuth2Api": {"id": "CREDENCIAL_DE_EJEMPLO", "name": "Hoja de Trigo Lento"}}
}
],
"connections": {
"Cada día a las 9": {"main": [[{"node": "Encargos de hoy", "type": "main", "index": 0}]]},
"Encargos de hoy": {"main": [[{"node": "¿Consentimiento?", "type": "main", "index": 0}]]},
"¿Consentimiento?": {"main": [[{"node": "Enviar plantilla", "type": "main", "index": 0}]]},
"Enviar plantilla": {"main": [[{"node": "Registrar envío", "type": "main", "index": 0}]]}
},
"settings": {"executionOrder": "v1", "timezone": "America/Mexico_City"},
"pinData": {},
"meta": {"templateCredsSetupCompleted": true}
}
En el nodo HTTP, las tres claves retryOnFail, maxTries y waitBetweenTries hacen lo que en Make hacía el manejador de error: hasta tres intentos con cinco segundos de espera. En el registro, la expresión $('¿Consentimiento?').item.json.id_pedido recupera el identificador del pedido desde el nodo del filtro, porque la salida del nodo HTTP ya no lo contiene: trae la respuesta de Twilio. Ese “mirar hacia atrás” a un nodo anterior por su nombre es una de las ideas del modelo de datos de n8n que el Día 36 estudiará a fondo.
Power Automate
En Power Automate, el flujo de nube se describe en el lenguaje de definición de flujos de trabajo de Microsoft, el mismo de Azure Logic Apps: un objeto con triggers y actions, donde cada acción declara con runAfter de qué acción depende y en qué estado. El disparador Recurrence se programa semanalmente, de lunes a sábado a las 9, en la zona Central Standard Time (Mexico). La acción Listar_filas usa el conector de Google Sheets (shared_googlesheet, operación GetItems); Filtrar_hoy_con_consentimiento es una acción Query (en la interfaz, “Filter array”) que conserva las filas de hoy con consentimiento; y Apply_to_each recorre el resultado con dos acciones dentro: HTTP, la petición a Twilio, y Registrar_envio, que inserta la fila del registro (PostItem).
Esta definición es ilustrativa y no se ejecutó: se escribió con la estructura documentada del lenguaje y debe contrastarse exportando un flujo real (en Power Automate, como paquete de solución o como paquete .zip del flujo), porque los operationId y los nombres de parámetros del conector cambian. Este es trigo_lento/dia_13/flujos/power_automate/recordatorio_recogida_v0.json:
{
"properties": {
"displayName": "TL Recordatorio de recogida v0",
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"$connections": {"defaultValue": {}, "type": "Object"},
"$authentication": {"defaultValue": {}, "type": "SecureObject"},
"twilio_token": {"defaultValue": "", "type": "SecureString"}
},
"triggers": {
"Recurrence": {
"type": "Recurrence",
"recurrence": {
"frequency": "Week",
"interval": 1,
"timeZone": "Central Standard Time (Mexico)",
"schedule": {"weekDays": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], "hours": ["9"], "minutes": [0]}
}
}
},
"actions": {
"Listar_filas": {
"type": "OpenApiConnection",
"inputs": {
"host": {"apiId": "/providers/Microsoft.PowerApps/apis/shared_googlesheet", "connectionName": "shared_googlesheet", "operationId": "GetItems"},
"parameters": {"dataset": "ID_DE_EJEMPLO", "table": "Encargos"},
"authentication": "@parameters('$authentication')"
},
"runAfter": {}
},
"Filtrar_hoy_con_consentimiento": {
"type": "Query",
"inputs": {
"from": "@outputs('Listar_filas')?['body/value']",
"where": "@and(equals(item()?['fecha_recogida'], formatDateTime(convertFromUtc(utcNow(), 'Central Standard Time (Mexico)'), 'yyyy-MM-dd')), equals(item()?['whatsapp_ok'], 'sí'))"
},
"runAfter": {"Listar_filas": ["Succeeded"]}
},
"Apply_to_each": {
"type": "Foreach",
"foreach": "@body('Filtrar_hoy_con_consentimiento')",
"actions": {
"HTTP": {
"type": "Http",
"inputs": {
"method": "POST",
"uri": "https://api.twilio.com/2010-04-01/Accounts/AC_DE_EJEMPLO/Messages.json",
"headers": {"Content-Type": "application/x-www-form-urlencoded"},
"body": "From=whatsapp:+5255000000XX&To=whatsapp:@{items('Apply_to_each')?['telefono']}&ContentSid=HX_PLANTILLA_DE_EJEMPLO",
"authentication": {"type": "Basic", "username": "AC_DE_EJEMPLO", "password": "@parameters('twilio_token')"},
"retryPolicy": {"type": "exponential", "count": 3, "interval": "PT10S"}
}
},
"Registrar_envio": {
"type": "OpenApiConnection",
"inputs": {
"host": {"apiId": "/providers/Microsoft.PowerApps/apis/shared_googlesheet", "connectionName": "shared_googlesheet", "operationId": "PostItem"},
"parameters": {
"dataset": "ID_DE_EJEMPLO",
"table": "Envios",
"item/id_pedido": "@items('Apply_to_each')?['id_pedido']",
"item/sid": "@body('HTTP')?['sid']",
"item/estado": "@body('HTTP')?['status']"
},
"authentication": "@parameters('$authentication')"
},
"runAfter": {"HTTP": ["Succeeded"]}
}
},
"runAfter": {"Filtrar_hoy_con_consentimiento": ["Succeeded"]}
}
},
"outputs": {}
}
},
"schemaVersion": "1.0.0.0"
}
Dos piezas de esta definición tienen consecuencias que no se ven en el dibujo. La primera es la licencia: según la documentación de Microsoft, el conector HTTP es premium, y un flujo con un conector premium exige que su propietario tenga una licencia Premium, de $15$ USD por usuario al mes en pago anual (página oficial de precios consultada en octubre de 2026). El conector de Twilio de Power Automate es estándar, pero su única acción de envío es “Send Text Message (SMS)”, sin parámetros de plantilla, así que no sirve para la plantilla de WhatsApp. La segunda es el secreto: la contraseña de Twilio no está en el archivo, sino en el parámetro seguro twilio_token, de tipo SecureString; aun así, la serie recomienda guardarla en una conexión o en un almacén de secretos, como verá el Día 17.
Atención aquí: “ya pagamos Microsoft 365” no equivale a “Power Automate nos sale gratis”. Muchas licencias de Microsoft 365 incluyen flujos de nube con conectores estándar, pero el recordatorio necesita el conector HTTP, que la documentación de Microsoft clasifica como premium, y un solo paso premium convierte todo el flujo en premium. Antes de elegir una plataforma “porque ya está pagada”, compruebe qué piezas de su flujo cubre la licencia que tiene y cuáles no; de lo contrario, descubrirá el coste el día que el flujo deje de ejecutarse. La clasificación de los conectores cambia: verifíquela en la ficha del conector y en su centro de administración.
Las cuatro versiones, dibujadas
Cuatro formatos distintos describen el mismo proceso, y la forma más rápida de comprobarlo es dibujarlos con las mismas reglas. El siguiente bloque reutiliza la función dibujar_flujo del Día 2, con la paleta de formas de la serie (disparador en óvalo verde, acción en rectángulo azul, decisión en rombo naranja, error en rectángulo rojo), y escribe tres lectores: uno para el blueprint de Make, que añade la programación como un nodo virtual y convierte cada filter de una conexión en un rombo; uno para el workflow de n8n, que sigue las connections desde el nodo que no tiene entrada; y uno para la definición de Power Automate, que ordena las acciones por runAfter y entra en las acciones anidadas del Foreach. El Zap se describe a mano. Además, el bloque comprueba que ninguno de los tres JSON lleva identificadores reales:
# Lectura de los tres JSON a nodos y aristas, Zapier descrito a mano y dibujo en cuadrícula en Python:
import textwrap
from matplotlib.patches import Ellipse, FancyBboxPatch, Polygon, RegularPolygon, FancyArrowPatch
FORMAS = { # paleta de formas de la serie: tipo -> (forma, relleno)
'disparador': ('ovalo', '#3a9d5d'), 'accion': ('rectangulo', '#2a78d6'),
'decision': ('rombo', '#eb6834'), 'ia': ('rectangulo', '#7b5ea7'),
'error': ('rectangulo', '#c8423b'), 'humano': ('hexagono', '#8a8986'),
}
def dibujar_flujo(nodos, aristas, titulo, ax = None, ancho = 2.2, alto = 1.25, recorte = 30):
if ax is None:
fig, ax = plt.subplots(figsize = (12, 5.6))
for n in nodos:
forma, color = FORMAS[n['tipo']]
x, y = n['x'], n['y']
if forma == 'ovalo':
figura = Ellipse((x, y), ancho, alto)
elif forma == 'rombo':
figura = Polygon([(x - ancho / 1.6, y), (x, y + alto / 1.4), (x + ancho / 1.6, y), (x, y - alto / 1.4)])
elif forma == 'hexagono':
figura = RegularPolygon((x, y), 6, radius = ancho / 2, orientation = np.pi / 6)
else:
figura = FancyBboxPatch((x - ancho / 2, y - alto / 2), ancho, alto, boxstyle = 'round,pad=0.03')
figura.set_facecolor(color)
figura.set_edgecolor('white')
figura.set_linewidth(2)
ax.add_patch(figura)
ax.text(x, y, n['texto'], ha = 'center', va = 'center', fontsize = 7.5, color = 'white')
posicion = {n['id']: (n['x'], n['y']) for n in nodos}
for origen, destino, etiqueta in aristas:
(x1, y1), (x2, y2) = posicion[origen], posicion[destino]
ax.add_patch(FancyArrowPatch((x1, y1), (x2, y2), arrowstyle = '-|>', mutation_scale = 12,
shrinkA = recorte, shrinkB = recorte + 2, color = '#52514e', linewidth = 1.3))
if etiqueta:
ax.text((x1 + x2) / 2 + 0.15, (y1 + y2) / 2, etiqueta, ha = 'left', fontsize = 8, color = '#52514e')
xs, ys = [n['x'] for n in nodos], [n['y'] for n in nodos]
ax.set_xlim(-1.4, 6 * 2.5 - 1.1)
ax.set_ylim(-2.3, 0.9)
ax.set_aspect('equal')
ax.axis('off')
ax.set_title(titulo, fontsize = 12)
return ax
def tipo_de(nombre):
n = nombre.lower()
if 'filterrows' in n:
return 'accion' # búsqueda de filas de Make, no un filtro
if any(p in n for p in ('schedule', 'recurrence', 'programación')):
return 'disparador'
if any(p in n for p in ('filter', 'query', 'filtro', 'consentimiento')):
return 'decision'
if 'break' in n:
return 'error'
return 'accion'
def rotulo(texto, ancho = 14):
return '\n'.join(textwrap.wrap(texto.replace('_', ' ').replace(':', ': '), ancho, break_long_words = False))
def en_fila(pasos, errores = ()):
# Coloca los pasos en una fila y los manejadores de error debajo del paso que protegen:
nodos = [{'id': p, 'tipo': tipo_de(p), 'texto': rotulo(p), 'x': i * 2.5, 'y': 0}
for i, p in enumerate(pasos)]
aristas = [(a, b, '') for a, b in zip(pasos, pasos[1:])]
for protegido, manejador in errores:
x = next(n['x'] for n in nodos if n['id'] == protegido)
nodos.append({'id': manejador, 'tipo': 'error', 'texto': rotulo(manejador), 'x': x, 'y': -1.6})
aristas.append((protegido, manejador, 'error'))
return nodos, aristas
def nodos_desde_blueprint(bp):
# La programación vive en los ajustes del escenario, no en el blueprint; se añade como nodo virtual:
pasos, errores = ['Programación'], []
for m in bp['flow']:
if 'filter' in m:
pasos.append('Filtro')
pasos.append(m['module'])
errores += [(m['module'], e['module']) for e in m.get('onerror', [])]
return en_fila(pasos, errores)
def nodos_desde_n8n(wf):
siguiente = {o: s['main'][0][0]['node'] for o, s in wf['connections'].items()}
destinos = set(siguiente.values())
actual = next(n['name'] for n in wf['nodes'] if n['name'] not in destinos)
pasos = [actual]
while actual in siguiente:
actual = siguiente[actual]
pasos.append(actual)
tipos = {n['name']: n['type'].split('.')[-1] for n in wf['nodes']}
nodos, aristas = en_fila(pasos)
for n in nodos:
n['tipo'] = tipo_de(tipos[n['id']])
n['texto'] = rotulo(n['id']) + '\n(' + tipos[n['id']] + ')'
return nodos, aristas
def nodos_desde_power_automate(pa):
definicion = pa['properties']['definition']
def recorrer(acciones):
pendientes, orden = dict(acciones), []
while pendientes: # orden por runAfter: primero lo que no espera a nadie pendiente
listo = next(k for k, v in pendientes.items() if not set(v.get('runAfter', {})) & set(pendientes))
orden.append(listo)
orden += recorrer(pendientes[listo].get('actions', {}))
del pendientes[listo]
return orden
pasos = list(definicion['triggers']) + recorrer(definicion['actions'])
return en_fila(pasos)
flujos = carpeta / 'flujos'
blueprint = json.loads((flujos / 'make' / 'recordatorio_recogida_v0.blueprint.json').read_text(encoding = 'utf-8'))
workflow = json.loads((flujos / 'n8n' / 'recordatorio_recogida_v0.json').read_text(encoding = 'utf-8'))
definicion_pa = json.loads((flujos / 'power_automate' / 'recordatorio_recogida_v0.json').read_text(encoding = 'utf-8'))
zapier = ['Schedule by Zapier', 'Lookup Spreadsheet Rows', 'Looping by Zapier',
'Filter by Zapier', 'Webhooks by Zapier (POST)', 'Create Spreadsheet Row'] # Zapier no exporta un formato importable
grafos = {'Zapier (descrito a mano)': en_fila(zapier),
'Make (desde el blueprint)': nodos_desde_blueprint(blueprint),
'n8n (desde el workflow)': nodos_desde_n8n(workflow),
'Power Automate (desde la definición)': nodos_desde_power_automate(definicion_pa)}
resumen = pd.DataFrame({nombre: {'nodos': len(n), 'aristas': len(a),
'disparadores': sum(x['tipo'] == 'disparador' for x in n),
'decisiones': sum(x['tipo'] == 'decision' for x in n),
'errores': sum(x['tipo'] == 'error' for x in n)}
for nombre, (n, a) in grafos.items()}).T
print(resumen.to_string())
# Comprobación de secretos: conexiones de Make en 0 y credenciales de n8n de ejemplo:
conexiones = [m['parameters'].get('__IMTCONN__', 0) for m in blueprint['flow']]
credenciales = [c['id'] for n in workflow['nodes'] for c in n.get('credentials', {}).values()]
print('Sin secretos ni identificadores reales:', all(c == 0 for c in conexiones)
and all(c.endswith('DE_EJEMPLO') for c in credenciales), '| credenciales revisadas:', len(credenciales))
fig, ejes = plt.subplots(2, 2, figsize = (14, 5.6))
for ax, (nombre, (nodos, aristas)) in zip(ejes.ravel(), grafos.items()):
dibujar_flujo(nodos, aristas, nombre, ax = ax)
fig.suptitle('TL Recordatorio de recogida v0: el mismo flujo en cuatro plataformas', fontsize = 16)
plt.tight_layout()
plt.show()
nodos aristas disparadores decisiones errores
Zapier (descrito a mano) 6 5 1 1 0
Make (desde el blueprint) 6 5 1 1 1
n8n (desde el workflow) 5 4 1 1 0
Power Automate (desde la definición) 6 5 1 1 0
Sin secretos ni identificadores reales: True | credenciales revisadas: 3

La tabla de la salida cuenta lo que muestra la cuadrícula. Zapier, Make y Power Automate tienen $6$ nodos cada uno y n8n $5$; los cuatro tienen exactamente un disparador y una decisión, la del consentimiento. Make es el único que muestra un manejador de error como nodo, porque en su blueprint el onerror es un módulo más; en n8n y en Power Automate el reintento es una propiedad del nodo HTTP (retryOnFail, retryPolicy) y no se dibuja, aunque exista. La comprobación final devuelve True: las conexiones de Make están en $0$ y las tres credenciales de n8n terminan en DE_EJEMPLO.
Mire la cuadrícula fila por fila. En Zapier y en Power Automate, la iteración ocupa una caja (Looping by Zapier, Apply to each); en Make y en n8n, no existe. En Make, la búsqueda de filas es una acción azul y el filtro un rombo entre módulos; en n8n, el filtro es un nodo con nombre propio. Las formas coinciden donde la función coincide, que es lo que la paleta de la serie pretende: un mismo proceso se reconoce por su forma, no por el nombre que cada plataforma da a sus piezas.
La metáfora que Valeria usa para explicárselo a su padre es la de la cocina, que la Figura 1 dibuja: la misma receta en cuatro cocinas con utensilios de nombre distinto y la misma función.
Figura 1. Cuatro cocinas, una receta: las seis piezas del recordatorio de recogida con el nombre que les da cada plataforma; el color indica la función y la fila inferior, los nodos y el consumo al mes.
La unidad de cobro aplicada a este flujo
El Día 12 explicó los cuatro taxímetros: Make cobra créditos por cada acción de módulo; Zapier, tareas por cada paso de acción exitoso; n8n Cloud, ejecuciones por cada corrida completa del workflow; y Power Automate, una licencia por usuario que no depende del volumen, aunque cada acción consume solicitudes de Power Platform con un límite diario. Hoy no hace falta repetir la teoría, solo aplicarla. Para un flujo que corre $d$ días al mes y atiende $E$ encargos, el consumo de la plataforma $p$ es:
$$ C_p = a_p \cdot d + b_p \cdot E $$
La lógica detrás de esta fórmula es múltiple:
- $a_p$ es lo que cobra la plataforma por corrida, haya los encargos que haya. En Make y en Zapier es la búsqueda de filas: $a = 1$. En n8n es la ejecución completa: $a = 1$, y es lo único que cuenta.
- $b_p$ es lo que cobra por encargo: en Make y en Zapier, la petición HTTP y la fila del registro, $b = 2$; en n8n, $b = 0$, porque los $18$ items viajan dentro de la misma ejecución.
- Los pasos que no cuestan nada no aparecen: la programación del escenario de Make, el disparador y el filtro de Zapier, y, con el supuesto que se declara abajo, el paso de bucle de Zapier.
- En conclusión, con $d = 26$ y $E = 468$, Make y Zapier consumen $26 \cdot 1 + 468 \cdot 2 = 962$ unidades y n8n consume $26$. El mismo número no es el mismo precio, porque cada unidad tiene su propia cuota.
El supuesto sobre Zapier se apoya en su documentación de octubre de 2026: el paso Looping by Zapier no cuenta como tarea, pero cada acción después de él cuenta una vez por iteración, y los filtros no cuentan. Que la búsqueda de filas cuente como tarea es lo esperable por la regla general (un paso de acción exitoso es una tarea), pero conviene verificarlo en la cuenta, porque las fuentes no lo dicen de forma explícita. El siguiente bloque implementa consumo_recordatorio con las reglas del Día 12, le añade el coste de WhatsApp, idéntico en las cuatro plataformas porque lo cobran Meta y Twilio y no la herramienta, y compara con la cuota de cada plan:
# Consumo del recordatorio en la unidad de cobro de cada plataforma y coste de WhatsApp en Python:
REGLAS = { # por corrida diaria y por encargo, con las reglas de conteo del Día 12
'Make': {'unidad': 'créditos', 'por_corrida': 1, 'por_encargo': 2}, # búsqueda; HTTP y fila
'Zapier': {'unidad': 'tareas', 'por_corrida': 1, 'por_encargo': 2}, # supuesto: bucle y filtro gratis
'n8n': {'unidad': 'ejecuciones', 'por_corrida': 1, 'por_encargo': 0}, # una corrida = una ejecución
'Power Automate': {'unidad': 'solicitudes', 'por_corrida': 3, 'por_encargo': 2}, # cuentan, pero no se cobran
}
META_UTILIDAD, RECARGO_TWILIO = 0.0085, 0.005 # USD por mensaje (Tabla C, revisado en octubre de 2026)
def consumo_recordatorio(encargos, dias, plataforma):
r = REGLAS[plataforma]
return r['por_corrida'] * dias + r['por_encargo'] * encargos
planes = { # plan de referencia, cuota mensual de la unidad y precio en USD si el flujo viviera solo
'Make': ('Free', 1_000, 0.00),
'Zapier': ('Professional', 750, 29.99),
'n8n': ('Starter (nube)', 2_500, 24 * USD_POR_EUR),
'Power Automate': ('Premium, 1 usuario', np.inf, 15.00),
}
whatsapp = ENCARGOS_MES * (META_UTILIDAD + RECARGO_TWILIO)
filas = []
for p, (plan, cuota, precio) in planes.items():
c = consumo_recordatorio(ENCARGOS_MES, DIAS, p)
if p == 'Zapier':
precio = precio * np.ceil(c / cuota) # supuesto proporcional del Día 12
filas.append({'plataforma': p, 'unidad': REGLAS[p]['unidad'], 'consumo': c, 'plan': plan,
'uso_%': round(100 * c / cuota, 1) if np.isfinite(cuota) else None,
'plataforma_usd': round(precio, 2), 'whatsapp_usd': round(whatsapp, 2)})
tabla3 = pd.DataFrame(filas)
print(tabla3.to_string(index = False))
# Make dentro del plan Core de Trigo Lento, junto al flujo de mensajes del Día 12:
creditos_core = 7_644 + consumo_recordatorio(ENCARGOS_MES, DIAS, 'Make')
print('Make Core con el flujo de mensajes:', creditos_core, 'de 10 000 créditos',
f'| coste prorrateado del recordatorio: {10.59 * 962 / 10_000:.2f} USD')
print(f'Power Automate: {consumo_recordatorio(ENCARGOS_MES, DIAS, "Power Automate") / DIAS:.0f} solicitudes por día')
plataforma unidad consumo plan uso_% plataforma_usd whatsapp_usd
Make créditos 962 Free 96.2 0.00 6.32
Zapier tareas 962 Professional 128.3 59.98 6.32
n8n ejecuciones 26 Starter (nube) 1.0 25.92 6.32
Power Automate solicitudes 1014 Premium, 1 usuario NaN 15.00 6.32
Make Core con el flujo de mensajes: 8606 de 10 000 créditos | coste prorrateado del recordatorio: 1.02 USD
Power Automate: 39 solicitudes por día
La Tabla 3 resume la salida con los planes revisados en octubre de 2026.
Tabla 3. Consumo y coste del recordatorio a 468 encargos al mes (revisado en octubre de 2026).
| Plataforma | Unidad | Consumo al mes | Plan de referencia | Uso de la cuota | Coste de la plataforma si el flujo viviera solo (USD) | WhatsApp (USD) |
|---|---|---|---|---|---|---|
| Make | Créditos | 962 | Free (1 000 créditos) | 96.2 % | 0.00 | 6.32 |
| Zapier | Tareas | 962 | Professional (750 tareas) | 128.3 % | 59.98 (supuesto: dos tramos de 750) | 6.32 |
| n8n | Ejecuciones | 26 | Starter en la nube (2 500) | 1.0 % | 25.92 (24 EUR) | 6.32 |
| Power Automate | Solicitudes | 1 014 | Premium, 1 usuario | Sin cuota mensual | 15.00 (pago anual) | 6.32 |
La tabla cuenta cuatro historias distintas con el mismo flujo:
- En primer lugar, Make cabe en el plan Free en un mes promedio, pero por muy poco: $962$ de $1,000$ créditos, el $96.2%$. En Trigo Lento, además, el recordatorio no viviría solo: se sumaría al flujo de mensajes del Día 12 dentro del plan Core, con $8,606$ de $10,000$ créditos, y su parte del coste prorrateado sería de $10.59 \cdot 962 / 10,000 = 1.02$ USD al mes.
- En segundo lugar, Zapier se queda corto: $962$ tareas superan las $750$ del tramo de entrada de Professional en un $28.3%$. Con el supuesto proporcional del Día 12 (otro tramo de $29.99$ USD por cada $750$ tareas), costaría $59.98$ USD; el precio real del tramo siguiente depende del deslizador de Zapier y las fuentes no coinciden.
- En tercer lugar, n8n apenas se entera: $26$ ejecuciones son el $1%$ del plan Starter. El recordatorio podría atender diez veces más encargos sin cambiar de plan; el precio lo fija el plan mínimo, no el flujo.
- En cuarto lugar, Power Automate no cuenta por volumen, cuenta personas: $1,014$ solicitudes al mes, $39$ al día, muy por debajo del límite diario de solicitudes de Power Platform de una licencia Premium (del orden de decenas de miles por usuario según la documentación de Microsoft, a verificar), por $15$ USD al mes por la persona que es dueña del flujo.
El coste de WhatsApp es el mismo en las cuatro filas y conviene calcularlo aparte, porque es, con diferencia, el rubro más grande del flujo:
$$ W = E \cdot (t_{Meta} + t_{Twilio}) = 468 \cdot (0.0085 + 0.005) = 6.32 \text{ USD} $$
La lógica es directa:
- $t_{Meta}$ es la tarifa de Meta por plantilla de utilidad entregada en México ($0.0085$ USD, Tabla C de la serie, revisado en octubre de 2026, con un rango de $0.0085$ a $0.015$ en las fuentes).
- $t_{Twilio}$ es el recargo de Twilio por mensaje ($0.005$ USD).
- $W$ crece con los encargos y no depende de la plataforma: elegir entre Make y n8n para este flujo mueve unos centavos; enviar o no enviar cada mensaje mueve dólares. Por eso el filtro de consentimiento y la deduplicación (no recordar dos veces el mismo pedido) también son decisiones de coste.
Un mes no es un promedio
El $96.2%$ de Make es un promedio, y un mes real no lo es. Los encargos llegan como llegadas de Poisson, y un mes con más encargos de la cuenta puede empujar el consumo por encima de los $1,000$ créditos del plan Free. Si cada día llegan $X_i \sim \text{Poisson}(18)$ encargos, la suma de los $26$ días es también de Poisson, $N \sim \text{Poisson}(468)$, y el plan Free se rompe cuando:
$$ 26 + 2N > 1,000 \iff N \ge 488, \qquad P(N \ge 488) = \sum_{k=488}^{\infty} \frac{e^{-468}, 468^{k}}{k!} \approx 0.183 $$
La lógica detrás de esta probabilidad es la siguiente:
- La suma de variables de Poisson independientes es de Poisson con la suma de las medias: $26 \cdot 18 = 468$.
- El umbral se despeja de la fórmula del consumo: $2N > 974$ exige $N \ge 488$ encargos, solo $20$ más que la media.
- La desviación típica de una Poisson es la raíz de su media, $\sqrt{468} \approx 21.6$; $488$ está a menos de una desviación típica de la media, y por eso la probabilidad no es pequeña.
- En conclusión, un plan que se ajusta al promedio con un margen del $4%$ se rompe, en promedio, casi un mes de cada cinco.
El siguiente bloque lo comprueba con $10,000$ meses simulados, y añade una variante más realista en la que la intensidad de cada día varía (como el Día 12, con una distribución gamma de coeficiente de variación $0.25$: hay sábados de fiesta y martes de lluvia):
# Monte Carlo de 10 000 meses: créditos de Make y tareas de Zapier frente a sus cuotas en Python:
N_MESES = 10_000
encargos_mes = rng.poisson(ENCARGOS_DIA, size = (N_MESES, DIAS)).sum(axis = 1)
creditos = consumo_recordatorio(encargos_mes, DIAS, 'Make')
tareas = consumo_recordatorio(encargos_mes, DIAS, 'Zapier')
# Variante con días irregulares: la intensidad diaria varía (gamma con coeficiente de variación de 0.25):
k = 1 / 0.25 ** 2
intensidad = rng.gamma(k, ENCARGOS_DIA / k, size = (N_MESES, DIAS))
creditos_irregular = consumo_recordatorio(rng.poisson(intensidad).sum(axis = 1), DIAS, 'Make')
print('Encargos al mes: media', round(encargos_mes.mean(), 1), '| percentiles 5 y 95:',
np.percentile(encargos_mes, [5, 95]).astype(int).tolist())
print(f'P(créditos de Make > 1 000): {(creditos > 1_000).mean():.3f}')
print(f'P(tareas de Zapier > 750): {(tareas > 750).mean():.3f}')
print(f'P(créditos de Make > 1 000) con días irregulares: {(creditos_irregular > 1_000).mean():.3f}')
print('Ejecuciones de n8n: siempre', DIAS)
fig, ax = plt.subplots(figsize = (10, 5.2))
ax.hist(creditos, bins = 50, color = '#2a78d6', alpha = 0.75, label = 'Poisson de 18 al día')
ax.hist(creditos_irregular, bins = 50, histtype = 'step', color = '#52514e', linewidth = 1.5,
label = 'días irregulares (CV 0.25)')
for cuota, color, texto in [(1_000, '#c8423b', 'Make Free: 1 000 créditos'),
(750, '#eb6834', 'Zapier Professional: 750 tareas')]:
ax.axvline(cuota, color = color, linestyle = '--', linewidth = 2)
ax.text(cuota + 6, ax.get_ylim()[1] * 0.92, texto, color = color, fontsize = 10)
ax.set_title('Consumo mensual del recordatorio en 10 000 meses simulados', fontsize = 16)
ax.set_xlabel('Créditos de Make = tareas de Zapier al mes (26 + 2 por encargo)')
ax.set_ylabel('Meses')
ax.legend(loc = 'center left', frameon = False)
ax.spines[['top', 'right']].set_visible(False)
plt.tight_layout()
plt.show()
Encargos al mes: media 467.4 | percentiles 5 y 95: [432, 503]
P(créditos de Make > 1 000): 0.182
P(tareas de Zapier > 750): 1.000
P(créditos de Make > 1 000) con días irregulares: 0.263
Ejecuciones de n8n: siempre 26

La simulación da $P = 0.182$ para el plan Free de Make, prácticamente la probabilidad exacta de $0.183$. Con días irregulares, la probabilidad sube a $0.263$: más de un mes de cada cuatro. Para Zapier Professional la respuesta es $1.000$: en los $10,000$ meses simulados, ninguno cabe en $750$ tareas, porque ni el percentil $5$ de los encargos ($432$) baja de los $363$ que harían falta. Y n8n consume siempre $26$ ejecuciones, llueva o truene, porque su unidad no depende de los encargos.
En el histograma, la línea naranja de Zapier queda a la izquierda de toda la distribución y la roja de Make la corta por la derecha; el contorno gris, el de los días irregulares, es más ancho y deja más masa por encima de los $1,000$ créditos. El riesgo de cuota no lo decide la media, sino la cola, y es la misma lección del Día 12 aplicada a un flujo más pequeño. Para Trigo Lento, que ya paga Make Core, el riesgo práctico es otro: con $8,606$ créditos de los $10,000$, el recordatorio deja el plan Core al $86%$, por encima del umbral de alerta del $80%$ que el Día 12 fijó para el presupuesto.
Cuando cambia el volumen
La tabla anterior describe el mes de hoy. ¿Qué pasa si Trigo Lento crece, o si el recordatorio se extiende a los pedidos de la Cafetería Brújula? El siguiente bloque dibuja el coste mensual de la plataforma (sin WhatsApp, que es igual para todas) entre $100$ y $2,000$ encargos. Deja un parámetro, PRECIO_POWER_AUTOMATE, para que usted escriba el precio de su propia licencia; si se queda vacío, se usa la referencia de $15$ USD y la línea se dibuja discontinua con la leyenda “precio sin confirmar”:
# Coste mensual del recordatorio frente al volumen de encargos por plataforma en Python:
PRECIO_POWER_AUTOMATE = None # escriba aquí el precio de su licencia; None usa la referencia de 15 USD
def coste_plataforma(encargos, plataforma):
c = consumo_recordatorio(encargos, DIAS, plataforma)
if plataforma == 'Make':
return 0.0 if c <= 1_000 else 10.59 * np.ceil(c / 10_000)
if plataforma == 'Zapier':
return 0.0 if c <= 100 else 29.99 * np.ceil(c / 750)
if plataforma == 'n8n Cloud':
return 24 * USD_POR_EUR # 26 ejecuciones: siempre dentro de Starter
if plataforma == 'n8n propio':
return 6.00 # servidor de la Tabla E
return 15.00 if PRECIO_POWER_AUTOMATE is None else PRECIO_POWER_AUTOMATE
REGLAS['n8n Cloud'] = REGLAS['n8n propio'] = REGLAS['n8n']
volumen = np.arange(100, 2_001)
nombres = ['Make', 'Zapier', 'n8n Cloud', 'n8n propio', 'Power Automate']
costes = pd.DataFrame({p: [coste_plataforma(v, p) for v in volumen] for p in nombres}, index = volumen)
print('Coste a 468 encargos (USD):', {p: round(float(coste_plataforma(468, p)), 2) for p in nombres})
print('Make deja el plan Free a partir de', int(volumen[costes['Make'].values > 0][0]), 'encargos')
print('Zapier: primeros saltos en', [int(v) for v in volumen[1:][np.diff(costes['Zapier'].values) > 0][:3]], 'encargos')
print('Más barata en cada tramo:', costes.idxmin(axis = 1).groupby(costes.idxmin(axis = 1)).size().to_dict())
fig, ax = plt.subplots(figsize = (10, 5.2))
colores = {'Make': '#2a78d6', 'Zapier': '#3a9d5d', 'n8n Cloud': '#eb6834', 'n8n propio': '#8a8986',
'Power Automate': '#7b5ea7'}
for p in nombres:
discontinua = p == 'Power Automate'
ax.step(volumen, costes[p], where = 'post', color = colores[p], linewidth = 2,
linestyle = '--' if discontinua else '-',
label = p + (' (precio sin confirmar)' if discontinua and PRECIO_POWER_AUTOMATE is None else ''))
ax.axvline(ENCARGOS_MES, color = '#0b0b0b', linestyle = ':', linewidth = 1.5)
ax.text(ENCARGOS_MES + 15, 115, 'Trigo Lento hoy:\n468 encargos', fontsize = 10)
ax.set_ylim(0, 170)
ax.set_title('Coste mensual del recordatorio según el volumen de encargos', fontsize = 16)
ax.set_xlabel('Encargos al mes (18 al día equivalen a 468)')
ax.set_ylabel('USD al mes (sin WhatsApp)')
ax.legend(loc = 'upper left', frameon = False, fontsize = 9)
ax.spines[['top', 'right']].set_visible(False)
plt.tight_layout()
plt.show()
Coste a 468 encargos (USD): {'Make': 0.0, 'Zapier': 59.98, 'n8n Cloud': 25.92, 'n8n propio': 6.0, 'Power Automate': 15.0}
Make deja el plan Free a partir de 488 encargos
Zapier: primeros saltos en [363, 738, 1113] encargos
Más barata en cada tramo: {'Make': 388, 'n8n propio': 1513}

A $468$ encargos, el coste de la plataforma, si el recordatorio viviera solo, es de $0$ USD en Make, $6$ en n8n propio (el servidor de la Tabla E de la serie), $15$ en Power Automate, $25.92$ en n8n Cloud y $59.98$ en Zapier. La figura muestra cómo cambia ese orden con el volumen:
- Make deja el plan Free a partir de $488$ encargos y salta a $10.59$ USD; desde ahí, el servidor propio de n8n, a $6$ USD fijos, pasa a ser la opción más barata y lo sigue siendo hasta $2,000$ encargos. En toda la rejilla, Make es la más barata de $100$ a $487$ encargos y n8n propio de $488$ en adelante.
- Zapier sube en escalera: el primer salto está en $363$ encargos, el segundo en $738$ y el tercero en $1,113$. Cada $375$ encargos más, un tramo más.
- n8n Cloud y Power Automate son planos: n8n porque $26$ ejecuciones nunca se acercan a $2,500$, y Power Automate porque cobra por usuario.
Las líneas planas tienen una lectura que la tabla no daba: para un flujo de pocas corridas y muchos elementos, las plataformas que cobran por corrida o por persona escalan mejor que las que cobran por paso. El recordatorio es justo ese tipo de flujo. El flujo de mensajes del Día 12, que se ejecuta una vez por mensaje, era el contrario, y allí la ventaja de n8n Cloud era mucho menor.
Conectores, autoalojamiento y datos
El coste es una columna de la decisión; la segunda es qué hace falta para que el flujo funcione. El recordatorio necesita tres conexiones: Google Sheets (leer y escribir), Twilio (enviar la plantilla) y, en todas, un lugar donde guardar las credenciales. La Tabla 4 reúne lo que ofrece cada plataforma para este flujo, según su documentación consultada en octubre de 2026.
Tabla 4. Conectores, autoalojamiento y lugar de los datos para el recordatorio (revisado en octubre de 2026; verifique en la documentación de cada plataforma).
| Aspecto | Zapier | Make | n8n | Power Automate |
|---|---|---|---|---|
| Google Sheets | Conector propio | Conector propio | Nodo propio | Conector estándar |
| Plantilla de WhatsApp en Twilio | Petición HTTP (Webhooks by Zapier) | Módulo HTTP | Nodo HTTP con credencial twilioApi | Conector HTTP, premium; el de Twilio solo envía SMS |
| Instalación en un servidor propio | No | No | Sí (edición Community; Día 34) | No (existe la variante de escritorio, que no aplica aquí) |
| Dónde se procesan los teléfonos | Servidores de Zapier | Servidores de Make (región elegida al crear la organización) | En el servidor de Trigo Lento, si es propio | En el entorno de Microsoft del inquilino |
| Dónde viven las credenciales | Conexión de la cuenta | Conexión de la organización | Credencial cifrada de la instancia | Referencia de conexión del entorno |
Tres observaciones sobre la tabla:
- Los cuatro llegan a Google Sheets con un conector propio, y los cuatro necesitan HTTP para la plantilla de WhatsApp. Para este flujo, el famoso “número de conectores” de cada plataforma, que va de cientos a miles, no decide nada: decide si los dos conectores que usted necesita existen y hacen la operación que usted necesita.
- Solo n8n se instala en un servidor propio. El Día 34 comparará la nube con la instalación propia; hoy basta con saber que es la única opción en la que los teléfonos de los clientes no salen de una máquina que Trigo Lento controla, salvo, claro, hacia Twilio y Meta, que los necesitan para entregar el mensaje.
- Elegir plataforma es elegir dónde viajan los teléfonos. Con la ley de protección de datos personales que el Día 6 llevó al código de honor, Trigo Lento debe poder decir en su aviso de privacidad qué encargados tratan los datos de sus clientes y en qué país. Con Zapier, Make o Power Automate, la respuesta incluye al proveedor de la plataforma; con n8n propio, solo al proveedor del servidor.
La Figura 2 de la sección siguiente lleva esta idea al terreno de la salida: no solo importa dónde viven los datos hoy, sino qué se puede llevar Trigo Lento el día que quiera irse.
Gobierno y dependencia del proveedor
El gobierno de una plataforma es el conjunto de controles que permiten que más de una persona trabaje en ella sin pisarse y sin poner en riesgo los datos: quién puede crear flujos, quién puede ver las ejecuciones, qué conectores se pueden combinar y qué queda registrado. En una panadería de seis personas parece un tema de empresas grandes, hasta el día en que alguien del mostrador copia un flujo “para probar” y envía cuarenta recordatorios repetidos.
Las cuatro plataformas ofrecen gobierno en grados muy distintos, y casi siempre en los planes caros:
- Power Automate es el más completo: entornos separados (pruebas y producción), políticas de prevención de pérdida de datos (en inglés, DLP) que impiden, por ejemplo, combinar en un mismo flujo un conector de la empresa con uno de redes sociales, y un centro de administración con inventario de flujos. Es su gran ventaja en organizaciones que ya viven en Microsoft.
- Make ofrece organizaciones, equipos y roles en el plan Teams, con plantillas compartidas; en los planes inferiores, la cuenta es prácticamente de una persona.
- Zapier reserva la administración (carpetas compartidas, permisos, registro de actividad) a sus planes de equipo y de empresa.
- n8n, en la edición Community, tiene usuarios básicos; los permisos por proyecto, los entornos y la integración con control de versiones dependen del plan de pago, y conviene verificarlos en su página de precios porque han cambiado varias veces.
La dependencia del proveedor se mide con la pregunta del Día 11: si mañana esta plataforma duplicara su precio, ¿qué me llevo? La Tabla 5 la responde para el recordatorio.
Tabla 5. Qué se exporta de cada plataforma y qué se pierde al salir (revisado en octubre de 2026).
| Plataforma | Formato de exportación | Se importa en | Qué se pierde al salir |
|---|---|---|---|
| Zapier | Sin formato de intercambio con otras herramientas | Solo en Zapier, y con limitaciones | El diseño entero: hay que reconstruirlo a partir de la descripción |
| Make | Blueprint JSON | Solo en Make | Conexiones, programación, almacenes de datos e historial; el diseño se traduce a mano a otra plataforma |
| n8n | Workflow JSON | Cualquier instancia de n8n, propia o en la nube | Casi nada: la plataforma viaja con el flujo; las credenciales se vuelven a crear |
| Power Automate | Paquete de solución o paquete .zip del flujo | Otro entorno de Power Platform | Conexiones y licencias; la definición solo se entiende dentro del ecosistema de Microsoft |
La lectura de la tabla coincide con la del Día 11, pero ahora tiene números. El blueprint de Make y el workflow de n8n del recordatorio describen lo mismo con gramáticas distintas, y el Día 45 traducirá uno en otro con un programa; la definición de Power Automate se parece mucho a la de n8n en estructura (acciones con dependencias), pero vive dentro de un ecosistema cerrado; y el Zap solo existe en la cuenta de Zapier. Cuanto más pequeña es la puerta de salida, más caro es cambiar de opinión.
La metáfora de las casas con puertas de distinto tamaño, que muestra la Figura 2, es la que Don Ernesto entendió mejor: en las cuatro casas se cocina lo mismo, pero no por todas las puertas cabe la mesa.
Figura 2. Puertas de salida: cada plataforma es una casa con una puerta de exportación de distinto tamaño; debajo, lo que sale por ella y lo que se queda dentro al cambiar de plataforma.
La matriz ponderada
La matriz del Día 11 puntuó las plataformas en abstracto, con cinco criterios, y n8n ganó por $4.05$ frente a $3.80$ de Make. Hoy la pregunta es más estrecha: ¿qué plataforma conviene para este flujo, en este momento? Por eso Valeria cambia los criterios y los pesos, y los fija antes de puntuar, como recomendaba el aviso de aquel día. La fórmula es la misma:
$$ S_j = \sum_{i=1}^{6} w_i , x_{ij}, \qquad \sum_{i=1}^{6} w_i = 1 $$
La lógica detrás de esta fórmula es múltiple:
- $x_{ij}$ es la puntuación de la plataforma $j$ en el criterio $i$, de $1$ a $5$, justificada en la Tabla 6.
- $w_i$ es el peso del criterio $i$; los de Valeria suman $1$, de modo que $S_j$ se lee como una nota media de $1$ a $5$.
- El criterio con más peso es la facilidad para Valeria hoy ($0.25$): el recordatorio tiene que funcionar el sábado del pico de pasteles, y quien lo construye y lo mantiene es ella sola. El autoalojamiento y control de datos pesa $0.10$ porque, hoy, Trigo Lento no tiene servidor propio; lo tendrá en el Día 34.
- En conclusión, la matriz responde a una pregunta con fecha: si la fecha cambia, cambian los pesos, y puede cambiar el ganador.
Tabla 6. Matriz ponderada del recordatorio de recogida: pesos de Valeria, puntuaciones de 1 a 5 y su justificación.
| Criterio | Peso | Zapier | Make | n8n | Power Automate | Justificación |
|---|---|---|---|---|---|---|
| Coste a 468 encargos | 0.20 | 2 | 5 | 4 | 2 | Make cabe en Free o suma 1.02 USD a Core; n8n propio cuesta el servidor; Zapier pasa de 750 tareas; Power Automate exige Premium |
| Conectores necesarios | 0.15 | 5 | 4 | 3 | 3 | Los cuatro tienen Sheets y HTTP; Zapier y Make con la configuración más guiada; n8n pide más ajuste; Power Automate necesita el HTTP premium |
| Autoalojamiento y control de datos | 0.10 | 1 | 1 | 5 | 1 | Solo n8n se instala en un servidor propio |
| Gobierno | 0.15 | 3 | 3 | 2 | 5 | Entornos y políticas de datos en Power Automate; roles en planes de equipo en Zapier y Make; básico en n8n Community |
| Dependencia del proveedor | 0.15 | 2 | 3 | 5 | 3 | n8n viaja con su flujo; el blueprint y la solución se importan solo en su plataforma; Zapier no exporta |
| Facilidad para Valeria hoy | 0.25 | 5 | 4 | 2 | 3 | Zapier se aprende en una tarde; Valeria ya practica Make; n8n exige servidor; Power Automate es otro ecosistema |
El siguiente bloque calcula la puntuación ponderada, prueba el intercambio de los pesos de facilidad y autoalojamiento y, para no depender de un único vector de pesos, genera $5,000$ vectores alrededor de los de Valeria con una distribución de Dirichlet:
$$ \mathbf{w} \sim \text{Dirichlet}(c \cdot \mathbf{w}0), \qquad E[w_i] = w{0,i}, \qquad \text{Var}(w_i) = \frac{w_{0,i}(1 - w_{0,i})}{c + 1} $$
La lógica de la perturbación es la siguiente:
- La distribución de Dirichlet genera vectores de números positivos que suman $1$: exactamente lo que es un vector de pesos.
- Con parámetro $c \cdot \mathbf{w}0$, la media de cada peso es el peso de Valeria, $w{0,i}$; los vectores se reparten alrededor de su opinión, no al azar.
- La concentración $c$ controla cuánto se alejan: con $c = 60$, el peso de la facilidad ($0.25$) tiene una desviación típica de $\sqrt{0.25 \cdot 0.75 / 61} \approx 0.055$, es decir, varía entre $0.20$ y $0.30$ con frecuencia.
- En conclusión, contar con qué frecuencia gana cada plataforma en los $5,000$ vectores mide cuánto depende la decisión de que Valeria haya acertado con los pesos exactos.
# Matriz ponderada de Valeria y sensibilidad con 5 000 vectores de pesos de Dirichlet en Python:
criterios = ['coste_468', 'conectores', 'autoalojamiento', 'gobierno', 'dependencia', 'facilidad_hoy']
pesos = np.array([0.20, 0.15, 0.10, 0.15, 0.15, 0.25])
puntuaciones = pd.DataFrame({
'Zapier': [2, 5, 1, 3, 2, 5],
'Make': [5, 4, 1, 3, 3, 4],
'n8n': [4, 3, 5, 2, 5, 2],
'Power Automate': [2, 3, 1, 5, 3, 3]}, index = criterios)
assert np.isclose(pesos.sum(), 1.0), 'Los pesos deben sumar 1'
total = (puntuaciones.T @ pesos).sort_values(ascending = False)
print('Puntuación ponderada:', total.round(2).to_dict())
# Intercambio de los pesos de facilidad (0.25) y autoalojamiento (0.10):
intercambio = pesos.copy()
intercambio[[2, 5]] = intercambio[[5, 2]]
print('Con facilidad y autoalojamiento intercambiados:', (puntuaciones.T @ intercambio).round(2).to_dict())
# 5 000 vectores de pesos alrededor de los de Valeria (concentración 60):
muestras = rng.dirichlet(pesos * 60, size = 5_000)
ganadores = pd.Series(puntuaciones.columns[np.argmax(muestras @ puntuaciones.values, axis = 1)])
frecuencia = ganadores.value_counts(normalize = True).reindex(puntuaciones.columns, fill_value = 0)
print('Frecuencia con que gana cada plataforma:', frecuencia.round(3).to_dict())
print('Desviación típica media de cada peso:', muestras.std(axis = 0).round(3).tolist())
fig, (ax1, ax2) = plt.subplots(1, 2, figsize = (12, 4.8))
colores = ['#3a9d5d', '#2a78d6', '#eb6834', '#7b5ea7']
ax1.bar(puntuaciones.columns, puntuaciones.T @ pesos, color = colores)
for i, v in enumerate(puntuaciones.T @ pesos):
ax1.text(i, v + 0.05, f'{v:.2f}', ha = 'center', fontsize = 11)
ax1.set_ylim(0, 5)
ax1.set_title('Puntuación con los pesos de Valeria', fontsize = 12)
ax2.bar(frecuencia.index, frecuencia.values, color = colores)
for i, v in enumerate(frecuencia.values):
ax2.text(i, v + 0.01, f'{v:.1%}', ha = 'center', fontsize = 11)
ax2.set_ylim(0, 1)
ax2.set_title('Frecuencia de victoria con 5 000 pesos perturbados', fontsize = 12)
for ax in (ax1, ax2):
ax.tick_params(axis = 'x', labelsize = 9)
ax.spines[['top', 'right']].set_visible(False)
fig.suptitle('Matriz ponderada del recordatorio de recogida', fontsize = 16)
plt.tight_layout()
plt.show()
Puntuación ponderada: {'Make': 3.6, 'n8n': 3.3, 'Zapier': 3.25, 'Power Automate': 2.9}
Con facilidad y autoalojamiento intercambiados: {'Zapier': 2.65, 'Make': 3.15, 'n8n': 3.75, 'Power Automate': 2.6}
Frecuencia con que gana cada plataforma: {'Zapier': 0.025, 'Make': 0.865, 'n8n': 0.11, 'Power Automate': 0.0}
Desviación típica media de cada peso: [0.051, 0.045, 0.039, 0.045, 0.045, 0.056]

Con los pesos de Valeria, Make obtiene $3.60$, n8n $3.30$, Zapier $3.25$ y Power Automate $2.90$. Make gana sin ser el mejor en casi nada: solo en coste es el primero, pero no tiene ninguna puntuación por debajo de $3$ salvo el autoalojamiento, que hoy pesa poco. Es el mismo perfil “redondo” que el radar del Día 11 le atribuía.
El intercambio de pesos cuenta la otra mitad de la historia: si la facilidad pesara $0.10$ y el autoalojamiento $0.25$, n8n subiría a $3.75$ y Make bajaría a $3.15$. No es un capricho de la aritmética: es exactamente lo que pasará cuando Trigo Lento tenga su servidor propio y Valeria haya aprendido n8n, en el módulo 4. La matriz no dice “Make para siempre”; dice “Make mientras la facilidad pese más que el control”.
La perturbación con Dirichlet responde a la pregunta de Don Ernesto sobre la confianza: Make gana en el $86.5%$ de los $5,000$ vectores, n8n en el $11.0%$, Zapier en el $2.5%$ y Power Automate en ninguno. Las desviaciones típicas de los pesos, entre $0.039$ y $0.056$, coinciden con la fórmula. Dicho de otro modo: con opiniones razonablemente parecidas a las de Valeria, Make gana casi nueve veces de cada diez; para que gane n8n hace falta cambiar de opinión, no solo de décima. A diferencia de la matriz del Día 11, que daba un empate técnico entre Make y n8n, esta tiene un ganador claro para este flujo y este momento.
Que Power Automate no gane nunca merece una frase justa: no es una mala plataforma, es una plataforma para otro negocio. Su $5$ en gobierno es el mejor de la tabla, y en una empresa con decenas de personas creando flujos y datos sensibles en Microsoft 365 ese criterio pesaría mucho más que $0.15$. La Figura 3 dibuja la matriz como una balanza: mover peso del platillo de la facilidad al del autoalojamiento basta para que el fiel cambie de lado.
Figura 3. La balanza de pesos: con los pesos de Valeria gana Make (3.60 frente a 3.30 de n8n); al intercambiar los pesos de facilidad (0.25) y autoalojamiento (0.10), gana n8n (3.75 frente a 3.15).
Lo que dijo Don Ernesto
Valeria imprime una sola hoja y se la entrega a su padre al terminar el turno. La hoja tiene cuatro partes, que la Tabla 7 reproduce: qué se decidió, por qué, cuánto cuesta y qué cambiaría la decisión.
Tabla 7. La decisión en una hoja: el recordatorio de recogida de Trigo Lento.
| Apartado | Contenido |
|---|---|
| Decisión | Make para el recordatorio, dentro del plan Core que ya se paga; se construirá en el Día 26 |
| Por qué | Gana la matriz con 3.60 y en el 86.5 % de 5 000 pesos perturbados; es la plataforma que Valeria ya practica |
| Cuánto cuesta | 962 créditos al mes (1.02 USD prorrateados de Core) más 6.32 USD de WhatsApp; Core queda al 86 % |
| Riesgos | Core por encima del 80 % de alerta; mapeo por índice de columna; teléfonos en servidores de Make |
| Qué cambiaría la decisión | Servidor propio de n8n en marcha (Día 34); más de 488 encargos al mes si el recordatorio viviera solo; créditos de Core por encima del 90 % dos meses seguidos |
| Qué no se hará | Elegir Power Automate solo porque se paga Microsoft 365; enviar recordatorios sin consentimiento |
Don Ernesto lee la hoja dos veces, en silencio, y pone el dedo sobre la última fila: “Esto me gusta. Lo que no vamos a hacer. ¿Y lo de que el recordatorio se va a mudar a n8n? ¿Para qué lo hace dos veces?” Valeria le explica que no lo hará dos veces, sino una en cada etapa: en Make lo tendrá funcionando la semana que viene, cuando todavía no hay servidor; cuando llegue el servidor propio, el Día 45 traducirá el blueprint a un workflow de n8n con un programa, y los mismos tres JSON de hoy servirán como prueba de que la traducción conserva la lógica. Lo que se gana con esperar es el mes de recordatorios que, de otro modo, no existiría.
Hay una objeción más, y es de oficio: "¿Y si el mensaje sale con la hora mal y la señora viene a las diez y el pastel no está?" La respuesta no está en ninguna plataforma, sino en la especificación: la hora sale de la columna hora_recogida de la hoja, que es la misma que usa el obrador, y el flujo no inventa ninguna. Si la hoja está mal, el mensaje estará mal; por eso el Día 14 empezará por la estructura de esa tabla, y el Día 16 por la fuente de verdad de los datos.
El padre dobla la hoja y la guarda en el bolsillo del delantal, junto a la libreta de encargos. Es la mejor señal de aprobación que Valeria ha recibido desde que empezó la serie.
Consideraciones finales
El día empezó con cuatro marcas y una pregunta, y termina con un flujo especificado una vez y construido cuatro veces, tres archivos JSON que dicen lo mismo con gramáticas distintas, un consumo de $962$, $962$, $26$ o $1,014$ unidades según quién cuente, una probabilidad de $0.183$ de romper el plan Free de Make, una puerta de salida de distinto tamaño en cada casa y una matriz que da a Make un $3.60$ y lo confirma en el $86.5%$ de los pesos perturbados. Comparar plataformas con el mismo flujo convierte una discusión de marcas en una discusión de piezas, unidades y salidas, y esa sí se puede ganar con números.
Antes de elegir una plataforma para su propio flujo, conviene hacerse algunas preguntas:
- ¿Escribió la especificación antes de abrir la primera plataforma? Si no, está comparando a quien construye y no la herramienta.
- ¿Su flujo tiene pocas corridas y muchos elementos, o muchas corridas y pocos elementos? La respuesta decide qué unidad de cobro le conviene.
- ¿Qué pieza de su flujo depende de un conector premium o de una operación que el conector “con nombre” no ofrece?
- ¿Qué se lleva el día que quiera irse, y cuánto tardaría en reconstruir lo que no se lleva?
Las cifras de hoy tienen límites claros. Los precios son los revisados en octubre de 2026 y algunas fuentes secundarias discrepan; el coste de Zapier por encima de $750$ tareas es un supuesto proporcional; la regla de que la búsqueda de filas cuenta como tarea es un supuesto razonable que conviene verificar; la definición de Power Automate y los identificadores de módulos son estructura documentada, no exportaciones reales; y las puntuaciones de la matriz son el juicio de Valeria, justificado pero discutible. Ninguno de esos límites cambia la estructura de la conclusión: para este flujo y esta Valeria, Make; para el mismo flujo con servidor propio y otra Valeria, n8n.
Un gran libro que habla de esto es Decisions with Multiple Objectives: Preferences and Value Tradeoffs, en el que Ralph Keeney y Howard Raiffa construyen la teoría del valor con varios atributos que sostiene cualquier matriz ponderada: cómo elegir los criterios, cuándo es legítimo sumarlos y por qué los pesos solo tienen sentido en relación con los rangos de cada criterio. Es un libro exigente, pero sus primeros capítulos bastan para no volver a confundir una suma de puntuaciones con una verdad, y para entender por qué Valeria fijó los pesos antes de puntuar.
Conclusiones clave
Un flujo, cuatro formas
- Una comparación honesta empieza por una especificación independiente de la plataforma: disparador, entrada, filtro, mensaje, registro, errores y responsable.
- Las siete piezas del recordatorio existen en las cuatro plataformas con nombres distintos; Zapier y Power Automate iteran con una pieza explícita, Make y n8n de forma implícita.
- Leídos con Python y dibujados con la paleta de la serie, el Zap, el blueprint, el workflow y la definición tienen $6$, $6$, $5$ y $6$ nodos, un disparador y una decisión: la misma forma con distinto vocabulario.
Coste a 468 encargos
- Con $C_p = a_p d + b_p E$, Make y Zapier consumen $962$ unidades, n8n $26$ ejecuciones y Power Automate $1,014$ solicitudes por una licencia de $15$ USD por usuario.
- El mismo número no es el mismo precio: $962$ créditos caben en el plan Free de Make, pero lo rompen con probabilidad $0.183$ ($0.263$ con días irregulares); $962$ tareas superan siempre las $750$ de Zapier Professional.
- WhatsApp cuesta $6.32$ USD al mes en las cuatro y es el rubro mayor; dentro de Make Core, el recordatorio suma $1.02$ USD y deja el plan al $86%$.
Gobierno y salida
- Solo n8n se instala en un servidor propio, y elegir plataforma es elegir dónde viajan los teléfonos de los clientes.
- Power Automate tiene el mejor gobierno, pero el conector HTTP premium y la licencia por usuario lo alejan de una panadería; “ya está pagado” no es un criterio.
- Con los pesos de Valeria, Make gana con $3.60$ y en el $86.5%$ de $5,000$ vectores perturbados; si la facilidad y el autoalojamiento intercambian pesos, n8n pasa a $3.75$, que es lo que ocurrirá con el servidor propio.
Mañana, en el Día 14: Estructuras de datos para automatizar: textos, listas, colecciones y tablas. El recordatorio de hoy mapea el teléfono por la posición de una columna y busca filas por una fecha escrita como texto; Valeria aprenderá a representar los encargos de Trigo Lento como listas, diccionarios y tablas con encabezados, para que un cambio en la hoja no acabe enviando un mensaje al número equivocado.
Referencias
- Make (2026). Precios y créditos. https://www.make.com/en/pricing
- Zapier (2026). Precios y cómo se cuentan las tareas. https://zapier.com/pricing
- Zapier (2026). Understanding Looping by Zapier. Centro de ayuda de Zapier. https://help.zapier.com/hc/en-us/articles/42969233918477
- n8n (2026). Precios. https://n8n.io/pricing
- Microsoft (2026). Precios de Power Automate y documentación de límites de solicitudes de Power Platform. https://www.microsoft.com/power-platform/products/power-automate/pricing
- Microsoft (2026). Twilio: referencia del conector. https://learn.microsoft.com/connectors/twilio/
- Microsoft (2026). Referencia del esquema del lenguaje de definición de flujos de trabajo de Azure Logic Apps. https://learn.microsoft.com/azure/logic-apps/logic-apps-workflow-definition-language
- Keeney, R. L. y Raiffa, H. (1976). Decisions with Multiple Objectives: Preferences and Value Tradeoffs. Wiley.

