Skip to main content
Version: Current

The submit

The submit: what execution does​

The submit of a skill with kinds is a list of named calls. A kind can have its own, in kinds.<kind>.submit.

    submit:
- name: dispatch
mode: request # request (default) | handover | self
tool: createDelivery
args:
body.address: "$item.fields.address"
body.items: "$selection[kind=dish]"
body.fee: "$item.price"
body.idempotency_key: "$action.key"
line_fields: {ref: slug, quantity: quantity}
keymeaning
namethe call's name: letters, digits, _, -. Unique among a skill's calls (its own and its kinds'). Required
moderequest by default; see the table below
toolthe operation called. Required for a request: without it, the station is refused
urlthe tenant's link, for a handover
argsthe operation's inputs (body.x, query.y) and their sources
outputwhat the call keeps of the tenant's answer, for a later call
line_fields, line_shapethe shape of a line sent to the tenant
modemeaningwhat is sent
requestConvoy calls an operation of the tenanttool with args
handoverthe person finishes on the tenant's sitenothing; they receive the declared url link
selfthe person takes care of it themselves (pickup at the counter)nothing; it is recorded

One call per skill or per kind, today. A list of two calls is refused at load. To chain two writes, use two skills, each with its call and each the task of a playbook, and have the second read the first with $submitted[…]. See Current limits.

The sources of args.

writegives
$selectionthis skill's lines, one per item
$selection[kind=X]the lines of kind X, across the whole selection — filed only if this operation succeeds; otherwise they stay in the selection
$item.fields.<field>a filled-in field of the item
$item.pricethe amount computed by the update: {price: …} guard
$item.refthe item's reference at the tenant
$submitted[<task>.<call>].<output>an output of another call in the same submit — see below
$params.<name>a parameter of the skill: the binding a task of the active playbook gives it, else its default — see below
$action.keythe idempotency key of the action this call files
$submit.<field>what the person answered in the submit guard's form, or what the room already knew for an identifies field (Auth)

Reading another call: $submitted and output​

skills:
- name: formation
invoke: {method: recommendLegalStructure}
kinds: {company_formation: {}}
submit:
- name: open
tool: openFormationDossier
args: {body.idempotency_key: "$action.key"}
output: {company_id: "$output.company_id"}
- name: accounting
invoke: {method: getAccountingPlans}
kinds: {accounting_subscription: {}}
submit:
- name: subscribe
tool: subscribeAccounting
args: {body.company_id: "$submitted[societe.open].company_id"}

playbooks:
- name: open-company
tasks:
societe: {skill: formation}
compta: {skill: accounting, required: false, after: [societe]}
  • The task is a playbook's: $submitted[societe.open] cites the call open of the skill formation, whose task is societe. Written on a skill's call, the reference holds for the whole station (a skill belongs to no playbook): two playbooks may share a task name if it designates the same call; a name two playbooks give to two different calls is refused when read. It does not place the task it reads first: write the after.
  • A choice is one reference. Two methods of one one_of may each have a call of the same name (pay for the refund and for the credit note): $submitted[geste.pay] reads the method that was filed.
  • Only what output declares can be read. An output is $output (the whole answer) or $output.<path> (a path into the answer). The rest of the answer is kept for no one.
  • Only a request has an answer. output on a handover or self call refuses the station, as does a reference to such a call.
  • Checked at load. Citing a call no task runs (a skill's name where a task's is meant, a skill that is the task of no playbook), an undeclared call, an undeclared output, the call's own answer, or any form other than $submitted[<task>.<call>].<output> refuses the station. An output nothing reads gives a note.
  • At execution, the call that reads another runs after it. If the cited call failed, if the reference cannot be answered, or if two methods of one choice answer it, the dependent call is put on hold (receipt held, with waits_for): it is never filed with a blank value. The same for a line whose stored call reads a source Core does not know: it is put on hold, never sent with that source as its own text; it has to be chosen again.
  • If the cited task has nothing in the selection, the reference is empty: the tenant applies its own default (the SIREN, for example).
  • A retry inside a journey reads what this journey already filed, from the room's record: after a partial submit (the company opened, the accounting refused), the accounting is linked to the company the first submit opened. What an earlier journey filed is never read. If that record cannot be read, the call depending on it is held ("… cannot be read right now — try again in a moment"), never sent blank; if the journey itself cannot be read, the submit is refused. Outside a journey, only an answer whose filed lines are still in the selection is read again.

$params at submit​

A submit call reads a parameter of its skill with $params.<name> in its args. Its value is the binding a task of the active playbook gives it, for the line's method (A task's params), else the parameter's default.

  • A binding leaves with the answer of the call it reads, in the same submit, after it.
  • A binding has no fallback. If nothing in this submit or earlier in this journey answered it (the gesture's line left the selection), or if the call it reads failed, the call is put on hold.
  • Neither a binding nor a default: the call is put on hold, with the reason — "… reads $params.refund_id, which nothing sets here — no task of the active playbook binds it, and it has no default". That is the case of a skill run outside the playbook that binds its parameter.
Idempotency: $action.key, never $item.id

$item.id is the catalogue reference, the same for every customer who chooses this item. A tenant that deduplicates on it gives the second customer the first customer's order, with ok: true. $action.key comes from the room and the lines the call files; it stays stable for a retry. Two lines filed by two calls get two keys. Several lines filed by one call (three dishes ordered together) are one action and share one key.

line_fields — what the tenant calls a line's reference and quantity. By default, Convoy sends {slug, qty}. If the tenant's schema expects quantity, its API ignores an unknown key: it orders 1 for a customer who wanted 2, with no error. Check its schema.

line_shape: ref — for a tenant that expects a list of identifiers (timesheet_ids: [..]). Refused on a part that has quantities.

handover — the URL is the tenant's, with a closed set of placeholders: {tenant_url}, {items}, {room}. An unknown placeholder makes the station refuse to start.

The conditions to meet before executing — the submit guard — are in Policies.