Documentazione

Operatori deterministici

Nodi di azione che aggirano il LLM — HTTP, DB, trasformazioni, calcoli.

Un operator è un nodo che esegue un'azione deterministica: nessun LLM, nessuna casualità. Per un dato input, l'output è prevedibile.

Perché usarli

Qualsiasi logica che può essere scritta esplicitamente dovrebbe esserlo. Un LLM che "calcola un totale" o "formatta una data" è un anti-pattern: è più lento, più costoso e può commettere errori.

Regola pratica: se puoi scrivere la funzione in 5 righe di Python, è un operator — non un agent.

Tipi disponibili

webhook_action (chiamata HTTP)

Effettua una chiamata HTTP in uscita. Configurazione:

  • URL, metodo, header e parametri di query (con placeholder dal contesto)
  • Body: none, json, form, raw, multipart o mapper (body composto dal linguaggio di mapping, vedi sotto)
  • Autenticazione: bearer, basic, api_key_header (header personalizzato) o oauth2 (vedi sotto)
  • Stati HTTP accettati, tempo massimo e numero di nuovi tentativi (retry_count, 0 per impostazione predefinita, backoff esponenziale)
  • Chiave di output in cui viene pubblicata la risposta

database_query / database_manage

database_query legge righe in un database no-code betool o in un database esterno (Postgres, MySQL, MongoDB) registrato in Applicazioni → Database → Connessioni: filtro where, ricerca full-text, limite. database_manage vi scrive (create o update), con il contenuto composto dal linguaggio di mapping.

file_transform

Trasforma un file. Trasformatori integrati:

  • pdf_extract_text — testo selezionabile di un PDF (nessun OCR: un PDF scansionato non restituisce testo)
  • pdf_split — divisione di un PDF
  • pdf_to_images — rendering delle pagine di un PDF in immagini
  • xlsx_to_json / xls_to_json — lettura di una cartella di lavoro Excel in righe JSON
  • unzip — estrazione di un archivio

Consegna file a terzi tramite link, senza mettere il loro contenuto nel flusso: per ogni file di un elenco del contesto (i file di un download, gli allegati ricevuti, le foto di un'ispezione…), il nodo Link di download produce un link di download firmato con durata di vita limitata. Un passaggio successivo compone ciò che riceve il destinatario: risposta di un webhook in entrata, email…

ImpostazioneRuolo
Elenco dei file da collegare (input_path)Dove leggere l'elenco nel flusso — ogni voce porta path (chiave del file nello storage dell'organizzazione) ed eventualmente un nome di file. Obbligatorio.
Sottocartelle consentite (path_scope)Facoltativo: limita i file firmabili ad alcune sottocartelle dello storage dell'organizzazione.
Durata dei link15 minuti per impostazione predefinita, da 1 minuto a 24 ore.
Numero massimo di file (max_files)20 per impostazione predefinita, 100 al massimo.
Chiave di output (output_key)Predefinita linked.files.

L'output contiene files (ogni voce di origine, arricchita di url e expires_at), file_count, failed, requested e ttl_seconds.

  • Mai fuori dalla tua organizzazione: un file fuori dal suo storage viene rifiutato.
  • Esistenza verificata prima di firmare: un file assente non viene mai firmato.
  • Nulla di omesso: un file non collegato (fuori perimetro, introvabile, oltre il limite, firma impossibile) compare in failed con il suo motivo.
  • I link vengono ricreati a ogni esecuzione, e ogni link emesso viene registrato nel log.

Il link è al portatore: chiunque lo possieda scarica il file fino alla sua scadenza. Mantieni una durata breve, e compila le sottocartelle consentite non appena l'elenco proviene da un dato modificabile (una riga di tabella) — altrimenti chiunque possa scrivere quel dato farebbe firmare un link verso qualsiasi file dell'organizzazione.

compute

Calcoli deterministici sui dati del contesto. Operazioni integrate:

  • column_stats — per colonna di un elenco di righe, quante valgono un determinato valore (count, total, pct)
  • compose_text — composizione di un testo a partire da un modello e da valori del flusso
  • regex_extract — estrazione di valori tramite espressione regolare
  • select_by_substring — suddivisione di un elenco in gruppi secondo predicati « contiene / non contiene »
  • list_compare — coerenza di più elenchi tramite chiave pivot
  • multi_source_compliance — audit di conformità multidimensionale e multi-sorgente
  • contact_extract — indirizzi email e numeri di telefono trovati in un testo, con la loro provenienza
  • free_slots — fasce libere dedotte da periodi occupati
  • url_expand — composizione di URL a partire da basi e percorsi

