> ## 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.

# Templates

> Manage and run AI agent templates and recipes

## Overview

Templates provide pre-built AI agent workflows that can be installed, customized, and run. The default repository is `agent-recipes` on GitHub.

<Note>
  Templates support **custom directories** with precedence-based discovery and **input sentinel protection** for secure variable substitution.
</Note>

## Python API

### Load a Template

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import load_template

# Load from default agent-recipes repository
template = load_template("transcript-generator")

# Load from GitHub with version pinning
template = load_template("github:MervinPraison/agent-recipes/transcript-generator@v1.0.0")

# Load from local path
template = load_template("./my-template")

# Load in offline mode (cache only)
template = load_template("transcript-generator", offline=True)
```

### List Available Templates

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import list_templates

# List all templates
templates = list_templates()

# List only cached templates
templates = list_templates(source="cached")

# List in offline mode
templates = list_templates(offline=True)

for t in templates:
    print(f"{t.name} v{t.version}: {t.description}")
```

### Search Templates

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import search_templates

# Search by keyword
results = search_templates("video")

# Search in offline mode
results = search_templates("transcript", offline=True)
```

### Install a Template

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import install_template

# Install to cache
cached = install_template("github:MervinPraison/agent-recipes/transcript-generator")
print(f"Installed to: {cached.path}")
```

### Clear Cache

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import clear_cache

# Clear all cached templates
count = clear_cache()
print(f"Cleared {count} templates")
```

### Create Agent from Template

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

# Create agent from template (lazy loads praisonai.templates)
agent = Agent.from_template("transcript-generator")

# With config overrides
agent = Agent.from_template(
    "transcript-generator",
    config={"output_format": "srt"}
)
```

### Create Workflow from Template

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import AgentFlow

# Create workflow from template
workflow = Workflow.from_template("data-transformer")

# With config and offline mode
workflow = Workflow.from_template(
    "github:MervinPraison/agent-recipes/video-editor@v1.0.0",
    config={"resolution": "1080p"},
    offline=True
)

# Run the workflow
result = workflow.run()
```

## Template URI Formats

| Format          | Example                                      |
| --------------- | -------------------------------------------- |
| Simple name     | `transcript-generator`                       |
| Package         | `package:agent_recipes/transcript-generator` |
| GitHub          | `github:owner/repo/template`                 |
| GitHub with ref | `github:owner/repo/template@v1.0.0`          |
| Local path      | `./my-template` or `~/templates/test`        |
| HTTP URL        | `https://example.com/template.yaml`          |

## Available Templates

| Template               | Description                           |
| ---------------------- | ------------------------------------- |
| `transcript-generator` | Generate transcripts from audio/video |
| `shorts-generator`     | Create short-form video clips         |
| `video-editor`         | AI-powered video editing              |
| `data-transformer`     | Transform data between formats        |

## Custom Templates Directory

Templates can be discovered from multiple directories with precedence:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import TemplateDiscovery, discover_templates, find_template_path

# Discover templates from custom directories
discovery = TemplateDiscovery(
    custom_dirs=["~/.praisonai/templates", "./my-templates"],
    include_package=True,  # Include agent-recipes package
    include_defaults=True  # Include default search paths
)

# List all discovered templates
templates = discovery.discover_all()
for name, template in templates.items():
    print(f"{name} ({template.source}): {template.path}")

# Find a specific template by name
template = discovery.find_template("my-custom-template")
if template:
    print(f"Found at: {template.path}")

# Get search paths with status
for path, source, exists in discovery.get_search_paths():
    status = "✓" if exists else "✗"
    print(f"{status} [{source}] {path}")
```

### Search Path Precedence

| Priority    | Path                            | Source  |
| ----------- | ------------------------------- | ------- |
| 1 (highest) | Custom dirs (via `custom_dirs`) | custom  |
| 2           | `~/.praisonai/templates`        | custom  |
| 3           | `~/.config/praison/templates`   | custom  |
| 4           | `./.praison/templates`          | project |
| 5 (lowest)  | `agent_recipes` package         | package |

When the same template name exists in multiple locations, the higher priority version is used.

## Input Sentinel Protection

Templates use secure variable substitution that protects user input from injection:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import TemplateLoader

loader = TemplateLoader()

# User input containing {{...}} syntax is protected
config = {
    "topic": "AI Safety",
    "input": "User says: {{malicious_var}} should not be processed"
}

# The {{malicious_var}} in user input remains literal
# Only template variables like {{topic}} are substituted
workflow_config = loader.load_workflow_config(template)
```

### How It Works

1. **Per-render unique sentinel** - A cryptographically random token is generated for each substitution
2. **Protection phase** - User-provided values containing `{{...}}` are replaced with sentinel tokens
3. **Substitution phase** - Template variables are substituted normally
4. **Restoration phase** - Sentinel tokens are replaced with original user values

This prevents:

* Template injection attacks
* Accidental variable resolution in user content
* Sentinel collision attacks (unique per render)

## Security

Templates support allowlists and checksum verification:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.templates import TemplateSecurity, SecurityConfig

config = SecurityConfig(
    allowed_sources={"github:MervinPraison/agent-recipes"},
    allow_any_github=False
)
security = TemplateSecurity(config=config)
```
