Python SDK for orra - Production-grade planning and orchestration for complex multi-agent workflows.
Project description
Orra SDK for Python
Python SDK for Orra - Build reliable multi-agent applications that handle complex real-world interactions.
Installation
pip install orra-sdk
Usage
import asyncio
from orra import OrraService, Task
from pydantic import BaseModel
# Define your models
class Input(BaseModel):
message: str
class Output(BaseModel):
response: str
# Initialize the SDK
echo_service = OrraService(
name="echo",
description="A simple echo provider that echoes whatever its sent",
url="https://api.orra.dev",
api_key="your-api-key"
)
# Register your service handler
@echo_service.handler()
async def handle_message(task: Task[Input]) -> Output:
return Output(response=f"Echo: {task.input.message}")
# Run the service
async def main():
try:
await echo_service.start()
except KeyboardInterrupt:
await echo_service.shutdown()
if __name__ == "__main__":
asyncio.run(main())
Advanced Features
Revertible Services with Compensations
from orra import OrraService, Task, CompensationResult, CompensationStatus, RevertSource
# Define your models
class Input(BaseModel):
order_id: str
product_id: str
quantity: int
class Output(BaseModel):
success: bool
reservation_id: str
# Initialize as revertible
inventory_service = OrraService(
name="inventory-service",
description="Handles product inventory reservations",
url="https://api.orra.dev",
api_key="your-api-key",
revertible=True
)
# Main handler
@inventory_service.handler()
async def reserve_inventory(task: Task[Input]) -> Output:
# Reserve inventory logic
return Output(success=True, reservation_id="res-123456")
# Compensation handler for reverting
@inventory_service.revert_handler()
async def revert_reservation(source: RevertSource[Input, Output]) -> CompensationResult:
# Access the compensation context information
if source.context:
reason = source.context.reason # Why compensation was triggered (ABORTED, FAILED, etc)
payload = source.context.payload # Any additional data passed with compensation
orchestration_id = source.context.orchestration_id # Parent orchestration ID
print(f"Compensation triggered for orchestration {orchestration_id} due to: {reason}")
if payload:
print(f"Additional context: {payload}")
print(f"Reverting reservation {source.output.reservation_id} for order {source.input.order_id}")
# Release the inventory
return CompensationResult(status=CompensationStatus.COMPLETED)
Aborting Tasks
from orra import OrraService, Task
from pydantic import BaseModel
class Input(BaseModel):
order_id: str
product_id: str
quantity: int
class Output(BaseModel):
success: bool
reservation_id: str
inventory_service = OrraService(
name="inventory-service",
description="Handles product inventory reservations",
url="https://api.orra.dev",
api_key="your-api-key",
revertible=True # Enable compensation for aborted tasks
)
@inventory_service.handler()
async def reserve_inventory(task: Task[Input]) -> Output:
# Check inventory availability
inventory_count = await check_inventory(task.input.product_id)
if inventory_count < task.input.quantity:
# If inventory is insufficient, abort the task
await task.abort({
"reason": "INSUFFICIENT_INVENTORY",
"available": inventory_count,
"requested": task.input.quantity
})
# Code below won't execute due to abort
# Normal processing continues if not aborted
reservation_id = await create_reservation(
task.input.order_id,
task.input.product_id,
task.input.quantity
)
return Output(success=True, reservation_id=reservation_id)
Aborting a task immediately stops execution and sends an abort signal to the orchestration engine. If the service is revertible, the abort information will be available in the compensation context:
@inventory_service.revert_handler()
async def revert_reservation(source: RevertSource[Input, Output]) -> CompensationResult:
if source.context and source.context.reason == "aborted":
# The abort payload is available in context.payload
abort_info = source.context.payload
print(f"Task was aborted due to: {abort_info.get('reason')}")
print(f"Available inventory: {abort_info.get('available')}")
print(f"Requested quantity: {abort_info.get('requested')}")
# No actual reservation to revert in this case
return CompensationResult(status=CompensationStatus.COMPLETED)
You can view abort information using the CLI:
# View task details including abort reason
orra inspect -d <orchestration-id> -t <task-id>
Progress Updates for Long-Running Tasks
from orra import OrraService, Task
from pydantic import BaseModel
class Input(BaseModel):
file_path: str
class Output(BaseModel):
success: bool
processed_rows: int
service = OrraService(
name="data-processor",
description="Processes large data files",
url="https://api.orra.dev",
api_key="your-api-key"
)
@service.handler()
async def process_file(task: Task[Input]) -> Output:
try:
# Start processing
await task.push_update({
"progress": 20,
"status": "processing",
"message": "Starting file analysis"
})
# Perform initial processing
await analyze_file(task.input.file_path)
# Update progress halfway
await task.push_update({
"progress": 50,
"status": "processing",
"message": "Processing data rows"
})
# Complete processing
rows = await process_data(task.input.file_path)
# Final progress update
await task.push_update({
"progress": 100,
"message": "Processing complete"
})
return Output(success=True, processed_rows=rows)
except Exception as e:
# Handle errors appropriately
raise
Progress updates allow you to send interim results to provide visibility into long-running tasks. View these updates using the CLI:
# View summarized updates (first/last)
orra inspect -d <orchestration-id> --updates
# View all detailed updates
orra inspect -d <orchestration-id> --long-updates
Custom Persistence
from pathlib import Path
from typing import Optional
def save_to_db(service_id: str) -> None:
# Your database save logic
pass
def load_from_db() -> Optional[str]:
# Your database load logic
return "previously-registered-service-id"
service = OrraService(
name="my-service",
description="Service with custom persistence",
url="https://api.orra.dev",
api_key="your-api-key",
# File-based persistence with custom path
persistence_method="file",
persistence_file_path=Path("./custom/path/service-key.json"),
# Or database persistence
# persistence_method="custom",
# custom_save=save_to_db,
# custom_load=load_from_db
)
Working with Agents
For AI agents instead of simple services:
from orra import OrraAgent, Task
from pydantic import BaseModel
class AgentInput(BaseModel):
query: str
context: str
class AgentOutput(BaseModel):
response: str
confidence: float
agent = OrraAgent(
name="qa-agent",
description="Question answering agent with context",
url="https://api.orra.dev",
api_key="your-api-key"
)
@agent.handler()
async def handle_question(task: Task[AgentInput]) -> AgentOutput:
# Agent processing logic here
return AgentOutput(
response="This is the answer to your question.",
confidence=0.95
)
Documentation
For more detailed documentation, please visit Orra Python SDK Documentation.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file orra_sdk-0.2.4.tar.gz.
File metadata
- Download URL: orra_sdk-0.2.4.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.4 CPython/3.11.9 Darwin/24.4.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ead54283b2b98308116af4505309d3fae6c67667c08b9745d10b4eeba214ffcf
|
|
| MD5 |
a8eedc9079a9caf4157ff5f6c5543ad4
|
|
| BLAKE2b-256 |
9b811cf93e759fc6a82a490d79aa5f6e6fddfa29ac7187880ed9753ff6f5d335
|
File details
Details for the file orra_sdk-0.2.4-py3-none-any.whl.
File metadata
- Download URL: orra_sdk-0.2.4-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.4 CPython/3.11.9 Darwin/24.4.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cdc34faf6a3ea7c7dc08133fa8fff8457d827d1a3f6e6290073ac9bea4e0dfd1
|
|
| MD5 |
9b7fbda8a6d10887e4d2fbe71b90ec8e
|
|
| BLAKE2b-256 |
235eca327473ee566219800d390f5f41554807e71e64eacfd649c12fa538e97f
|