Linguaggio di mapping

Non è un nodo: è il linguaggio che compone un payload di output dai dati del contesto (funzioni $now, $uuid, $concat…). Serve per il body mapper di webhook_action, per il contenuto scritto da database_manage e per le variabili di una chiamata in uscita phone_call.

data_to_file

Produce un file Excel (.xlsx) a partire dai dati del contesto — un elenco di righe, una griglia o più elenchi (un foglio ciascuno). Opzioni: nome del file (templatable), nome del foglio, scelta e ordine delle colonne, riga di intestazione. Il file viene salvato nello storage della tua organizzazione, pronto per essere inviato via email o depositato su un Drive.

Per sicurezza, le celle che iniziano con =, +, - o @ vengono scritte come testo per impostazione predefinita (nessuna formula iniettata). Quando i limiti di Excel obbligano a troncare, il file viene contrassegnato come troncato.

web_fetch

Legge una o più pagine web e pubblica il loro testo leggibile nel contesto (predefinito web.pages). Impostazioni: numero di pagine, concorrenza, timeout, dimensione massima. Il verdetto robots.txt viene sempre calcolato e riportato; viene applicato solo se lo attivi (respect_robots).

Le pagine renderizzate solo tramite JavaScript non vengono eseguite: viene letto solo l'HTML servito. Una pagina in errore viene riportata nel risultato, senza far fallire la pipeline.

Lato agent, due tool equivalenti:

  • web_scrape.fetch_page — legge una pagina (titolo, testo, link email e telefono trovati).
  • web_search.search — ricerca web tramite un motore SearXNG ospitato dalla piattaforma: fino a 5 risultati (titolo, URL, estratto).

Tutte le letture web passano dalla stessa protezione anti-SSRF: indirizzi interni, privati e di metadati cloud rifiutati dopo la risoluzione DNS, reindirizzamenti ricontrollati a ogni salto.

code_step

Quando la logica deterministica supera ciò che compute può gestire, un code step esegue codice personalizzato in una sandbox Starlark — modificabile direttamente, eseguito non appena salvato e delimitato da una allowlist di tool. Vedi Code Step.

Autenticazione e segreti

Gli operator che comunicano con un sistema esterno (HTTP, DB) referenziano un account registrato all'interno dell'organizzazione. Le credenziali non sono mai visibili all'interno della pipeline stessa — viene referenziato solo un nome di account.

Di conseguenza, la rotazione di una password non richiede alcuna modifica a nessuna pipeline.

Quando un segreto viene inserito direttamente in un nodo (token bearer, password basic o valore api_key_header di webhook_action, password di un PDF o di un archivio cifrati per file_transform), viene mascherato non appena salvato: l'editor, l'API e gli strumenti MCP ne mostrano solo un marcatore. Vedi L'editor visuale, sezione Segreti.

OAuth2 in uscita (client_credentials)

Per le API che richiedono un token OAuth2 (cloud enterprise, ERP, provider di terze parti), l'operator HTTP supporta la modalità oauth2. Registri una credenziale OAuth2 nell'organizzazione — token_url, client_id, client_secret, scope — e il nodo referenzia solo un identificatore non sensibile.

Al momento della chiamata, betool ottiene un token e lo riutilizza finché resta valido; lo rinnova in modo lazy alla scadenza, senza task in background. Il client_secret non viene mai restituito dall'API di amministrazione (viene esposto solo un indicatore has_secret), e il token ottenuto viene posto come Authorization: Bearer … sulla richiesta in uscita.

La rotazione del segreto dopo una rotazione lato provider non richiede modifiche alla pipeline: la chiamata successiva si rinnova automaticamente.

Idempotenza

Qualsiasi operator che produce un effetto collaterale (POST HTTP, INSERT DB, invio email) deve essere progettato per l'idempotenza lato destinazione. Pratica consigliata:

  • Includi un idempotency_key nel payload (in genere exchange_id).
  • Verifica lato destinazione se la chiave è già stata elaborata.

Al di fuori dei nuovi tentativi che configuri esplicitamente su webhook_action (retry_count), betool non riprova automaticamente un operator fallito: è responsabilità della tua pipeline orchestrare la strategia di retry. webhook_action è inoltre protetto contro il doppio invio in caso di re-dispatch interno: una richiesta già consegnata con uno stato accettato non viene reinviata.