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

# Variable Handling

> Extract and validate variables in your prompts

# Variable Handling

Claro prompts support variables that can be dynamically replaced with values. Learn how to extract, validate, and use variables.

## Understanding Variables

Variables in prompts use double curly brace syntax:

```
Hello {{user_name}}! You have {{count}} unread messages.
```

Variables can include type hints and descriptions:

```
{{user_name:string}}
{{count:number // Number of unread messages}}
{{is_premium:boolean}}
```

## Extracting Variables

Use the `extract_variables()` method to find all variables in a prompt:

```python theme={null}
from baytos.claro import BaytClient

client = BaytClient(api_key="your_api_key")
prompt = client.get_prompt("@workspace/template:v1")

# Extract all variables
variables = prompt.extract_variables()

for var in variables:
    print(f"Name: {var['name']}")
    if 'type' in var:
        print(f"Type: {var['type']}")
    if 'description' in var:
        print(f"Description: {var['description']}")
    print()
```

### Variable Information

Each extracted variable contains:

```python theme={null}
{
    "name": "user_name",           # Variable name
    "type": "string",              # Type (optional)
    "description": "User's name"   # Description (optional)
}
```

## Variable Types

Claro supports several variable types:

### String Variables

```python theme={null}
# In prompt: Hello {{name:string}}!

variables = prompt.extract_variables()
# [{'name': 'name', 'type': 'string'}]
```

### Number Variables

```python theme={null}
# In prompt: You have {{count:number}} items

variables = prompt.extract_variables()
# [{'name': 'count', 'type': 'number'}]
```

### Boolean Variables

```python theme={null}
# In prompt: Premium: {{is_premium:boolean}}

variables = prompt.extract_variables()
# [{'name': 'is_premium', 'type': 'boolean'}]
```

### Array Variables

```python theme={null}
# In prompt: Tags: {{tags:array}}

variables = prompt.extract_variables()
# [{'name': 'tags', 'type': 'array'}]
```

### Object Variables

```python theme={null}
# In prompt: User: {{user:object}}

variables = prompt.extract_variables()
# [{'name': 'user', 'type': 'object'}]
```

## Validating Variables

Validate variable values before using them:

```python theme={null}
prompt = client.get_prompt("@workspace/notification:v1")

# Values to validate
values = {
    'user_name': 'Alice',
    'count': 42,
    'is_premium': True
}

# Validate
errors = prompt.validate_variables(values)

if errors:
    print("Validation errors:")
    for field, message in errors.items():
        print(f"  {field}: {message}")
else:
    print("All variables valid!")
```

### Validation Rules

The validator checks:

1. **Missing Variables** - All required variables must be provided
2. **Unexpected Variables** - No extra variables allowed
3. **Type Mismatches** - Values must match declared types

```python theme={null}
# Missing variable
values = {'user_name': 'Alice'}  # Missing 'count'
errors = prompt.validate_variables(values)
# {'count': 'Missing required variable: count'}

# Type mismatch
values = {'user_name': 'Alice', 'count': 'not a number'}
errors = prompt.validate_variables(values)
# {'count': 'Expected number, got str'}

# Unexpected variable
values = {'user_name': 'Alice', 'count': 42, 'extra': 'value'}
errors = prompt.validate_variables(values)
# {'extra': 'Unexpected variable: extra'}
```

## Using Prompts as Templates

Replace variables with actual values:

```python theme={null}
import re

def render_template(prompt_text: str, values: dict) -> str:
    """Replace {{variable}} placeholders with values"""
    def replace(match):
        var_name = match.group(1).split(':')[0].strip()
        return str(values.get(var_name, match.group(0)))

    pattern = r'\{\{([^}]+)\}\}'
    return re.sub(pattern, replace, prompt_text)

# Get prompt
prompt = client.get_prompt("@workspace/greeting:v1")

# Define values
values = {
    'user_name': 'Alice',
    'message_count': 5
}

# Render template
rendered = render_template(prompt.generator, values)
print(rendered)
```

## Complete Example

```python theme={null}
#!/usr/bin/env python3
"""
Example: Extract, validate, and use variables
"""

import os
import re
from baytos.claro import BaytClient

def render_template(text: str, values: dict) -> str:
    """Replace {{variable}} or {{variable:type}} with values"""
    def replace(match):
        # Extract variable name (before : if type is specified)
        var_name = match.group(1).split(':')[0].strip()
        return str(values.get(var_name, match.group(0)))

    pattern = r'\{\{([^}]+)\}\}'
    return re.sub(pattern, replace, text)

def use_prompt_with_variables(package_name: str, values: dict):
    """Get prompt, validate variables, and render"""

    client = BaytClient(api_key=os.getenv("BAYT_API_KEY"))
    prompt = client.get_prompt(package_name)

    print(f"Prompt: {prompt.title}\n")

    # Extract variables
    variables = prompt.extract_variables()
    print(f"Found {len(variables)} variable(s):")
    for var in variables:
        type_info = f" ({var['type']})" if 'type' in var else ""
        desc_info = f" - {var['description']}" if 'description' in var else ""
        print(f"  - {var['name']}{type_info}{desc_info}")
    print()

    # Validate
    errors = prompt.validate_variables(values)
    if errors:
        print("Validation errors:")
        for field, message in errors.items():
            print(f"  {field}: {message}")
        return

    print("Variables validated successfully!\n")

    # Render
    rendered = render_template(prompt.generator, values)
    print("Rendered prompt:")
    print(rendered)

if __name__ == "__main__":
    # Example usage
    values = {
        'user_name': 'Alice',
        'product_name': 'Premium Subscription',
        'price': 29.99,
        'is_trial': False
    }

    use_prompt_with_variables("@workspace/sales-email:v1", values)
```

