# Function Calling

Function calling enables AI models to interact with external tools, APIs, and services by generating structured function calls with validated parameters. This powerful capability transforms language models into intelligent agents that can perform actions, retrieve data, and orchestrate complex workflows.

## Overview

When you provide function definitions to a model, it can intelligently decide when and how to call those functions based on the user's request. The model generates structured JSON with function names and parameters, which you can then execute in your application.

### How It Works


```mermaid
sequenceDiagram
 participant User
 participant API
 participant Model
 participant Backend

 User->>API: Request with tools defined
 API->>Model: Process with tool schemas
 Model->>Backend: Decides to call tool
 Backend->>Backend: Execute tool
 Backend->>Model: Return tool results
 Model->>API: Generate final response
 API->>User: Complete answer
```

**The Flow:**

1. **Define Tools** - Provide function schemas with names, descriptions, and parameters
2. **Model Analyzes** - AI determines if and which tools to call based on context
3. **Structured Output** - Model generates valid JSON with function name and arguments
4. **Execution** - Your application executes the function or backend handles it automatically
5. **Result Integration** - Function results are fed back to the model
6. **Final Response** - Model generates natural language response using the data


## Function Types

Aitronos supports two types of function calling:

### 1. Pass-Through Functions (Client-Side)

**Custom functions you define and execute in your application.**

**When to Use:**

- Interact with your own APIs or databases
- Perform business logic specific to your application
- Access resources only available to your backend
- Maintain full control over function execution


**Example:**


```json
{
 "type": "function",
 "name": "get_user_orders",
 "description": "Retrieve order history for a user",
 "parameters": {
 "type": "object",
 "properties": {
 "userId": {
 "type": "string",
 "description": "The unique user identifier"
 },
 "limit": {
 "type": "integer",
 "description": "Maximum number of orders to return"
 }
 },
 "required": ["userId"]
 }
}
```

### 2. Built-In Functions (Server-Side)

**Pre-built tools executed automatically by Aitronos backend.**

**Available Built-In Tools:**

- **Web Search** - Real-time internet search and information retrieval
- **File Search** - Search through uploaded documents and files
- **Code Interpreter** - Execute Python code in sandboxed environment
- **Image Generation** - Generate or edit images


**Example:**


```json
{
 "type": "webSearch",
 "searchContextSize": "medium"
}
```

## Agentic Tool Calling

**New in 2025:** Aitronos now supports **fully automatic agentic tool calling** where the backend manages the entire multi-step execution loop.

### What is Agentic Tool Calling?

Traditional function calling requires your application to:

1. Make initial request
2. Receive tool call from model
3. Execute the tool
4. Send results back to model
5. Repeat until model is satisfied


**Agentic tool calling automates this entirely.** Make a single API request, and the backend:

- Executes tools automatically (for built-in tools)
- Feeds results back to the model
- Allows model to make additional tool calls
- Returns only the final, complete answer


### Benefits

**Simplified Integration** - Single API call instead of multi-turn loop
**Automatic Orchestration** - No manual tool result handling
**Built-In Execution** - Common tools executed server-side
**Conversation History** - Full context preserved automatically
**Multi-Step Workflows** - Model can chain multiple tool calls intelligently

### Supported Models

| Model | Function Calling | Parallel Tool Calls |
|  --- | --- | --- |
| GPT-5 | ✅ | ✅ |
| GPT-4o | ✅ | ✅ |
| Claude Sonnet 4 | ✅ | ✅ |
| Claude 3.5 Sonnet | ✅ | ✅ |
| Gemini 2.5 | ✅ | ✅ |


All models that support function calling can generate multiple tool calls in a single turn. The model decides whether to call tools in parallel based on the task.

### Example: Weather Report Workflow

**Single API Call:**


```python
import requests

response = requests.post(
 "https://api.aitronos.com/v1/model/response",
 headers={"X-API-Key": api_key},
 json={
 "organizationId": "org_abc123",
 "model": "gpt-5",
 "inputs": [
 {
 "role": "user",
 "content": "Give me a weather report for major Asian cities"
 }
 ],
 "functions": [
 {
 "type": "function",
 "name": "get_cities",
 "description": "Get a list of 5 cities for a region",
 "parameters": {
 "type": "object",
 "properties": {
 "region": {
 "type": "string",
 "enum": ["asia", "europe", "americas"]
 }
 },
 "required": ["region"]
 }
 },
 {
 "type": "function",
 "name": "get_temperature",
 "description": "Get current temperature for a city",
 "parameters": {
 "type": "object",
 "properties": {
 "city": {"type": "string"}
 },
 "required": ["city"]
 }
 }
 ]
 }
)

result = response.json()
print(result['response'])
```

**What Happens Automatically:**

1. **Model calls** `get_cities(region="asia")`
2. **Backend executes** → Returns `["Tokyo", "Singapore", "Seoul", "Bangkok", "Mumbai"]`
3. **Model calls** `get_temperature(city="Tokyo")`
4. **Backend executes** → Returns `{"temperature": 28}`
5. **Model calls** `get_temperature` for remaining 4 cities
6. **Backend executes** all calls
7. **Model generates** comprehensive report:


