Skip to content

Test runs ​

A test run executes the draft of a workflow on real data — a real email from your mailboxes, a JSON body you write, or the latest item of a connected service — but without its effects: nothing is sent, moved, written or posted. Reads, on the other hand, are real, and AI models are really called. A test run shows exactly what the workflow would do, step by step, with the data each step produces.

Test runs are what you use to build a workflow. The workflow does not need to be published, and testing never changes the published version.

Starting a test run ​

In the editor, a test run starts from:

  • Test workflow in the header: runs the whole draft. While it runs, the button shows "Test running…".
  • Test on a trigger (on the canvas, or in its panel), or "Test with this email" for an email trigger: runs the branches of that trigger.
  • Test up to here on any node (the node's panel, the canvas menu, or the keyboard shortcut Mod+Enter): runs only that node and the nodes it depends on, then stops. Use it to check one step without running the rest of the graph.

Before every test run, the editor saves the draft. If the save fails, the test does not start: "The test run did not start: the draft could not be saved."

What blocks a test run. A draft with blocking errors cannot be tested: the Test panel shows "The test did not run: the draft has blocking errors" and the list of nodes to fix — click a row to open the node. Warnings do not block. A disabled node can't be the target of "Test up to here", and neither can a model provider node (it never runs on its own: wire it to an AI node).

Which trigger. When the draft has several triggers, only the branches of the trigger you test from run. If they are of different kinds (an email trigger and a webhook trigger, for example), choose it under "Test from". Disabled triggers can still be tested.

What a test runs on ​

Each kind of trigger needs a different input:

TriggerInput of the test run
Email received, Manual runthe active test email, a real email from one of your mailboxes
Webhook receiveda test body: the JSON a caller would send, placed under data.webhook
Called by a workflowa test body: the JSON a calling workflow would pass, placed under data.input
MyNotary — event, Yousign — event, Notion — eventa test body, placed under the trigger's own key (data.mynotary, data.yousign, data.notion)
Airtable row changed, Notion entry changedthe service is really queried and the most recent row or entry is used; nothing to provide
Schedulenothing: the run is replayed now, with no input

A test body is limited to 256 KB, like a real webhook call. "Restore the example" puts back the sample body.

For polling triggers, the test never moves the trigger's position: what the test shows will still be processed by the real checks once the workflow is published. If the service query fails (revoked connection, deleted base), the test reports the real reason instead of running on nothing. If nothing is found, the test runs with empty data.

The test email ​

For email triggers, a test run replays one real email of your mailboxes — including the history imported when you connected the mailbox. Choose it in the Test email dialog:

  • Your test emails: up to 20 emails kept for this workflow ("{count}/{max} emails kept"). They are kept with the workflow, so you find them again later.
  • Only one is active at a time — "that is the one “Test” replays, always without sending anything for real". Click "Make active" to switch; "Remove from the list" to drop one.
  • Add an email from your mailbox: search the mirror (filter by typing two characters or more), then keep the email.
  • From the webmail, "Keep as test email" adds the open email to the list of a workflow.

If you click Test with no active test email, the editor asks you to pick one first ("Pick the active test email before running a test."). The email must belong to one of your own mailboxes. An email deleted from the mirror disappears from the list.

Through the API: GET and PUT /api/v1/workflows/:id/test-messages read and replace the list ({ "messageIds": [ … ] }, 20 at most).

Reading a test run ​

Each step of the test shows, on the canvas and in the Test panel:

  • its status and the output port it took ("Output: {port}") and its duration;
  • Produced data: the data the step published, the same data the next nodes read with expressions. Very large data is truncated in the preview ("Data truncated — too large for the preview.");
  • what the step would have done: "Would have: {description}" for each effect it held back — for example the message it would have sent, with its recipients, or the request it would have made.

The steps appear as they finish. A test run is also an entry in the workflow's Runs tab, marked as a test (see Finding test runs).

Pinned outputs ​

Pinning a node's output freezes it: during a test run, the pinned node is not executed, and the nodes after it receive the pinned output as if the node had produced it. Use it to:

  • stop calling a slow or costly node (an AI model, an outside service) on every test while you work further down the graph;
  • build the end of a workflow before its beginning works, by writing the output by hand;
  • keep a precise case (a category, an extracted value) to test a branch.

In the node's panel, after a test run, pin the output the node just produced, or write it by hand ("Write the output by hand"): it must be a JSON object, prefilled with the last test output when there is one. A pinned node shows a "Pinned output" mark on the canvas and "(not executed)" in the test. Release the pin to run the node again.

Limits and rules:

  • a pinned output is at most 256 KB of JSON and must be a JSON object;
  • an output from a test run may contain identifiers that do not exist (a draft that was never created): the editor warns before pinning it;
  • pins are saved with the draft (the pins field of the workflow document), but a live run ignores them: only test runs use them;
  • a pin on a node that no longer exists is ignored.

What is real and what is only described ​

During a test run, every node runs its real code. What changes is the services it uses: those that would act on the outside world are replaced by stand-ins that describe the action instead of doing it. In short:

  • Real: reading the mirror and attachments, extracting text, AI model calls, reading tables, searching drives and calendars, reading integration data, looking up contacts.
  • Described only: sending, drafting, moving and flagging emails; every HTTP request of HTTP request and Notify, GET included; every write to a table, a drive, a calendar, a sheet or an integration; signals, waits and approvals.

Each node declares an effect (none, external_write or send, see Workflows). It tells you what the node can do outside the product; the table below gives what actually happens in a test run.

NodeEffectIn a test run
Triggers (trigger.*)noneprovide the input described above
ai.categorize, ai.extract, ai.summarize, ai.prompt, ai.composenonethe model is really called (see AI in test runs)
Model providers (llm.*)noneused by the AI node they are wired to
mail.composenonecomposes the message for real; nothing is saved or sent
mail.sendsenddescribed: no draft, no message; the step says what would have been saved or sent
mail.move, mail.flagexternal_writedescribed: the email is not touched
attachment.extract_textnonereal: attachments are read
http.requestexternal_writedescribed, GET included: nothing leaves the server; the step returns status 200 and an empty body {}
notify.sendexternal_writedescribed: nothing is posted
table.find, table.listnonereal: the table is read
table.insert, table.update, table.upsert, table.delete, table.append_textexternal_writedescribed: nothing is written, but the row is really looked up when the node needs one
google_drive.search, onedrive.searchnonereal
google_calendar.find_free, outlook_calendar.find_freenonereal
google_drive.upload, google_drive.create_folder, onedrive.upload, onedrive.create_folderexternal_writedescribed: returns identifiers starting with simulated
google_calendar.create_event, outlook_calendar.create_eventexternal_writedescribed: no event, nobody invited
google_sheets.appendexternal_writedescribed: nothing is written
airtable.api, sharepoint.api, calendly.api, excel.api, notion.api, mynotary.api, yousign.apiexternal_writemixed: read operations run for real; create, update, delete, upload and send operations are only described
flow.if, flow.switch, flow.stop, data.transform, date.computenonereal: they only compute
flow.loopnoneruns only the first iterations (see Limits)
flow.waitnonedoes not wait: continues at once, and its data says how long it would have waited
flow.approvalnoneasks nobody: takes the approved branch at once and records the request it would have sent
flow.signalexternal_writedescribed: the signal is not emitted, so no real run is woken or cancelled
workflow.callnonethe called workflow really runs, as a test run too: its own effects are described

For integration nodes with several operations, the node pages say exactly which operations are read for real. Many nodes also add simulated: true to their data when their effect was only described; each node page says what it returns in a test run.

AI in test runs ​

AI nodes call the real model during a test run, with the provider and model they would use live: you read the real category, extraction, summary or draft. Consequences:

  • a test call costs the same as a live one, and appears in AI usage and costs;
  • quotas, refused models and provider outages fail the test as they would fail a live run.

Only when the instance has no AI provider configured does a test run fabricate the output instead (a fixed text, or placeholder values matching the expected shape). The step then says "AI skipped: no key on this instance" — "The output was fabricated, it is not a model answer." Configure a provider (see Integrations) to get real answers.

Limits of test runs ​

PointIn a test run
Versionalways the draft; to run the published version for real on an email, use a manual run
Loopsonly the first iterations run: 3 by default, LOOP_SIMULATED_MAX_ITERATIONS (1 to 50). The loop step says so ("only ran the first {count} iterations"); the instance's maximum number of items is not applied
Sub-workflowsthe called workflow runs its published version, as a test run; an unpublished, paused or archived target fails the step as it would live. Calls chain at most three levels deep
Retriesthe same number of attempts as live, but only 2 seconds between attempts
Timeoutsthe same per-step timeouts as live
Error workflownever started by a failed test run
Replaya test run cannot be replayed from the runs list: run a new test from the editor
One at a timethe editor runs one test at a time; a new test replaces the previous one in the Test panel
Prioritytest runs go ahead of live work in the queue, so the editor answers quickly

A test run does not check whether the workflow is paused or archived, and does not count as a live run for "one run per email per version": you can test the same email as often as you like.

Finding test runs ​

Test runs are kept like live runs, marked as such:

  • in the workflow's Runs tab, filter with "Tests and real", "Tests only" or "Real only"; test runs carry the badge "Simulated";
  • under Activity → Runs, the "Type" filter shows "Live" by default; choose "Test runs" or "Live and test runs" to see them. A test run is marked "Test": "A test run started from the editor: no real effect went out.";
  • the detail of a test run reads "Simulated", where a live run reads "Real — effects have been sent".

Through the API, GET /api/v1/executions?simulated=true lists test runs, and POST /api/v1/workflows/:id/test starts one. Its body takes messageId (email triggers), triggerData (test body), triggerNodeId (the trigger to test from, required when the triggers are of different kinds) and targetNodeId ("up to here"). It answers 202 with the run and the steps planned; refusals are 422 workflow.not_publishable (blocking errors, with the list), 404 workflow.test_message_not_found, 400 workflow.trigger_required, 400 workflow.unknown_node, 400 workflow.node_not_executable and 502 workflow.trigger_poll_failed.

How long test runs are kept ​

Test runs, with their steps and data, are deleted 7 days after they were created. The instance setting SIMULATED_EXECUTIONS_RETENTION_DAYS changes this delay (1 to 365 days). Live runs follow their own retention, described in Runs.