> ## Documentation Index
> Fetch the complete documentation index at: https://docs.praison.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# App Developer Persona

> Build applications that integrate PraisonAI recipes

# App Developer Persona

<Callout type="info">
  **Role**: Build applications that use PraisonAI recipes to deliver AI-powered features to end users.
</Callout>

## Primary Goals

* **Integrate recipes** into applications with minimal friction
* **Handle errors gracefully** to maintain good UX
* **Optimize latency** for responsive user experiences
* **Stream results** for real-time feedback

## Recommended Integration Models

<CardGroup cols={2}>
  <Card title="Embedded SDK" icon="python" href="/docs/guides/recipes/integration-models/embedded-sdk">
    **Best for Python apps** - Lowest latency, direct integration
  </Card>

  <Card title="CLI Invocation" icon="terminal" href="/docs/guides/recipes/integration-models/cli-invocation">
    **Best for scripts** - Simple, language-agnostic
  </Card>

  <Card title="Local HTTP Sidecar" icon="server" href="/docs/guides/recipes/integration-models/local-http-sidecar">
    **Best for microservices** - Polyglot, HTTP-based
  </Card>

  <Card title="Plugin Mode" icon="puzzle-piece" href="/docs/guides/recipes/integration-models/plugin-mode">
    **Best for extensions** - IDE/CMS integration
  </Card>
</CardGroup>

## Typical Workflow

<Steps>
  <Step title="Discover Available Recipes">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonai import recipe

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

    # Get recipe details
    info = recipe.describe("support-reply-drafter")
    print(f"Inputs: {info.config_schema}")
    ```
  </Step>

  <Step title="Integrate into Application">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonai import recipe
    from praisonai.recipe import RecipeError

    def handle_support_ticket(ticket_id: str, message: str) -> str:
        """Generate AI-powered support reply."""
        try:
            result = recipe.run(
                "support-reply-drafter",
                input={"ticket_id": ticket_id, "message": message},
                options={"timeout_sec": 30}
            )
            
            if result.ok:
                return result.output
            else:
                # Fallback to manual handling
                return None
                
        except RecipeError as e:
            logger.error(f"Recipe failed: {e}")
            return None
    ```
  </Step>

  <Step title="Add Streaming for Better UX">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    async def stream_response(recipe_name: str, input_data: dict):
        """Stream recipe output to frontend."""
        for event in recipe.run_stream(recipe_name, input=input_data):
            if event.event_type == "progress":
                yield {"type": "progress", "message": event.data.get("message")}
            elif event.event_type == "completed":
                yield {"type": "complete", "output": event.data.get("output")}
            elif event.event_type == "error":
                yield {"type": "error", "message": event.data.get("message")}
    ```
  </Step>

  <Step title="Handle Errors Gracefully">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonai.recipe import (
        RecipeError,
        RecipeNotFoundError,
        RecipeDependencyError,
        RecipeValidationError
    )

    def run_recipe_safely(name: str, input_data: dict) -> dict:
        """Run recipe with comprehensive error handling."""
        try:
            result = recipe.run(name, input=input_data)
            return {"success": True, "output": result.output}
            
        except RecipeNotFoundError:
            return {"success": False, "error": "Recipe not available"}
        except RecipeDependencyError as e:
            return {"success": False, "error": f"Missing dependency: {e}"}
        except RecipeValidationError as e:
            return {"success": False, "error": f"Invalid input: {e}"}
        except RecipeError as e:
            return {"success": False, "error": f"Recipe failed: {e}"}
    ```
  </Step>
</Steps>

## Key Concerns

### Latency Optimization

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Use connection pooling for HTTP clients
import requests
from requests.adapters import HTTPAdapter

session = requests.Session()
adapter = HTTPAdapter(pool_connections=10, pool_maxsize=10)
session.mount("http://", adapter)

# Cache recipe metadata
from functools import lru_cache

@lru_cache(maxsize=100)
def get_recipe_info(name: str):
    return recipe.describe(name)
```

### Error Recovery

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
def run_with_fallback(primary: str, fallback: str, input_data: dict):
    """Try primary recipe, fall back if it fails."""
    try:
        result = recipe.run(primary, input=input_data, options={"timeout_sec": 10})
        if result.ok:
            return result.output
    except Exception:
        pass
    
    # Fallback
    result = recipe.run(fallback, input=input_data)
    return result.output if result.ok else None
```

### User Experience

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Show progress to users
def run_with_progress(name: str, input_data: dict, progress_callback):
    """Run recipe with progress updates."""
    for event in recipe.run_stream(name, input=input_data):
        if event.event_type == "progress":
            progress_callback(
                step=event.data.get("step"),
                message=event.data.get("message"),
                percent=event.data.get("percent", 0)
            )
        elif event.event_type == "completed":
            return event.data.get("output")
    return None
```

## Common Patterns

### Request-Response Pattern

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Simple synchronous call
result = recipe.run("summarizer", input={"text": document})
summary = result.output if result.ok else "Summary unavailable"
```

### Fire-and-Forget Pattern

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import threading

def run_async(name: str, input_data: dict, callback):
    """Run recipe in background thread."""
    def worker():
        result = recipe.run(name, input=input_data)
        callback(result)
    
    thread = threading.Thread(target=worker)
    thread.start()
```

### Batch Processing Pattern

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from concurrent.futures import ThreadPoolExecutor

def process_batch(items: list, recipe_name: str) -> list:
    """Process multiple items in parallel."""
    def process_one(item):
        result = recipe.run(recipe_name, input=item)
        return result.output if result.ok else None
    
    with ThreadPoolExecutor(max_workers=5) as executor:
        return list(executor.map(process_one, items))
```

## Troubleshooting

<Accordion title="Recipe runs slowly">
  * Check network latency to recipe server
  * Use streaming for perceived performance
  * Consider caching for repeated inputs
  * Profile to find bottlenecks
</Accordion>

<Accordion title="Intermittent failures">
  * Implement retry logic with exponential backoff
  * Add circuit breaker for failing recipes
  * Log errors with context for debugging
  * Set appropriate timeouts
</Accordion>

<Accordion title="Memory issues">
  * Stream large outputs instead of buffering
  * Process results incrementally
  * Clear caches periodically
  * Monitor memory usage
</Accordion>

## Security Checklist

* [ ] Validate user input before passing to recipes
* [ ] Don't expose recipe errors directly to users
* [ ] Store API keys securely (env vars, secrets manager)
* [ ] Implement rate limiting on your API
* [ ] Log recipe calls for audit trail
* [ ] Sanitize recipe output before displaying

## Next Steps

* [Embedded SDK](/docs/guides/recipes/integration-models/embedded-sdk) - Detailed Python integration
* [Use Cases](/docs/guides/recipes/use-cases) - Implementation patterns
* [Platform/DevOps Persona](/docs/guides/recipes/personas/platform-devops) - Deployment guidance
