Documentation

Opérateurs déterministes

Nœuds d'action qui ne passent pas par un LLM — HTTP, DB, transformations, calculs.

Opérateurs

Un opérateur est un nœud qui exécute une action déterministe : pas de LLM, pas d'aléatoire. Pour chaque entrée donnée, la sortie est prévisible.

Pourquoi les utiliser

Toute logique qui peut être écrite explicitement doit l'être. Un LLM qui « calcule un total » ou « formate une date » est un anti-pattern : il est plus lent, plus cher, et peut se tromper.

Règle pratique : si vous savez écrire la fonction en 5 lignes de Python, c'est un opérateur — pas un agent.

Types disponibles

webhook_action (appel HTTP)

Effectue un appel HTTP sortant. Configuration :

  • URL, méthode, headers et paramètres de requête (avec placeholders depuis le contexte)
  • Body : none, json, form, raw, multipart, ou mapper (body composé par le langage de mapping, voir ci-dessous)
  • Authentification : bearer, basic, api_key_header (header custom) ou oauth2 (voir ci-dessous)
  • Statuts HTTP acceptés, délai maximal, et nombre de réessais (retry_count, 0 par défaut, backoff exponentiel)
  • Clé de sortie où la réponse est publiée

database_query / database_manage

database_query lit des lignes dans une base no-code betool ou dans une base externe (Postgres, MySQL, MongoDB) enregistrée dans Applications → Bases de données → Connexions : filtre where, recherche plein texte, limite. database_manage y écrit (create ou update), le contenu étant composé par le langage de mapping.

file_transform

Transforme un fichier. Transformers livrés :

  • pdf_extract_text — texte sélectionnable d'un PDF (pas d'OCR : un PDF scanné ne rend pas de texte)
  • pdf_split — découpe d'un PDF
  • pdf_to_images — rendu des pages d'un PDF en images
  • xlsx_to_json / xls_to_json — lecture d'un classeur Excel en lignes JSON
  • unzip — extraction d'une archive

compute

Calculs déterministes sur les données du contexte. Opérations livrées :

  • column_stats — par colonne d'une liste de lignes, combien valent une valeur donnée (count, total, pct)
  • compose_text — composition d'un texte à partir d'un gabarit et de valeurs du flux
  • regex_extract — extraction de valeurs par expression régulière
  • select_by_substring — répartition d'une liste en groupes selon des prédicats « contient / ne contient pas »
  • list_compare — cohérence de plusieurs listes par clé pivot
  • multi_source_compliance — audit de conformité multi-dimensions et multi-sources
  • contact_extract — adresses email et numéros de téléphone trouvés dans un texte, avec leur provenance
  • free_slots — créneaux libres déduits de périodes occupées
  • url_expand — composition d'URL à partir de bases et de chemins

Langage de mapping

Ce n'est pas un nœud : c'est le langage qui compose un payload de sortie depuis les données du contexte (fonctions $now, $uuid, $concat…). Il sert au body mapper de webhook_action, au contenu écrit par database_manage et aux variables d'un appel sortant phone_call.

data_to_file

Produit un fichier Excel (.xlsx) à partir de données du contexte — une liste de lignes, une grille, ou plusieurs listes (un onglet chacune). Options : nom du fichier (templatable), nom d'onglet, choix et ordre des colonnes, ligne d'en-tête. Le fichier est rangé dans le stockage de votre organisation, prêt à être envoyé par email ou déposé sur un Drive.

Par sécurité, les cellules qui commencent par =, +, - ou @ sont écrites comme du texte par défaut (pas de formule injectée). Quand les limites d'Excel obligent à couper, le fichier est marqué comme tronqué.

web_fetch

Lit une ou plusieurs pages web et publie leur texte lisible dans le contexte (défaut web.pages). Réglages : nombre de pages, concurrence, délai, taille maximale. Le verdict robots.txt est toujours calculé et rapporté ; il n'est appliqué que si vous l'activez (respect_robots).

Les pages rendues uniquement par JavaScript ne sont pas exécutées : seul le HTML servi est lu. Une page en échec est rapportée dans le résultat, sans faire échouer le pipeline.

Côté agent, deux tools équivalents :

  • web_scrape.fetch_page — lit une page (titre, texte, liens email et téléphone trouvés).
  • web_search.search — recherche web via un moteur SearXNG auto-hébergé par la plateforme : jusqu'à 5 résultats (titre, URL, extrait).

Toutes les lectures web passent par la même protection anti-SSRF : adresses internes, privées et de métadonnées cloud refusées après résolution DNS, redirections revérifiées à chaque saut.

code_step

Quand une logique déterministe dépasse ce que compute sait faire, une étape de code exécute du code custom en sandbox Starlark — éditable directement, exécuté dès sauvegarde, et borné par une allowlist de tools. Voir Étapes de code.

Authentification & secrets

Les opérateurs qui parlent à un système externe (HTTP, DB) référencent un compte enregistré dans l'organisation. Les credentials ne sont jamais visibles dans le pipeline lui-même — juste un nom de compte.

Conséquence : changer un mot de passe ne nécessite pas de rééditer chaque pipeline.

OAuth2 sortant (client_credentials)

Pour les APIs qui exigent un jeton OAuth2 (cloud d'entreprise, ERP, providers tiers), l'opérateur HTTP supporte le mode oauth2. Vous enregistrez un credential OAuth2 dans l'organisation — token_url, client_id, client_secret, scope — et le nœud n'y référence qu'un identifiant non secret.

Au moment de l'appel, betool obtient un jeton et le réutilise tant qu'il est valide ; il le rafraîchit paresseusement à expiration, sans tâche de fond. Le client_secret n'est jamais renvoyé en lecture par l'API d'administration (seul un indicateur a un secret est exposé), et le jeton obtenu est posé en Authorization: Bearer … sur la requête sortante.

Changer le secret après une rotation côté provider ne demande aucune réédition de pipeline : le prochain appel rafraîchit automatiquement.

Idempotence

Tout opérateur qui produit un effet de bord (POST HTTP, INSERT DB, envoi d'email) doit être pensé idempotent côté cible. Pratique recommandée :

  • Inclure un idempotency_key dans le payload (typiquement exchange_id).
  • Vérifier côté cible si la clé a déjà été traitée.

En dehors des réessais que vous configurez explicitement sur webhook_action (retry_count), betool ne réessaie pas automatiquement un opérateur qui a échoué : c'est à votre pipeline d'orchestrer la stratégie de retry. webhook_action est de plus protégé contre le double envoi lors d'un re-dispatch interne : une requête déjà livrée avec un statut accepté n'est pas renvoyée.