Skip to main content

Endpoints - Python Usage

This guide covers how to interact with recipe endpoints programmatically using Python and other languages.

Python SDK

Basic Usage

from praisonai import recipe

# List available recipes
recipes = recipe.list_recipes()
for r in recipes:
    print(f"{r.name} ({r.version}): {r.description}")

# Get recipe details
info = recipe.describe("my-recipe")
print(f"Name: {info.name}")
print(f"Schema: {info.config_schema}")

# Run a recipe
result = recipe.run(
    "my-recipe",
    input={"query": "Hello, world!"},
    options={"timeout_sec": 60}
)

if result.ok:
    print(f"Output: {result.output}")
else:
    print(f"Error: {result.error}")

Streaming Results

from praisonai import recipe

for event in recipe.run_stream(
    "my-recipe",
    input={"query": "Generate a story"}
):
    if event.event_type == "started":
        print(f"Started: {event.data['run_id']}")
    elif event.event_type == "progress":
        print(f"Progress: {event.data['message']}")
    elif event.event_type == "completed":
        print(f"Done: {event.data['status']}")

Error Handling

from praisonai import recipe
from praisonai.recipe.exceptions import (
    RecipeError,
    RecipeNotFoundError,
    RecipeTimeoutError,
    RecipePolicyError
)

try:
    result = recipe.run("my-recipe", input={"query": "test"})
except RecipeNotFoundError as e:
    print(f"Recipe not found: {e.recipe}")
except RecipeTimeoutError as e:
    print(f"Timeout after {e.timeout_sec}s")
except RecipePolicyError as e:
    print(f"Policy denied: {e.policy}")
except RecipeError as e:
    print(f"Recipe error: {e}")

Configuration Options

from praisonai import recipe
from praisonai.recipe.models import RecipeConfig

# Create config
config = RecipeConfig(
    timeout_sec=120,
    policy_mode="strict",
    trace_enabled=True
)

# Run with config
result = recipe.run(
    "my-recipe",
    input={"query": "test"},
    config={"model": "gpt-4o"},
    options={
        "dry_run": False,
        "timeout_sec": config.timeout_sec
    }
)

HTTP Client (Any Language)

Python with requests

import requests

BASE_URL = "http://localhost:8765"
API_KEY = "your-api-key"  # Optional, if auth enabled

headers = {
    "Content-Type": "application/json",
    "X-API-Key": API_KEY
}

# Health check
response = requests.get(f"{BASE_URL}/health")
print(response.json())

# List recipes
response = requests.get(f"{BASE_URL}/v1/recipes", headers=headers)
recipes = response.json()["recipes"]

# Describe recipe
response = requests.get(
    f"{BASE_URL}/v1/recipes/my-recipe",
    headers=headers
)
info = response.json()

# Run recipe
response = requests.post(
    f"{BASE_URL}/v1/recipes/run",
    headers=headers,
    json={
        "recipe": "my-recipe",
        "input": {"query": "Hello"},
        "config": {},
        "options": {"dry_run": False}
    }
)
result = response.json()
print(f"Run ID: {result['run_id']}")
print(f"Output: {result['output']}")

JavaScript/TypeScript

const BASE_URL = "http://localhost:8765";
const API_KEY = "your-api-key";

// Health check
const health = await fetch(`${BASE_URL}/health`);
console.log(await health.json());

// List recipes
const recipesRes = await fetch(`${BASE_URL}/v1/recipes`, {
  headers: { "X-API-Key": API_KEY }
});
const { recipes } = await recipesRes.json();

// Run recipe
const runRes = await fetch(`${BASE_URL}/v1/recipes/run`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": API_KEY
  },
  body: JSON.stringify({
    recipe: "my-recipe",
    input: { query: "Hello" }
  })
});
const result = await runRes.json();
console.log(`Output: ${result.output}`);

Streaming with JavaScript

const response = await fetch(`${BASE_URL}/v1/recipes/stream`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": API_KEY
  },
  body: JSON.stringify({
    recipe: "my-recipe",
    input: { query: "Generate a story" }
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  
  const chunk = decoder.decode(value);
  const lines = chunk.split("\n");
  
  for (const line of lines) {
    if (line.startsWith("data:")) {
      const data = JSON.parse(line.slice(5));
      console.log(`Event: ${data}`);
    }
  }
}

curl

# Health check
curl http://localhost:8765/health

# List recipes
curl -H "X-API-Key: your-key" http://localhost:8765/v1/recipes

# Run recipe
curl -X POST http://localhost:8765/v1/recipes/run \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "recipe": "my-recipe",
    "input": {"query": "Hello"}
  }'

# Stream recipe
curl -X POST http://localhost:8765/v1/recipes/stream \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-key" \
  -d '{
    "recipe": "my-recipe",
    "input": {"query": "Hello"}
  }'

Response Models

RecipeResult

@dataclass
class RecipeResult:
    ok: bool                    # Success status
    run_id: str                 # Unique run identifier
    recipe: str                 # Recipe name
    version: str                # Recipe version
    status: str                 # Status: success, error, dry_run, etc.
    output: Any                 # Recipe output
    metrics: Dict[str, Any]     # Execution metrics
    error: Optional[str]        # Error message if failed
    trace: Dict[str, str]       # Tracing info (run_id, session_id, trace_id)

RecipeEvent (Streaming)

@dataclass
class RecipeEvent:
    event_type: str             # started, progress, completed, error
    data: Dict[str, Any]        # Event-specific data
    timestamp: str              # ISO timestamp

Best Practices

1. Use Timeouts

result = recipe.run(
    "my-recipe",
    input=data,
    options={"timeout_sec": 30}  # Always set timeout
)

2. Handle Errors Gracefully

result = recipe.run("my-recipe", input=data)
if not result.ok:
    if result.status == "timeout":
        # Retry or fallback
        pass
    elif result.status == "policy_denied":
        # Log and alert
        pass
    else:
        # General error handling
        pass

3. Use Session IDs for Stateful Workflows

session_id = "user-123-session"

# First call
result1 = recipe.run(
    "conversation",
    input={"message": "Hello"},
    session_id=session_id
)

# Subsequent calls share state
result2 = recipe.run(
    "conversation",
    input={"message": "What did I say?"},
    session_id=session_id
)

4. Monitor with Trace IDs

result = recipe.run("my-recipe", input=data)
print(f"Trace ID: {result.trace['trace_id']}")
# Use trace_id for debugging and observability

Next Steps