Actions API¶
The Zelos SDK Actions API provides a way to define interactive Python functions with rich input validation and metadata. Actions can be decorated with input parameters, validation rules, and UI hints to create dynamic, user-friendly interfaces.
Quick Start¶
Define a simple action and make it available to the Zelos Agent:
from zelos_sdk import init, action
# Define a simple action
@action("Add Numbers", "Add two numbers together")
@action.input("x", type="number", required=True, description="First number")
@action.input("y", type="number", required=True, description="Second number")
def add(x: float, y: float):
return x + y
# Make your actions available to the Zelos Agent, block until Ctrl+C
init(actions=True, block=True)
Running the script above results in this Action in the Zelos App:
Core Components¶
@action Decorator¶
The @action
decorator transforms regular Python functions into rich, interactive actions with metadata and validation.
from zelos_sdk.actions import action
@action("Process Data", "Process incoming sensor data")
@action.input("data", type="object", required=True, description="Raw sensor data")
@action.input("threshold", type="number", default=100, description="Alert threshold")
def process_sensor_data(data: dict, threshold: float = 100):
processed = {
"timestamp": data.get("timestamp"),
"values": [v for v in data.get("values", []) if v < threshold],
"alerts": [v for v in data.get("values", []) if v >= threshold]
}
return processed
Input Field Types¶
Actions support rich input validation with multiple field types:
@action("Configure System", "Configure system settings")
@action.input("name", type="text", required=True, min_length=3, max_length=50)
@action.input("port", type="number", minimum=1, maximum=65535, default=8080)
@action.input("enabled", type="boolean", default=True)
@action.input("mode", type="select", choices=["dev", "staging", "prod"], required=True)
def configure_system(name: str, port: int = 8080, enabled: bool = True, mode: str = "dev"):
return {
"configuration": {
"name": name,
"port": port,
"enabled": enabled,
"mode": mode
},
"status": "configured"
}
Dynamic Input Fields¶
Create inputs that change based on other field values:
def get_available_models(category: str):
models = {
"car": ["sedan", "suv", "truck"],
"bike": ["road", "mountain", "hybrid"]
}
return models.get(category, [])
@action("Select Vehicle", "Choose a vehicle type and model")
@action.input("category", type="select", choices=["car", "bike"], required=True)
@action.input("model", type="select", choices=get_available_models,
depends_on="category", required=True)
def select_vehicle(category: str, model: str):
return {"selected": f"{category} - {model}"}
Class-Based Actions¶
Organize related actions within classes:
from zelos_sdk.actions import action
class DeviceManager:
def __init__(self):
self.devices = {}
@action("Start Device", "Start a device by ID")
@action.input("device_id", type="text", required=True)
def start_device(self, device_id: str):
self.devices[device_id] = {"status": "running"}
return {"device_id": device_id, "status": "started"}
@action("Get Device Status", "Get current status of a device")
@action.input("device_id", type="text", required=True)
def get_device_status(self, device_id: str):
return self.devices.get(device_id, {"status": "unknown"})
# Create instance to make actions available
device_manager = DeviceManager()
ActionsRegistry¶
Registries are used to collect actions. The default global registry is actions_registry
.
The actions_registry
discovers available actions by scanning the environment or by manual registration:
from zelos_sdk import actions_registry
# Register individual functions
actions_registry.register(add_numbers, name="math")
# Register class instances with all their actions
actions_registry.register(device_manager, name="devices")
# List all registered actions
namespaces = actions_registry.list_namespaces()
print(namespaces) # {"math": ["add_numbers"], "devices": ["start_device", "get_device_status"]}
# Get specific action metadata
action_obj = actions_registry.get_action("math", "add_numbers")
schema = action_obj.to_schema() # JSON Schema for validation
ActionsClient¶
The ActionsClient can be used to serve actions to the Zelos Agent and/or list, execute actions. See Using Custom Registries with ActionsClient
JSON Schema Generation¶
Actions automatically generate JSON Schema for validation and UI generation:
# Get the action object
action_obj = actions_registry.get_action("math", "add_numbers")
# Generate JSON Schema
schema = action_obj.to_schema()
print(schema)
# {
# "title": "Add Numbers",
# "description": "Add two numbers together",
# "type": "object",
# "properties": {
# "x": {"type": "number", "title": "X", "description": "First number"},
# "y": {"type": "number", "title": "Y", "description": "Second number"}
# },
# "required": ["x", "y"]
# }
# Generate UI Schema for form rendering
ui_schema = action_obj.to_ui_schema()
Making Actions Available¶
There are two ways to make your actions available to the Zelos Agent:
Using the Global Registry with init()¶
The init()
function with actions=True
is the simplest approach:
from zelos_sdk import init
from zelos_sdk.actions import action
@action("Process Data", "Process some data")
@action.input("value", type="number", required=True)
def process(value: float):
return {"processed": value * 2}
# Make actions available to the Zelos Agent
init(actions=True)
Using Custom Registries with ActionsClient¶
For more control or isolated services, create your own ActionsClient
with a custom registry:
from zelos_sdk.actions import action, ActionsRegistry, ActionsClient
@action("Process Data", "Process some data")
@action.input("value", type="number", required=True)
def process(value: float):
return {"processed": value * 2}
# Create custom registry and register actions
custom_registry = ActionsRegistry()
custom_registry.register(process, name="data_processor")
# Create client and serve with custom registry
client = ActionsClient()
client.serve("my_service", actions_registry=custom_registry)
Multiple Actions in Custom Registries¶
You can register multiple actions in a custom registry:
from zelos_sdk.actions import action, ActionsRegistry, ActionsClient
@action("Add", "Add two numbers")
@action.input("a", type="number", required=True)
@action.input("b", type="number", required=True)
def add(a: float, b: float):
return {"result": a + b}
@action("Multiply", "Multiply two numbers")
@action.input("x", type="number", required=True)
@action.input("y", type="number", required=True)
def multiply(x: float, y: float):
return {"result": x * y}
# Create a custom registry for specific actions
math_registry = ActionsRegistry()
math_registry.register(add, name="math")
math_registry.register(multiply, name="math")
# Create client and serve with custom registry
client = ActionsClient()
client.serve("math_service", actions_registry=math_registry)
Class-Based Service Organization¶
Organize related actions into services. You can use the global registry, custom registries, or both:
from zelos_sdk import init, action, actions_registry
class MotorController:
@action("Set Speed", "Set motor speed")
@action.input("motor_id", type="text", required=True)
@action.input("rpm", type="number", minimum=0, maximum=3000, required=True)
def set_speed(self, motor_id: str, rpm: float):
return {"motor_id": motor_id, "speed_set": rpm, "status": "running"}
motor_controller = MotorController()
# Option 1: Use global registry
actions_registry.register(motor_controller, name="motor_controller")
init(actions=True)
# Option 2: Use custom registry
from zelos_sdk.actions import ActionsRegistry, ActionsClient
custom_registry = ActionsRegistry()
custom_registry.register(motor_controller, name="motor_controller")
client = ActionsClient()
client.serve("motor_service", actions_registry=custom_registry)
Action Execution¶
Execute actions directly with validation:
# Execute action directly
result = action_obj.execute(x=5, y=3)
print(result) # {"result": 8, "operation": "addition"}
# Validation happens automatically
try:
action_obj.execute(x="invalid") # Will raise ValidationError
except ValidationError as e:
print(f"Validation failed: {e}")
Module Documentation¶
Module | Description |
---|---|
Advanced Usage | Deep dives into field types, validation, and complex patterns |
The actions system provides a powerful foundation for creating interactive, validated Python functions that can be used in various contexts including web UIs, CLI tools, and automated systems.