## Type Safety with Python

For better type safety, use TypedDict:

```python theme={null}
from typing import TypedDict
from baytos.claro import BaytClient

class EmailVariables(TypedDict):
    user_name: str
    product_name: str
    price: float
    is_trial: bool

def send_email(values: EmailVariables):
    """Type-safe variable usage"""
    client = BaytClient(api_key="...")
    prompt = client.get_prompt("@workspace/sales-email:v1")

    # Validate
    errors = prompt.validate_variables(values)
    if errors:
        raise ValueError(f"Invalid variables: {errors}")

    # Use prompt...
    print(prompt.generator)

# Usage - IDE provides autocomplete and type checking
send_email({
    'user_name': 'Alice',
    'product_name': 'Premium',
    'price': 29.99,
    'is_trial': False
})
```

## Dynamic Variable Discovery

Discover variables at runtime:

```python theme={null}
def get_required_variables(package_name: str) -> dict:
    """Get information about required variables"""
    client = BaytClient(api_key="...")
    prompt = client.get_prompt(package_name)

    variables = prompt.extract_variables()

    var_info = {}
    for var in variables:
        var_info[var['name']] = {
            'type': var.get('type', 'any'),
            'description': var.get('description', ''),
            'required': True
        }

    return var_info

# Usage
required = get_required_variables("@workspace/template:v1")

print("This prompt requires:")
for name, info in required.items():
    print(f"  {name}: {info['type']}")
    if info['description']:
        print(f"    {info['description']}")
```

## Best Practices

<AccordionGroup>
  <Accordion title="Always Validate Variables" icon="shield-check">
    Validate variables before using a prompt:

    ```python theme={null}
    # ✅ Good: Validate first
    errors = prompt.validate_variables(values)
    if not errors:
        rendered = render_template(prompt.generator, values)

    # ❌ Bad: Skip validation
    rendered = render_template(prompt.generator, values)
    ```
  </Accordion>

  <Accordion title="Use Type Hints in Prompts" icon="tag">
    Include type hints in your prompts for better validation:

    ```
    ✅ Good:
    Hello {{name:string}}! You have {{count:number}} items.

    ❌ Less clear:
    Hello {{name}}! You have {{count}} items.
    ```

    Type hints enable automatic validation and better documentation.
  </Accordion>

  <Accordion title="Handle Missing Variables Gracefully" icon="circle-exclamation">
    Provide defaults for optional variables:

    ```python theme={null}
    def render_safe(text: str, values: dict, defaults: dict = None) -> str:
        """Render with fallback defaults"""
        defaults = defaults or {}
        all_values = {**defaults, **values}

        def replace(match):
            var_name = match.group(1).split(':')[0].strip()
            return str(all_values.get(var_name, match.group(0)))

        pattern = r'\{\{([^}]+)\}\}'
        return re.sub(pattern, replace, text)

    # Usage with defaults
    rendered = render_safe(
        prompt.generator,
        {'user_name': 'Alice'},
        defaults={'greeting': 'Hello', 'message_count': 0}
    )
    ```
  </Accordion>

  <Accordion title="Document Variable Usage" icon="book">
    Use descriptions to document variables:

    ```
    ✅ Good:
    {{user_email:string // User's email address for notifications}}
    {{retry_count:number // Number of retry attempts (max: 3)}}

    ❌ Less helpful:
    {{user_email}}
    {{retry_count}}
    ```
  </Accordion>
</AccordionGroup>

## Advanced: Variable Extraction from All Fields

Extract variables from all prompt fields (generator, system, critique):

```python theme={null}
def extract_all_variables(prompt):
    """Extract variables from all prompt fields"""
    all_variables = {}

    # This is already done by extract_variables()
    # It searches generator, system, and critique fields
    variables = prompt.extract_variables()

    # Group by field
    for var in variables:
        name = var['name']
        if name not in all_variables:
            all_variables[name] = var

    return list(all_variables.values())

# Usage
prompt = client.get_prompt("@workspace/complex:v1")
variables = extract_all_variables(prompt)

print(f"Found {len(variables)} unique variable(s)")
for var in variables:
    print(f"  - {var['name']}")
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Context Files" icon="paperclip" href="/sdk/python/context">
    Work with file attachments and URLs
  </Card>

  <Card title="Listing Prompts" icon="list" href="/sdk/python/pagination">
    Browse and paginate through prompts
  </Card>

  <Card title="Error Handling" icon="shield" href="/sdk/python/error-handling">
    Handle validation and API errors
  </Card>

  <Card title="API Reference" icon="book" href="/sdk/python/api-reference">
    Complete API documentation
  </Card>
</CardGroup>
