Pular para o conteúdo principal
Atualizado em Nov 1, 2026

Executar código

Use esta ação quando um passo precisar de lógica personalizada que o CEL não consegue expressar — reformatar dados, calcular valores, processar arquivos ou chamar uma API com código. Uma única ação cobre as duas linguagens: escolha JavaScript ou Python no campo Linguagem.

Melhor para​

  • Transformar JSON de passos anteriores exatamente no formato de que um passo posterior precisa
  • Cálculos, parsing e validações além do que expressões CEL conseguem fazer
  • Pequenas integrações usando fetch (qualquer linguagem) quando a ação Requisição HTTP não for flexível o suficiente
  • Trabalho com documentos e arquivos usando as bibliotecas incluídas do Python — planilhas, PDFs, imagens, DOCX/PPTX

Escolhendo a linguagem​

JavaScriptPython
RuntimeSandbox V8 isolado (sem APIs do Node.js)Python 3.12 em um container descartável
Redefetch com proteção SSRFfetch com proteção SSRF (mediado pelo host)
Tempo limite (ms)100–30.000, padrão 5.0001.000–120.000, padrão 30.000
Memória (MB)8–256, padrão 128128–2.048, padrão 512
BibliotecasRecursos padrão do JavaScript e módulos publicados da empresaopenpyxl, python-docx, python-pptx, pdfplumber, pypdf, pandas, Pillow, reportlab, markitdown — sem pip em tempo de execução

As duas linguagens compartilham as mesmas entradas e saídas: Dados de entrada estruturados, Arquivos de entrada, um resultado estruturado, arquivos de saída e logs em um formato unificado.

Campos principais​

CampoO que faz
Linguagemjavascript (padrão) ou python
CódigoO código a executar. JavaScript é envolvido em uma IIFE assíncrona, então você pode usar await no nível superior e terminar com return <valor>. Python executa como um script comum; escreva o resultado em /work/out/output.json
Dados de entradaExpressão CEL opcional avaliada antes da execução. JavaScript vê o valor na variável input; Python vê na variável INPUT
Arquivos de entradaExpressão CEL opcional que avalia para um array de referências de storage [{bucket, fullPath, name?}] — por exemplo workflow.step(0).files ou um input de workflow do tipo arquivo. O conteúdo dos arquivos é entregue ao sandbox; o código nunca acessa o storage diretamente
BibliotecasBibliotecas publicadas da empresa, fixadas em versões exatas para esta etapa de código e linguagem
PropósitoRótulo opcional do que o código faz, exibido nos logs
Tempo limite (ms)Limite de tempo de execução em milissegundos, restrito por linguagem (veja a tabela acima). Código que ultrapassa o limite — incluindo loops infinitos — é encerrado
Limite de memória (MB)Limite de memória do sandbox, restrito por linguagem

Bibliotecas reutilizáveis da empresa​

A lógica que você precisa em mais de um passo pode ficar em uma biblioteca da empresa: um módulo JavaScript ou Python publicado em versões numeradas que nunca mudam. Um passo fixa uma versão exata de cada biblioteca que usa, na caixa Bibliotecas acima do código, e mantém essa versão até você atualizá-la.

  • Adicionar biblioteca fixa uma biblioteca publicada na linguagem do passo. Quando existe uma versão mais nova, Atualizar para vN mostra o que muda antes de você passar para ela.
  • Abra a linha de uma biblioteca para ver as exportações e os parâmetros, e insira uma chamada na posição do cursor.
  • Mudar a Linguagem do passo remove as bibliotecas fixadas.

Um passo JavaScript chama uma biblioteca fixada por meio de autotalk_libraries:

return autotalk_libraries.greetings.greet(input.name);

Um passo Python a importa e grava o resultado como de costume:

import json
from autotalk_libraries import greetings

with open("/work/out/output.json", "w") as output:
json.dump(greetings.greet(INPUT["name"]), output)

Um passo JavaScript só alcança as bibliotecas fixadas nele, não os imports delas. A ferramenta MCP run_code aceita as mesmas fixações exatas em codeLibraries: [{libraryId, releaseId}], e get_code_library_reference as encontra. Para escrever, testar e publicar bibliotecas, e para os limites e permissões, veja Bibliotecas.

Arquivos de entrada e de saída​

As duas direções compartilham os mesmos limites: no máximo 10 arquivos, 20 MiB por arquivo, 24 MiB no total. Nomes de arquivo devem começar com letra ou dígito e podem conter letras, dígitos, ., _, - e espaços (até 128 caracteres). Os nomes input.json e output.json são reservados — eles são os canais de dados estruturados.

Lendo arquivos de entrada:

  • JavaScript — files.readText(name) retorna o conteúdo como string de texto (decodificado como UTF-8); files.read(name) retorna como string base64, para dados binários
  • Python — os arquivos aparecem em /work/in/<nome> (somente leitura)

Escrevendo arquivos de saída:

  • JavaScript — files.writeText(name, text, {contentType?}) para texto; files.write(name, contentBase64, {contentType?}) para binário. contentType é inferido da extensão quando omitido
  • Python — escreva os arquivos em /work/out/

Para trabalhar com texto — CSV, JSON, Markdown — use readText / writeText e dispense o base64:

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

O par base64 existe para arquivos binários (imagens, PDFs, planilhas), normalmente para repassar os bytes sem alteração ou entregá-los ao fetch.

Os arquivos de saída são enviados ao storage da sua empresa após a execução e aparecem como referências de storage em workflow.step(N).files. Passos posteriores podem encadeá-los — por exemplo, um passo Python cujos Arquivos de entrada sejam workflow.step(0).files lê tudo o que o passo de código anterior produziu.

O sandbox JavaScript​

