Skip to main content

Flow source visualization

dexcli visualize turns one Go or Python Flow source file into a static Flow Definition Graph. The graph shows every possible path that can be determined from the source. It does not represent one Flow run or its history.

dexcli visualize ./order_flow.go

This opens the local Flow Rendering page and keeps it available until you press Ctrl+C. Use --json when you need a Flow Definition Graph artifact. Without --out, it writes JSON to stdout. Use --out to choose a file prefix:

dexcli visualize ./order_flow.py --json --out ./build/order-flow

Use --json to write the JSON to stdout:

dexcli visualize ./order_flow.py --json

Render definitions in Dex Web

Start Dex with a directory containing generated JSON files:

dexcli dev --flow-rendering-dir ./build

Open Flow Rendering in Dex Web. This page is independent from Flow search and run details. It renders the selected definition interactively. Its legend can show or hide control flow, WaitFor, RPCs, Attributes, Channels, Streams, SubFlows, and diagnostics. Flow timeout handlers are always shown as part of the Flow. Streams are hidden by default. The other layers start visible.

Dex scans JSON files recursively and takes a snapshot when it starts. Restart Dex after changing the files. Invalid JSON, an unsupported schema version, or a path that is not a directory stops startup with an error.

What the graph contains

The main Flow appears as a lavender frame. Each Step is a blue frame inside it. WaitFor paths appear above Execute decisions. A conditional WaitFor or Execute return first passes through a diamond, then branches into separate cards labeled with the source condition.

The definition graph includes:

  • the Flow and start Step
  • registered Steps and statically known transitions grouped by Execute decision
  • condition labels and fixed or runtime-sized fan-out
  • ordered WaitFor conditions, including Channel counts, Timer durations, and external SubFlows
  • RPC and timeout decisions and their next Steps
  • Attribute names, source-language value types, and map status
  • Channel, Attribute, and optional Stream access
  • completion, failure, Channel-empty checks, and cancellation inside Execute cards
  • Execute failure recovery paths

Terminal decisions do not create separate terminal nodes. Cancellation is shown inside the Execute card instead of adding duplicate arrows. The start Step carries a START marker instead of receiving an artificial start edge. Timers appear as rows in WaitFor rather than separate nodes.

An error return or raised exception does not identify another Step. It therefore does not create a transition. An explicit ProceedToOnExecuteFailure or on_execute_failure_proceed_to policy creates a solid magenta recovery edge to the recovery Step. The label records when the recovery skips WaitFor.

Resource arrows have a consistent direction:

  • publisher → Channel → consuming WaitFor
  • Attribute writer → Attribute box → Attribute reader
  • WaitFor → folded SubFlow

Resource and SubFlow relations are dashed, so they remain visually weaker than solid Step transitions. Channels are grouped at the upper left of the Flow. Attributes share one box. RPC hexagons cross the left Flow boundary. A SubFlow is a small dashed frame containing only its Flow type; its internal Steps are not expanded.

The renderer fits the complete Flow into the viewport by default. Channel and Attribute arrows stay hidden until you select that resource or a related Step, WaitFor, Execute decision, RPC, or timeout handler. This keeps the default graph focused on control flow while preserving resource access on demand.

Attribute relations include reads, writes, and locks. The Python analyzer follows static resource aliases on the Flow class, and records Attribute locks declared by RPC or Step options.

Stream relations describe observable application output, not control flow. They are hidden by default in Flow Rendering and can be enabled from the legend. The JSON marks Step Stream writes as repeatable and best effort. Heartbeat calls and checkpoint reads are runtime reliability details, so they are not included in the definition graph.

Supported source profile

Version 1 supports one Flow per source file. The file must directly contain:

  • static Step registration
  • each registered Step handler
  • Dex transitions and WaitFor definitions
  • RPC next Steps
  • execute-failure recovery targets
  • persistence resource definitions and access
  • Step Stream progress operations

Ordinary business helpers and imported models are allowed. A helper must not hide a Dex transition, WaitFor definition, resource definition, or recovery target. Step types, Flow types, and resource names must be statically known.

Go analysis requires a local Go toolchain. The input must belong to a module and package that can be type checked. Python analysis requires Python 3.11 or newer. The Python analyzer uses the standard-library AST in isolated mode. It never imports or executes the application module.

For Python, the analyzer recognizes Stream outputs yielded by synchronous Step generators and synchronously enqueued Stream writes in asynchronous Step handlers. Step Stream progress in an RPC or Flow timeout handler is invalid and produces a blocking diagnostic.

Version 1 does not support multiple Flows in one file, reflection, dynamic classes, wildcard Dex imports, getattr-based targets, monkeypatching, or movement collections that escape the handler. TypeScript, Java, Rust, and recursive multi-file analysis are not included.

Unknown nodes and diagnostics

Unsupported dynamic control flow is never omitted silently. The output contains an Unknown node and an error diagnostic. The default renderer still shows the partial graph. With --json, a partial JSON artifact is written, and the command exits with status 1.

Warnings do not invalidate the graph. For example, an Attribute whose value type cannot be determined uses unknown and produces a warning. A registered Step that cannot be reached from the start Step or an RPC also produces a warning. Invalid command arguments exit with status 2.

The JSON valid field is false when any blocking diagnostic is present. Consumers should reject editing or deployment based on an invalid graph while still using its known nodes and edges for explanation.

JSON contract

The Flow Definition Graph v1 schema defines source spans, parent-child relationships, structured WaitFor and decision details, resource types, branch conditions, edge direction, and diagnostics. The schema is the integration boundary for future visual editors and additional language analyzers.

See Dex CLI for commands that operate on running Flows.