Skip to content

D04 — A flower order, priced, confirmed and painted

A flower shop in Milan sells online to customers who write from Munich, London or around the corner. Every order needs a confirmation that is right to the cent and reads naturally in the customer’s language; and some orders are gifts, which travel with a card. This workflow prices the order with rules, writes every amount and the delivery day the way the customer reads them, lets an AI write the message around those facts — and, when the order is a gift, paints a card of the bouquet that was actually ordered and writes the customer’s own words on it by hand.

A greeting card in watercolour: pink peonies and sprigs of eucalyptus in an amber glass vase on cream cotton paper, and below, in blue handwriting, “Cara Giulia, buon compleanno! Che quest’anno fiorisca come queste peonie. Un abbraccio da Monaco, Lena”

The card of the first reference run: the order was twelve pink peonies, two sprigs of eucalyptus and an amber blown-glass vase — and that is what is painted. The message is Lena’s, word for word, set in the Caveat handwriting font.

Order Customer Priced Confirmation Card Credits
Gift, inner districts Lena, de-DE 69.90 + delivery 9.00 = 78.90 in German painted 5.03
No gift, province, 10 % coupon James, en-GB 80.60, delivery free, − 8.06 = 72.54 in English skipped 0.02

The two confirmations, as the AI wrote them:

Liebe Lena,
Deine Bestellung ist unterwegs und wird am Samstag, 3. Oktober 2026 geliefert:
• 1 Strauß rosa Pfingstrosen (12 Stück)
• 2 Zweige Eukalyptus
• 1 bernsteinfarbene Vase aus mundgeblasenem Glas
Eine handbemalte Karte liegt den Blumen bei.
Zwischensumme: 69,90 €
Lieferung: 9,00 €
Gesamt bezahlt: 78,90 €
Herzlich,
Fiori di Brera
Hello James,
Your flowers are on their way for delivery on Monday, 5 October 2026:
- 1 large bunch of mixed ranunculus
- 7 white garden roses
Subtotal: €80.60
Delivery: free
Discount: €8.06
Total paid: €72.54
Warm wishes,
Fiori di Brera

Both runs, with their priced lines, are in the runs’ outputs.

The shop’s web store sends each order as one JSON document: the lines with their quantities and unit prices, the delivery day and zone, the customer’s language, a coupon when there is one, and a gift section with the occasion and the message when the customer asked for a card. The shop’s rules are simple and must be applied exactly: delivery costs 6 € in the city centre, 9 € in the inner districts, 15 € in the province and 22 € anywhere else, and it is free when the flowers come to 80 € or more; a coupon takes a percentage off the flowers.

{
"order_id": "FDB-2026-10417", "currency": "EUR",
"customer": { "name": "Lena Hoffmann", "locale": "de-DE" },
"delivery": {
"date": "2026-10-03", "zone": "semicentro",
"recipient": "Giulia Ferri", "address": "Via Solferino 12, 20121 Milano"
},
"lines": [
{ "item": "Peonie rosa, mazzo da 12", "qty": 1, "unit_price": 42.0 },
{ "item": "Rami di eucalipto", "qty": 2, "unit_price": 4.5 },
{ "item": "Vaso in vetro soffiato color ambra",
"qty": 1, "unit_price": 18.9 }
],
"gift": {
"occasion": "birthday",
"message": "Cara Giulia, buon compleanno! Che quest'anno fiorisca come queste peonie. Un abbraccio da Monaco, Lena"
}
}
Input Who provides it Example
Order the web store, one document per order above; James’s order has coupon_percent and no gift
  • Numbers come from rules, never from the AI. Each line is priced by Calculate inside an iteration, the lines are collected and summed, the zone fee is chosen by Select by Key from four number constants (an unknown zone takes the highest), delivery becomes free with if(subtotal >= 80, 0, zone_fee), and a missing coupon is read as 0 by Extract with a default. The total is exact decimal arithmetic.
  • Written the way the customer reads it. Format as Text turns each amount and the delivery day into text in the order’s own language — its locale input is connected to the customer’s language, so 78.9 becomes 78,90 € for Lena and 72.54 becomes €72.54 for James, and 2026-10-03 becomes Samstag, 3. Oktober 2026. The same node writes the priced lines as compact JSON for the prompt, and the gift flag as a sentence.
  • The AI writes around the facts, not the facts. The confirmation’s prompt lists the formatted facts and tells the model to copy every amount and date character for character. The AI’s work is the part it is good at: a warm message in German or English, the Italian product names translated (Peonie rosa → rosa Pfingstrosen, Ranuncoli misti → mixed ranunculus), “free” instead of €0.00, no discount line when there is none.
  • An optional part costs only when it is asked for. Extract reads gift.message with on_missing: absent: when the order has no gift section, the message is rejected and every step that needs it is skipped. The card’s AI prompt and image do not need the message, so a Filter on Extract’s found puts them behind the same decision — without a gift, the card costs nothing, and James’s run costs two hundredths of a credit.
  • Generated, but faithful to the order. The card is not a stock bouquet: an AI turns the priced lines into an image prompt — these flowers, this vase, in their colours, the lower half left blank — and the image model paints it. The message is then set on the blank half by Text Overlay in an exact font, so the customer’s words are never retyped or “improved” by a model.

