Skip to main content

Create a Journey

Creating a Journey
Create a Journey, add welcome messages, a week-later check-in, and a path for your team. Read the transcript

Use a Journey to organize a longer program into steps and conditions. This example combines welcome messages, a delayed check-in, and a separate path for staff follow-up.

Before You Begin​

  • Use a Workspace where Journey V2 is available.
  • Configure an Inbox and sending phone number, and identify the check-in Workflow.
  • Have a colleague and Member label ready for the manual follow-up path.

Build the Journey​

  1. Open Journeys, create a Journey named Wellness follow-up, choose Journey V2, and create its first step, Welcome.
  2. On Welcome, add a Send SMS action and save the message. Add Send Email with a subject and body.
  3. Add Week 1 Check-in after Welcome. In its settings, set Continue When to Delay and enter seven days.
  4. Add Automated check-in after the delay. Add an SMS action connected to the check-in Workflow.
  5. Add a sibling step for a colleague to call. Add a Member label condition directly on this step; create the automated path with the opposite condition.
  6. Add a notification for the colleague responsible for the call.

What You Should See​

The draft Journey contains the welcome actions, a seven-day delay, an automated check-in, and a condition-based colleague path with a notification. Review the steps and communication settings, then choose Publish when ready to enroll Members.

A Journey advances each Member through a longer program using their data and the conditions you configure. Actions at a step can send messages or start a Workflow; the step conditions determine progression.

Two ways to build a journey​

There are two journey builders. The version chosen when a journey is created determines which one it uses; both are supported.

Step graph (the canvas)Journeys v2 (the map)
Looks likeA diagram you drag steps around onA map you pan and zoom: one card per step, with numbered condition cards on connectors
You edit byClicking a step on the canvasUsing the settings gear, condition cards and action links to open the right panel
Members can beAt several steps at onceAt exactly one place at a time
FinishingWhen every step is doneWhere nothing follows, marked End, or when an End Condition matches
Leaving earlyDraw an exit arrow from each stepDeclare each End Condition once
SplittingSeveral arrows can all fireExactly one route wins

The step-graph sections below describe the canvas builder. For the new builder, read Journeys v2: its steps, End Conditions, and ordered routes replace the step-graph authoring and progression model. Existing V2 journeys open in the map editor regardless of the workspace’s rollout setting.

Create or clone a journey​

Choose Create Journey from the Journeys list, enter a name, and choose the version. One of the two is already selected for you — which one depends on whether your workspace has the new builder turned on — and you can always pick the other before you create. Choose Journey V2 for ordered routes and End Conditions. Creating a journey does not activate it.

Where you pick a journey, such as the Enroll in Journey action, you can also choose Create Journey... to create one without leaving the form. The new journey is selected for you.

To make a V2 copy of an existing V1 journey, open that row’s … menu and choose Clone as Journey V2, then Clone Journey. The copy opens as a draft with its steps, actions, and settings. Actions that run when a member is enrolled or when they finish the journey are copied too, switched on or off exactly as they were on the original. V1 goals are not copied; source goals, history, and enrolled Members stay unchanged. Actions managed by a connected app are not copied — they stay with that connection. Empty journeys and supported journeys with unfinished actions can be copied. Complete and review the copy before activating; nothing in the copy runs until you do.

Review the copy’s numbered paths before publishing. V1 can advance along multiple matching paths; V2 takes the first matching path. An earlier Always path can make later paths unreachable. Review issues identifies those paths; add the intended conditions or change their order before publishing.

Some V1 graphs cannot be converted automatically. If cloning is refused, the message explains whether to repair the starting step and connections or create a V2 journey and recreate its steps and routes. No partial copy is saved.

Draft with the Manager​

On an empty Journeys list, Ask the Manager and the Common starting points cards open the Workspace Manager with a starter prompt. Review the proposed steps, goals, labels, and related Workflows before creating the Journey. The new Journey remains a draft until you activate it.

Journey Status​

Every journey has a status that controls whether it accepts new enrollments and processes steps:

StatusWhat It Means
DraftBeing designed. Members cannot be enrolled.
ActiveAccepting enrollments and processing steps.
PausedTemporarily frozen. No steps advance, but enrolled members remain in place.
ArchivedRead-only. Historical reference only.

Building the Step Graph​

A journey is made up of steps connected by edges. Steps are the things that happen; connections control the order.

Steps​

Every step is the same kind of node. Name it, attach any Actions that should fire when it activates, and use connections to control when the next step becomes eligible. There is no separate wait / checkpoint / goal step type in the editor — those behaviors come from the graph:

  • Wait — put a CEL condition on the incoming connection (for example days_since(parent_step.completed_at) >= 7). The Journey context supplies its own variables and functions; see the Developer CEL reference.
  • Checkpoint / convergence — mark incoming connections as required so the child waits for every parent
  • Goal — add a goal on the Goals tab; optionally link it to a step or give it its own CEL expression. Completing a step does not by itself mark a goal achieved

