O bloco Function roda seu próprio código JavaScript ou Python como um passo de um workflow. Use para remodelar um valor, fazer um cálculo ou adicionar lógica que nenhum outro bloco cobre.
Configuração
Code
Seu código, em JavaScript (o padrão) ou Python — escolha a linguagem no bloco. Referencie uma saída anterior diretamente, sem aspas em torno da tag, e leia uma variável de ambiente com {{VAR}}:
const data = <api.data>;
return data.items.filter((i) => i.active).map((i) => i.id);import json
data = json.loads('<api.data>')
print(json.dumps([i["id"] for i in data["items"] if i["active"]]))Retorne um valor em JavaScript com return. Em Python, imprima-o como JSON no stdout com print(json.dumps(...)); o bloco captura o stdout como resultado. Seu código roda em um contexto async, então você pode await diretamente em JavaScript.
Saídas
| Saída | O que é |
|---|---|
<function.result> | O valor que seu código retorna (objeto, array, string, number, …) |
<function.stdout> | Qualquer coisa impressa com console.log() ou print() |
Linguagem
JavaScript roda em um sandbox local rápido, ou num sandbox E2B quando seu código usa import ou require. Python sempre roda no sandbox E2B.
| JavaScript | Python | |
|---|---|---|
| Execução | Sandbox local (rápido), ou E2B com imports | Sempre sandbox E2B |
| Retornar um valor | return { … } | print(json.dumps({ … })) |
| Requests HTTP | fetch() embutido | requests ou httpx |
| Melhor para | transforms rápidos, JSON | data science, charts, math complexa |
Python exige E2B. Está habilitado por padrão em app.zoen.space; numa instância self-hosted, habilite E2B para ver Python no dropdown de linguagem. Qualquer figura que você gerar é capturada como imagem automaticamente.
Além da biblioteca padrão do Python, o sandbox traz o stack de data science do E2B mais algumas adições do Zoen:
- Dados:
pandas,numpy,scipy,xarray,numba,joblib - ML e NLP:
scikit-learn,gensim,nltk,spacy,textblob - Plots e imagens:
matplotlib,seaborn,plotly,bokeh,pillow,opencv-python,scikit-image,imageio - Áudio:
librosa,soundfile - Web e arquivos:
requests,aiohttp,beautifulsoup4,openpyxl,xlrd,python-docx,orjson - Math e testes:
sympy,pytest - Adições do Zoen:
awscli,yq,csvkit
Exemplos
Remodelar uma resposta de API
O Function lê <api.data>, retorna só o campo de que o resto do workflow precisa e o expõe como <extract.result>.
Validar entrada antes de gravar
O Function sanitiza a entrada do formulário e retorna o valor limpo, que o bloco API envia como body.
Um exemplo trabalhado: loyalty score
const { purchaseHistory, accountAge, supportTickets } = <agent>;
const totalSpent = purchaseHistory.reduce((sum, p) => sum + p.amount, 0);
const purchaseFrequency = purchaseHistory.length / (accountAge / 365);
const ticketRatio = supportTickets.resolved / supportTickets.total;
const spendScore = Math.min((totalSpent / 1000) * 30, 30);
const frequencyScore = Math.min(purchaseFrequency * 20, 40);
const supportScore = ticketRatio * 30;
const loyaltyScore = Math.round(spendScore + frequencyScore + supportScore);
return {
customer: <agent.name>,
loyaltyScore,
loyaltyTier: loyaltyScore >= 80 ? 'Platinum' : loyaltyScore >= 60 ? 'Gold' : 'Silver',
};import json
data = json.loads('<agent>')
purchase_history = data["purchaseHistory"]
account_age = data["accountAge"]
support_tickets = data["supportTickets"]
total_spent = sum(p["amount"] for p in purchase_history)
purchase_frequency = len(purchase_history) / (account_age / 365)
ticket_ratio = support_tickets["resolved"] / support_tickets["total"]
spend_score = min(total_spent / 1000 * 30, 30)
frequency_score = min(purchase_frequency * 20, 40)
support_score = ticket_ratio * 30
loyalty_score = round(spend_score + frequency_score + support_score)
tier = "Platinum" if loyalty_score >= 80 else "Gold" if loyalty_score >= 60 else "Silver"
print(json.dumps({ "customer": data["name"], "loyaltyScore": loyalty_score, "loyaltyTier": tier }))Entradas grandes
O Zoen entrega a um bloco Function seu código, parâmetros e referências resolvidas numa única request, então valores muito grandes são mantidos por referência em vez de inline.
Prefira uma referência estreita a um valor grande inteiro: use <api.data.id> em vez de <api.data>. Se uma função JavaScript sem imports referenciar um valor grande inteiro, o Zoen a reescreve para uma leitura lazy server-side automaticamente.
Arquivos são metadata-first: ler <file.name> ou <file.url> não carrega o conteúdo do arquivo. Leia conteúdo sob demanda com os helpers sim.files (só JavaScript sem imports):
const file = <readfile.file>;
const text = await sim.files.readText(file);
const chunk = await sim.files.readTextChunk(file, { offset: 0, length: 1024 * 1024 });
const bytes = await sim.files.readBase64Chunk(file, { offset: 0, length: 1024 * 1024 });sim.files.readText, readBase64 e as variantes …Chunk fazem stream do storage de execução sob caps de memória. sim.values.read(ref) e sim.values.readArray(ref) leem referências grandes de valor e array. offset e length de chunk são baseados em bytes, então para parsing Unicode exato prefira referências estruturadas menores. Para dados gerados grandes, grave o resultado num arquivo ou tabela com outputPath, outputSandboxPath ou outputTable em vez de retornar o payload inteiro inline.
Os helpers lazy sim.files e sim.values estão disponíveis só em funções JavaScript sem imports. JavaScript com imports, Python e shell ainda não os suportam.
Boas práticas
- Mantenha cada função focada. Um transform por bloco é mais fácil de ler, testar e debugar.
- Trate erros. Envolva código arriscado em
try/catche retorne uma mensagem clara, ou deixe lançar para o error path. - Referencie só o que precisa. Puxe um campo estreito em vez de um objeto grande inteiro para manter valores fora do body da request.
- Use stdout para debug.
console.log()eprint()caem em<function.stdout>e nos logs da execução.