The workflow in four stages. 1, read the order: the web order with its lines, zone, coupon, language and gift; the runs are in de-DE and en-GB. 2, price it by rules, not by AI: lines and subtotal by Calculate per line, Aggregate and sum, 69.90 and 80.60; delivery, a fee per zone, free from 80, 9.00 and free; coupon and total, no coupon is 0 percent, 78.90 and 72.54. 3, write it the customer’s way: the amounts and the date as text in the order’s language, 78,90 € and €72.54; the confirmation, where the AI copies the facts and recomputes nothing, in German and English. 4, only a gift gets a card: is it a gift?, the card message is absent when not, yes for Lena and no for James; yes leads to the painted bouquet, a watercolour of what was ordered, 5 credits, and to the handwritten message, the customer’s words in Caveat, skipped for James.

The figure tells the workflow as stages, with the reference runs’ results on the cards; the exact graph is the workflow (as a diagram), node by node in the table.

Node Type Why
Order input/json_value The whole order as one document; it never iterates
Each line / Line total / Priced lines / Subtotal enumerate/json, utility/calculate qty * unit_price, aggregate/json, utility/calculate sum(priced_lines[*].line_total) Every line priced, then added up
Delivery zone, Customer name, Customer language, Currency, Delivery date utility/extract, expected_type text The fields the rules and the message need, typed
City centre fee … Any other zone utility/constant, type number The shop’s fees, as values to choose from
Fee for the zone utility/select_by_key, number, use_default The fee of the order’s zone; 22 € when the zone is unknown
Delivery / Discount / Total utility/calculate if(subtotal >= 80, 0, zone_fee), round(subtotal * coupon / 100, 2), subtotal - discount + delivery
Coupon percent utility/extract, on_missing: default 0 No coupon is 0 percent
… as text text/format: currency with locale and currency connected; date full; json compact; auto for the gift flag Every fact written for the reader
Confirmation facts / Confirmation message text/template, ai/text_generation with low reasoning effort The facts in a list; the message around them
Card message utility/extract gift.message, on_missing: absent Present only for a gift; its absence cuts the card
Only for a gift / Card brief / Card illustration prompt utility/filter on found, text/template, ai/text_generation The image prompt, written only for a gift
Watercolour card / Handwritten message ai/text_to_image 3:4, image/text_overlay with Caveat The painted bouquet, then the customer’s words
Outputs output/text, output/json ×2, output/image The confirmation, the total, the priced lines, the card

Reading a run: Total is the number to charge; Priced lines shows how it was reached. Without a gift, Card comes back absent and the trace shows the card’s prompt, image and lettering as skipped.

Cost: the image of the card is almost the whole bill, about 5 credits; the two short AI texts cost under two hundredths each, and everything else — pricing, formatting, deciding — is free. An order without a gift costs about two hundredths of a credit.

The example installs into your workspace with an API key, through the public API only — see Installing an example:

Terminal window
node madoo-install-example.mjs d04-florist-order --api <your Madoo API URL> --key <key.json> --run

--run prices Lena’s gift order and paints its card (about 5 credits). James’s order is in run-inputs-no-gift.json.

  • Your rules: the fees are constants and the threshold is in the Delivery expression; VAT, a minimum order or a surcharge for Sundays are one more Calculate each.
  • Your shop’s voice: the confirmation’s system prompt holds the tone and the rules the AI must keep; the facts stay in the template.
  • Other currencies: the order’s currency is already connected to every amount; a Swiss order in CHF with de-CH is written the Swiss way.
  • Another card: the style lives in the illustration prompt (pencil, gouache, pressed flowers), the lettering in the Text Overlay typography — another font, colour or position.
  • Other domains: the same shape serves a restaurant booking with a deposit, a print shop’s quote, an event ticket with an optional printed pass.

manifest · workflow · the complete graph