How steps drive automation. When a step activates it hands its configured Actions to the automation system as fire-and-forget nudges. Those actions may start a Chat, a Workflow, a message, or any other automation — and the same Workflow can be started from many different steps. Whether an individual action then runs, is skipped, succeeds, or fails does not by itself advance the journey; a step "completing" only means its actions were durably handed off for execution. Navigation is driven by the step graph, the member's data, and the CEL conditions on connections, so a member advances (or doesn't) based on their observable state — even if the relevant conversation happened outside Gravity Rail.

Adding Steps​

There are two ways to add a step, and they differ in whether the new step is connected:

  • Add Step (the toolbar button on the canvas) adds a step that is not connected to anything. It appears where you are looking and stays unconnected until you connect it yourself. Nothing leads into it, so — like Start — it is a place members begin: it is a starting step, not an inert one, and its Actions fire when it activates. Members already in the journey start on it too.
  • Drag from a step's output handle and drop on empty canvas creates the next step already connected to the step you dragged from, in a single gesture, so it comes after that step rather than alongside it.

Either way, name the step and attach any Actions that should fire when it activates.

Connecting Steps​

Draw connections between steps to define the order of progression:

  • Click a step's output handle and drag to another step's input
  • A member moves from one step to the next when the parent step completes and the child connection's conditions (if any) are true
  • You can connect one step to multiple children (branching) or multiple parents to one child (convergence)

Adding a step and connecting it are separate actions, and the connection is what decides whether the step comes after another step or is another place members start. A step no connection leads into starts members there — every member already in the journey begins on it as well — so if you added a step with Add Step and meant it to follow an existing step, connect it before you leave the editor. Connecting a step for the first time moves the members who have not started on it yet back to waiting for the step above; anyone who already started on it keeps their history.

Removing a Step While Members Are In It​

Removing a step from a live journey is safe, and you do not have to clear the members sitting on it first. Removing the step also settles their place in the journey in the same action:

  • A member who was waiting on the removed step is moved past it. Their step shows as skipped, with a history entry reading "Journey step archived", so the record says the step was removed rather than pretending the member completed it.
  • A member who was part-way through the step — the step had already started sending — is handled differently depending on which engine the journey runs on. Journeys carrying the Version 2 [beta] badge next to their status are settled on what actually happened, not on a guess: if the message went out, the step is recorded as completed; if it can be shown that nothing was ever sent, it is recorded as skipped; and when neither can be established (the send was cancelled or failed part-way), the step is deliberately left as it is for someone to look at, because recording a message as delivered when it may not have been is worse than leaving the record open. This settling happens within about half an hour of the removal, not instantly, so that a send still in flight is never cut off. If settling it leaves that member with nothing else to do, their journey is marked Completed then.
  • On journeys without that badge, a part-way-through step is recorded as skipped straight away, along with everyone else waiting on the step. That is the simpler behavior, and it has one honest limitation worth knowing: if the message had in fact already gone out, the record will say the member was not contacted. Journeys are moving to the new engine, where the check above replaces the assumption. If you are removing a step that members are actively being messaged on and the record matters, check the member's messages before you rely on the step history.
  • A member who had already finished that step keeps their history exactly as it was. Completed, skipped and timed-out steps are never rewritten.
  • If the removed step was the last thing a member had left, that member's journey is marked Completed — and any actions you configured for journey completion are triggered. Without this they would have been stuck part-way through a journey they could never finish. Those completion actions are attempted once and are not retried, so in the rare case that one cannot be delivered it does not run at all; the Completed status itself is always recorded. Treat completion actions as a notification on top of the status rather than a guarantee — anything that must happen for every finisher is safer as a final step in the journey.
  • Goals are not affected either way. Removing a step never marks a goal achieved for someone who never got there, and never takes away a goal someone had already reached.
  • If a lot of members are in the step, the removal itself still takes effect immediately; the rest of the members are settled in the background over the next few minutes. Nothing is lost, and you do not need to do anything.

If you restore the step later, members' existing history for it is left as-is — a step that was skipped when you removed it stays skipped. Restoring the step does not re-run it for people who have already moved on. To genuinely put someone through it again, re-enroll them.

When a step becomes eligible​

A step becomes eligible from its incoming connections, not from a per-step trigger setting (the editor has none). The child waits until:

  1. Every required parent has completed (archived parents do not count)
  2. Any CEL condition on those connections is true — or there isn't one
  3. Any member filter on those connections matches
  4. The journey is Active and inside its Active Hours window, if you set one

A step with no incoming connections at all is not waiting for anything: it is a starting step and is eligible immediately, the same as Start. That is why an unconnected step is a place members begin rather than a step that waits — see Adding Steps.

Time-based waits belong on the connection as CEL (days_since(parent_step.completed_at) >= 7 or now > parent_step.completed_at + duration("4h")). To advance a member by hand, use the Members tab.

Connections and Conditional Branching​

