Studio Flows
Studio is where you shape the released graph the runtime will execute. For Triggers v2, the main thing to get right is not the canvas styling. It is the graph grammar and the boundary between top-level sources, service segments, and actions.
Start with the first allowed shape
Use this for your first local success:
source (flow_lab_in)
-> service (flow_lab)
-> action (parse)
That shape matches the flow_lab example and keeps the first debug loop short:
- the source registration is obvious
- the target service is obvious
- the action result is easy to inspect
- the runs panel has very little noise
Graph rules that matter
The repo examples and grammar tests enforce a few rules that trip people up early:
- a source does not connect directly to an action
- an action does not connect directly to another action
- actions live under their parent service segment in the canvas
So this is the right mental model:
source -> service-in -> action -> next node
In Studio, the service segment is the visible representation of the runtime service-in node kind.
Chaining actions
If you want parse -> wrap, do not connect action to action directly. Add another service segment:
source (flow_lab_in)
-> service (flow_lab)
-> action (parse)
-> service (flow_lab)
-> action (wrap)
That second segment is not ceremony. It is the runtime boundary where Studio and the orchestrator agree on how the downstream service entrypoint is addressed.
For flow_lab, wrap should bind its message input from the upstream parse result fields. That only works cleanly because the upstream action advertises result_event metadata.
Handing off to another service
An action is owned by its parent service segment. Studio offers only the actions declared by that service's active manifest, so a Notify action must sit beneath a Notify service segment, not beneath a Spark Bonus segment.
After a lookup or action has enriched the record, a branch may hand off to another service:
service (spark_bonus)
-> lookup or action
-> condition
-> service (notify)
-> action (send_inapp)
The lookup or action is required on every path into the new service. This remains invalid:
service (spark_bonus)
-> condition
-> service (notify)
The rule does not change how a flow begins: a source still enters its first service segment. It also does not change Durable Timer setup or retry paths; keep those on the timer's supported internal-NATS route.
Boolean conditions
Conditions compare values of the same declared type. A Boolean field such as presence_is_active must be compared with True or False, never a numeric or text value. If Studio opens a legacy Boolean condition with an invalid saved value, it shows an empty, repair-required choice instead of guessing a value. Select True or False and apply the repair before release.
Release discipline
A draft graph is not enough. The runtime executes released flow versions. For local work, keep this order:
- Confirm the service is online and its manifest is visible.
- Create or update the flow in Studio.
- Release the version you want to test.
- Enable it too if your local workflow keeps enable separate from release.
- Produce one event and inspect runs.
If you skip step 1, you can waste time debugging the graph when the real issue is missing service registration.
After you release a version, the server re-aligns the working copy to that normalized released graph. Studio compares the canvas against that baseline, so a freshly released flow should show Clean in the Versions panel until you edit the graph again.
Nodes beyond the first path
The first walkthrough uses source -> service -> action, but that is not the whole graph grammar. The runtime can also route through nodes such as:
conditionrate-limitmappingoutput-topicservice-in
That matters when you move from one-service smoke tests to real flows. Still, the repo's current guidance is to prove the small path first, then extend.
Recommended debug loop
Use this loop whenever a Studio flow does not behave the way you expect:
- Check
/api/v2/services/<service>and confirmlivenessisonline. - Inspect the manifest actions and
service_sourcesfor the service you targeted. - Verify the flow version in Studio is actually released.
- Produce one event, not many.
- Inspect
/api/v2/flows/<flow_id>/runs. - Only then move to DLQ or fleet-level inspection.
Read next
- /triggers/services for what the runtime actually learns from a service registration
- /triggers/sources for the split between flow-starting sources and service ingress
- /triggers/outputs for how result payloads keep moving after an action finishes
- /triggers/overview-and-stats for the first observability entrypoint