Un operador es un nodo que ejecuta una acción determinista: sin LLM, sin aleatoriedad. Para una entrada dada, la salida es predecible.
Por qué usarlos
Cualquier lógica que se pueda escribir explícitamente debería escribirse así. Un LLM que «calcula un total» o «formatea una fecha» es un antipatrón: es más lento, más caro y puede equivocarse.
Regla práctica: si puedes escribir la función en 5 líneas de Python, es un operador — no un agente.
Tipos disponibles
webhook_action (llamada HTTP)
Realiza una llamada HTTP saliente. Configuración:
- URL, método, cabeceras y parámetros de consulta (con marcadores de posición del contexto)
- Cuerpo:
none,json,form,raw,multipartomapper(cuerpo compuesto por el lenguaje de mapeo, ver más abajo) - Autenticación:
bearer,basic,api_key_header(cabecera personalizada), uoauth2(ver más abajo) - Estados HTTP aceptados, tiempo máximo y número de reintentos (
retry_count, 0 por defecto, backoff exponencial) - Clave de salida donde se publica la respuesta
database_query / database_manage
database_query lee filas en una base no-code de betool o en una base externa (Postgres, MySQL, MongoDB) registrada en Aplicaciones → Bases de datos → Conexiones: filtro where, búsqueda de texto completo, límite. database_manage escribe en ella (create o update), con el contenido compuesto por el lenguaje de mapeo.
file_transform
Transforma un archivo. Transformadores integrados:
pdf_extract_text— texto seleccionable de un PDF (sin OCR: un PDF escaneado no devuelve texto)pdf_split— división de un PDFpdf_to_images— renderizado de las páginas de un PDF en imágenesxlsx_to_json/xls_to_json— lectura de un libro de Excel en filas JSONunzip— extracción de un archivo comprimido
file_link (enlaces de descarga)
Entrega archivos a un tercero mediante enlace, sin poner su contenido en el flujo: para cada archivo de una lista del contexto (los archivos de una descarga, adjuntos recibidos, las fotos de una inspección…), el nodo Enlaces de descarga produce un enlace de descarga firmado con vida útil limitada. Un paso siguiente compone lo que recibe el destinatario: respuesta de un webhook entrante, email…
| Ajuste | Función |
|---|---|
Lista de archivos que enlazar (input_path) | Dónde leer la lista en el flujo — cada entrada lleva path (clave del archivo en el almacenamiento de la organización) y opcionalmente un nombre de archivo. Obligatorio. |
Subcarpetas permitidas (path_scope) | Opcional: restringe los archivos que se pueden firmar a ciertas subcarpetas del almacenamiento de la organización. |
| Vida de los enlaces | 15 minutos por defecto, de 1 minuto a 24 horas. |
Número máximo de archivos (max_files) | 20 por defecto, 100 como máximo. |
Clave de salida (output_key) | Por defecto linked.files. |
La salida contiene files (cada entrada original, enriquecida con url y expires_at), file_count, failed, requested y ttl_seconds.
- Nunca fuera de tu organización: un archivo fuera de su almacenamiento se rechaza.
- Existencia verificada antes de firmar: un archivo ausente nunca se firma.
- Nada omitido: un archivo no enlazado (fuera de perímetro, no encontrado, por encima del límite, firma imposible) figura en
failedcon su motivo. - Los enlaces se vuelven a crear en cada ejecución, y cada enlace emitido queda registrado.
El enlace es al portador: quien lo tenga descarga el archivo hasta su expiración. Mantén una duración corta, y rellena las subcarpetas permitidas en cuanto la lista proceda de un dato modificable (una fila de tabla) — si no, cualquiera que pueda escribir ese dato podría hacer firmar un enlace hacia cualquier archivo de la organización.
compute
Cálculos deterministas sobre los datos del contexto. Operaciones integradas:
column_stats— por columna de una lista de filas, cuántas valen un valor dado (count,total,pct)compose_text— composición de un texto a partir de una plantilla y de valores del flujoregex_extract— extracción de valores mediante expresión regularselect_by_substring— reparto de una lista en grupos según predicados «contiene / no contiene»list_compare— coherencia de varias listas por clave pivotemulti_source_compliance— auditoría de conformidad multidimensión y multifuentecontact_extract— direcciones de email y números de teléfono encontrados en un texto, con su procedenciafree_slots— franjas libres deducidas de periodos ocupadosurl_expand— composición de URL a partir de bases y rutas
Lenguaje de mapeo
No es un nodo: es el lenguaje que compone una carga útil de salida a partir de los datos del contexto (funciones $now, $uuid, $concat…). Sirve para el cuerpo mapper de webhook_action, para el contenido escrito por database_manage y para las variables de una llamada saliente phone_call.
data_to_file
Produce un archivo Excel (.xlsx) a partir de datos del contexto — una lista de filas, una cuadrícula o varias listas (una pestaña cada una). Opciones: nombre del archivo (con plantilla), nombre de la pestaña, elección y orden de las columnas, fila de encabezado. El archivo se guarda en el almacenamiento de tu organización, listo para enviarse por email o depositarse en un Drive.
Por seguridad, las celdas que empiezan por =, +, - o @ se escriben como texto por defecto (sin fórmula inyectada). Cuando los límites de Excel obligan a cortar, el archivo se marca como truncado.
web_fetch
Lee una o varias páginas web y publica su texto legible en el contexto (por defecto web.pages). Ajustes: número de páginas, concurrencia, tiempo de espera, tamaño máximo. El veredicto de robots.txt siempre se calcula y se informa; solo se aplica si lo activas (respect_robots).
Las páginas renderizadas únicamente por JavaScript no se ejecutan: solo se lee el HTML servido. Una página fallida se informa en el resultado, sin hacer fallar el pipeline.
En el lado del agente, dos herramientas equivalentes:
web_scrape.fetch_page— lee una página (título, texto, enlaces de email y teléfono encontrados).web_search.search— búsqueda web mediante un motor SearXNG autoalojado por la plataforma: hasta 5 resultados (título, URL, extracto).
Todas las lecturas web pasan por la misma protección anti-SSRF: direcciones internas, privadas y de metadatos cloud rechazadas tras la resolución DNS, redirecciones verificadas de nuevo en cada salto.
code_step
Cuando la lógica determinista supera lo que compute puede manejar, un code step ejecuta código personalizado en un sandbox Starlark — editable directamente, ejecutado nada más guardarlo y acotado por una allowlist de tools. Consulta Code steps.
Autenticación y secretos
Los operadores que se comunican con un sistema externo (HTTP, BD) referencian una cuenta registrada dentro de la organización. Las credenciales nunca son visibles dentro del propio pipeline — solo se referencia un nombre de cuenta.
Como resultado, rotar una contraseña no requiere ninguna edición en ningún pipeline.
Cuando se introduce un secreto directamente en un nodo (token bearer, contraseña basic o valor api_key_header de webhook_action, contraseña de un PDF o de un archivo comprimido cifrados para file_transform), queda enmascarado en cuanto se guarda: el editor, la API y las herramientas MCP solo muestran un marcador. Consulta El editor visual, sección Secretos.
OAuth2 saliente (client_credentials)
Para las API que requieren un token OAuth2 (cloud empresarial, ERP, proveedores de terceros), el operador HTTP admite el modo oauth2. Registras una credencial OAuth2 en la organización — token_url, client_id, client_secret, scope — y el nodo referencia solo un identificador no sensible.
En el momento de la llamada, betool obtiene un token y lo reutiliza mientras siga siendo válido; lo refresca de forma perezosa al expirar, sin tarea en segundo plano. El client_secret nunca lo devuelve la API de administración (solo se expone un indicador has_secret), y el token obtenido se coloca como Authorization: Bearer … en la petición saliente.
Rotar el secreto tras una rotación del lado del proveedor no requiere ninguna edición del pipeline: la siguiente llamada se refresca automáticamente.
Idempotencia
Todo operador que produzca un efecto secundario (HTTP POST, DB INSERT, envío de email) debe diseñarse para ser idempotente del lado del destino. Práctica recomendada:
- Incluye una
idempotency_keyen la carga útil (típicamenteexchange_id). - Comprueba del lado del destino si la clave ya ha sido procesada.
Fuera de los reintentos que configures explícitamente en webhook_action (retry_count), betool no reintenta automáticamente un operador fallido: es responsabilidad de tu pipeline orquestar la estrategia de reintento. Además, webhook_action está protegido contra el doble envío durante un re-dispatch interno: una petición ya entregada con un estado aceptado no se reenvía.