Creating tasks¶
This guide explains how to create tasks that can be orchestrated by purjo using either traditional Robot Framework keyword libraries or a more advanced pure Python approach.
Basic task (Robot Framework)¶
The most common way to define tasks in purjo is by using Robot Framework keyword libraries. This involves creating a Python file with your custom keywords and a .robot file to define the task suite.
Example: The “Hello” task¶
Here is a basic illustration.
Hello.py (Keyword library)¶
from robot.api.deco import keyword
from robot.api.deco import library
@library()
class Hello:
@keyword()
def hello(self, name: str) -> str:
return f"Hello {name}!"
This Python file defines a simple Robot Framework library named Hello with one keyword: hello. This keyword takes a name and returns a greeting string.
hello.robot (Task suite)¶
*** Settings ***
Library Hello
*** Tasks ***
My Task in Robot
${greeting}= Hello World
Log To Console ${greeting}
The hello.robot file imports the Hello library and defines a task named “My Task in Robot”. This task calls the hello keyword, passes “World” as the name, and logs the returned greeting to the console.
hello.bpmn (BPMN process)¶
Your BPMN process would then include an external service task that references this Robot Framework task. For instance, a service task with Topic “My Topic in BPMN” might be configured to execute “My Task in Robot” from hello.robot.
Configuration¶
To map the BPMN topic to the Robot Framework task, you need to configure pyproject.toml.
[tool.purjo.topics."My Topic in BPMN"]
name = "My Task in Robot"
on-fail = "ERROR"
process-variables = true
pythonpath = ["./libs", "./modules"]
[tool.purjo.topics."<Topic Name>"]: Defines the configuration for a specific BPMN topic.name: The name of the Robot Framework task (or Python function) to execute.on-fail: Determines the behavior when the task fails (e.g., “ERROR”, “FAIL”). See Variables of a failed task for what a failed task leaves behind.process-variables: Iftrue, process variables are passed to the task. Iffalse, only task scope variables are passed to the task.pythonpath: (Optional) A list of additional paths to add to Robot Framework’s--pythonpath. This allows importing custom libraries and modules from specified directories.
Advanced task (Pure Python)¶
purjo also supports defining tasks directly in Python, allowing for more complex logic and direct integration with Python’s type hinting and data validation features like Pydantic. This approach can replace the need for a separate .robot file for simple tasks.
Example: A pure Python task¶
This approach is demonstrated below.
tasks.py (Pure Python task)¶
from pydantic import BaseModel
from robot.api import logger
from robot.libraries import BuiltIn
from typing import Literal
import json
VariableScope = Literal["BPMN:TASK", "BPMN:PROCESS"]
class InputVariables(BaseModel):
name: str = "John Doe"
class OutputVariables(BaseModel):
message: str
def get_variables() -> InputVariables:
library = BuiltIn.BuiltIn()
return InputVariables(**library.get_variables(no_decoration=True))
def set_variables(
variables: OutputVariables, scope: VariableScope = "BPMN:PROCESS"
) -> None:
library = BuiltIn.BuiltIn()
try:
if scope == "BPMN:TASK":
for name, value in variables.model_dump().items():
{% raw %}
library._variables.set_bpmn_task(f"${{{name}}}", value)
else:
for name, value in variables.model_dump().items():
library._variables.set_bpmn_process(f"${{{name}}}", value)
{% endraw %}
except AssertionError:
logger.info(json.dumps(variables.model_dump(), indent=2))
def main():
variables = get_variables()
set_variables(OutputVariables(message=f"Hello, {variables.name}!"))
if __name__ == "__main__":
from purjo import PythonParser
from robot import run
run(__file__, parser=PythonParser("tasks.main"))
Key features:¶
Pydantic Models (
InputVariables,OutputVariables): These models enforce strict typing and validation for variables exchanged with the BPMN engine, making your task more robust.get_variables()andset_variables(): Helper functions to easily retrieve input variables from the BPMN process and set output variables back to it.main()Function: Encapsulates the core logic of your task. It retrieves variables, performs operations, and sets new variables.if __name__ == "__main__":Block: This block enables the Python script to be executed directly as a Robot Framework task usingpurjo’sPythonParser. This means you can specifytasks.mainas the Robot Framework task to be executed by your BPMN process, without needing a separate.robotfile.
This advanced approach is particularly useful for tasks that are primarily Python-based, requiring minimal or no Robot Framework specific syntax beyond what purjo provides for variable handling.
Configuration¶
To map the BPMN topic to the Pure Python task, you need to configure pyproject.toml.
[tool.purjo.topics."My Topic in BPMN"]
name = "tasks.main"
on-fail = "FAIL"
process-variables = true
name: The name of the Python function to execute, in the formatmodule.function. In this example,tasks.mainrefers to themainfunction intasks.py.
Adding dependencies¶
When your tasks require external Python libraries (e.g., requests, pandas, PyPDF2), you need to add them to your project’s dependencies. purjo uses uv for dependency management.
To add a dependency, use the uv add command:
$ uv add requests
This command updates your pyproject.toml file and the uv.lock file, ensuring that the dependency is available when your tasks are executed.
Packaging¶
Once your tasks are ready, you can package them into a robot.zip file using the pur wrap command.
$ pur wrap
This command creates a robot.zip file containing your project files, excluding those specified in .wrapignore (and default exclusions like .git, __pycache__, etc.). This zip file can be deployed to an external worker or used for distribution.
Creating BPMN resources¶
purjo provides a convenient way to create new BPMN, DMN, and Form files using the pur operaton create command.
$ pur operaton create my-process.bpmn
$ pur operaton create my-decision.dmn
$ pur operaton create my-form.form
This generates template files with unique IDs, ready for editing in any bpmn.io-compatible modeler.