Scripting in Flows
Declarative extractions and assertions (body path / header / status, equals/contains/exists/…) cover most flows. When you need something they can't express — a computed value, a hash, a loop over the response body, a multi-field check — drop down to JavaScript using the same Scripting engine and pro.* API the rest of Probe uses.
Script node
Section titled “Script node”A Script node runs a JS snippet through Probe's embedded QuickJS engine — the same sandbox, limits, and pro global documented in Scripting and the API Reference. It has one in-port and one out-port, and its inspector is a plain code editor.
Reading upstream data: every upstream node's outputs are flattened into the script's variable scope as <nodeName>.<key>, alongside the active environment/globals and (inside a loop body) the current loop scope. Read them with pro.variables.get(...):
const token = pro.variables.get('login.outputs.token');const cartTotal = pro.variables.get('getCart.body.total');Publishing outputs: anything you set with pro.environment.set(...) becomes one of the node's outputs, readable downstream exactly like a declared extraction — {{scriptNode.outputs.key}}:
pro.environment.set('signature', pro.crypto.sha256(token + ':' + Date.now()));console.log (and warn/error/table/etc.) calls inside the script show up as console logs in that node's row of the run report — handy for debugging without adding extra extractions just to inspect a value.
Script assertions
Section titled “Script assertions”On a Request node, each assertion can be either Value (the declarative source/operator/expected form) or Script. A script assertion runs in test mode against that node's response, after any declarative assertions on the same node, using pro.test/pro.expect:
pro.test('id is a positive integer', () => { const id = pro.response.json().data.id; pro.expect(id).to.be.above(0);});A failing pro.test fails the node the same way a failing declarative assertion does — downstream nodes that depend on it are skipped.
The headless limitation
Section titled “The headless limitation”Script nodes and script assertions need the app's embedded JavaScript engine, which only exists inside the running Probe UI. When a flow runs headlessly — the probe_flow CLI, or a bare dart VM — there is no engine wired up, so a script node fails with script engine unavailable and script assertions produce a failed outcome with the same message, rather than throwing or silently passing. See Running in CI for what that means for flows you plan to automate.