Python library for building automation agents on the Ondemand platform. Provides step supervision, input handling, artifact management, R2 storage, and HITL approval requests.
Robots use the install_private_packages.py shim in bin/ which installs the library at runtime using GITHUB_TOKEN. See robo-demo for the pattern.
# Via SSH (recommended)
pip install git+ssh://git@github.com/Ondemand-AI/ondemand-python.git@main
# Or install locally in editable mode
git clone git@github.com:Ondemand-AI/ondemand-python.git
cd ondemand-python
pip install -e .from ondemand import supervised_step
@supervised_step("Processamento de Dados")
def process(self):
# Your automation logic here
# Step reporting, artifact upload, and error handling are automatic
passfrom ondemand.shared import get_inputs
inputs = get_inputs() # Parses ONDEMAND_INPUTS JSON env var
empresa = inputs.get("empresa")
periodo = inputs.get("periodo")
input_files = inputs.get("input_file") # Can be a list of R2 keysfrom ondemand.shared import save_artifact, load_artifact
# Save artifact (to output/{run_id}/{task_name}/)
save_artifact({"companies": data})
# Load artifact from another task
state = load_artifact(task="Iniciar Coleta")from ondemand.shared import download_input_files
# Downloads all R2-keyed inputs to a local directory
downloaded = download_input_files(inputs, dest_dir=Path("./downloads"))Pause execution and wait for human approval before continuing.
from ondemand import request_approval
# Request approval — returns URLs for approve/reject
approval_url, rejection_url = request_approval(
message="3 divergências encontradas. Revisar?",
data={"total": 15000, "empresas": ["ABC Corp", "XYZ Inc"]},
show_buttons=True, # Show buttons in portal UI
timeout_days=7, # Max wait time (default: 7)
)
# Developer sends notification however they want
logger.info(f"Approval: {approval_url}")
logger.info(f"Rejection: {rejection_url}")
send_email(to="reviewer@client.com", body=f"Approve: {approval_url}")Behavior:
request_approval()is synchronous — sends webhook to portal, gets URLs back- After calling, the step should exit normally (artifacts are uploaded)
- The Temporal workflow pauses automatically (worker slot is freed)
- If approved → next task executes
- If rejected → remaining steps cancelled, run completes successfully
- If timeout → run status becomes
timed_out, approval auto-rejected
Raises ApprovalRequestError if the portal is unreachable after 3 retries.
from ondemand import build_manifest_step, update_manifest
steps = [
build_manifest_step("company_a", "Process Company A", children=[
build_manifest_step("company_a_extract", "Extract Data"),
build_manifest_step("company_a_validate", "Validate Data"),
])
]
update_manifest(steps, parent_step_id="Processing")- CLI
--inputs— JSON string (local testing) - CLI
--inputs-file— Path to JSON file (local testing) ONDEMAND_INPUTSenv var — Set by worker in production (JSON string)
Note: Inputs are NOT individual env vars. They come as a single JSON string in
ONDEMAND_INPUTS.
| Variable | Description |
|---|---|
ONDEMAND_RUN_ID |
Current run UUID |
ONDEMAND_INPUTS |
JSON string with all user inputs |
ONDEMAND_WEBHOOK_URL |
Webhook URL for reporting progress |
ONDEMAND_WEBHOOK_SECRET |
Auth secret for webhooks |
GITHUB_TOKEN |
For private package installation |
R2_ENDPOINT, R2_ACCESS_KEY, R2_SECRET_KEY, R2_BUCKET |
R2 storage credentials |
BW_* |
Bitwarden vault credentials (per-org) |
# With inline inputs
python src/process.py --inputs '{"empresa": "Test", "periodo": "2024-01"}'
# With input file
python src/process.py --inputs-file test_inputs.json
# With RCC
rcc task run --task Process -- --inputs '{"empresa": "Test"}'ondemand/
├── __init__.py # Top-level exports (supervised_step, request_approval, etc.)
├── shared/
│ ├── __init__.py # Shared exports
│ ├── approval.py # request_approval() for HITL
│ ├── artifacts.py # save_artifact, load_artifact, output dirs
│ ├── cli.py # CLI parsing, get_inputs()
│ ├── logging.py # OndemandLogger
│ └── r2_storage.py # R2 client, download_input_files, upload
└── supervisor/
├── __init__.py # Supervisor exports
└── connector.py # @supervised_step decorator, webhook reporting