Your first workflow
In this lesson we build a small clinical workflow from scratch in the visual editor: a lab result arrives, and we compute the patient's estimated glomerular filtration rate (eGFR). We wire it up, test it on a forged event, save it, and run it for real — all without writing a line of code or a line of YAML by hand.
By the end you will have a saved, executable workflow and will have seen it compute a result twice: once in simulation, once in a real run.
Nothing to install: we use the Config Plane UI that ships with the platform. If you do not have an instance running yet, follow Bring up your first instance first, then come back here.
What we are building
Two things happen in our workflow:
- A trigger fires when a lab result is received — this establishes the patient/encounter context and hands us the result.
- A compute node takes that result plus the patient's demographics and returns an eGFR (using the CKD-EPI 2021 equation).
A workflow is a typed dataflow graph: we connect the typed output of one node to the typed input of another, and the editor checks type compatibility as we go. See The dataflow model for the why; here we just follow the steps.
Step 1 — Open the editor on a new workflow
Open the Config Plane and go to Workflows. In the workflow list header, click + New.
The editor opens in editing mode on a blank workflow. We already see one node on the canvas: the trigger, labelled Lab result received. The blank workflow starts with this trigger selected by default, so we do not need to add it — it is our starting point.
Notice the three panels: the palette on the left (AI assistant, trigger selector, and a searchable node list), the canvas in the middle with a toolbar, and the inspector on the right.
Step 2 — Name the workflow
In the toolbar at the top of the canvas, set:
- the name field to
My first workflow; - the file name field (shown only for a new workflow) to
my-first-workflow.workflow.yaml.
The name appears in the breadcrumb, and the file name is where the editor will write the YAML when we save.
Step 3 — Add the compute node
In the palette, type eGFR into the ⌕ Filter nodes… box. One entry appears:
eGFR (CKD-EPI 2021). Click it.
A new node lands on the canvas and becomes selected. In the inspector on the
right we can see its Identifier (auto-generated as ckd_epi_2021) and its
type, clinical.egfr.ckd-epi-2021. This node has two required inputs:
result (an Observation) and demographics.
Step 4 — Add the demographics source
Our compute node needs demographics, so we add a node that provides them.
Clear the filter box, type Load demographics, and click the Load
demographics entry. This node (patient.load-demographics) reads the current
patient's demographics and exposes them on its demographics output.
We now have three nodes on the canvas: the trigger, the eGFR compute node, and the demographics source.
Step 5 — Wire the nodes together
We connect ports by dragging from an output socket to an input socket. Each node shows its output ports on its right edge and its input ports on its left edge.
Make two connections:
- Drag from the trigger's
resultoutput to the eGFR node'sresultinput. - Drag from Load demographics'
demographicsoutput to the eGFR node'sdemographicsinput.
As each connection lands, the editor validates the two port types against each
other and flashes a confirmation such as Connected: result → result. If the
types were incompatible it would refuse the link and tell us why — this is the
same static check the engine runs. For more on ports and this live validation,
see Wire ports.
Both required inputs of the eGFR node are now fed. We have a complete little graph.
Step 6 — Simulate it
Before saving anything, we test the graph on a forged event. Simulation runs the current graph through the same interpreter as production, but with no durable run and no side effects.
Click ▶ Simulate in the toolbar. The inspector turns into the simulation panel, pre-filled for us:
- a Patient field set to
patient-42(a real snapshot is read for that patient); - an Event (JSON) payload built from the trigger's example, e.g.:
{
"type": "BioResultReceived",
"patientId": "patient-42",
"encounterId": "sejour-7",
"analyte": "creatinine",
"value": 160,
"unit": "µmol/L"
}
Click ▶ Run the simulation. Within a moment an overlay appears on the graph: each node is marked ✓ executed (or ⤼ skipped, with the reason), and the computed values appear under the output ports. A flash message reports how long it took and how many writes were captured.
Click the eGFR node to open its full detail in the inspector — its inputs and
its egfr output, exactly what it produced. That eGFR value is our first visible
result.
Simulation is the fast feedback loop for authoring; see Simulate a workflow for its options (validation scenarios, captured writes, real vs. mock agents).
Step 7 — Save it
We are happy with the graph, so we persist it. Click 💾 Create the workflow.
The editor sends the graph to be validated (schema and dataflow) and, if it
passes, writes the YAML file. We get a confirmation like Saved to workflows/my-first-workflow.workflow.yaml — valid spec, executable immediately,
and the editor reloads on the saved workflow in editing mode.
The file the editor just wrote is plain, readable YAML — this is the single source of truth for our workflow:
apiVersion: meridian/v3
name: My first workflow
context:
- patient
- encounter
trigger:
type: trigger.bio-result-received
nodes:
load_demographics:
type: patient.load-demographics
ckd_epi_2021:
type: clinical.egfr.ckd-epi-2021
connections:
- from: trigger.result
to: ckd_epi_2021.result
- from: load_demographics.demographics
to: ckd_epi_2021.demographics
For the full grammar of this file, see the Workflow DSL reference.
Step 8 — Run it for real
Now we run the workflow as a durable execution. In the Config Plane, go to Executions and click + Emit an event.
In the composer:
- Under Target workflow, pick
my-first-workflow.workflow.yaml. - The Event payload (JSON) is pre-filled from the trigger's example
(including
patientId) — leave it as is. - Click ▶ Send the event.
A new run appears in the list and the composer closes onto its detail. The timeline shows the event being received and each node executing, and the run reaches completed. This is the same computation we saw in simulation, now as a real, durable run.
To watch runs, filter them, and inspect their timelines in general, see Monitor executions. For why these runs are durable and resumable, see Why durable execution.
What we did
We built a workflow entirely in the editor — a trigger and a compute node, connected by type-checked wires — then simulated it, saved it as YAML, and ran it for real. Every step gave us a visible result.
Where to go next
- Persist the result or notify a clinician by adding more nodes — start from Wire ports and the core primitives reference.
- Add a decision point: Branch with guards and switch.
- Pause a run for a human decision: Add human validation.
- Let an assistant draft a workflow from a plain-language description: Use the AI assistant.
- Learn the editor's affordances in depth: Use the visual editor.
- Unsure what a node or term means? Check the glossary.