This page covers the internal data structures, lifecycle, and execution mechanics of the graph processing engine used during flow builds and runs. This includes the Graph, Vertex, and Edge abstractions, how a flow JSON is deserialized into these structures, topological ordering, vertex state management, and the component instantiation step that occurs during a build.
For the higher-level flow execution loop that drives the graph (managing job queues, event streaming, and API integration), see page 4.4 For the Server-Sent Events system that delivers build events to the frontend, see page 4.7
All core graph code lives in the lfx package under src/lfx/. The langflow-base package imports from it directly:
These symbols are consumed throughout the backend API layer.
Sources: src/backend/base/langflow/api/v1/chat.py1-14 src/backend/base/langflow/api/v1/endpoints.py1-28 src/backend/base/langflow/api/build.py1-14
Module-to-class mapping for the graph layer:
Sources: src/backend/base/langflow/api/v1/chat.py11-53 src/backend/base/langflow/api/v1/endpoints.py23-24
The Graph class is the root data structure for a flow. Its key surface-area, as observed from API code:
| Attribute / Method | Type | Description |
|---|---|---|
Graph.from_payload(data, flow_id, user_id, flow_name, context) | classmethod | Deserializes flow JSON into a Graph |
graph.prepare(stop_component_id, start_component_id) | method | Computes execution order; returns self |
graph.set_run_id(run_id) | method | Stamps the graph with a run UUID |
graph.initialize_run() | async method | Resets state for a fresh execution pass |
graph.vertices | list[Vertex] | All vertices in the graph |
graph.vertices_to_run | set[str] | Vertex IDs that must execute this run |
graph.first_layer | list[str] | Vertex IDs with no unsatisfied dependencies (entry points) |
graph.run_id | str | UUID identifying the current run |
graph.stop_vertex | str | None | If set, execution halts at this vertex |
graph.inactivated_vertices | list[str] | Vertices marked inactive after a build step |
graph.run_manager | RunnableVerticesManager | Tracks concurrency state |
graph.build_vertex(vertex_id, user_id, inputs_dict, files, get_cache, set_cache) | async method | Builds one vertex; returns VertexBuildResult |
graph.get_next_runnable_vertices(lock, vertex, cache) | async method | Returns IDs runnable after a given vertex completes |
graph.get_top_level_vertices(ids) | method | Filters to non-intermediate vertices |
graph.reset_inactivated_vertices() | method | Clears inactivated_vertices |
graph.reset_activated_vertices() | method | Clears activated vertex tracking |
graph.end_all_traces_in_context(error) | async method | Finalizes tracing for all vertices |
Sources: src/backend/base/langflow/api/v1/chat.py94-135 src/backend/base/langflow/api/v1/chat.py299-433 src/backend/base/langflow/api/v1/endpoints.py146-205
Each node in the flow is a Vertex. Key attributes observed from API code:
| Attribute | Type | Description |
|---|---|---|
vertex.id | str | Matches the id from the ReactFlow node JSON |
vertex.vertex_type | str | Component class name (e.g., "ChatInput") |
vertex.base_type | str | Either "component" or "custom_components" |
vertex.params | dict | Resolved input parameter values |
vertex.outputs | list[dict] | Output port definitions |
vertex.is_output | bool | True for terminal output vertices |
vertex.built | bool | True after a successful build |
vertex.frozen | bool | True if the vertex should use a cached result |
vertex.will_stream | bool | True if this vertex streams output tokens |
vertex.built_result | Any | Result after build |
vertex.result | Any | Alias for built result |
vertex.custom_component | Component | The instantiated component object |
vertex.load_from_db_fields | list[str] | Fields requiring DB-variable resolution |
vertex.stream() | async generator | Streams output tokens |
vertex.add_build_time(delta) | method | Records build duration |
Sources: src/backend/base/langflow/api/v1/chat.py322-395 src/backend/base/langflow/interface/initialize/loading.py25-52
Edges are represented as EdgeData objects from lfx.graph.edge.schema. Each edge captures the connection between a source vertex's output port and a target vertex's input parameter. Components hold references to their edges via Component._edges.
Sources: src/lfx/src/lfx/custom/custom_component/component.py135
PlaceholderGraph (a NamedTuple in lfx.custom.custom_component.component) is a lightweight substitute for Graph used when a component runs outside a full graph (e.g., in tests or standalone execution). It provides the same interface methods that components call, such as get_vertex_neighbors(), but returns empty results.
Sources: src/lfx/src/lfx/custom/custom_component/component.py75-109
A flow is stored in the database as a JSON blob matching the ReactFlow schema (nodes, edges, viewport). The Graph.from_payload() classmethod converts this into the in-memory graph.
Graph construction data flow:
Sources: src/backend/base/langflow/api/v1/endpoints.py165-170 src/backend/base/langflow/api/v1/chat.py97-103
Two helper functions in langflow.api.utils also build graphs:
build_graph_from_db(flow_id, session, chat_service) — loads flow data from the database, then calls Graph.from_payload(), and caches the result.build_and_cache_graph_from_data(flow_id, graph_data, chat_service) — builds from inline request data instead of the database.build_graph_from_data(flow_id, graph_data, ...) — a variant used during the streaming build path.Sources: src/backend/base/langflow/api/build.py199-260 src/backend/base/langflow/api/v1/chat.py96-101
prepare() and Topological SortAfter construction, graph.prepare(stop_component_id, start_component_id) computes the execution order. This involves:
graph.first_layer — vertices that have no dependencies and can execute immediately.graph.vertices_to_run — the set of vertices that must execute (based on start_component_id / stop_component_id filters, if provided).The first_layer list is returned to the frontend in VerticesOrderResponse so the UI knows which vertices to request builds for first.
Execution planning:
Sources: src/backend/base/langflow/api/v1/chat.py102-120 src/backend/base/langflow/api/v1/chat.py389-392
Each vertex transitions through several states during a build. These states are tracked as boolean attributes on the Vertex object.
Relevant state transitions in the API:
| Transition | Code location |
|---|---|
| Mark frozen | node.data.node.frozen = True in flow JSON |
| Check built/frozen | if not vertex.frozen or not vertex.built in _stream_vertex |
| Collect inactivated | list(graph.inactivated_vertices) after build_vertex |
| Reset inactivated | graph.reset_inactivated_vertices() |
| Reset activated | graph.reset_activated_vertices() |
Sources: src/backend/base/langflow/api/v1/chat.py335-395 src/backend/base/langflow/api/v1/chat.py479
graph.run_manager is a RunnableVerticesManager that tracks:
vertices_being_run — set of vertex IDs currently executing (used for concurrency tracking).After each build_vertex() call, graph.get_next_runnable_vertices(lock, vertex=vertex, cache=False) consults the run_manager to return the next batch of vertex IDs whose dependencies have all been satisfied.
The API checks graph.run_manager.vertices_being_run to decide when to finalize tracing:
Sources: src/backend/base/langflow/api/v1/chat.py337-394
When graph.build_vertex() is called for a vertex, the internal flow is:
Vertex build sequence:
Sources: src/backend/base/langflow/interface/initialize/loading.py25-75 src/backend/base/langflow/interface/initialize/loading.py147-202
instantiate_classDefined in langflow.interface.initialize.loading:
vertex.params and pops the "code" key.eval_custom_component_code(code) (from lfx.custom.eval) to get the component class._user_id, _parameters, _vertex, _tracing_service, _id.custom_component.set_event_manager(event_manager) if available.Sources: src/backend/base/langflow/interface/initialize/loading.py25-51
get_instance_resultsResolves any parameters that need to be fetched from the database (global variables / secrets) via update_params_with_load_from_db_fields, then dispatches to either:
build_component(params, custom_component) for Component-based subclasses — calls custom_component.set_attributes(params) then await custom_component.build_results().build_custom_component(params, custom_component) for legacy CustomComponent subclasses — calls custom_component.build(**params) directly.Sources: src/backend/base/langflow/interface/initialize/loading.py54-75 src/backend/base/langflow/interface/initialize/loading.py147-202
update_params_with_load_from_db_fieldsFor each field in vertex.load_from_db_fields, attempts to resolve the stored variable name to its actual value by calling custom_component.get_variable(name, field, session). If resolution fails and fallback_to_env_vars=True, falls back to os.getenv().
Sources: src/backend/base/langflow/interface/initialize/loading.py111-144
This diagram shows how the graph processing layer integrates with the API and event system during a POST /build/{flow_id}/flow call.
Sources: src/backend/base/langflow/api/v1/chat.py138-203 src/backend/base/langflow/api/build.py59-98 src/backend/base/langflow/api/build.py199-260
The Graph object is cached between requests using the ChatService. After Graph.from_payload() + prepare(), the graph is stored:
Subsequent API calls (e.g., the individual build_vertex endpoint) retrieve it:
initialize_run() resets transient execution state (e.g., which vertices have been built) without reconstructing the full graph structure, enabling incremental vertex builds in the interactive playground.
Sources: src/backend/base/langflow/api/v1/chat.py299-320 src/backend/base/langflow/api/v1/chat.py383-385
| Schema | Module | Description |
|---|---|---|
RunOutputs | lfx.graph.schema | Structured output of a complete graph run |
EdgeData | lfx.graph.edge.schema | Source/target vertex + port for one edge |
InputValueRequest | lfx.schema.schema | Input values passed at run time |
OutputValue | lfx.schema.schema | Output value from a vertex, including type |
VertexBuildResponse | langflow.api.v1.schemas | API response after building one vertex |
VerticesOrderResponse | langflow.api.v1.schemas | Returns first_layer, run_id, vertices_to_run |
ResultDataResponse | langflow.api.v1.schemas | Per-vertex result including outputs and logs |
Sources: src/backend/base/langflow/api/v1/schemas.py260-332 src/backend/base/langflow/schema/schema.py1-24
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.