Connections between steps have three important properties:

  • Required — When a connection is marked as required, the child step cannot become eligible until this parent completes. A step with several required parents waits for all of them.
  • CEL Condition — An optional CEL expression evaluated at runtime. If the condition is false, the child step stays pending and is re-evaluated when the time it is waiting for arrives, when the member's data or labels change, and periodically in between. This enables both conditional branching and time-gated advancement.
  • Timeout (seconds) — An optional fallback for connections that have a celCondition. If the condition stays false for longer than this many seconds, the child step is marked as timed_out (a terminal status) rather than waiting forever. A timeout alone — without a celCondition — has no effect, because the step is never blocked in the first place.

Example — conditional branching: After a screening step, you might have two connections:

  • Connection to "Schedule Appointment" with condition member.data.screening.risk_level == "high"
  • Connection to "Send Resources" with condition member.data.screening.risk_level == "low"

The member follows only the branch whose condition matches.

Weekly (or Any Fixed-Interval) Cadence​

To advance a member one step every 7 days, use a celCondition that checks how long ago the parent step completed. The member's journey wakes when 7 days have elapsed; the condition becomes true and the child step becomes eligible.

CEL condition for "7 days after parent completed":

days_since(parent_step.completed_at) >= 7

Using the CLI:

# Connect Week 1 → Week 2 with a 7-day gate
gr journeys connections create -w $WID --journey-id <id> \
--data '{
"parentStepUuid": "<week-1-uuid>",
"childStepUuid": "<week-2-uuid>",
"celCondition": "days_since(parent_step.completed_at) >= 7"
}'

Repeat for each pair of consecutive steps (Week 2 → Week 3, and so on).

How it works: When Week 1 completes, Week 2 starts in pending status. For the first 6 days, days_since(parent_step.completed_at) >= 7 returns false and the step stays pending. On day 7, the condition returns true, the step becomes eligible, and it starts in turn with the workspace's other due steps. The member's journey workflow wakes at the computed day-7 boundary.

Important: Do not use timeoutSeconds alone for time-based advancement. timeoutSeconds is a fallback timeout for steps that are blocked by a condition — if the condition never unblocks, the step is marked timed_out (skipped/terminated) instead of waiting indefinitely. It is not a delay mechanism. To delay a step by N days, always use a celCondition as shown above.

Calendar Days Instead of Elapsed Days​

days_since(...) keeps the previous step's time of day: a step delivered at 3 PM on Monday releases the next one at 3 PM on Tuesday. Sometimes you want the calendar instead — "the next day", as soon as that day's contact window opens.

On journeys carrying the Version 2 [beta] badge, a day wait offers Same time of day and Start of active hours. New waits use Same time of day; existing waits retain their saved choice. Hover the information icon for an explanation.

Choose Start of active hours and the wait counts calendar dates in the timezone your Active Hours resolve in, and the step becomes due at the first permitted time on or after the target date rather than at the previous step's time of day. So a 3 PM Monday delivery, a one-day wait and a 9 AM–5 PM window means 9 AM Tuesday, not 3 PM. An overnight window that is already open at midnight can run then.

The saved condition is window_days_since(parent_step.completed_at) >= N in place of days_since(...). Three things worth knowing:

  • Nothing is converted for you. A wait already saved with days_since(...) opens with Same time of day selected and retains that setting until you choose Start of active hours; the same applies in reverse.
  • It needs Active Hours, and it is only about whole days. Without Active Hours a calendar wait would become eligible at midnight, so the timing choices are disabled and the information note explains why. On an hours wait it is not shown at all — hours are exact elapsed time, which is a different thing entirely.
  • Turning Active Hours off does not rewrite a saved calendar wait. It keeps counting calendar dates, in the workspace timezone, and can then run from midnight. Start of active hours stays selected and disabled; turn Active Hours back on to change the choice, or rewrite the wait as an advanced expression.

Hour-Level Gates​

For waits shorter than a day, compare now against a timestamp plus a duration:

now > parent_step.completed_at + duration("4h")

duration() accepts hours ("4h"), minutes ("90m"), seconds ("30s"), days ("1d"), and compound values ("1h30m"). Single or double quotes both work.

Timing note — which form to use: both the days_since(...) >= N form and the parent_step.completed_at + duration("...") form get an exact scheduled wake-up at their boundary, so the step becomes due within seconds of it rather than up to a re-check cycle late — the duration form now covers sub-day waits too, not just whole days.

  • Whole days — days_since(parent_step.completed_at) >= N is the clearest idiom for a day cadence. It keeps the previous step's time of day.
  • Calendar days — on a Version 2 [beta] journey, window_days_since(parent_step.completed_at) >= N counts calendar dates instead, and releases at the start of the next permitted window on the target date. See Calendar Days Instead of Elapsed Days.
  • Hours, minutes, or seconds — use parent_step.completed_at + duration("4h") (or "90m", "45s", "1h30m"). The journey waits until the computed instant and then re-checks, a little after it rather than exactly on it.
  • A wake target, not a stopwatch guarantee. Advancement keeps a 30-second minimum delay, and anything the scheduler does not recognize — or a value that never becomes due — still falls back to a periodic re-check and to nudges. If you need strict second-level scheduling, a journey edge is the wrong mechanism — reach for a scheduled routine instead.

