Hello World: Tierkreis Edition¶
In this example we will construct a workflow graph that uses the greet function from the hello_world_worker we defined in the previous example.
We want to write a graph that produces the output hello world.
First we provide the necessary imports, the GraphBuilder, a class for constructing workflows, and TKR; you can think of it as tierkreis types (more on this at the bottom of the page).
This ensures, that only types are used that can be processed internally.
%pip install tierkreis
/home/runner/work/tierkreis/tierkreis/.venv/bin/python3: No module named pip
Note: you may need to restart the kernel to use updated packages.
from tierkreis.builder import GraphBuilder
from tierkreis.controller.data.models import TKR
A workflow is just a representation of a computation.
The example we are going to build represents a function str -> str.
This signature is defined at instantiation of the Graph builder object
graph = GraphBuilder(inputs_type=TKR[str], outputs_type=TKR[str])
We could simply use a graph that just returns its input.
Instead were going to construct the string hello world from an constant value and an input.
First we define the constant part, by adding a constant node to the graph.
hello = graph.const("Hello ")
We capture the output of that node in the variable hello, which we can use as input to other nodes to insert an edge in the graph.
Inputs to the graph cah be referenced in two ways depending if we have a single input (graph.inputs) or multiple inputs (graph.inputs.<input_name>).
We will cover multiple inputs in a later example.
For now, we want to call the greet function from the hello_world_worker.
To use the type hints from that worker we can import the interface and then use it as a task.
from hello_world_worker import greet
output = graph.task(greet(greeting=hello, subject=graph.inputs))
The benefit of using the function interface is the type checking. The python typechecker will warn us if we provide a type of an incorrect input. To complete our graph, we now have to define an output. As an invariant, a well-formed graph has exactly one output. Although, this output can consist of multiple values, we will cover this in a later example.
graph.outputs(output)
Now that we have defined a workflow we can run the graph.
The most generic way to do this is the run_workflow function which requires the following inputs:
The graph to run.
A dictionary providing the inputs to the graph. A single input will always have the key
"value". In this case we want to set it to{"value": "world!"}
To make this reproducible we can define a name and a run_id.
To make sure tierkreis can find our worker, we have to define the registry_path.
Since it is a python worker we use uv to run it.
from pathlib import Path
from tierkreis.cli.run_workflow import run_workflow
def main(input_value: str) -> None:
run_workflow(
graph.data,
{"value": input_value},
name="hello_world",
run_id=100, # Assign a fixed uuid for our workflow.
registry_path=Path().parent
/ "example_workers", # Look for workers in the `example_workers` directory.
use_uv_executor=True,
print_output=True,
)
Finally we can run the code, which will print the desired output Hello world!.
if __name__ == "__main__":
main("world!")
value: 'Hello world!'
On tierkreis types¶
Tierkreis values correspond to the edges in the graph.
These values can have a type assigned to them at construction time.
The set of available types is a subset of all python types, e.g. we require serialization; see more in complex types how to add your own serialization.
As result we use the TKR container to promote the python types into tierkreis compatible types.