Skip to main content

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:

  1. Confirm the service is online and its manifest is visible.
  2. Create or update the flow in Studio.
  3. Release the version you want to test.
  4. Enable it too if your local workflow keeps enable separate from release.
  5. 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:

  • condition
  • rate-limit
  • mapping
  • output-topic
  • service-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.

Use this loop whenever a Studio flow does not behave the way you expect:

  1. Check /api/v2/services/<service> and confirm liveness is online.
  2. Inspect the manifest actions and service_sources for the service you targeted.
  3. Verify the flow version in Studio is actually released.
  4. Produce one event, not many.
  5. Inspect /api/v2/flows/<flow_id>/runs.
  6. Only then move to DLQ or fleet-level inspection.