This hello-world example demonstrates three foundational workflow patterns:
- A minimal task definition (
calculate_square) - A task that chains runs of another task (
sum_squares) - A task with custom retry behavior (
flip_coin)
- How to define tasks with
@app.task - How to chain task runs using
awaitandasyncio.gather - How to customize retry behavior with
Retry
The smallest possible task: takes one integer and returns its square.
Chains two runs of calculate_square and sums the results.
It uses asyncio.gather(...) to chain the two runs in parallel:
result1, result2 = await asyncio.gather(
calculate_square(a),
calculate_square(b),
)Simulates a coin flip:
- Heads: Returns success
- Tails: Raises an error to trigger retry
Retry policy in this example:
- max retries:
3 - wait duration:
1000ms - backoff scaling:
1.5
- Python 3.10+
Make sure you've installed the latest version of the Render CLI.
-
From this template's root, start the local task server:
pip install -r requirements.txt render workflows dev -- python main.py
-
In a separate terminal, trigger task runs:
render workflows tasks start calculate_square --local --input='{"a": 5}' render workflows tasks start sum_squares --local --input='{"a": 3, "b": 4}' render workflows tasks start flip_coin --local --input='{}'
Expected behavior:
calculate_squarewitha=5returns25sum_squareswitha=3,b=4returns25flip_coinmay fail and retry before succeeding
Configure your Workflow service with:
| Option | Value |
|---|---|
| Build command | pip install -r requirements.txt |
| Start command | python main.py |
Any function decorated with @app.task is registered when your service starts via app.start().
Inside an async task, calling await other_task(...) runs that task as a subtask.
Use @app.task(retry=Retry(...)) when transient failures should be retried automatically.
- Confirm the service is running
- Verify task names exactly match:
calculate_square,sum_squares,flip_coin
- Confirm dependency install completed from
requirements.txt - Confirm Python version is 3.10+