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

# Pre-Call Functions

> Modify system prompt and metadata before calls start

## Overview

Pre-call functions execute **before** your AI agent starts a call. They allow you to customize the system prompt and update call metadata based on external data.

**Common Use Cases:**

* Fetch user preferences from database
* Customize greeting based on language
* Load context from CRM
* Set dynamic variables in system prompt

## Execution Timing

```
[Pre-Call Function Executes] → [Call Starts] → [Conversation]
```

Pre-call functions run once before the call connects, allowing you to prepare the agent with custom context.

## Basic Mode

Configure API integrations without writing code.

<img src="https://mintcdn.com/callkaroai/_yHIwUXcSxcKfjME/images/functions/pre-call-basic.png?fit=max&auto=format&n=_yHIwUXcSxcKfjME&q=85&s=06f58abb0a4607a87e811c1d013250c0" alt="Pre-Call Basic Mode" width="1920" height="1084" data-path="images/functions/pre-call-basic.png" />

### Configuration Fields

| Field      | Required | Description                       |
| ---------- | -------- | --------------------------------- |
| Name       | Yes      | Function name (no spaces)         |
| API URL    | Yes      | Endpoint to call                  |
| Method     | Yes      | GET, POST, PUT, or DELETE         |
| Headers    | No       | Authentication and custom headers |
| Parameters | No       | Query or body parameters          |

### Example: Fetch User Language

**API URL:** `https://api.example.com/users/{user_id}/preferences`

**Method:** GET

**Headers:**

```
Authorization: Bearer YOUR_TOKEN
```

The API response is used to update metadata and system prompt.

## Advanced Mode (Python)

Write custom Python code for complex logic.

<img src="https://mintcdn.com/callkaroai/_yHIwUXcSxcKfjME/images/functions/pre-call-advanced.png?fit=max&auto=format&n=_yHIwUXcSxcKfjME&q=85&s=d98fa16462b6a95a449662100d009fee" alt="Pre-Call Advanced Mode" width="1920" height="1077" data-path="images/functions/pre-call-advanced.png" />

### Function Signature

```python theme={null}
async def function_name(metadata: dict, system_prompt: str) -> str:
    """
    Pre-call function to customize system prompt
    """
    # Your code here
    return system_prompt  # Must return updated prompt
```

**Rules:**

* Must be `async def`
* Takes exactly 2 parameters: `metadata` and `system_prompt`
* Must return the updated `system_prompt` string
* Can modify existing metadata keys only (cannot add new keys)

### Metadata Rules

<Warning>
  You can only modify existing metadata keys. Adding new keys is forbidden.
</Warning>

**Allowed:**

```python theme={null}
# Read and update existing keys
if "preferred_language" in metadata:
    metadata["preferred_language"] = "hi"

# Safe access
user_id = metadata.get("user_id")
```

**Not Allowed:**

```python theme={null}
# Adding new keys is forbidden
metadata["new_field"] = "value"  # ❌
```

### System Prompt Updates

Replace placeholders in the system prompt with actual values:

```python theme={null}
final_prompt = system_prompt

# Replace placeholders
final_prompt = final_prompt.replace("{user_name}", user_name)
final_prompt = final_prompt.replace("{greeting}", greeting)

return final_prompt
```

### Example: Load Language Preferences

```python theme={null}
async def load_language_and_greeting(metadata: dict, system_prompt: str) -> str:
    """
    Fetches preferred language from API and updates system prompt
    """
    final_prompt = system_prompt
    lead_id = metadata.get("lead_id")
    preferred_language = None
    
    # Fetch language from API
    if lead_id:
        try:
            async with httpx.AsyncClient(timeout=5.0) as client:
                resp = await client.get(
                    f"https://api.callkaro.ai/v1/user-language",
                    params={"lead_id": lead_id}
                )
            
            if resp.status_code == 200:
                data = resp.json()
                preferred_language = data.get("language")
        except httpx.RequestError:
            logger.error("Network error calling user-language API")
    
    # Update metadata if key exists
    if preferred_language and "preferred_language" in metadata:
        metadata["preferred_language"] = preferred_language
    
    # Update system prompt
    lang_val = preferred_language or "en"
    greeting = {
        "hi": "नमस्ते",
        "en": "Hello",
        "ta": "வணக்கம்"
    }.get(lang_val, "Hello")
    
    final_prompt = final_prompt.replace("{preferred_language}", lang_val)
    final_prompt = final_prompt.replace("{greeting}", greeting)
    
    return final_prompt
```

## AI Generation

Click **"Generate with AI"** to create functions using natural language.

**Example Prompt:**

```
Fetch user's preferred language from https://api.example.com/users/{lead_id}/language
and update the system prompt with the appropriate greeting
```

The AI will generate the complete function code following all rules and best practices.

## Allowed Operations

<Tabs>
  <Tab title="Allowed ✅">
    * HTTP calls with `httpx.AsyncClient`
    * JSON parsing
    * String manipulation
    * Environment variables
    * Logging
  </Tab>

  <Tab title="Forbidden ❌">
    * `eval`, `exec`, `compile`
    * Filesystem access
    * OS commands
    * Arbitrary external domains
  </Tab>
</Tabs>

## Best Practices

* **Timeout API calls** - Always set timeouts (5-10 seconds)
* **Handle errors gracefully** - Don't break the call if API fails
* **Use existing keys** - Only modify metadata keys that already exist
* **Keep it fast** - Pre-call functions delay call start
* **Log important events** - Use logger for debugging

<Tip>
  Keep pre-call functions fast (under 2 seconds) to avoid delaying call start.
</Tip>