Available CEL variables on connections:

VariableTypeDescription
parent_step.completed_attimestampWhen the parent step completed (empty until it does)
parent_step.activated_attimestampWhen the parent step was activated
parent_step.eligible_attimestampWhen the parent step became eligible
parent_step.statusstringCurrent status of the parent step
journey.enrolled_attimestampWhen the member enrolled in the journey
days_since(ts)integerDays between ts and now (truncated)
window_days_since(ts)integerCalendar dates between ts and now (Version 2 only)
member.*member objectMember labels, data fields, and properties
nowtimestampCurrent time in your workspace's timezone
datetime.timestamptimestampThe same instant as now

window_days_since() counts calendar dates rather than elapsed time, in the same timezone your Active Hours use, and it is only available on journeys carrying the Version 2 [beta] badge. See Calendar Days Instead of Elapsed Days.

Working with timestamps

Timestamp variables are real date-and-time values, not text. That is what lets you write parent_step.completed_at + duration("4h") and compare two timestamps directly.

Two consequences worth knowing:

  • Comparing a timestamp to a quoted date — now > "2026-01-01" — is an error, because one side is a timestamp and the other is text. Convert explicitly when you really want text comparison: string(now) > "2026-01-01".
  • If a timestamp has no value yet (for example parent_step.completed_at before the parent step completes), days_since() returns 0 and the condition stays false. The step waits rather than advancing early.

Evaluation Order​

When multiple connections leave a step, the order field controls which conditions are evaluated first. Lower numbers are evaluated before higher numbers.

Goals​

Goals are available in Journey V1. Journeys v2 does not show, author, or evaluate goals; existing historical goal data is retained.

Goals represent the high-value outcomes of a journey — the end-states you are trying to achieve. They live on the Goals tab as their own records, not as a special step type.

  • Each goal can have an optional monetary value for tracking ROI
  • A goal can optionally link to a step and/or use a CEL expression to decide when it is achieved
  • Completing a step does not by itself mark a linked goal achieved — the goal's own condition (or the heartbeat evaluating it) does

To create a goal:

  1. Open the journey
  2. Go to the Goals tab
  3. Click Add Goal
  4. Enter a name, optional description, and optional value
  5. Optionally link a step and/or write a completion expression

Journeys v2​

Open Edit to build the Journey on its map. Begin marks enrollment; connected steps lead to End. The top bar shows the Journey's status, version, and any issues to review.

Finding Your Way Around the Map​

Drag the background or scroll to move around. Hold Cmd (Mac) or Ctrl (Windows/Linux) while scrolling to zoom; touch screens also support pinch zoom. Use the bottom-left controls to zoom or fit the whole map.

The top-left menu contains Publish, Settings, Schedule, and the orientation control. Enrollment conditions appear above Begin on the map; End Conditions appear in cards below the menu. Click Vertical to switch to Horizontal, or the reverse. With a path selected, Focus branch narrows the map to that part of the Journey. Show journey in the top-left menu restores the full map.

Use Tab to reach controls, arrow keys to follow the map, Home to return to its beginning, and Escape to clear selection.

Editing Steps​

Click a step to select it. Each editing control has a separate purpose:

  • Click its name to rename it inline.
  • Click its gear to open step settings in the right panel.
  • Click an action to edit that action in the right panel.
  • Click + or Add action in its Actions section to add an action.
  • Use its ⋮ menu for the available step operations.

The step settings panel contains the name, Add description, Continue When, and Actions in one form. Optional descriptions have a Remove button when expanded; step names remain required. Update step becomes available after a valid change to the step or its actions. Saving closes the panel; the step stays selected, so clicking it again reopens its settings. If the save fails, the panel stays open with your changes. On narrow screens the panel fits inside the editor; its contents scroll while its header and footer remain accessible.

Changes to the map save when you add, move, or remove something. A form saves when you press its save button. Typing alone does not save a form. A colored-dot status below the top-left menu stays visible: Saving, Saved, or Not saved. If a map save fails, use Retry save or discard the unsaved change. See Drafts You Have Saved for incomplete drafts.

Journey Settings​

Choose Settings in the top-left menu to edit the Journey's name, and description in the right panel. Use Add description to expand an empty description. Choose Save to apply the settings. Scheduling is separate: choose Schedule in the same menu to edit active hours. The panel header's ⋮ menu contains Archive.

Pause During Human Handoff​

The settings panel also has a Pause during human handoff switch. It is off by default. When you turn it on, the journey does not start its next automatic step for a member while a person is handling one of that member's chats — for example, a chat where the assistant is paused so a teammate can take over, or an escalation nobody has answered yet. The step is not skipped: it waits, and starts once the person hands the chat back (resumes the assistant, answers the escalation, or archives the chat).

  • There is no time limit. The journey waits for as long as the handoff lasts. If a chat is left paused, turn the switch off or hand the chat back to let the member continue.
  • You can still advance a member by hand from the Members tab while they are paused.
  • Steps that already started are not stopped. The switch only holds the next automatic step.