> "Here's the weather report for major Asian cities: Tokyo is 28°C, Singapore is 31°C..."


## Function Schema Definition

Functions must be defined using JSON Schema format:

### Required Fields

**`type`** - Always set to `"function"`

**`name`** - Unique identifier for the function

- Must be alphanumeric with underscores
- Example: `get_current_weather`, `create_order`, `send_email`


**`description`** - Clear explanation of what the function does

- Be specific and descriptive
- Include when the function should be called
- Mention any important constraints


**`parameters`** - JSON Schema defining input parameters

- Use `type`, `properties`, `required`
- Add descriptions for each parameter
- Specify enums for restricted values


### Example Schema


```json
{
 "type": "function",
 "name": "book_flight",
 "description": "Book a flight ticket for a passenger. Use this when the user wants to purchase airline tickets.",
 "parameters": {
 "type": "object",
 "properties": {
 "departure": {
 "type": "string",
 "description": "Departure airport code (e.g., 'JFK', 'LAX')"
 },
 "arrival": {
 "type": "string",
 "description": "Arrival airport code"
 },
 "date": {
 "type": "string",
 "format": "date",
 "description": "Flight date in YYYY-MM-DD format"
 },
 "passengers": {
 "type": "integer",
 "minimum": 1,
 "maximum": 9,
 "description": "Number of passengers"
 },
 "class": {
 "type": "string",
 "enum": ["economy", "business", "first"],
 "description": "Ticket class"
 }
 },
 "required": ["departure", "arrival", "date", "passengers"]
 },
 "strict": true
}
```

## Tool Choice Control

Control how and when the model uses tools with the `toolChoice` parameter:

### Options

**`auto`** (default) - Model decides whether to use tools


```json
{
 "toolChoice": "auto"
}
```

**`none`** - Disable all tool usage


```json
{
 "toolChoice": "none"
}
```

**`required`** - Force the model to use at least one tool


```json
{
 "toolChoice": "required"
}
```

**Specific Tool** - Force the model to use a particular tool


```json
{
 "toolChoice": {
 "type": "function",
 "function": {
 "name": "get_current_weather"
 }
 }
}
```

## Parallel Tool Calls

Models can generate **multiple tool calls in a single turn** when they determine that several independent operations are needed. This happens automatically — there is no parameter to enable or disable it.

### How It Works

When the model needs multiple pieces of information simultaneously, it generates all the tool calls at once:

**Example:** User asks "Get weather for NYC, LA, and Chicago"

The model generates three tool calls in one turn:


```json
{
  "response": [
    {"type": "text", "text": "Let me check the weather for all three cities."},
    {"type": "tool_use", "id": "call_001", "name": "get_weather", "input": {"city": "NYC"}},
    {"type": "tool_use", "id": "call_002", "name": "get_weather", "input": {"city": "LA"}},
    {"type": "tool_use", "id": "call_003", "name": "get_weather", "input": {"city": "Chicago"}}
  ],
  "stop_reason": "tool_use"
}
```

### Server-Side vs Custom Function Tools

| Tool Type | Execution | Your App |
|  --- | --- | --- |
| **Server-side** (personal connectors, MCP, web search) | Executed automatically and concurrently by the backend | Receives only the final answer — no action needed |
| **Custom functions** | NOT executed by the backend | Must execute all pending calls, then send results back |


### The Tool Call Loop

For custom function tools, implement a loop that continues until the model is done:


```python
import asyncio
import json

async def run_with_tools(prompt, tools):
    messages = [{"role": "user", "content": prompt}]

    while True:
        response = call_responses_api(messages, tools)

        if response["stop_reason"] == "end_turn":
            return response["response"]  # Final answer

        # Extract all tool calls from this turn
        tool_calls = [b for b in response["response"] if b["type"] == "tool_use"]

        # Execute ALL tool calls in parallel
        results = await asyncio.gather(*[
            execute_tool(tc["name"], tc["input"]) for tc in tool_calls
        ])

        # Add assistant response + tool results to conversation
        messages.append({"role": "assistant", "content": response["response"]})
        for tc, result in zip(tool_calls, results):
            messages.append({
                "role": "tool",
                "tool_call_id": tc["id"],
                "content": json.dumps(result)
            })

        # Loop continues — model may make more calls or give final answer
```

### Key Points

- **`stop_reason: "tool_use"`** means the model wants you to execute function calls
- **`stop_reason: "end_turn"`** means the model is done — this is the final answer
- Always execute **all** pending tool calls before sending results back
- Execute independent tool calls **in parallel** for best performance
- The model may chain multiple rounds of tool calls (call → result → more calls → result → final answer)


## Best Practices

### 1. Clear Function Descriptions

**Bad:**


```json
{
 "name": "get_data",
 "description": "Gets data"
}
```

**Good:**


```json
{
 "name": "get_user_profile",
 "description": "Retrieve detailed user profile information including name, email, preferences, and account status. Use this when you need to access user data for personalization or account management."
}
```

### 2. Validate Function Results

Always validate and sanitize data returned from functions before passing to the model:


