Aller au contenu principal
Version: Cible · roadmap

Le submit

Le submit termine le playbook : il évalue son submit guard, exécute les écritures réservées dans l'ordre — les appels des skills et ceux du playbook —, et ferme le parcours.

    submit_guard:
form: {accept_terms: {type: boolean, required: true, label: "J'accepte les conditions générales"}}
confirm: true
guards: [{policy: commande-inhabituelle}]
submitted_by:
- {who: agent, when: "total <= 50 and agent.mode == 'autonomous'"}
- {who: {role: support-manager}, when: "total > 50"}
- {who: owner}

submitted_by — qui peut soumettre​

Des règles dans l'ordre ; la première qui correspond s'applique.

whosens
ownerle propriétaire vérifié de la room : une personne dont l'identité a été prouvée par un fournisseur (Identité). Un numéro seulement tapé ne suffit pas
principalla personne qui a envoyé l'agent
user.approverl'autorité au-dessus du user : l'approbateur fixé par l'organisation cliente (product), son manager (process)
{role: x}un user qui a ce rôle
agentl'agent lui-même

Tous sont des users. Un admin n'approuve et ne soumet jamais une action métier. Voir Human In The Loop.

  • Sans submitted_by, un humain dans la room soumet, même anonyme : le clic du client. C'est le comportement d'aujourd'hui. Exiger owner ferme ce passage à quiconque ne détient que le code de la room.
  • Pas d'autonomie sans condition : une règle who: agent sans when est refusée au chargement. Une règle agent qui couvre une écriture high et irréversible donne un avertissement.
  • Évalué par Core, au moment du submit. Ni cacher ni montrer un outil ne donne ou ne retire ce droit.
  • Le reçu dit qui a soumis, et sous quelle règle.

Quand plusieurs couches s'appliquent (le playbook, une sous-identité, un profil), la plus stricte gagne : si l'une exige un humain, c'est un humain.

Une commande se déclare sur le playbook​

Un appel vit là où vit ce qu'il dépose :

  • Un appel qui dépose une action d'une skill — un remboursement, une livraison, un retrait — vit sur la skill ou sur son kind (Skills).
  • Un appel qui envoie en une requête les lignes de plusieurs tâches — une commande : les plats, la boisson, les couverts, dans un seul placeOrder — se déclare une seule fois, sur le playbook, dans submit, à côté de son submit_guard.
  • Une skill utilisée hors de tout playbook garde tous ses appels.
playbooks:
- name: take-meal-order
tasks:
plats: {skill: takeMealSelection}
boisson: {skill: takeDrinkSelection, after: [plats]}
submit:
- name: order
tool: placeOrder
args:
body.items: "$selection[task=plats,boisson]"
body.customer.phone: "$submit.phone"
body.idempotency_key: "$action.key"
line: {product_id: "$line.ref", quantity: "$line.quantity", variant_id: "$line.fields.variante"}
extra_lines:
- {ref: couverts-avec, quantity: "$submit.couverts", when: "$submit.couverts > 0"}
- {ref: couverts-sans, when: "$submit.couverts == 0"}
output: {order_id: {from: "$output.id", type: id}}
submit_guard:
form:
phone: {type: phone, required: true, label: "Téléphone"}
couverts: {type: quantity, required: true, label: "Combien de couverts ?"}
  • Les lignes se prennent par tâche : $selection[task=plats,boisson] envoie les lignes de ces deux tâches ; $selection[kind=dish] celles d'un kind, parmi les tâches du playbook. $selection seul est refusé dans un appel du playbook : ce qu'il enverrait dépendrait des lignes présentes dans la room.
  • Une ligne part par un seul appel. Dans un playbook dont un appel prend les lignes d'une tâche, les appels de la skill de cette tâche ne s'exécutent pas pour ces lignes : c'est l'appel du playbook qui les envoie. Hors de ce playbook, la skill garde ses appels.
  • Une ligne qu'aucun appel n'envoie est refusée : au chargement, une skill dont les lignes ne partent par aucun appel — ni le sien, ni celui d'un playbook qui l'utilise ; au submit, une ligne choisie hors d'un playbook par une skill qui n'a pas d'appel à elle est retenue, avec la phrase qui dit d'ouvrir le parcours. Elle ne part jamais nulle part.
  • Un appel du playbook ne lit pas $item : il envoie plusieurs lignes. Ce qui vient d'une ligne passe par line: ; ce qui vient de la personne, par le formulaire du submit ($submit.<champ>).
  • Il se cite par son nom seul : $submitted[order].order_id. Un appel d'une skill se cite par sa tâche et son nom ($submitted[geste.pay]). Les noms des appels d'un playbook sont uniques dans ce playbook. Une tâche dont les params lisent $submitted[order] attend les tâches dont l'appel prend les lignes.
  • Deux playbooks qui passent la même commande la déclarent chacun : chaque submit a son appel, jamais deux copies d'un même appel dans un même submit. Une ancre YAML (&order, *order) évite de la recopier.