While a member is paused this way, their Journeys tab shows Journey paused while this Member is in a human handoff. when you expand that journey. Active Hours can hold the same step at the same time; the banner still shows while the handoff lasts.

Adding and Ordering Steps​

Choose a + on a connecting line to insert a step there. Enter its name and press Enter or Add step. Cancel or Escape removes the new-step form without saving. Finish or cancel this inline creation before making another structural change; you can still pan and zoom.

Use the + beside a step to add a sibling: an alternative step for the Members who match a condition. The new-step form asks for that condition under Member Match, with a saved Member filter or a CEL expression under Additional conditions, and does not add the step without one. Members who do not match keep following the existing step, on a path labelled Otherwise. When the step already starts a path, the new path instead joins that choice and is checked in order with its other paths, never after the Otherwise. Use the arrows on the canvas to reorder adjacent steps or the order in which sibling conditions are checked.

If the existing step waits before it runs, the form says what happens to that wait before you add anything. A condition, saved filter or expression it waited for now chooses its path instead, checked first; you can then give the new step a condition of its own, checked second, or choose Everyone else (Otherwise) to send everyone else to it. A delay now applies to the whole choice — both paths wait for it. If the step's condition is one you cannot edit (or cannot change right now), the form explains that a step cannot be added beside it and Add step stays disabled, so the condition is never lost.

Choose Add a branch on a connecting line to start a choice after a step. List its paths in the order they are checked, each with its own condition, using Add route for another and the remove button beside one you no longer want. Names are optional: a path you leave unnamed is shown as "Route 1", "Route 2" and so on, by the order it is checked. Under If no route matches, choose Take the Otherwise route (an Otherwise path is added last) or Keep waiting here. Every path starts empty and continues to the step that came next; add steps to a path afterwards. Reorder paths after creating the branch.

Each path that finishes stops at its own End marker. Insert a step on the line before an End to extend that path. When the main list ends in a choice between paths, its End sits after that choice with no line leading into it; adding a step there gives every finishing path the same final step. When paths meet at a later step, that step runs once for the Member who reaches it.

A step can have no actions and no delay. It passes through to the next step and does not prevent saving or publishing.

Continue When​

Open a step's gear and choose one Continue When tab. One line under the tabs explains the selected choice, and its controls appear directly below it.

ChoiceBehavior
ImmediatelyContinue as soon as the previous step is done. Clears any Member filter.
DelayWait a specified number of hours or days after the previous step.
Field is setWait for the selected Form field to have any value.
Member filterWait until the Member matches a saved Member filter.
ExpressionWait for a CEL condition.

Under Delay, Field is set, or Expression you can also tick Also check member filter at the bottom of the options to add a saved Member filter. The Member must then satisfy both requirements. Untick it to take the filter off again without changing the wait. A wait appears as a clock pill before the step on the map.

Inline Member conditions​

When inline Member conditions are available in your workspace, the tabs are Immediately, Member Match, Delay, Field is set, and Expression:

ChoiceBehavior
Member MatchWait until the Member matches a condition built from Member fields and Form values. Choose Check a member filter instead to wait for a saved Member filter in its place, and Use a member condition instead to switch back. It is one or the other: switching clears the one you leave.
Delay, Field is set, ExpressionAs above, with Also check member filter to add a saved Member filter.

Member conditions live only on Member Match: choosing another tab removes the step's condition when you save. A step that only checked a saved filter opens on Member Match with that filter shown and is saved unchanged unless you edit it. A newly chosen tab does not show its "required" message until you have started filling it in, but Save stays unavailable until it is complete. If a condition uses Member fields you cannot view, it is kept as it is on every tab, and you cannot switch it away or choose another tab that would remove it until someone with access changes it.

When inline conditions are not available, a condition a step already has is shown read-only and kept when you save. You can remove it if you have access to its Member fields, but you cannot add or change one.

Hours measure elapsed time. Whole-day waits keep the previous step's time of day in the workspace timezone. Start of active hours counts calendar dates and becomes eligible at the first permitted time on or after the target date; see Calendar Days Instead of Elapsed Days. Changing the unit keeps the number you entered: three days becomes three hours, not 72 hours. Existing hand-written expressions remain unchanged unless you edit them.

Due steps run on the Journey's regular background pass, subject to active hours and the workspace's delivery rate. A due time is not an exact delivery time: a regular pass can add about half an hour, and a large queue can add further delay.

Actions​

Choose the action type, fill in its settings, and save. Names are optional; the action type supplies its default label.

Click a saved action to open its right panel. Active in the header turns it on or off. Inactive actions remain on the step in italic text with a strikethrough, and can still be opened for editing.

  • Action contains the action's settings and optional name.
  • Delay waits a specified amount of time before executing this action.
  • Conditions adds an optional condition for this action alone.

Save Changes keeps the panel open. After saving, the button is disabled until you make another change.

End Conditions — leaving the journey early​

