Eager and Lazy Execution
ControlFlow supports two execution modes: eager execution and lazy execution. Understanding these modes is essential for controlling the behavior of your workflows and optimizing performance.
Eager Execution
Eager mode is the default for the functional API. In this mode, flows and tasks are executed immediately when called.
In this example, the write_poem
task is executed by an AI agent as soon as its function is called. The AI agent generates a short poem based on the provided topic, and the generated poem is returned as the poem
variable.
Eager execution allows you to mix task-decorated functions with normal Python code seamlessly, enabling you to use standard Python control flow statements, such as conditionals and loops, to control the execution of tasks.
Lazy Execution
Lazy execution means that tasks are not executed when they are created. Instead, ControlFlow builds a directed acyclic graph (DAG) of tasks and their dependencies, and executes them only when necessary.
Lazy execution is the only mode available for the imperative API, as imperative tasks must be run explicitly. You can also run functional tasks lazily by passing lazy_=True
when calling the task.
Running Lazy Tasks Eagerly
You can run a lazy task eagerly by calling its run()
method. This will run not only the task itself but also any tasks it depends on. This is useful when you need to use a task result immediately or with standard Python control flow or functions.
Benefits of Lazy Execution
Lazy execution is generally recommended because it permits the orchestration engine to optimize workflow execution based on knowledge of the entire workflow structure. For example, agents may handle a task differently if they know how its result will be used. In some cases, agents may even be able to combine multiple tasks into a single operation or parallelize tasks that are independent of each other.
This can lead to more efficient execution, especially in complex workflows with many dependencies.
In addition, lazy execution allows you to exercise more precise control over how and when tasks are executed. Instead of running tasks to completion, you can use run_once()
to run a single step or the agentic loop, or assign a specific agent to work on the task.
When Do Lazy Tasks Run?
Lazily-executed tasks are run under the following conditions, in order:
- When their
run()
method is called. - When they are an upstream dependency of another task that is run
- When their parent flow is run