Note
Go to the end to download the full example code.
WorkGraph
WorkGraph is a collection of tasks and links.
Create workgraph
First, create an empty workgraph:
from aiida_workgraph import WorkGraph, task
wg = WorkGraph(name='my_first_workgraph')
Define and use tasks
# Define a task:
@task()
def add(x, y):
return x + y
# Add tasks to the workgraph
add1 = wg.add_task(add, name='add1')
add2 = wg.add_task(add, name='add2')
Add a link between tasks:
wg.add_link(add1.outputs.result, add2.inputs.x)
# Visualize the graph
wg
Note
By creating a link to add2.inputs.x, you can no longer set this task’s input
directly. It can only be changed through changes to add1.outputs.result.
Execute the workgraph
With the graph defined, you can now execute it. You provide the inputs for the tasks.
from aiida import load_profile
load_profile()
wg.run(inputs={'add1': {'x': 1, 'y': 2}, 'add2': {'y': 3}})
{}
Graph-level inputs and outputs
As workflows grow, managing inputs for many tasks can become cumbersome. WorkGraph allows you to define graph-level inputs and outputs to create a cleaner, more user-friendly interface for your complex logic.
This lets you:
Reuse a single input across multiple tasks.
Hide internal complexity and only expose essential inputs.
Collect and rename key results as named workflow outputs.
wg = WorkGraph('graph_inputs_outputs')
# Define graph-level input
wg.inputs.x = 2
# Add tasks using the graph-level input
wg.add_task(add, 'add1', x=wg.inputs.x, y=3)
wg.add_task(add, 'add2', x=wg.inputs.x, y=wg.tasks.add1.outputs.result)
# Define graph-level outputs to expose selected task results
wg.outputs.sum1 = wg.tasks.add1.outputs.result
wg.outputs.sum2 = wg.tasks.add2.outputs.result
# Run the WorkGraph
wg.run()
# Verify the final output
assert wg.outputs.sum2.value == 2 + (2 + 3)
# Visualize the graph with inputs and outputs
wg
Note
As when explicitly linking tasks, graph-level inputs create a link that cannot be
overridden by setting task-level inputs. In this case, this means you cannot set
wg.tasks.add1.inputs.x or wg.tasks.add2.inputs.x, in addition to
being unable to set wg.tasks.add2.inputs.y due to the link to add1’s
result.
Context variables
Context variables (ctx) are used to store and pass intermediate data within a workflow that isn’t directly an input or output of a task. This is especially useful for workflows with conditional logic (if/else) or loops, where you need to manage state between steps.
wg = WorkGraph(name='context_example')
# Setting the ``ctx`` attribute of the WorkGraph directly, on initialization
wg.ctx = {'x': 2, 'data.y': 3}
wg.add_task(add, 'add1', x=wg.ctx.x, y=wg.ctx.data.y)
# Assign the result of a task to a context variable
wg.ctx.sum = wg.tasks.add1.outputs.result
# Use the context variable in another task
wg.add_task(add, 'add2', x=wg.ctx.x, y=wg.ctx.sum)
Context variables can be nested, allowing you to organize complex data structures. For example, you can store multiple results in a structured way:
wg.ctx.data = {
'sum1': wg.tasks.add1.outputs.result,
'sum2': wg.tasks.add2.outputs.result,
}
WorkGraph engine
The WorkGraph engine operates on a dataflow programming model. Once submitted, the engine continuously monitors the tasks in the graph. A task is executed only when all of its inputs are available. This means:
Tasks with no inputs are executed first.
A task starts only after all the upstream tasks linked to its inputs are finished.
Total running time of the script: (0 minutes 1.886 seconds)