---
title: "Control Flow"
description: "Workflows are broken into multiple steps, which can be executed following different behaviours"
---

## Dependencies between Steps

We have previously seen how to access the [Run Context](../core-concepts/context/#accessing-the-runcontext) to store additional data of the run.
Additionally, steps can access the data from their parent run or neighbour steps within the workflow.

- `current_trace()` - Access the current step's data
- `parent_trace()` - Access the parent workflow's data
- `step_trace("step_name")` - Access any specific neighbour step's data

Referencing data from another run creates dependencies within the Workflow.
**Timbal automatically resolves these dependencies** to ensure proper execution.


## Default Execution

Steps run in **parallel** by default. If one step produces an output needed by another, **the framework automatically enforces sequential execution between those steps**. The dependency is resolved under the hood.

```python highlight={13}
import asyncio
from timbal import Workflow

async def func_1(x: str):
    asyncio.sleep(1)
    return x

async def func_2(y: str):
    asyncio.sleep(10)
    return y

async def func_3():
    return get_run_context().step_trace("func_1").output    # output from func_1

workflow = (Workflow(name='my_workflow')
    .step(func_1, x="a")
    .step(func_2, y="b")
    .step(func_3)
)
```

In this example, we have:
- `func_1` and `func_2` run concurrently.
- `func_3` starts only after `func_1` has finished.
- The workflow's final output will be ***b***, since `func_2` it is the last to finish.

## Forcing Sequential Execution

Steps can be run sequentially even if there is no data dependency with `depends_on` parameter.

```python highlight={3}
workflow = (Workflow(name='my_workflow')
    .step(func_1, x="a")
    .step(func_2, y="b", depends_on=[func_1])
    .step(func_3)
)
```

Now, both steps `func_2`and `func_3` must wait for `func_1` to finish.


## Summary

- Parallel execution by default.
- Sequential execution is applied automatically when parameter dependencies exist between steps.
- Sequential execution can be enforced with `depends_on`.
