Saltar al contenido principal
Actualizado el Aug 5, 2026

Ejecutar código

Usa esta acción cuando un paso necesite lógica personalizada que CEL no puede expresar — reformatear datos, calcular valores, procesar archivos o llamar a una API con código. Una sola acción cubre ambos lenguajes: elige JavaScript o Python en el campo Lenguaje.

Mejor para

  • Transformar JSON de pasos anteriores exactamente a la forma que un paso posterior necesita
  • Cálculos, parsing y validaciones más allá de lo que pueden hacer las expresiones CEL
  • Pequeñas integraciones usando fetch (JavaScript) cuando la acción Solicitud HTTP no es lo bastante flexible
  • Trabajo con documentos y archivos usando las bibliotecas incluidas de Python — hojas de cálculo, PDFs, imágenes, DOCX/PPTX

Elegir el lenguaje

JavaScriptPython
RuntimeSandbox V8 aislado (sin APIs de Node.js)Python 3.12 en un contenedor desechable
Redfetch con protección SSRFNinguna — por diseño
Tiempo límite (ms)100–30.000, por defecto 5.0001.000–120.000, por defecto 30.000
Memoria (MB)8–256, por defecto 128128–2.048, por defecto 512
BibliotecasRecursos estándar de JavaScriptopenpyxl, python-docx, python-pptx, pdfplumber, pypdf, pandas, Pillow, reportlab, markitdown — sin pip en tiempo de ejecución

Ambos lenguajes comparten las mismas entradas y salidas: Datos de entrada estructurados, Archivos de entrada, un resultado estructurado, archivos de salida y logs en un formato unificado.

Campos principales

CampoQué hace
Lenguajejavascript (por defecto) o python
CódigoEl código a ejecutar. JavaScript se envuelve en una IIFE asíncrona, así que puedes usar await en el nivel superior y terminar con return <valor>. Python se ejecuta como un script normal; escribe el resultado en /work/out/output.json
Datos de entradaExpresión CEL opcional evaluada antes de la ejecución. JavaScript ve el valor en la variable input; Python lo ve en la variable INPUT
Archivos de entradaExpresión CEL opcional que evalúa a un array de referencias de storage [{bucket, fullPath, name?}] — por ejemplo step(0).files o un input de workflow de tipo archivo. El contenido de los archivos se entrega al sandbox; el código nunca accede al storage directamente
PropósitoEtiqueta opcional de lo que hace el código, mostrada en los logs
Tiempo límite (ms)Límite de tiempo de ejecución en milisegundos, acotado por lenguaje (ver la tabla de arriba). El código que lo supera — incluidos los bucles infinitos — se termina
Límite de memoria (MB)Límite de memoria del sandbox, acotado por lenguaje

Archivos de entrada y de salida

Ambas direcciones comparten los mismos límites: como máximo 10 archivos, 20 MiB por archivo, 24 MiB en total. Los nombres de archivo deben empezar con letra o dígito y pueden contener letras, dígitos, ., _, - y espacios (hasta 128 caracteres). Los nombres input.json y output.json están reservados — son los canales de datos estructurados.

Leer archivos de entrada:

  • JavaScript — files.readText(name) devuelve el contenido como string de texto (decodificado como UTF-8); files.read(name) lo devuelve como string base64, para datos binarios
  • Python — los archivos aparecen en /work/in/<nombre> (solo lectura)

Escribir archivos de salida:

  • JavaScript — files.writeText(name, text, {contentType?}) para texto; files.write(name, contentBase64, {contentType?}) para binario. contentType se infiere de la extensión cuando se omite
  • Python — escribe los archivos en /work/out/

Para trabajar con texto — CSV, JSON, Markdown — usa readText / writeText y olvídate del base64:

const rows = files.readText("data.csv").split("\n").map((line) => line.split(","));
files.writeText("summary.txt", `${rows.length} filas`);

El par base64 existe para archivos binarios (imágenes, PDFs, hojas de cálculo), normalmente para pasar los bytes sin cambios o entregarlos a fetch.

Los archivos de salida se suben al storage de tu empresa después de la ejecución y aparecen como referencias de storage en step(N).files. Los pasos posteriores pueden encadenarlos — por ejemplo, un paso Python cuyos Archivos de entrada sean step(0).files lee todo lo que produjo el paso de código anterior.

El sandbox JavaScript

