Running a studyflow
The Runner is a companion to the Modeler app that walks a participant through a .studyflow diagram one node at a time. It loads the diagram, validates it, then traverses the flow from the StartEvent to the EndEvent, rendering each activity as a UI step.
Opening the runner
The runner lives at run.html (alongside the modeler at app.html). There are three ways to hand it a diagram:
From the Modeler – click Run in the toolbar. The current diagram is serialized to local storage, the runner opens in a new tab, and the seed is passed through the URL.
By URL – append
?studyflow_url=<absolute or relative URL>to fetch a hosted.studyflowfile:run.html?studyflow_url=/assets/my-study.studyflow&seed=42By file upload – open
run.htmldirectly. A landing screen lets you choose a.studyflow/.bpmn/.xmlfile from disk.
The seed query parameter (integer) makes random branches deterministic, which is useful for pilot runs and reproducibility.
Launching a study
The runner accepts three URL query parameters:
| Parameter | Purpose |
|---|---|
studyflow_url |
Absolute or relative URL of a hosted .studyflow file to fetch and run. |
diagram_id |
Key of a diagram stored in the browser’s local storage. Used when the runner is launched from the modeler’s Run button; not useful across browsers or machines. |
seed |
Integer RNG seed. Makes gateway draws (random/stratified branches) reproducible across runs. |
studyflow_url and diagram_id are alternatives; if neither is given, the runner shows the file-upload landing screen.
What the runner does
After loading, the runner:
- Parses the diagram – both serializations are accepted, YAML
.studyflowand legacy BPMN 2.0 XML – using the bundled studyflow + cognitive schemas (plus any optional extension schemas the diagram references). - Pre-fetches the Behaverse runtime manifest if (and only if) the diagram contains a
BehaverseTask. Other diagrams skip this network call. - Validates the diagram. Each node kind contributes its own validator (missing required attributes, unsupported types, etc.). Issues are listed in the logs and the run is aborted with a
phase=invalidstatus. - Traverses the diagram starting at the
StartEvent. Each node yields a job; the runner renders the corresponding component and waits for the participant to complete or skip it. OnEndEvent, the run finishes withphase=done.
Gateway behavior:
RandomGateway/StratifiedAllocationGateway– pick one outgoing branch uniformly at random (seeded by?seed). The stratified variant is currently treated as a random pick; stratification logic is reserved for future work.- Exclusive / Inclusive gateway with
conditionExpressionon an outgoing sequence flow – the first flow whose expression evaluates truthy wins. Conditions are evaluated against the runtime variable bag (nodes callsetVariable(name, value)to write to it). - No matching condition – the gateway’s
defaultflow is taken if set, otherwise the first un-conditioned outgoing flow, otherwise the first outgoing flow. ParallelGateway– not yet supported; the runner throws.
Built-in node kinds
| Node | Matches | Behavior |
|---|---|---|
| Start | bpmn:StartEvent |
Renders consent screen if consentFormUri is set; otherwise advances immediately. |
| End | bpmn:EndEvent |
Issues a completion code (none/static/dynamic) and redirects via redirectTo if set. |
| Instruction | cognitive:Instruction |
Renders the markdown content; participant clicks Continue. |
| Questionnaire | cognitive:Questionnaire |
Renders the chosen instrument (PHQ-9, GAD-7, BDI-II ship as built-ins) and stores responses. |
| Behaverse Task | behaverse:BehaverseTask |
Embeds the Behaverse Unity runtime in an iframe and bridges messages. |
| Generic Task | Any bpmn:Task / UserTask / ServiceTask / etc. |
Fallback step with a Continue button. |
Other element kinds (data references, score gateways, sub-processes that aren’t traversed inline, etc.) are skipped at run time – they affect modeling and analysis, not execution.
What executes vs what is design-only
Not every element you can model has a dedicated runtime. The current support matrix:
- Executed natively –
StartEvent(consent),EndEvent(completion code, redirect),Instruction,Questionnaire,BehaverseTask, and the gateways listed above. - Generic fallback –
CognitiveTask,VideoGame, andRestare design-time elements; at run time they render the generic task step (a Continue button), like any plain BPMN task. - Questionnaire instruments – only PHQ-9, GAD-7, and BDI-II ship as built-in forms. Other
instrumentvalues (STAI, PSS, custom IDs, …) fall back to the generic step. ParallelGateway– unsupported; the runner raises an error during validation/traversal.
Configuring Behaverse tasks
A BehaverseTask carries instrument-specific YAML in its configurations property. The Timelines: section supports two styles:
- Built-in by name – a timeline listed by name only (e.g.
XCIT_NB_01) runs a timeline that ships with the Behaverse build. - Inline, merged over the baseline – a timeline that declares its own blocks is authored inline. At run time it is merged over the per-scene baseline configuration (
Resources/<scene>.json), so you only author the fields that diverge from the defaults. New blocks should setInherits: Defaultto pick up the baseline block parameters.
Behaverse tasks can also be driven by a bot instead of a human participant – see LLM and bot participants.
Recording data
The runner can stream run data to a Behaverse data server. Recording is controlled by the Record events toggle in the runner header – it is off by default (privacy first) and the choice is persisted in the browser’s local storage.
To record, configure a data server in the modeler’s Settings (API key; the base URL defaults to https://data.behaverse.org/v1); the study name is taken from the diagram. When the toggle is on and a server is configured, the runner:
- Creates a session on the server at the start of the run.
- Streams batched studyflow events – trial outcomes, questionnaire responses, and timings – as the participant progresses.
- Records a SHA-256 hash of the diagram source alongside the events, so every data point is traceable to the exact study version that produced it.
PATCHes the session with the final status and completion code when the run ends.
If no server is configured (or the toggle is off), the run proceeds local-only – nothing leaves the browser and the study still works end-to-end. See src/runner/dataServer.ts and src/lib/core/runnerSettings.ts for details.
Adding a new node kind
The runner discovers node modules under src/runner/nodes/<kind>/index.tsx at startup. Each module calls registerNode(...) with a match predicate (typically extensionType: 'myschema:MyType'), a toJob(node) mapper, and a React Component. See src/runner/nodes/README.md for the full template – adding a new node kind only requires creating one new folder.
Logs and debugging
The Logs panel (top-right of the runner header) records parsing, validation, and per-node messages. The header also shows the current phase (loading, running, job:<kind>, done, aborted, invalid, error) and the seed if one was passed.
What’s next
- Modeler app – how to author a diagram.
- LLM and bot participants – run Behaverse tasks with simulated participants.
- Read a studyflow – learn the notation by reading one.
- Publish – how to share a diagram so the runner can load it from a URL.