Diese Anleitung zeigt dir, wie du einen neuen UV-basierten Robot für das ProcessCube Robot Agent System erstellst.
UV ist ein moderner Python Package Manager (20-40x schneller als pip), der für ProcessCube Robots verwendet wird. Ein UV-Robot besteht aus:
- main.py - Das Robot-Skript mit der Hauptlogik
- pyproject.toml - Konfiguration mit Abhängigkeiten
- uv.lock - Lock-Datei für reproduzierbare Installationen
- README.md (optional) - Dokumentation
Erstelle ein neues Verzeichnis für deinen Robot im robots/src/uv/ Ordner:
mkdir -p robots/src/uv/mein-neuer-robot
cd robots/src/uv/mein-neuer-robotErstelle eine pyproject.toml Datei mit der Grundkonfiguration:
[project]
name = "mein-neuer-robot"
version = "0.1.0"
description = "Beschreibung meines Robots"
requires-python = ">=3.11"
dependencies = [
"robocorp-workitems>=1.0.0",
]Script-basierte Robots brauchen KEINE [build-system] Section. Diese ist nur für Python Pakete notwendig, die gebaut werden sollen. Mit [build-system] versucht UV, deinen Robot als Wheel zu bauen, was fehlschlägt.
❌ FALSCH:
[build-system]
requires = ["flit_core"]
build-backend = "flit_core.buildapi"✅ RICHTIG:
[project]
name = "mein-neuer-robot"
version = "0.1.0"
# ... dependencies ...
# KEINE [build-system] Section!Erstelle die Hauptdatei main.py mit deiner Robot-Logik:
"""Beschreibung deines Robots."""
import json
import logging
from typing import Any, Dict
from robocorp.workitems import inputs, outputs
# Logging konfigurieren
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def process_data(input_data: Dict[str, Any]) -> Dict[str, Any]:
"""Verarbeite die Eingabedaten.
Args:
input_data: Eingabe-Payload vom Work Item
Returns:
Dictionary mit Verarbeitungsergebnis
"""
logger.info(f"Verarbeite Input: {input_data}")
# Hier kommt deine Geschäftslogik hin
result = {
"original_input": input_data,
"processed": True,
"status": "completed"
}
logger.info(f"Output: {result}")
return result
def main():
"""Haupteinstiegspunkt für den Robot.
Liest Input Work Items, verarbeitet sie und schreibt Output Work Items.
"""
logger.info("Robot gestartet")
try:
logger.info("Lese Input Work Items...")
# In robocorp.workitems >= 1.0: durch inputs iterieren
for input_item in inputs:
payload = input_item.payload
logger.info(f"Erhalten: {payload}")
# Verarbeite die Daten
result = process_data(payload)
# Schreibe Output Work Item
logger.info("Schreibe Output Work Item...")
output_item = outputs.create(result)
output_item.save()
logger.info("Robot erfolgreich abgeschlossen")
except Exception as e:
logger.error(f"Fehler während Ausführung: {e}", exc_info=True)
# Optional: Fehlerexit erstellen
error_output = {
"error": str(e),
"status": "failed"
}
try:
output_item = outputs.create(error_output)
output_item.save()
except Exception as output_error:
logger.error(f"Fehler beim Schreiben: {output_error}", exc_info=True)
raise
if __name__ == "__main__":
main()Generiere die Lock-Datei für reproduzierbare Installationen:
cd robots/src/uv/mein-neuer-robot
uv lock --upgradeDies erstellt eine uv.lock Datei mit den genauen Versionen aller Abhängigkeiten.
Du kannst deinen Robot lokal testen:
# Virtuelle Umgebung erstellen
uv venv .venv
# Abhängigkeiten installieren
uv pip install -p .venv/bin/python robocorp-workitems>=1.0.0
# Robot ausführen
uv run -p .venv/bin/python main.pyNachdem dein Robot fertig getestet ist, kann er vom System automatisch verpackt werden:
cd processcube-robot-agent
python -m processcube_robot_agent pack_robots_commandDies erstellt automatisch eine ZIP-Datei in robots/installed/uv/mein-neuer-robot.zip.
Alternativ kannst du auch manuell packen:
cd robots/src/uv/mein-neuer-robot
zip -r ../../installed/uv/mein-neuer-robot.zip \
main.py pyproject.toml uv.lock README.md \
--exclude ".venv/*" ".git/*" "__pycache__/*" "*.pyc"Das System erkennt deinen Robot automatisch basierend auf seiner ZIP-Datei. Der Robot wird verfügbar unter dem Topic:
uv.mein-neuer-robot
Du kannst die verfügbaren Robots über die REST API abrufen:
curl http://localhost:8000/api/robot_agents/robotsAntwort:
{
"topics": [
{
"name": "example-python-robot",
"topic": "uv.example-python-robot"
},
{
"name": "mein-neuer-robot",
"topic": "uv.mein-neuer-robot"
}
]
}Um weitere Python-Abhängigkeiten hinzuzufügen, bearbeite pyproject.toml:
[project]
name = "mein-neuer-robot"
version = "0.1.0"
description = "..."
requires-python = ">=3.11"
dependencies = [
"robocorp-workitems>=1.0.0",
"requests>=2.28.0",
"beautifulsoup4>=4.11.0",
"pandas>=1.5.0",
]Dann regeneriere die Lock-Datei:
uv lock --upgradefrom robocorp.workitems import inputs
for item in inputs:
payload = item.payload # Dictionary mit den Daten
print(payload)from robocorp.workitems import outputs
output_data = {
"result": "success",
"data": "meine daten"
}
output_item = outputs.create(output_data)
output_item.save()import logging
logger = logging.getLogger(__name__)
logger.info("Informationsnachricht")
logger.warning("Warnung")
logger.error("Fehler", exc_info=True)from robocorp.workitems import inputs, outputs
def main():
for item in inputs:
result = {
"echo": item.payload,
"processed": True
}
outputs.create(result).save()
if __name__ == "__main__":
main()from robocorp.workitems import inputs, outputs
import json
def transform_data(data):
"""Transformiere Daten in Großbuchstaben."""
return {
"original": data,
"transformed": {k: v.upper() if isinstance(v, str) else v
for k, v in data.items()}
}
def main():
for item in inputs:
result = transform_data(item.payload)
outputs.create(result).save()
if __name__ == "__main__":
main()from robocorp.workitems import inputs, outputs
import logging
logger = logging.getLogger(__name__)
def main():
for item in inputs:
try:
# Verarbeitung
if "required_field" not in item.payload:
raise ValueError("required_field fehlt")
result = {
"status": "success",
"data": item.payload
}
outputs.create(result).save()
except Exception as e:
logger.error(f"Fehler: {e}")
error_result = {
"status": "error",
"error": str(e)
}
outputs.create(error_result).save()
if __name__ == "__main__":
main()Lösung: Stelle sicher, dass main.py im Root-Verzeichnis liegt (nicht in einem Unterverzeichnis).
Lösung: Entferne jede [build-system] Section aus pyproject.toml. Script-basierte Robots brauchen dies nicht.
Lösung: Du verwendest die alte robocorp.workitems API. Nutze for item in inputs: statt inputs.get().
Lösung: Füge die Abhängigkeit zu pyproject.toml hinzu und regeneriere uv.lock:
# Bearbeite pyproject.toml
uv lock --upgradeLösung: Überprüfe die Abhängigkeiten. Jede zusätzliche Abhängigkeit erhöht die Installationszeit. Entferne unnötige Dependencies.
- Immer Logging verwenden - Hilft bei der Fehlerbehebung
- Fehlerbehandlung implementieren - Verwende try/except blocks
- Kleine, fokussierte Robots - Ein Robot = eine Aufgabe
- Abhängigkeiten minimieren - Nur notwendige Packages hinzufügen
- README.md dokumentieren - Erkläre, was der Robot tut
- Lokal testen - Bevor du in ProcessCube deployst
- Versionen aktualisieren - Regelmäßig Dependencies updaten
# UV ist 20-40x schneller als pip
uv pip install robocorp-workitems# uv.lock garantiert, dass alle Umgebungen identisch sind
uv lock[project.optional-dependencies]
dev = [
"pytest>=7.0",
"black>=22.0",
]Dann installieren mit:
uv pip install -p .venv/bin/python ".[dev]"- Erstelle dein Robot-Verzeichnis
- Schreibe
pyproject.tomlundmain.py - Generiere
uv.lock - Teste lokal
- Verpacke den Robot
- Deployiere in ProcessCube
- Überwache die Logs
Viel Erfolg beim Erstellen deiner UV-basierten Robots!