line: — la forme d'une ligne​

line: dit à quoi ressemble une ligne pour le tenant. Il se déclare sur l'appel qui envoie les lignes : celui du playbook, ou celui d'une skill.

formeenvoie
line: {product_id: "$line.ref", quantity: "$line.quantity"}un objet par ligne, avec les noms du tenant
line: "$line.ref"la référence seule, pour un tenant qui attend une liste d'identifiants
rien{slug: "$line.ref", qty: "$line.quantity"}, la forme de Convoy

Les sources : $line.ref (la référence de l'item), $line.quantity, $line.price (le prix facturé de la ligne), $line.fields.<champ> (un champ de la ligne). Tout est vérifié au chargement :

  • $line.fields.<champ> doit être un champ déclaré du kind de la ligne : un champ de present.fields ou un champ de ligne. Un nom qu'aucun kind des lignes de l'appel ne déclare est refusé.
  • Une clé dont la source n'existe pas sur une ligne est omise, jamais envoyée vide : un champ facultatif sans réponse, un champ que le kind de cette ligne n'a pas.
  • La forme "$line.ref" est refusée sur une tâche qui a des quantités : la quantité serait perdue.
  • Vérifiez line: contre le schéma du tenant. Une clé qu'il ne connaît pas, il l'ignore et applique sa valeur par défaut, sans erreur : sans line:, un tenant qui attend quantity reçoit qty et livre une seule pièce.

extra_lines — des lignes envoyées sans être choisies​

Certaines lignes partent avec la commande sans que personne les choisisse : les couverts, quand le restaurant les tient comme deux produits à 0 F.

        extra_lines:
- {ref: couverts-avec, quantity: "$submit.couverts", when: "$submit.couverts > 0"}
- {ref: couverts-sans, when: "$submit.couverts == 0"}
  • ref est une référence du catalogue du tenant. quantity est de type quantity : un nombre, ou $submit.<champ> ; 1 sans elle. Une quantité qui n'est pas un entier positif retient l'appel, avec la phrase qui le dit : jamais une ligne à 0.
  • when s'écrit dans le langage des conditions. C'est le seul endroit où une condition lit $submit.<champ> : un champ du formulaire du submit_guard du même playbook, ou de celui de la station pour l'appel d'une skill hors playbook (vérifié au chargement). Un champ de ce formulaire lu comme une quantité refuse un nombre négatif : aucun when ne laisse alors une commande partir sans la ligne prévue.
  • Les lignes ajoutées rejoignent les lignes de l'appel : il en prend par une source $selection[…], sinon il est refusé. Elles ont la forme de son line: ; une ligne ajoutée n'a que ref et quantity, et les clés qui lisent $line.price ou $line.fields y sont omises.
  • Une ref doit exister chez le tenant. Le provisioner le vérifie à chaque provisionnement. Une ref absente est une erreur de provisionnement : la station ne part pas, plutôt que d'envoyer une ligne fantôme. Par quelle lecture du tenant il le vérifie n'est pas encore fixé : une ligne ajoutée n'a été montrée par aucune skill.

L'exécution​

  • Dans l'ordre : un appel qui lit $submitted[…] part après celui qu'il lit ; sinon, les appels des tâches dans l'ordre des tâches, puis ceux du playbook dans l'ordre où il les écrit. Les irréversibles en dernier.
  • Une écriture qui lit le résultat d'une écriture échouée est mise en attente, jamais exécutée sur une valeur vide.
  • Idempotence par action ($action.key) : une nouvelle tentative, un double clic, une automatisation déclenchée deux fois ne produisent qu'un seul effet.
  • Échec partiel : ce qui est exécuté le reste. Annuler passe par l'opération déclarée en reversible, comme une action explicite.

Un sous-playbook a son propre submit​

Son submit n'exécute que ses actions. Le parent reprend avec son résultat. Voir Playbooks.