AI nodes and the assistant
The AI nodes, the heuristic each falls back to, Assess, the flow copilot and the workspace assistant.
OrderLoop uses Workers AI in three places: the AI nodes in a flow, the flow copilot, and the workspace assistant. The AI nodes and the copilot share the same guarantees:
- Structured answers. Every call asks for JSON in a fixed schema, at a low temperature
(
0.2, at most 2048 tokens). - Answers are checked. An answer that doesn’t match its schema counts as a failure, so the fallback below applies.
- A 20-second cap. A slower call is abandoned.
- A deterministic fallback. When AI is unavailable, or the model errors, times out or returns nothing, a heuristic produces the result instead. An order never stalls on the model.
- The source is recorded. Each AI node’s output carries
source: "model"orsource: "heuristic"; the Extract order and Demand forecast summaries show it too.
By default the AI nodes and the copilot use @cf/meta/llama-3.3-70b-instruct-fp8-fast, the
assistant @cf/moonshotai/kimi-k2.6, and Assess @cf/cloudflare/clef. Your OrderLoop
administrator can change them for the workspace.
AI nodes
Section titled “AI nodes”Each node’s output is in nodes.<id> for later expressions, along with source.
| Node | Model task | Fallback | Result |
|---|---|---|---|
| Extract order | Read documentText (or the order’s document at documentKey) and map items to catalog SKUs |
Regexes for 120 x WID-100-style lines and SKU … qty N, PO #…, From: … |
When it finds known SKUs, replaces the order’s lines with them; sets customerId when the order had none and customerName matches exactly one customer’s name, ignoring case and punctuation (a near match or several matches attach nobody); titles the order PO <number> on b2b and procurement orders and Ref <number> on the rest, sets vars.poNumber. With no document it passes the order through. The model reads the first 20,000 characters |
| Classify | Pick one of labels with a confidence |
Keyword match on the title and lines; the first label otherwise | Sets vars.<into> (default category). A label outside the list becomes the first label |
| Risk score | Score fraud and credit risk 0–100 with up to three reasons | 10, +15 for a guest (a contact, no customer), +30 with neither, +30 over 20,000, +20 for a line over 1,000 units |
Takes high at or above threshold (default 70), else low; sets vars.risk |
| Demand forecast | Suggest quantities for SKUs whose available stock (stock minus reserved) is at or below their reorder point, over horizonDays |
Each low SKU’s reorderQty |
Replaces the order’s lines; sets vars.supplier from the first SKU. With nothing low it reports “Stock is healthy” without calling the model |
| Summarize | Two sentences on the order and its progress | <model label> order <id>: N lines, total … <currency> |
Sets vars.<into> (default summary) |
| Agent router | Follow instructions and choose exactly one of routes, with a one-sentence reason |
No lines → ask_customer (the last route if there is none by that name); total over 10,000 USD → needs_approval (the first route if none); else the first route |
Takes the chosen route as its branch; a route outside the list becomes the first route |
The router’s routes are its outputs, so editing routes changes the handles on the canvas.
The model sees the order, the customer record, the run variables and the outputs of completed
nodes.
Assess
Section titled “Assess”Assess (ai.assess) asks Clef, a multimodal decision model, typed
questions about the order and gets a probability for every allowed option, not just a pick. It
reads a state (the order as text/JSON) and up to 4 images. It has the same 20-second cap and
heuristic fallback as the other AI nodes. Clef has no video input, so video can’t be assessed.
questions maps a question id (letters, digits, _ . -, up to 100 characters) to one of three
types, with 1 to 64 questions per node:
| Type | criteria |
Answer |
|---|---|---|
noul |
Optional | noul: the probability of yes |
choice |
Option id → description, 2 to 255 options | choice (the most probable option), probabilities per option and confidence |
score |
An ordered list of 2 to 10 levels, lowest first | score (the probability-weighted level, from 0), legend, probabilities per level and confidence |
instructions is text, or an object or list that holds the question with data it refers to.
Answers are held to the questions asked: unknown ids and options are dropped, probabilities are
renormalised to sum to 1, the chosen option and the score are recomputed from them, and a question
the model skipped gets an uninformed answer (noul 0.5, uniform probabilities).
The node’s other fields:
branchOnnames onenoulorchoicequestion (scorecan’t branch; saving a flow with such a name is a validation error). A choice’s options become the node’s outputs, anoulgivesyes(at or above 0.5) andno. EmptybranchOngives oneoutoutput.minConfidence(0 to 1, default 0). Above 0 adds anunsureoutput, taken when the branch question’s confidence is below it. Anoul’s confidence is|2p − 1|.state:ordersends the order alone;order_and_context(default) adds the customer,varsand the outputs of completed nodes.images: up to 4 references. An entry that is exactly{{path}}takes the value there as is, a string or a list ({{order.meta.photos}}); any other entry is interpolated.into(defaultassessment):vars.<into>holds the answers by question id.
An image reference is one of:
- a document key under
orders/<orderId>/, this order’s own documents only; - an
httpsURL (10-second fetch); - a base64
data:URL.
http and any other scheme are refused. Only PNG, JPEG and WebP are accepted, up to 4 MiB each and
8 MiB in all. A reference that can’t be used is skipped and reported in the output’s notes
instead of failing the node.
The output, in nodes.<id>, is { answers, images, notes, usage, source }, where images is the
number used. Later nodes can read the answers, for example in a
Condition expression:
{ ">": [{ "var": "vars.assessment.urgent.noul" }, 0.8] }{ ">=": [{ "var": "vars.assessment.route.probabilities.needs_approval" }, 0.3] }Without the model, a noul is 0.5, a score is uniform over its levels, and a choice leans
toward the option whose id and description share the most words (4 letters or more) with the state.
The flow copilot
Section titled “The flow copilot”The copilot proposes a whole graph. It is reachable from Describe it when creating a flow and, in the editor, through the assistant. The model gets the node catalog (types, outputs, config fields) and the graph rules, and returns a complete graph plus an explanation. OrderLoop then fills each node’s missing config from its defaults, keeps existing nodes’ positions (laying the graph out again only when nodes were added), and validates the result.
In the editor the result is a proposal: it shows the explanation and what it adds, removes, edits and rewires, and the graph changes only if you accept it. Accepting doesn’t publish.
Without the model, the copilot understands one sentence shape, “add a node label after node id or label” (“fraud” or “risk” mean Risk score; “the”, “a” and “an” are ignored), and splices the node into that node’s outgoing edges.
The assistant
Section titled “The assistant”The workspace assistant is the chat panel available on every page. It holds
a multi-turn, tool-calling conversation, with up to 6 tool steps per message, and offers only the
tools your role can use. Its assess_order tool runs the same Assess call as the node on one order
(questions, optional images) and returns the probabilities; its propose_flow_change tool uses
the copilot above. Without the model, a rule-based fallback takes the turn; see
Without the model.