Skip to main content

Recipe Serve

The praisonai recipe serve command starts an HTTP server that exposes recipe endpoints for remote invocation.

Quick Start

# Start server on default port (8765)
praisonai recipe serve

# Start on custom port
praisonai recipe serve --port 8000

# Start with authentication
praisonai recipe serve --auth api-key

Command Options

OptionDescriptionDefault
--port <num>Server port8765
--host <addr>Server host127.0.0.1
--auth <type>Auth type: none, api-key, jwtnone
--api-key <key>API key for authentication-
--reloadEnable hot reload (dev mode)false
--preloadPreload all recipes on startupfalse
--recipes <list>Comma-separated recipe names to serveall
--config <path>Path to serve.yaml config file-

Security

Host Binding Safety

By default, the server binds to 127.0.0.1 (localhost only). Binding to 0.0.0.0 (all interfaces) requires authentication.
# This will be REFUSED (no auth on public interface)
praisonai recipe serve --host 0.0.0.0

# This works (auth enabled)
praisonai recipe serve --host 0.0.0.0 --auth api-key

Authentication Modes

API Key Authentication

# Start with API key auth
praisonai recipe serve --auth api-key --api-key my-secret-key

# Or use environment variable
export PRAISONAI_API_KEY=my-secret-key
praisonai recipe serve --auth api-key
Clients must include the X-API-Key header:
curl -H "X-API-Key: my-secret-key" http://localhost:8765/v1/recipes

Configuration File

Create a serve.yaml file for persistent configuration:
# serve.yaml
host: 127.0.0.1
port: 8765
auth: api-key
api_key: your-secret-key  # or use PRAISONAI_API_KEY env var

# Optional: limit which recipes are served
recipes:
  - my-recipe
  - another-recipe

# Optional: preload recipes on startup
preload: true

# Optional: CORS configuration
cors_origins: "*"
Use the config file:
praisonai recipe serve --config ./serve.yaml

Configuration Precedence

  1. CLI flags (highest priority)
  2. Environment variables
  3. Config file
  4. Defaults (lowest priority)

API Endpoints

Health Check

GET /health
Response:
{
  "status": "healthy",
  "service": "praisonai-recipe-runner",
  "version": "2.7.1"
}

List Recipes

GET /v1/recipes
GET /v1/recipes?tags=audio,video
Response:
{
  "recipes": [
    {
      "name": "my-recipe",
      "version": "1.0.0",
      "description": "Recipe description",
      "tags": ["audio", "video"]
    }
  ]
}

Describe Recipe

GET /v1/recipes/{name}
Response:
{
  "name": "my-recipe",
  "version": "1.0.0",
  "description": "Recipe description",
  "requires": {
    "packages": [],
    "env": ["OPENAI_API_KEY"]
  },
  "config_schema": {},
  "outputs": []
}

Get Recipe Schema

GET /v1/recipes/{name}/schema
Response:
{
  "name": "my-recipe",
  "version": "1.0.0",
  "input_schema": {},
  "output_schema": []
}

Run Recipe

POST /v1/recipes/run
Content-Type: application/json

{
  "recipe": "my-recipe",
  "input": {"query": "Hello"},
  "config": {},
  "options": {"dry_run": false}
}
Response:
{
  "ok": true,
  "run_id": "run-abc123",
  "recipe": "my-recipe",
  "version": "1.0.0",
  "status": "success",
  "output": {"result": "..."},
  "metrics": {"duration_sec": 1.5},
  "trace": {
    "run_id": "run-abc123",
    "session_id": "session-xyz",
    "trace_id": "trace-123"
  }
}

Stream Recipe (SSE)

POST /v1/recipes/stream
Content-Type: application/json

{
  "recipe": "my-recipe",
  "input": {"query": "Hello"}
}
Response (Server-Sent Events):
event: started
data: {"run_id": "run-abc123", "recipe": "my-recipe"}

event: progress
data: {"step": "loading", "message": "Loading recipe..."}

event: progress
data: {"step": "executing", "message": "Running workflow..."}

event: completed
data: {"run_id": "run-abc123", "status": "success"}

Examples

Development Mode

# Start with hot reload for development
praisonai recipe serve --reload

Production Mode

# Production with auth and preloading
praisonai recipe serve \
  --host 0.0.0.0 \
  --port 8000 \
  --auth api-key \
  --preload

Using with Docker

FROM python:3.11-slim
RUN pip install praisonai[serve]
COPY serve.yaml /app/
WORKDIR /app
CMD ["praisonai", "recipe", "serve", "--config", "serve.yaml"]

Client Examples

curl

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

# List recipes
curl http://localhost:8765/v1/recipes

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

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

Python

import requests

# Run recipe
response = requests.post(
    "http://localhost:8765/v1/recipes/run",
    json={
        "recipe": "my-recipe",
        "input": {"query": "Hello"}
    },
    headers={"X-API-Key": "my-secret-key"}
)
result = response.json()
print(result["output"])

JavaScript

const response = await fetch("http://localhost:8765/v1/recipes/run", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": "my-secret-key"
  },
  body: JSON.stringify({
    recipe: "my-recipe",
    input: { query: "Hello" }
  })
});
const result = await response.json();
console.log(result.output);

Environment Variables

VariableDescription
PRAISONAI_API_KEYAPI key for authentication
PRAISONAI_SERVE_HOSTDefault host
PRAISONAI_SERVE_PORTDefault port

Troubleshooting

Port Already in Use

Error: [Errno 48] Address already in use
Solution: Use a different port or stop the existing process:
praisonai recipe serve --port 8766
# Or
lsof -i :8765 | grep LISTEN | awk '{print $2}' | xargs kill

Missing Dependencies

Error: Serve dependencies not installed. Run: pip install praisonai[serve]
Solution: Install serve extras:
pip install praisonai[serve]

Auth Required for Public Binding

Error: Auth required for non-localhost binding. Use --auth api-key or --auth jwt
Solution: Enable authentication:
praisonai recipe serve --host 0.0.0.0 --auth api-key