Rendering a LlamaIndex Workflow as an Interactive Diagram
The last missing piece in our exploration of LlamaIndex’s execution engine is the single line that turns the abstract workflow into a browsable picture. The helper draw_all_possible_flows consumes a workflow class and produces an HTML file that can be opened in any modern browser.
from llama_index.utils.workflow import draw_all_possible_flows
if __name__ == "__main__":
import asyncio
asyncio.run(main())
draw_all_possible_flows(MyWorkflow, filename="multi_step_workflow.html")
How the Helper Works
Under the hood the routine performs five discrete tasks:
- Instantiates a drawing canvas.
- Reflects over the workflow class and collects every method decorated with
@step. - Creates a node for each discovered step.
- Connects the nodes with directed edges that mirror the declared event flow.
- Serializes the resulting graph to an HTML file using the pyvis library.
Python: pyvis in a Nutshell
pyvis is a thin Python wrapper around the JavaScript vis-network library. It exposes a Network object that can be scripted entirely from Python yet produces fully interactive front-end output.
from pyvis.network import Network
net = Network(directed=True, height="750px", width="100%")
net.add_node("Hello", label="Hello", color="#E27AFF", shape="ellipse")
net.add_node("World", label="World", color="#90EE90", shape="ellipse")
net.add_edge("Hello", "World")
net.show("hello_world.html", notebook=False)
The snippet above renders a tiny two-node graph and opens it in the default browser. Dragging, zooming, and hover tool-tips are available out of the box.
Java Alternatives
When the same requirement arises in a JVM stack there are two mature options: JUNG (Java Universal Network/Graph Framwork) and GraphStream.
JUNG
Add the following coordinates to pom.xml:
<dependency>
<groupId>net.sf.jung</groupId>
<artifactId>jung-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>net.sf.jung</groupId>
<artifactId>jung-graph-impl</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>net.sf.jung</groupId>
<artifactId>jung-visualization</artifactId>
<version>2.1.1</version>
</dependency>
Minimal Swing example:
import edu.uci.ics.jung.graph.*;
import edu.uci.ics.jung.visualization.*;
import edu.uci.ics.jung.algorithms.layout.*;
Graph<String, String> g = new DirectedSparseGraph<>();
g.addVertex("Hello");
g.addVertex("World");
g.addEdge("Hello->World", "Hello", "World");
Layout<String, String> layout = new CircleLayout<>(g);
BasicVisualizationServer<String, String> vv =
new BasicVisualizationServer<>(layout, new Dimension(750, 750));
vv.getRenderContext().setVertexLabelTransformer(Object::toString);
vv.getRenderContext().setVertexFillPaintTransformer(v -> Color.decode("#E27AFF"));
JFrame f = new JFrame("Hello World Network");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(vv);
f.pack();
f.setVisible(true);
The result is a static, non-interactive panel embedded in a Swing window.
GraphStream
GraphStream offers both static and dynamic graph rendering. Include the artifacts:
<dependency>
<groupId>org.graphstream</groupId>
<artifactId>gs-core</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.graphstream</groupId>
<artifactId>gs-ui</artifactId>
<version>1.3</version>
</dependency>
Three lines are enough to display a triangle:
System.setProperty("org.graphstream.ui", "swing");
Graph g = new SingleGraph("Demo");
g.addNode("A"); g.addNode("B"); g.addNode("C");
g.addEdge("AB", "A", "B", true);
g.addEdge("BC", "B", "C", true);
g.addEdge("CA", "C", "A", true);
g.display();
The viewer supports pan, zoom, and automatic layout updates when nodes or edges are added at runtime.
While AI assistants accelerate initial scaffolding, language-specific quirks—such as JUNG’s split package naming or GraphStream’s Swing backend flag—still require human fine-tuning.