Exit condition cards sit below the top-left menu. Choose Add End Condition to create one. Each card has a settings gear and an Actions section, using the same controls as a step. Click an action to edit it, or + to add one.

An exit can use an inline Member condition, a saved Member filter, a CEL expression, or a combination. All conditions configured on that exit must match. You do not need an arrow from every step to the exit.

The first matching exit wins; its actions are the only exit actions that run. Cards stay in evaluation order. When more than one exit has actions, priority numbers and reorder controls appear so you can choose which wins if conditions overlap. An earlier exit with no actions can still win before one with actions.

Where a path finishes without an End Condition, the map shows its own End marker after its last step. Change these paths on the canvas.

Three behaviours worth knowing:

  • End Conditions are checked before every step is sent, and again on every background pass — so a member who becomes eligible to exit does not receive the next message first.
  • End Conditions are checked even outside your active hours. Active hours stop outreach, not thinking. If an End Condition has no actions the journey finishes immediately; if it does have actions, they wait for your contact window to open — and nothing else sends in the meantime.
  • The first match is final. Once a member exits through an End Condition, a later change in their data cannot move them to a different one.

Without End Conditions, members finish after the last step.

Sibling Conditions​

Click a numbered condition card to edit who takes that path. A name is optional; use Add name if it helps. Then choose how to say who takes it:

  • Member Match (the default): build a condition from Member fields and Form values. This condition belongs to this path: it needs no separate name and does not appear in the saved Member filters list. Choose Check a member filter instead to use a saved Member filter in its place — one or the other.
  • Expression: enter a CEL expression instead. Tick Also check a saved member filter to require a saved Member filter as well; the Member must match both.

Switching between Member Match and Expression keeps the condition or expression you entered in the other until you save, but only the one shown is saved. Leave Member Match empty for Always.

Choosing Inline Conditions, Saved Filters, or CEL​

NeedUse
A Member or Form condition used only by this pathMember Match. Edit it directly here, without creating a named Member filter.
One definition of a group reused across Journeys, enrollment, or the Members listA saved Member filter: Check a member filter instead on Member Match, or Also check a saved member filter under Expression. Changes to that filter apply everywhere it is used.
A Journey clock, a calculation, or logic unavailable in the filter builderExpression.

For example, a path that checks a Form's completion field can keep that check in Member Match. A shared eligibility policy used for enrollment in several programs is better kept as a saved filter. Copying that policy into each path would create separate conditions that must be maintained separately.

Keep experiment-assignment expressions when they are responsible for assigning Members to Experiment Groups. Filtering on an existing Experiment Group only checks an assignment; it does not create one.

To replace an existing saved filter, pause the Journey and rebuild the condition in Member Match; switching to the condition removes the saved filter. A path set up earlier with both a Member condition and an expression opens on Member Match and shows the expression beneath it as Also requires this expression: both must match until you switch tabs, which keeps only the one shown. Check Members who should take each path, including Members with no value for the selected field, before publishing again. Do not delete a saved filter until you have checked its other uses.

Inline conditions can belong to sibling paths, automatic enrollment conditions, and exit conditions — and, where inline Member conditions are available, to a step's or a branch's Continue When (see Inline Member conditions). Where they are not available, Member Match is not offered on a path either: use its expression or a saved filter, and any condition it already has is kept read-only. Changing a step's gate into a branch can change when its actions run; it is not an equivalent shortcut for replacing a filter.

A number inside the card shows its evaluation order. Use the arrows beside the card to change that order. The Otherwise path has no number and no arrows: it is always last, taken when no numbered path matches. It reads If the wait times out when the choice has a give-up time.

The first matching path is taken. Put an Always path after more specific conditions; placing it first makes later conditions unreachable, and Journey health warns about that. A lower-priority condition can match on an earlier background pass; the Journey does not wait to see whether a higher-priority condition will match later. Once a Member takes a path, later data changes do not move them to another path.

A branch's settings use the same Continue When tabs as a step: Immediately, Delay, Field is set, Member filter, or Expression decides when the branch starts checking its paths. Delay waits a set number of hours or days after the step and then checks every path; it has no time limit or condition of its own. Under Field is set, Member filter, or Expression, …or after sets an optional time limit in hours or days: the branch then decides anyway, taking the Otherwise path. Leave it blank to wait as long as it takes.

Where inline Member conditions are available, the branch tabs are Immediately, Member Match, Delay, Field is set, and Expression. Member Match works as on a step: a Member condition, or a saved filter instead. Delay has no condition, filter or time limit of its own. …or after stays outside it: the branch decides once what you configured is true, or once the time limit has passed, whichever comes first. A branch that only checked a saved filter opens on Member Match with that filter shown.

For a group of alternatives, If no route matches controls whether the Member keeps waiting at the branch (Keep waiting here) or moves on right away (Take the Otherwise route). The branch's own timing is set above it, under Check routes. Existing fallback paths stay last. If a fallback contains steps, move or remove those steps before removing the fallback.

Use Remove path to remove an empty conditional path. Remove its steps first if it still contains steps. The confirmation identifies the pending removal; Cancel leaves the Journey unchanged.

