Referência de Funções CEL
Referência das funções e operadores integrados disponíveis nas expressões CEL do AutoTalk, organizados por categoria.
Dois conjuntos de nomes entram nesse escopo, e ambos estão nesta página. A
biblioteca padrão do CEL — operadores, macros de lista, funções de string,
conversões de tipo e os getters de timestamp — vem do registro CEL compartilhado
no AutoTalk Commons (src/functions/cel/index.ts), o mesmo registro do qual o
painel Explorer do editor CEL é projetado, então tudo o que o
Explorer oferece está documentado aqui. Além disso, o AutoTalk adiciona os
próprios auxiliares — get, coalesce, pluck, a família math_*, os
auxiliares de data, os auxiliares de workflow step_* — que existem apenas
aqui.
Core
get(obj, path, default?)
Acessa com segurança uma propriedade aninhada através de um caminho pontilhado.
get(contact, "address.city") // "São Paulo"
get(contact, "address.zip", "00000-000") // retorna o padrão se ausente
get(null, "name") // null
get(step(0), "data.results.0.title") // caminho profundo com índice de array
| Param | Tipo | Descrição |
|---|---|---|
obj | any | Objeto a acessar (seguro para null) |
path | string | Caminho pontilhado (ex: "a.b.c") |
default | any | Valor retornado se o caminho estiver ausente (padrão: null) |
has(obj, path?)
Verifica se um valor ou caminho aninhado existe e não é null/undefined.
has(contact, "platformId") // true se contact.platformId estiver definido
has(myVar) // true se myVar não for null/undefined
has(obj, "a.b.c") // true se o caminho completo resolver para não-null
coalesce(...vals)
Retorna o primeiro valor não-null e não-undefined. Variádica — aceita até 5 argumentos. Se precisar de mais, aninhe as chamadas: coalesce(a, b, c, d, coalesce(e, f)).
coalesce(get(contact, "customAttributes.nickname"), contact.name, "Guest") // o primeiro não-null vence
coalesce(0, 42) // 0 (não é null!)
coalesce(false, true) // false (não é null!)
coalesce("", "fallback") // "" (não é null!)
coalesce() ignora apenas null e undefined. Valores como 0, false e "" são válidos e retornados.
now(tz?)
Retorna a data/hora atual como uma string ISO 8601.
now() // "2024-01-15T14:30:00.000Z"
format_datetime(now(), "YYYY-MM-DD") // "2024-01-15"
O resultado é sempre expresso em UTC (sufixo Z), mesmo quando o argumento opcional de fuso horário é passado. Para exibir a hora atual em um fuso horário específico, formate-a — ex.: format_datetime(now(), "HH:mm", "America/Sao_Paulo").
present(val)
Verifica se um valor está significativamente presente. Retorna false para null, undefined, strings vazias/somente espaços e arrays vazios. Números e booleanos são sempre considerados presentes.
present(contact.platformId) // true se for string não vazia
present("") // false
present(" ") // false (somente espaços)
present(0) // true
present([]) // false
present([1, 2]) // true
present(x) substitui o padrão comum size(trim(coalesce(x, ""))) > 0.
blank(val)
Inverso de present(). Retorna true para null, undefined, strings vazias/somente espaços e arrays vazios.
blank(contact.platformId) // true se for null ou vazio
blank("hello") // false
blank(0) // false
Utilitários
pluck(arr, path)
Extrai uma propriedade de cada objeto em um array.
pluck(contacts, "name") // ["Alice", "Bob", "Carol"]
pluck(tools, "tool.function.name") // caminho profundo suportado
slice(arr, start, end?)
Fatia um array com segurança. Retorna [] para entradas que não são arrays. Suporta índices negativos.
slice(results, 0, 5) // primeiros 5 itens
slice(results, -3) // últimos 3 itens
slice(results, 1, -1) // todos exceto o primeiro e o último
slice(null, 0, 2) // [] (seguro para não-arrays)
defaults(obj, fallbacks)
Mescla valores de fallback em um objeto para chaves que são null/undefined. Mesclagem superficial.
defaults(response, {"status": "unknown", "retryable": false})
// Preenche status e retryable somente se forem null/undefined em response
Assim como coalesce(), apenas valores null/undefined são substituídos. 0, false e "" são mantidos.
url_params(base, params)
Constrói uma URL com parâmetros de query. Ignora valores null e vazios. Codifica automaticamente.
url_params("https://api.example.com/search", {"q": query, "page": 1, "lang": null})
// "https://api.example.com/search?q=hello&page=1" (lang ignorado)
truncate(str, maxLen, suffix?)
Trunca uma string até um comprimento máximo com um sufixo opcional.
truncate("Hello World", 5) // "Hello"
truncate("Hello World", 8, "...") // "Hello..."
truncate(null, 10) // "" (seguro para null)
truncate("Hi", 100) // "Hi" (sem necessidade de truncar)
| Param | Tipo | Descrição |
|---|---|---|
str | any | Valor a truncar (convertido para string, null retorna "") |
maxLen | number | Comprimento máximo do resultado (incluindo o sufixo) |
suffix | string | Adicionado quando truncado (padrão: "") |
O sufixo é incluído dentro de maxLen: truncate("Hello World", 8, "...") retorna "Hello..." (8 caracteres).
tpl(template, vars)
Interpolação simples de string. Substitui marcadores {key} por valores de um objeto.
tpl("Hello {name}!", {"name": "Alice"}) // "Hello Alice!"
tpl("*{title}*\n{domain}\n{url}", article) // texto formatado do artigo
tpl("{address.city}, {address.country}", contact) // suporte a caminho pontilhado
tpl("Hi {name}", {"name": null}) // "Hi " (null → vazio)
| Param | Tipo | Descrição |
|---|---|---|
template | string | String de template com marcadores {key} |
vars | object | Objeto com valores para interpolar |
join_present(separator, ...values)
Junta valores com um separador, ignorando valores em branco. Usa as mesmas regras de present(): null, strings vazias/somente espaços e arrays vazios são ignorados. 0 e false são mantidos. Aceita no máximo 5 argumentos no total — o separador mais até 4 valores.
join_present(", ", "Alice", "Bob", "Carol") // "Alice, Bob, Carol"
join_present(" - ", title, null, author) // "Title - Author" (null ignorado)
join_present(" ", "Hello", "", "World") // "Hello World" (vazio ignorado)
join_present(" | ", 0, false, "text") // "0 | false | text" (0/false mantidos)
join_present(" - ", prefix, text) substitui o padrão (present(prefix) ? prefix + " - " : "") + text.
encode_uri(str)
Codifica uma string para URL. Caracteres URI reservados (&, =, ?, /, #) não são escapados, então ela só é adequada para codificar uma URL inteira — não valores individuais de parâmetros de query.
encode_uri("hello world") // "hello%20world"
encode_uri("a&b=c") // "a&b=c" (caracteres reservados preservados)
Para adicionar parâmetros de query a uma URL com segurança, use url_params() — ela codifica cada valor de parâmetro para você.
format_currency(currency, locale, amount)
Formata um número como moeda. Os três argumentos são obrigatórios, nesta ordem: código da moeda, locale e, por fim, o valor.
format_currency("USD", "en-US", 1234.5) // "$1,234.50"
format_currency("BRL", "pt-BR", 99.9) // "R$ 99,90"
Operadores
| Operador | O que faz | Exemplo |
|---|---|---|
! | NÃO lógico | !step_ok(0) |
&& | E lógico, com curto-circuito | step_ok(0) && present(step_data(0, "id")) |
|| | OU lógico, com curto-circuito | blank(contact.name) || contact.name == "-" |
==, != | Igualdade e desigualdade | step_data(0, "status") == "open" |
<, <=, >, >= | Comparação | size(step_data(0, "items")) > 0 |
+ | Soma. Também junta duas strings, concatena duas listas e soma uma duração a um timestamp | [1, 2] + [3] → [1, 2, 3] |
-, *, /, % | Subtração, multiplicação, divisão, resto | (total - paid) % 2 == 0 |
in | Pertencimento: este elemento está na lista, ou esta chave está no mapa? | "vip" in contact.tags → true |
in é o que mais passa despercebido. Ele evita um laço inteiro quando você só
precisa saber se um valor está presente, e combina com o map abaixo:
"open" in step_data(0, "items").map(r, r.status)
Listas e macros
As macros executam uma expressão sobre cada elemento de uma lista. Elas são escritas no estilo receptor — a lista primeiro — e o primeiro argumento dá nome à variável do laço, que existe apenas dentro daquela macro.
| Macro | O que faz | Exemplo |
|---|---|---|
list.all(x, pred) | Verdadeiro quando todos os elementos correspondem. Verdadeiro para uma lista vazia | rows.all(x, x.total > 0) |
list.exists(x, pred) | Verdadeiro quando ao menos um elemento corresponde. Falso para uma lista vazia | rows.exists(x, x.status == "open") |
list.exists_one(x, pred) | Verdadeiro quando exatamente um elemento corresponde | rows.exists_one(x, x.primary) |
list.map(x, expr) | Uma nova lista, com expr aplicada a cada elemento | rows.map(x, x.email) |
list.map(x, pred, expr) | O mesmo, mas apenas sobre os elementos que correspondem a pred | rows.map(x, x.status == "open", x.id) |
list.filter(x, pred) | Uma nova lista contendo apenas os elementos correspondentes | rows.filter(x, x.status == "open") |
Este é o caminho mais curto para "quantas das linhas devolvidas por uma etapa de pesquisa ainda estão abertas" — sem precisar de uma etapa Executar Código:
size(step_data(0, "items").filter(r, r.status == "open"))
step_data(0, "items").map(r, r.status == "open", r.name) // nomes das abertas
step_data(0, "items").all(r, present(r.email)) // toda linha é utilizável?
Conversão de tipos
| Função | O que faz | Exemplo |
|---|---|---|
int(v) | Para número inteiro. Trunca um decimal em direção a zero; um timestamp vira segundos de época, e uma duração vira segundos inteiros | int("42") → 42, int(4.9) → 4 |
uint(v) | Para número inteiro sem sinal. Volta como um valor encapsulado, e não como um número simples — veja abaixo | uint("42") |
double(v) | Para número decimal | double("3.14") → 3.14 |
bool(v) | Para booleano, a partir de "true", "false", "1" ou "0" | bool("true") → true |
bytes(v) | Uma string para bytes brutos | bytes("hi") |
string(v) | Qualquer coisa para sua forma textual. Um timestamp vira uma string ISO 8601, e uma duração vira segundos com um s | string(123) → "123" |
timestamp(v) | Uma string ISO 8601 completa, ou milissegundos de época, para um timestamp | timestamp("2024-01-15T00:00:00Z") |
duration(v) | Uma string de duração — "90m", "1h30m", "3600s" — para uma duração | duration("48h") |
type(v) | O tipo de um valor | type(1) |
dyn(v) | Passa um valor adiante, como tipo dinâmico | dyn(v) |
Cinco coisas para saber antes de colocar uma destas em um campo:
-
Uma conversão que não pode dar certo não apenas volta vazia — ela leva a expressão inteira junto, e nenhuma proteção consegue capturar isso.
int("abc"),bool("yes"),uint("abc"),duration("abc")etimestamp("2024-01-15")(sem a parte de hora) não produzem nada, e tudo o que for construído em volta delas também não:int("abc") > 5fica vazio em vez defalse,"n=" + string(int("abc"))fica vazio em vez de"n=", epresent,blank,coalescee? :também ficam vazios —present(int("abc"))não éfalseecoalesce(int("abc"), 0)não é0. Este é o único ponto em que a falha não é igual à de um caminho de etapa inexistente, ondepresentrealmente respondefalse: uma condição escrita como!present(int(step_data(0, "qty")))para significar "a quantidade não era um número" nunca dispara. Teste o valor bruto antes de converter, para que a conversão só rode em algo que ela aceita:qty.matches("^-?[0-9]+$") ? int(qty) : 0 // 0 quando qty é "abc" -
doublefalha de outro jeito, e ainda mais silenciosamente.double("abc")éNaN:presento considera presente,blanko considera não vazio,string()o renderiza como"NaN", e toda comparação com ele éfalse— tantodouble("abc") > 5quantodouble("abc") <= 5. A proteção commatchesacima também resolve aqui. -
uint()devolve um valor encapsulado, e não um número.uint("42")compara corretamente (uint("42") == 42étrue), mas não faz aritmética —uint("42") + 1fica vazio — e um campo guarda o encapsulamento em vez de42. Useint()a menos que você precise mesmo do tipo sem sinal, ou desembrulhe:int(uint(v)),string(uint(v)). -
timestampedurationnão são valores que um campo consegue guardar. Eles são úteis dentro de uma expressão — comparando, somando, alimentando um getter. Para obter algo que um campo possa armazenar, envolva-os:string(timestamp(x) + duration("48h"))é uma string ISO, eint(duration("90m"))é5400. -
type()também não sobrevive até um campo, e suas comparações não funcionam aqui. Usepresent/blankpara perguntar se um valor existe, e compare com o próprio valor em vez do tipo dele.
String
CEL inclui funções de string integradas. A maioria funciona tanto no estilo receptor quanto no estilo função:
"hello".contains("ell") // true (estilo receptor)
contains("hello", "ell") // true (estilo função)
| Função | Descrição | Exemplo |
|---|---|---|
contains(str, sub) | Verifica se a string contém a substring | "hello".contains("ell") |
startsWith(str, prefix) | Verifica prefixo | "hello".startsWith("he") |
endsWith(str, suffix) | Verifica sufixo | "hello".endsWith("lo") |
matches(str, pattern) | Correspondência por expressão regular | "abc123".matches("^abc[0-9]+$") → true |
size(x) | Comprimento de uma string, lista ou map | size("hello") → 5, size([1, 2, 3]) → 3 |
split(str, sep) | Divide em array | split("a,b,c", ",") → ["a","b","c"] |
lowerAscii(str) | Minúsculas | lowerAscii("HELLO") → "hello" |
upperAscii(str) | Maiúsculas | upperAscii("hello") → "HELLO" |
trim(str) | Remove espaços | trim(" hi ") → "hi" |
substring(str, start, end?) | Extrai substring | substring("hello", 1, 4) → "ell" |
replace(str, old, new) | Substitui ocorrências | replace("aab", "a", "x") → "xxb" |
indexOf(str, sub) | Primeiro índice da substring | indexOf("hello", "l") → 2 |
lastIndexOf(str, sub) | Último índice da substring | lastIndexOf("hello", "l") → 3 |
charAt(str, index) | Caractere no índice | charAt("hello", 0) → "h" |
join(list, sep?) | Junta array em string | join(["a","b"], ",") → "a,b" |
format(str, args) | Preenche os marcadores %s / %d a partir de uma lista | "%d open".format([2]) → "2 open" |
strings.quote(str) | Envolve em aspas e escapa o conteúdo | strings.quote("a b") → "\"a b\"" |
Math
| Função | Descrição | Exemplo |
|---|---|---|
math_add(a, b) | Adição | math_add(5, 3) → 8 |
math_subtract(a, b) | Subtração | math_subtract(10, 3) → 7 |
math_multiply(a, b) | Multiplicação | math_multiply(4, 3) → 12 |
math_divide(a, b) | Divisão | math_divide(10, 3) → 3.333... |
math_round(n, decimals?) | Arredondamento | math_round(3.456, 2) → 3.46 |
math_floor(n) | Piso | math_floor(3.7) → 3 |
math_ceil(n) | Teto | math_ceil(3.1) → 4 |
math_abs(n) | Valor absoluto | math_abs(-5) → 5 |
math_pow(base, exp) | Potência | math_pow(2, 3) → 8 |
math_sqrt(n) | Raiz quadrada | math_sqrt(16) → 4 |
math_sin(n) | Seno (radianos) | math_sin(0) → 0 |
math_cos(n) | Cosseno (radianos) | math_cos(0) → 1 |
math_tan(n) | Tangente (radianos) | math_tan(0) → 0 |
math_log(n, base?) | Logaritmo (natural por padrão) | math_log(8, 2) → 3 |
math_exp(n) | e elevado à potência n | math_exp(0) → 1 |
math_max(arr) | Máximo | math_max([1,5,3]) → 5 |
math_min(arr) | Mínimo | math_min([1,5,3]) → 1 |
math_mean(arr) | Média | math_mean([1,2,3]) → 2 |
math_median(arr) | Mediana | math_median([1,2,10]) → 2 |
math_std(arr) | Desvio padrão (amostral) | math_std([2,4,6]) → 2 |
math_variance(arr) | Variância (amostral) | math_variance([2,4,6]) → 4 |
math_dot(a, b) | Produto escalar de dois vetores | math_dot([1,2,3], [4,5,6]) → 32 |
math_norm(arr) | Norma euclidiana (comprimento do vetor) | math_norm([3,4]) → 5 |
math_clamp(val, min, max) | Restringe ao intervalo | math_clamp(15, 0, 10) → 10 |
math_evaluate(expr) | Avalia uma string de expressão matemática | math_evaluate("2 + 3 * 4") → 14 |
math_clamp(val, min, max)
Restringe um número dentro de um intervalo.
math_clamp(page, 1, 100) // garante que page está entre 1 e 100
math_clamp(-5, 0, 10) // 0 (abaixo do mínimo)
math_clamp(15, 0, 10) // 10 (acima do máximo)
DateTime
| Função | Descrição |
|---|---|
now(tz?) | Data/hora atual como uma string ISO 8601 (sempre expressa em UTC) |
format_datetime(d, fmt, tz?, locale?) | Formata uma data/hora. Aceita qualquer string de formato do dayjs — ex.: "DD/MM/YYYY", "YYYY-MM-DD HH:mm:ss", "HH:mm" — mais um fuso horário e locale opcionais ("en", "pt-BR", "es") |
add_datetime(d, n, unit) | Adiciona tempo. Unidades: "years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds" |
diff_datetime(d1, d2, unit) | Diferença entre duas datas/horas |
zoned_datetime(dateStr, timeStr, tz, format?) | Constrói uma data/hora com fuso horário a partir de strings separadas de data e hora, ex.: zoned_datetime("2024-01-15", "14:30", "America/Sao_Paulo"). Para converter ou exibir uma data/hora já existente, use format_datetime |
is_before(d1, d2) | d1 antes de d2? |
is_after(d1, d2) | d1 depois de d2? |
is_between(d, start, end) | d entre start e end? |
is_same_date(d1, d2, unit?, tz?) | d1 e d2 iguais na unidade dada? (unidade padrão: "millisecond") — ex.: is_same_date(a, b, "day") verifica o mesmo dia do calendário |
is_same_or_before(d1, d2, unit?, tz?) | d1 igual ou anterior a d2? |
is_same_or_after(d1, d2, unit?, tz?) | d1 igual ou posterior a d2? |
Getters de timestamp e duração
Estes leem uma parte de um timestamp ou de uma duration. Funcionam tanto no
estilo receptor — timestamp(x).getFullYear() — quanto no estilo função —
getFullYear(timestamp(x)) — e todo getter de timestamp aceita um fuso horário
IANA opcional como último argumento. Sem ele, leem o valor em UTC.
| Getter | Em um timestamp | Em uma duração |
|---|---|---|
getFullYear(t, tz?) | Ano com quatro dígitos | — |
getMonth(t, tz?) | Mês, 0–11 — janeiro é 0 | — |
getDate(t, tz?) | Dia do mês, 1–31 | — |
getDayOfMonth(t, tz?) | Dia do mês, começando em 0 — o dia 15 é 14 | — |
getDayOfWeek(t, tz?) | Dia da semana, 0–6, domingo é 0 | — |
getDayOfYear(t, tz?) | Dia do ano, começando em 0 — 1º de janeiro é 0 | — |
getHours(v, tz?) | Hora, 0–23 | Horas inteiras na duração |
getMinutes(v, tz?) | Minuto, 0–59 | Minutos totais — duration("1h30m") dá 90, não 30 |
getSeconds(v, tz?) | Segundo, 0–59 | Segundos totais |
getMilliseconds(v, tz?) | Milissegundo, 0–999 | A parte abaixo de um segundo, ou seja 0 para qualquer duração em segundos inteiros |
timestamp(step_data(0, "createdAt")).getDayOfWeek("America/Sao_Paulo") == 0 // caiu num domingo, hora local
getMonth(timestamp(now())) + 1 // mês como 1-12
Dois destes são fáceis de errar: getDate conta a partir de 1 enquanto
getDayOfMonth conta a partir de 0, e getMonth conta a partir de 0. Quando
você quer uma data para mostrar a alguém, e não um número para comparar,
format_datetime acima é a ferramenta melhor.
JSON
| Função | Descrição |
|---|---|
json_parse(str) | Converte string JSON em objeto |
json_stringify(obj) | Serializa objeto em string JSON |
TOON
TOON é um formato de serialização de dados compacto e legível por humanos.
| Função | Descrição |
|---|---|
toon_encode(value) | Codifica um valor em uma string TOON |
toon_decode(str) | Faz o parse de uma string TOON de volta em um valor |
toon_encode({"name": "Alice", "age": 30}) // "name: Alice\nage: 30"
toon_decode("name: Alice\nage: 30") // {"name": "Alice", "age": 30}
BSON / ObjectId
| Função | Descrição |
|---|---|
object_id(value?) | Cria ou normaliza uma instância de ObjectId (uma nova se não houver argumento). Use object_id_to_string() para obter a string hexadecimal |
object_id_is_valid(id) | Verifica se a string é um ObjectId válido |
object_id_to_string(id) | Converte um ObjectId em sua string hexadecimal |
bson_serialize(value, encoding?) | Serializa um valor em bytes BSON, retornados como uma string base64 (padrão) ou "hex" |
bson_deserialize(str, encoding?) | Decodifica uma string BSON base64 (padrão) ou "hex" de volta em um valor |
ejson_stringify(value, relaxed?) | Serializa um valor em uma string Extended JSON do MongoDB (modo relaxado por padrão) |
ejson_parse(str, relaxed?) | Faz o parse de uma string Extended JSON do MongoDB em um valor |
bson_serialize({"a": 1}) // "DAAAABBhAAEAAAAA" (base64)
bson_serialize({"a": 1}, "hex") // "0c0000001061000100000000"
bson_deserialize("DAAAABBhAAEAAAAA") // {"a": 1}
ejson_stringify({"a": 1}) // "{\"a\":1}"
Específicas de Workflow
Estas funções estão disponíveis apenas em expressões de workflow e agentes (não em CEL de formulários).
step(N)
Acessa a saída do passo N do workflow (indexado a partir de 0).
step(0) // objeto completo de saída do passo
step(0).data // payload de dados do passo
step(0).status // código de status HTTP (para passos HTTP)
step_ok(N)
Verifica se o passo N foi concluído com sucesso. Retorna true quando executionContext.status é "completed" E o status HTTP é 200 (ou null para passos não-HTTP).
// Antes: verboso
get(step(0), "executionContext.status") == "completed" && (get(step(0), "status") == null || get(step(0), "status") == 200)
// Depois: uma chamada de função
step_ok(0)
step_data(N, path?, default?)
Obtém dados do passo N em um caminho pontilhado opcional. Retorna o padrão (ou null) se ausente.
O caminho é relativo ao data do passo — step_data(0, "title") lê step(0).data.title. Não repita data no caminho: step_data(0, "data.title") procura step(0).data.data.title, erra em silêncio e devolve o valor padrão — indistinguível do campo estar vazio. (step_data(0, "data.x") só está correto quando o corpo da resposta tem, ele próprio, uma chave data no topo, como em respostas JSON:API.)
// Antes
get(step(0), "data.title", null)
// Depois
step_data(0, "title")
step_data(0, "results.0.name", "Unknown")
step_data(1, "choices.0.message.content")
Ações que publicam na raiz da etapa
A maioria das ações coloca sua saída sob data, e é por isso que o caminho é
relativo a ele. Vinte não fazem isso — elas declaram suas saídas na raiz da
etapa e não têm objeto data nenhum. Esse não é um caso raro:
actions/ai/llm/chat/generate está na lista, e o choices dela é a saída de
etapa que os workflows mais percorrem.
| Ação | Saídas na raiz |
|---|---|
actions/ai/agent/send | messages |
actions/ai/llm/chat/generate | choices |
actions/agent/lifecycle/session/set_reply_delay | replyDelayMs |
actions/ai/text/speakable | text, model |
actions/data/company/resource/count | count |
actions/mcp/connect | url, toolCount |
actions/mcp/connect/autotalk-mcp | url, toolCount |
actions/media/audio/synthesize | file, bucket, fullPath, size, contentType, format, cache, billedMeter, billedMs |
actions/media/audio/transcribe | jobId, jobStatus, enginePath, providerType, diarized |
actions/media/document/generate | file, bucket, fullPath, fileName, size, contentType, format |
actions/media/read | text, supported, truncated, reason, mediaKind, mimeType, fileName, size |
actions/media/storage/delete | deleted, existed, bucket, fullPath |
actions/media/storage/probe | durationSeconds, width, height, formatName, videoCodec, audioCodec, hasAudio, sizeBytes, contentType, cached |
actions/media/storage/signed-url | signedUrl, contentType, size, mediaKind, bucket, fullPath, name, expiresAt |
actions/media/storage/upload | file, signedUrl, contentType, size |
actions/media/transform | jobId, jobStatus, preset |
actions/monitors/cancel | monitorId, monitorState |
actions/monitors/create | monitorId, monitorState, expiresAtIso |
actions/network/http/download-to-storage | status, file, signedUrl, contentType, size |
actions/security/auth/jwt/generate | jwt |
Leia essas saídas com get(step(N), "field"):
get(step(0), "count") > 0 // resource/count
get(step(1), "choices.0.message.content") // llm/chat/generate
get(step(2), "mediaKind") == "pdf" // media/read
step_data também resolve contra a raiz nesses casos — uma etapa que não tem
nem data nem result recai sobre o próprio objeto da etapa — então
step_data(0, "count") também funciona. Esse fallback é deliberadamente estreito
e não se aplica a uma etapa que de fato tem data: em
actions/network/http/request/send, step_data(N, "status") continua devolvendo
o seu valor padrão em vez do código de status HTTP, porque status é irmão de
data na raiz, e não um campo dentro dele. (Na
actions/network/http/download-to-storage, que é da forma raiz, status é uma
saída da etapa, então step_data(N, "status") devolve o valor — a regra é a
mesma, o formato da ação é que é diferente.) Chaves que pertencem ao envelope de
execução (executionContext, actionContext, safeError, safeResult,
conditionPassed, aclInfo) nunca são alcançáveis por step_data em nenhuma
etapa.
Existe um terceiro formato, e exatamente uma ação está nele hoje. Executar
Código publica seu valor de retorno como um result no topo e não tem data,
então step_data e step_has_content resolvem dentro daquele valor:
step_data(0, "count") lê step(0).result.count, que normalmente é o que você
quer. Os irmãos dele na raiz da etapa — files, logs, executionTimeMs — não
são alcançáveis por esse caminho e precisam ser lidos com get(step(N), "files").
Isso vale mesmo quando o código não retornou nada, porque aí result é null, o
que já basta para tomar esse ramo. É por isso que a tabela acima não tem uma
linha para actions/code/execute: ele não tem nem o formato data nem o formato
de raiz.
Seja qual for a forma que você use, um caminho que não existe devolve o valor
padrão em silêncio — step_ok(N) continua true. Nunca confie em uma lista
lembrada de cor: verifique as saídas declaradas da ação
(get_action_definition(actionType), cuja dica STEP OUTPUTS é derivada dessas
saídas, ou a referência da ação) antes de escrever o caminho.
step_error(N)
Obtém informações de erro de um passo que falhou. Retorna {code, user_message, retryable} ou null.
// Antes
coalesce(get(step(0), "executionContext.safeError.code"), "UNKNOWN")
// Depois
step_error(0) // {code: "TIMEOUT", user_message: "...", retryable: true}
get(step_error(0), "code", "UNKNOWN") // "TIMEOUT"
step_has_content(N, path)
Verifica se o passo N foi concluído com sucesso E possui dados presentes (não-null, não-vazio) no caminho dado. Combina step_ok(N) && present(step_data(N, path)) em uma única chamada.
// Antes: duas verificações
step_ok(0) && present(step_data(0, "articles"))
// Depois: uma chamada de função
step_has_content(0, "articles")
O caminho segue exatamente a mesma regra de step_data: relativo a data ou —
nas ações que publicam na raiz — relativo à raiz da etapa.
getContext()
Obtém o objeto de contexto de execução do workflow.
getTool()
Obtém o objeto de contexto da ferramenta em execução no momento — o mesmo contexto que os auxiliares step(N) leem. Não recebe argumentos; quaisquer argumentos passados são ignorados.
getRoot()
Obtém o contexto raiz do workflow.