O código executa em um sandbox V8 isolado em um serviço de execução separado. Não há acesso a APIs do Node.js (require, process, sistema de arquivos) nem a APIs de navegador — apenas os recursos padrão do JavaScript mais estas pontes:

  • input — o valor avaliado de Dados de entrada (null quando ausente)
  • console.log/info/warn/error — capturados e retornados na saída logs
  • fetch(url, options) — HTTP com proteção SSRF (endereços privados e internos são bloqueados) que retorna {ok, status, statusText, body}, com body interpretado como JSON quando possível e retornado como texto caso contrário. Corpos de resposta são limitados a 10 MiB — uma resposta maior falha a etapa em vez de ser carregada na memória
  • files.read / files.readText / files.write / files.writeText — veja acima
  • atob(base64) / btoa(binaryString) — o codec base64 padrão, para converter os valores com que files.read e files.write trabalham. btoa segue a regra da web de rejeitar caracteres acima de U+00FF, então use files.writeText para texto UTF-8 em vez de btoa

Não existe Buffer, nem TextDecoder/TextEncoder, nem require — atob/btoa e os helpers de texto de files são a forma suportada de converter entre bytes e strings.

O sandbox Python​

O código executa como python3 job.py em um container novo que é destruído após a execução:

  • INPUT — o valor avaliado de Dados de entrada, carregado de /work/in/input.json (None quando ausente)
  • fetch(url, method="GET", headers=None, body=None) — o mesmo HTTP com proteção SSRF da linguagem JavaScript, fornecido pela plataforma (o container em si não tem rede bruta; cada requisição é mediada pelo host). Retorna um dict {"ok", "status", "statusText", "body"}, com body interpretado como JSON quando possível e retornado como texto caso contrário; corpos de resposta são limitados a 10 MiB. Levanta FetchError quando a requisição não pode ser feita (um alvo bloqueado ou inacessível). Uma resposta não-2xx não é um erro — ela retorna com ok=False, como na linguagem JavaScript. Não dependa de requests ou urllib para chamadas externas — use fetch()
  • Arquivos de entrada em /work/in/ (somente leitura), arquivos de saída em /work/out/
  • Escreva o resultado estruturado do passo como JSON em /work/out/output.json — é isso que workflow.step(N).result recebe. print() vai para a saída logs, não para o resultado. Um job que não escreve output.json recebe workflow.step(N).result = null
  • Módulos da biblioteca padrão, os pacotes incluídos listados acima e bibliotecas fixadas da empresa são importáveis — não há pip em tempo de execução
  • Apenas um job Python executa por vez; um runner ocupado falha o passo com um erro com retry (veja abaixo)

Buscar dados e transformá-los com as bibliotecas incluídas:

import json
resp = fetch("https://api.example.com/report", headers={"accept": "application/json"})
if not resp["ok"]:
raise FetchError(f"upstream retornou {resp['status']}")
rows = resp["body"]["items"]
with open("/work/out/output.json", "w") as f:
json.dump({"count": len(rows)}, f)

O que passos posteriores podem usar​

  • workflow.step(N).result — o resultado estruturado (valor do return em JavaScript / output.json em Python), limitado a 2 MiB — escreva dados volumosos como arquivos. null quando o código não retornou nada / não escreveu output.json
  • workflow.step(N).files — referências de storage dos arquivos que o código escreveu: [{name, bucket, fullPath, contentType, size}]
  • workflow.step(N).logs — saída capturada como entradas [{level, message}] (níveis de console no JavaScript; stdout / stderr no Python), até 200 entradas de 2.000 caracteres cada
  • workflow.step(N).executionTimeMs — quanto tempo o código executou

Versões anteriores expunham o valor de retorno do JavaScript como workflow.step(N).data. Agora é workflow.step(N).result, para as duas linguagens.

Como esta etapa publica result e não data, workflow.stepData e workflow.stepHasContent resolvem dentro de result: workflow.stepData(N, "count") lê workflow.step(N).result.count, que normalmente é o que você quer. Os três irmãos na raiz da etapa são invisíveis para eles — leia esses com maps.get(workflow.step(N), "files"), e não com workflow.stepHasContent(N, "files"), que erraria em silêncio enquanto workflow.stepOk(N) continua true. Isso vale mesmo quando o código não retornou nada, porque aí result é null. Veja Ações que publicam na raiz da etapa.

Erros​

CódigoSignificado
code_execution_failedO código lançou uma exceção — verifique workflow.step(N).logs
code_execution_timeoutO código ultrapassou o tempo limite (ambas as linguagens)
code_executor_busyO único slot do runner Python está ocupado — com retry; executar o passo novamente é seguro
code_result_too_largeO resultado serializado passa de 2 MiB — retorne um resumo pequeno e escreva dados volumosos como arquivos
code_result_invalid_jsonPython escreveu /work/out/output.json, mas não é JSON válido
code_input_files_invalidArquivos de entrada não avaliou para referências válidas, ultrapassou os limites ou usou um nome reservado
code_input_file_not_accessibleUm arquivo de entrada não foi encontrado ou não está acessível a partir deste workspace
code_input_file_unavailableFalha transitória de storage ao ler um arquivo de entrada — com retry
python_unavailableA linguagem Python não está habilitada neste ambiente

Dicas​

  • Sempre produza um resultado — return no JavaScript, output.json no Python — e mantenha-o compatível com JSON.
  • Use console.log / print() enquanto constrói o passo; a saída logs é a forma mais fácil de depurar.
  • Cada chamada de fetch também é limitada pelo tempo do passo, então mantenha chamadas a terceiros bem dentro do orçamento de tempo.
  • Arquivos são o canal certo para qualquer coisa grande: o resultado é limitado a 2 MiB, enquanto arquivos carregam até 24 MiB por execução.