Publishing and Reviewing Issues​

Choose Publish at the top of the menu, then confirm in the dialog. Cancel leaves the Journey's status unchanged. Publishing is unavailable while a change is saving or a known blocking configuration issue remains.

Choose Review issues in the status bar to open Journey health. Each issue identifies the affected configuration and what needs fixing. Its repair control opens the relevant step, condition, or action. Suggestions do not block publication. Empty steps and immediate passage are valid.

Pause a live Journey before changing its steps, ordering, waits, or End Conditions. Those controls are disabled while live. Members keep their current positions while paused. Publish again when the changes are ready. Names, descriptions, and settings of existing actions can be edited while live.

Drafts You Have Saved​

An incomplete configuration, such as a connection to a removed step, can be stored as a saved draft. Review and repair its issues before publishing. If the Journey is already active, it continues using the accepted definition while an unfinished draft is stored.

Discard saved draft restores the accepted definition after confirmation. It also replaces unsaved editor changes; it cannot undo changes already saved to the accepted definition. If someone else saved the Journey, reload before trying to discard their changes.

Reading a member's history​

A member's enrollment history shows which route they took and which End Condition finished them, with timestamps — the route's name, as you wrote it. It does not show the values that were evaluated or the condition text. If you need to know why a particular member went one way, look at their record.

Enrolling Members​

Single member (or a short list)​

  1. Open the journey
  2. Go to the Members tab
  3. Click Add Member
  4. Search for and select a member. Use + to add more to the batch
  5. Click Enroll

The member's enrollment starts immediately. Starting steps (those with no required parents) begin eligible right away; downstream or gated steps begin pending and become eligible once their incoming connections are satisfied.

There is no "enroll everyone matching this filter" option in that dialog. To enroll a known list at once, use the API (memberIds, up to 1000).

Auto-Enrollment (Continuous)​

Automatic enrollment checks for matching Members on each background pass while the Journey is active. It does not limit who you can enroll manually.

Journey V2​

  1. In the editor, choose Auto Enroll Members above Begin.
  2. Choose Inline filter to build conditions here, or Saved filter to reuse an existing Member filter.
  3. Optionally add a name, then choose Save.
  4. Add another entrance when you want an alternative way to qualify.

A Member matching any entrance can enroll. Matching several entrances creates one enrollment, not several. An inline condition belongs to the Journey and does not create an item in the saved Member filters list. Use a saved filter when the same criteria should be maintained centrally for several uses.

Use an entrance card's gear to edit it and its menu to remove it. Removing one entrance leaves the others in place. With no entrances, enrollment is manual. The Members tab shows a read-only summary with a link back to the editor.

The API and CLI also support enrollmentConditions on Journey create and update. Send the complete replacement list; omit the property to leave it unchanged, or send an empty list to remove automatic enrollment. For example, save this JSON in entrances.json, then update the Journey:

{
"enrollmentConditions": [
{ "name": "Eligible members", "filterId": 123 }
]
}
yarn gr journeys update -w $UUID --id $JOURNEY_UUID --file entrances.json

Use returned condition UUIDs when editing existing entrances; omit UUIDs for new ones. Inline conditions use the memberPredicate property instead of filterId.

Legacy Journeys​

On the Members tab, the Auto-Enrollment card selects one saved Member filter. Choose Remove to stop automatic enrollment. The equivalent CLI update is:

yarn gr journeys update -w $UUID --id $JOURNEY_UUID --data '{"autoEnrollFilterId": 123}'

Set autoEnrollFilterId to null to remove that legacy filter.

Members already enrolled in any status, including completed or canceled, are not automatically enrolled again. Changing or removing criteria does not cancel an existing enrollment.

To find Members enrolled in a Journey or on a particular step, use the saved Member filter Journeys fields. Those search filters do not configure the Journey's automatic enrollment.

Step Progression​

Each member's progress through a step follows this lifecycle:

StatusMeaning
PendingStep exists but prerequisites are not yet met
EligibleAll incoming required connections are satisfied
In ProgressStep has been activated and its actions are being handed off to the automation system
CompletedThe step's actions were durably accepted for execution and the graph may now evaluate its outgoing connections — individual actions may still run later, be skipped, or fail; this is not a measure of whether any conversation or workflow succeeded
SkippedBypassed (manual skip or conditional branch not taken)
Timed outAn incoming connection's CEL condition stayed false longer than its timeout
FailedA legacy status kept readable for historical enrollments and health diagnostics. Step activation does not mark a step failed based on a conversation, message, or action outcome.

When a step completes, downstream connections are evaluated immediately to determine which child steps should become eligible next; a periodic background sweep also re-checks and repairs progression as a fallback. The member's journey is marked as completed once every one of their steps has reached a terminal status — Completed, Skipped, or Timed out. A step left Pending or Eligible keeps the journey active.

In Journey V1, goals are evaluated alongside this but do not gate completion: a journey can complete with goals unsatisfied, and satisfying every goal does not complete a journey on its own. See Goals for how each goal's linked step and/or condition decides satisfaction.