```python
def execute_function(name, args):
 try:
 result = call_function(name, args)

 # Validate result
 if not result:
 return {"error": "Function returned no data"}

 # Sanitize sensitive data
 if 'password' in result:
 del result['password']

 return result
 except Exception as e:
 return {"error": f"Function failed: {str(e)}"}
```

### 3. Use Enums for Fixed Options

Restrict parameters to known values:


```json
{
 "parameters": {
 "properties": {
 "priority": {
 "type": "string",
 "enum": ["low", "medium", "high", "urgent"],
 "description": "Task priority level"
 }
 }
 }
}
```

### 4. Set Reasonable Limits

Prevent excessive tool calls:


```json
{
 "maxToolCalls": 10 // Limit total tool calls per request
}
```

### 5. Handle Errors Gracefully

Return structured error messages:


```json
{
  "success": false,
  "error": "User not found",
  "error_code": "USER_NOT_FOUND",
  "suggestion": "Try searching by email instead"
}
```

## Common Patterns

### Pattern 1: Data Retrieval

**Use Case:** Fetch information from external systems


```json
{
 "type": "function",
 "name": "get_customer_info",
 "description": "Retrieve customer information from CRM",
 "parameters": {
 "type": "object",
 "properties": {
 "customerId": {"type": "string"}
 },
 "required": ["customerId"]
 }
}
```

### Pattern 2: Data Modification

**Use Case:** Create, update, or delete records


```json
{
 "type": "function",
 "name": "update_order_status",
 "description": "Update the status of an existing order",
 "parameters": {
 "type": "object",
 "properties": {
 "orderId": {"type": "string"},
 "newStatus": {
 "type": "string",
 "enum": ["pending", "processing", "shipped", "delivered", "cancelled"]
 },
 "reason": {"type": "string"}
 },
 "required": ["orderId", "newStatus"]
 }
}
```

### Pattern 3: Multi-Step Workflows

**Use Case:** Chain multiple operations


```python
# User: "Find available hotels in Paris and book the cheapest one"

# Step 1: Model calls search_hotels
{
 "function": "search_hotels",
 "arguments": {"city": "Paris", "checkIn": "2025-06-01"}
}

# Step 2: Backend executes and returns results
# Step 3: Model analyzes results and calls booking
{
 "function": "book_hotel",
 "arguments": {"hotelId": "hotel_123", "price": 89}
}

# Step 4: Model generates confirmation message
```

### Pattern 4: Conditional Logic

**Use Case:** Different actions based on data


```python
# User: "Check my account balance and transfer $100 if I have enough"

# Step 1: Check balance
result = get_account_balance(accountId="acc_123")
# Returns: {"balance": 500}

# Step 2: Model decides to proceed with transfer
transfer_funds(from="acc_123", to="acc_456", amount=100)
```

## Error Handling

### Common Errors

**Invalid Function Definition:**


```json
{
 "error": {
 "message": "Invalid function schema",
 "code": "invalid_function_schema",
 "details": "Missing required field: 'parameters'"
 }
}
```

**Function Execution Failed:**


```json
{
 "error": {
 "message": "Function execution failed",
 "code": "function_execution_error",
 "function": "get_weather",
 "details": "API timeout after 30s"
 }
}
```

**Max Tool Calls Exceeded:**


```json
{
 "error": {
 "message": "Maximum tool calls exceeded",
 "code": "max_tool_calls_exceeded",
 "limit": 10,
 "actual": 11
 }
}
```

## Advanced Topics

### Function Call Logs

Enable detailed logging with `include`:


```json
{
 "include": ["function_calls.logs", "function_calls.sources"]
}
```

Returns:


```json
{
 "functionCalls": [
 {
 "name": "get_weather",
 "arguments": {"city": "Paris"},
 "executionTime": 234,
 "timestamp": "2025-01-15T10:30:00Z"
 }
 ]
}
```

### Strict Mode

Enforce exact schema compliance:


```json
{
 "strict": true // Model guarantees parameters match schema exactly
}
```

### Combining Tools

Mix built-in and custom functions:


```json
{
 "tools": [
 {"type": "webSearch"}, // Built-in
 {"type": "fileSearch"}, // Built-in
 { // Custom
 "type": "function",
 "name": "save_to_database",
 "parameters": {...}
 }
 ]
}
```

## Related Resources

- [Agentic Workflows Guide](/docs/documentation/core-concepts/agentic-workflows) - Deep dive into multi-step automation
- [Web Search Tool](/docs/documentation/system-tools/web-search) - Built-in internet search
- [Code Interpreter](/docs/documentation/system-tools/code-interpreter) - Python execution environment
- [Structured Output](/docs/documentation/core-concepts/structured-output) - JSON response formatting
- [API Reference: Create Response](/docs/api-reference/responses/create) - Full API documentation


## Examples

See complete working examples:

- [Weather Report Workflow](/docs/documentation/examples/weather-report-workflow)
- [E-commerce Assistant](/docs/documentation/examples/ecommerce-assistant)
- [Customer Support Bot](/docs/documentation/examples/customer-support-bot)