El código se ejecuta en un sandbox V8 aislado en un servicio de ejecución separado. No hay acceso a APIs de Node.js (require, process, sistema de archivos) ni a APIs de navegador — solo los recursos estándar de JavaScript más estos puentes:

  • input — el valor evaluado de Datos de entrada (null cuando está ausente)
  • console.log/info/warn/error — capturados y devueltos en la salida logs
  • fetch(url, options) — HTTP con protección SSRF (las direcciones privadas e internas están bloqueadas) que devuelve {ok, status, statusText, body}, con body interpretado como JSON cuando es posible y devuelto como texto en caso contrario. Los cuerpos de respuesta están limitados a 10 MiB: una respuesta mayor hace fallar el paso en lugar de almacenarse en memoria
  • files.read / files.readText / files.write / files.writeText — ver arriba
  • atob(base64) / btoa(binaryString) — el codec base64 estándar, para convertir los valores con los que trabajan files.read y files.write. btoa sigue la regla de la web de rechazar caracteres por encima de U+00FF, así que usa files.writeText para texto UTF-8 en lugar de btoa

No existe Buffer, ni TextDecoder/TextEncoder, ni requireatob/btoa y los helpers de texto de files son la forma soportada de convertir entre bytes y strings.

El sandbox Python

El código se ejecuta como python3 job.py en un contenedor nuevo que se destruye después de la ejecución:

  • Sin acceso a la red — deliberado. Usa el lenguaje JavaScript para llamadas HTTP
  • INPUT — el valor evaluado de Datos de entrada, cargado desde /work/in/input.json (None cuando está ausente)
  • Archivos de entrada en /work/in/ (solo lectura), archivos de salida en /work/out/
  • Escribe el resultado estructurado del paso como JSON en /work/out/output.json — eso es lo que recibe step(N).result. print() va a la salida logs, no al resultado. Un job que no escribe output.json recibe step(N).result = null
  • Solo las bibliotecas incluidas listadas arriba son importables — no hay pip en tiempo de ejecución
  • Solo un job Python se ejecuta a la vez; un runner ocupado hace fallar el paso con un error reintentable (ver abajo)

Qué pueden usar los pasos posteriores

  • step(N).result — el resultado estructurado (valor de return en JavaScript / output.json en Python), limitado a 2 MiB — escribe los datos voluminosos como archivos. null cuando el código no devolvió nada / no escribió output.json
  • step(N).files — referencias de storage de los archivos que el código escribió: [{name, bucket, fullPath, contentType, size}]
  • step(N).logs — salida capturada como entradas [{level, message}] (niveles de consola en JavaScript; stdout / stderr en Python), hasta 200 entradas de 2.000 caracteres cada una
  • step(N).executionTimeMs — cuánto tiempo se ejecutó el código

Las versiones anteriores exponían el valor de retorno de JavaScript como step(N).data. Ahora es step(N).result, para ambos lenguajes.

Errores

CódigoSignificado
code_execution_failedEl código lanzó una excepción — revisa step(N).logs
code_execution_timeoutEl código superó el tiempo límite (ambos lenguajes)
code_executor_busyEl único slot del runner Python está ocupado — reintentable; volver a ejecutar el paso es seguro
code_result_too_largeEl resultado serializado supera los 2 MiB — devuelve un resumen pequeño y escribe los datos voluminosos como archivos
code_result_invalid_jsonPython escribió /work/out/output.json, pero no es JSON válido
code_input_files_invalidArchivos de entrada no evaluó a referencias válidas, superó los límites o usó un nombre reservado
code_input_file_not_accessibleUn archivo de entrada no se encontró o no es accesible desde este workspace
code_input_file_unavailableFallo transitorio de storage al leer un archivo de entrada — reintentable
python_unavailableEl lenguaje Python no está habilitado en este entorno

Consejos

  • Siempre produce un resultado — return en JavaScript, output.json en Python — y mantenlo compatible con JSON.
  • Usa console.log / print() mientras construyes el paso; la salida logs es la forma más fácil de depurar.
  • Cada llamada a fetch también está limitada por el tiempo del paso, así que mantén las llamadas a terceros bien dentro del presupuesto de tiempo.
  • Los archivos son el canal correcto para cualquier cosa grande: el resultado está limitado a 2 MiB, mientras que los archivos llevan hasta 24 MiB por ejecución.