Monitoring Progress​

Viewing Enrolled Members​

Open the journey's Members tab to see all enrolled members and their current status. Each enrollment shows:

  • Member name
  • Enrollment status (active, completed, canceled)
  • Current step progress
  • Enrollment date

Step Statuses​

Click on a member's enrollment to see their step-by-step progress. Each step shows its current status and when it last changed.

Goal Progress​

This reporting applies to Journey V1. Goals are not shown in Journeys v2.

For Journey V1, the Goals section shows aggregate progress — how many enrolled members have achieved each goal.

Experiment breakdown (A/B testing)​

Members with the experiments:read scope can filter goal reporting by Experiment:

  1. Open the Journey
  2. Choose an Experiment from the goal reporting selector
  3. Each goal shows per-Group metrics: exposed, achieved, and conversion rate

Filtering rules for this view:

  • Only Members enrolled in this Journey who have an experiment exposure for the selected Experiment appear in the breakdown
  • Members assigned to a Group elsewhere but never exposed in this Journey context are excluded
  • Counts below five display as "<5" for privacy; conversion rate is hidden when the exposed denominator is suppressed

See Experiments (A/B Testing) for authoring and eligibility filters.

Re-Enrollment​

If a member needs to go through a journey again, you can re-enroll them. A new enrollment is created, and the member starts from the beginning with fresh step statuses.

Unenrollment​

To remove a member from a journey:

  1. Open the journey's Members tab
  2. Find the member's enrollment
  3. Click Unenroll or Cancel

The enrollment is marked as canceled. The member's progress is preserved for historical reference but no further steps will advance.

Journey Notes​

Use notes on a journey to document internal context — design decisions, clinical protocols, or operational notes. Anyone with journeys:read can view them and journeys:write can add them. They are never shown to patients.

Automation with Actions​

Journey lifecycle events can trigger Actions in the event rule system, letting you attach automation to key moments:

EventWhen It Fires
journey:enrolledA member is enrolled (or re-enrolled) in a journey
journey:completedA member completes a journey
journey_step:executeA step activates — this is how the step fires its Actions as nudges

The step's Actions run as fire-and-forget nudges: the journey does not wait for them and never treats their success or failure as a reason to advance. See Routines for more on attaching automation to events.

Active Hours​

Active Hours let you restrict when a journey can advance for each member. When configured, the engine will not move a member's pending step to eligible, and will not start eligible steps, outside the allowed window. Any work that is already in-flight (started steps, running workflows, member replies) is never blocked — only new outbound advancement is gated.

If no Active Hours are set, the journey runs around the clock (the default behavior).

How to Configure​

Choose Schedule (the clock icon) in the top-left menu in Journeys V2, or the settings control on the legacy step-graph canvas, and enable Active hours. The schedule opens in a wider dialog. Save applies changes and closes it; Cancel discards unsaved edits. The editor shows a row for each day of the week. Each day can be:

  • Enabled with a start time and end time (HH:MM, 24-hour)
  • Disabled — the journey does not advance for any member on that day

At least one day must be enabled. The default template enables Monday–Friday, 09:00–18:00.

Timezone Mode​

Because Gravity Rail serves members across time zones, Active Hours has two modes:

ModeBehavior
Member (default)Times resolve in each member's own timezone (Member.timezone, falling back to the workspace timezone). A 09:00 window opens at 9 AM local time for each member independently — an EST member and a PT member on the same journey gate three hours apart.
WorkspaceTimes resolve in the workspace timezone for everyone. The window opens simultaneously for all enrolled members. Use this for campaign-style journeys where "all at 9 AM ET" matters more than each member's local time.

Select the mode from the dropdown above the day grid in the Active Hours editor.

If a member's timezone changes, the new timezone takes effect on the next window evaluation — no re-enrollment is required.

Out-of-Window Policy​

When a member's step would advance but the current time is outside the window, the step holds: it stays eligible and starts once the window next opens, in turn with the other steps due then. A step that has not started by five minutes before the window closes (sooner for a very short window) waits for the next opening, so a large group that becomes due late in the day may finish the next day. Steps are never skipped or canceled by the Active Hours gate.

Configuring via API or CLI​

Pass an activeHours object when creating or updating a journey:

gr journeys update -w $WID --id $JOURNEY_UUID --data '{
"activeHours": {
"days": [
{"day": "monday", "enabled": true, "start": "09:00", "end": "17:00"},
{"day": "tuesday", "enabled": true, "start": "09:00", "end": "17:00"},
{"day": "wednesday", "enabled": true, "start": "09:00", "end": "17:00"},
{"day": "thursday", "enabled": true, "start": "09:00", "end": "17:00"},
{"day": "friday", "enabled": true, "start": "09:00", "end": "17:00"},
{"day": "saturday", "enabled": false},
{"day": "sunday", "enabled": false}
],
"timezone_mode": "member",
"out_of_window_policy": "hold"
}
}'

To remove Active Hours and make the journey always-on again, set activeHours to null.

For developers​