This PR introduces a comprehensive event-based debugging system for Langflow graph execution, enabling detailed tracking and analysis of graph state mutations during execution. The implementation uses a pure observer pattern that provides zero overhead when not in use, making it production-safe.
- Event Infrastructure: New
GraphMutationEventsystem that tracks all graph state changes with before/after snapshots - Observer Pattern: Pure observer pattern implementation with
register_observer()andunregister_observer()methods - Zero Overhead: Fast path when no observers are registered, ensuring no performance impact in production
- Serializable Events: Events can be serialized to dictionaries for replay and storage
- EventRecorder: Observer that captures all graph mutations during execution
- EventBasedRecording: Rich recording object with analysis methods:
get_events_by_type()- Filter events by typeget_events_for_vertex()- Get all events for a specific vertexget_queue_evolution()- Track how the execution queue changes over timeget_dependency_changes()- Monitor dependency modificationsshow_summary(),show_timeline(),show_events_for_component()- Visualization methods
- Save/Load: Recordings can be saved to and loaded from files for later analysis
- Synchronized Dependencies: Loop component now properly updates both
run_predecessorsandrun_mapto keep dependency structures synchronized - State Reset: New
reset_loop_state()method for clean loop state management between executions - Better Documentation: Added critical comments explaining the relationship between dependency structures
- Async Methods: Made
remove_from_predecessors()andremove_vertex_from_runnables()async for consistency - Sync Variants: Added
mark_branch_sync()for synchronous contexts (used by custom components) - Centralized Mutations: All graph mutations now go through centralized methods that emit events
- Path Equivalence Testing: New test suite that validates both
async_start()andarun()execution paths produce identical results - Test Data Flows: Uses test flows that don't require API keys for reliable CI testing
- Comprehensive Tracing:
ExecutionTracercaptures complete execution traces for comparison
- Mutation Event Tests: Tests for queue operations, dependency updates, and event emission
- Event Recorder Tests: Tests for event capture, queue evolution tracking, and recording analysis
- Graph Mutation Tests: Tests ensuring both dependency structures stay synchronized
- TYPE_CHECKING Block Support: Component validation now properly handles
TYPE_CHECKINGblocks, extracting imports needed forget_type_hints()to work correctly - Better Error Handling: Improved error handling for components defined in notebooks or REPL environments
- Source Code Extraction: More robust source code extraction with graceful fallbacks
queue_extended- When vertices are added to the execution queuequeue_dequeued- When vertices are removed from the queuedependency_added- When dynamic dependencies are addedvertex_marked- When vertex states change (ACTIVE/INACTIVE)
Graph
├── register_observer() / unregister_observer()
├── _emit_event() - Emits events to all observers
└── All mutations → emit before/after events
├── extend_run_queue()
├── add_dynamic_dependency()
├── mark_branch_sync()
└── remove_from_predecessors()
from lfx.graph.graph.base import Graph
from lfx.debug.event_recorder import record_graph_with_events
# Record graph execution
graph = Graph.from_payload(flow_data)
recording = await record_graph_with_events(graph, "My Flow")
# Analyze the recording
recording.show_summary()
recording.show_timeline()
# Get specific insights
queue_evolution = recording.get_queue_evolution()
dependency_changes = recording.get_dependency_changes()
# Save for later analysis
recording.save("flow_recording.pkl")src/lfx/src/lfx/debug/__init__.py- Debug module initializationsrc/lfx/src/lfx/debug/events.py- GraphMutationEvent and observer typessrc/lfx/src/lfx/debug/event_recorder.py- EventRecorder and EventBasedRecordingsrc/backend/tests/unit/graph/test_execution_path_validation.py- Execution path equivalence testssrc/backend/tests/unit/graph/test_execution_path_equivalence.py- Execution tracing utilitiessrc/backend/tests/unit/graph/test_event_recorder.py- Event recorder testssrc/backend/tests/unit/graph/test_graph_mutation_events.py- Mutation event tests
src/lfx/src/lfx/graph/graph/base.py- Added observer pattern, event emissionsrc/lfx/src/lfx/graph/graph/runnable_vertices_manager.py- Made methods asyncsrc/lfx/src/lfx/components/logic/loop.py- Improved dependency synchronizationsrc/lfx/src/lfx/custom/custom_component/component.py- Better error handlingsrc/lfx/src/lfx/custom/custom_component/custom_component.py- Use mark_branch_syncsrc/lfx/src/lfx/custom/validate.py- TYPE_CHECKING block supportpyproject.toml- Added marimo dependency for debugging notebooks
- Debugging: Comprehensive visibility into graph execution state changes
- Testing: Better test coverage with execution path validation
- Reliability: Synchronized dependency structures prevent bugs
- Performance: Zero overhead when debugging is not active
- Extensibility: Easy to add new event types and observers
- ✅ All existing tests pass
- ✅ New execution path validation tests pass
- ✅ Event system tests pass
- ✅ Loop component tests pass with improved dependency handling
None - This is a purely additive change. The event system is opt-in and has zero overhead when not used.
- Add more event types (vertex execution start/end, memory updates, etc.)
- Create visualization tools for event recordings
- Add event filtering and querying capabilities
- Integrate with Langflow UI for real-time debugging