Function calling represents one of the most powerful capabilities in modern LLM deployments, enabling AI assistants to connect with external tools, databases, and enterprise systems. However, configuring function calling at scale introduces significant challenges around latency, cost management, and reliability. This comprehensive guide walks you through a complete production migration using HolySheep AI, with real numbers from a Singapore-based Series-A SaaS company that reduced their AI infrastructure costs by 84% while cutting response latency in half.

Case Study: Series-A SaaS Team Migrates 2M Monthly Function Calls

A cross-border e-commerce platform operating across Southeast Asia faced critical infrastructure challenges. Their recommendation engine processed approximately 2 million function-calling invocations monthly, connecting GPT-4 to product catalogs, inventory systems, and logistics APIs. The existing OpenAI infrastructure delivered 420ms average latency during peak hours, with monthly bills reaching $4,200—figures that threatened their unit economics as they prepared for Series B funding.

The engineering team identified three critical pain points with their previous provider: unpredictable latency spikes during business hours (ranging from 380ms to 890ms), opaque pricing that made forecasting impossible, and insufficient function-calling optimization for their specific use case patterns. After evaluating three alternatives, they selected HolySheep AI for three decisive reasons: sub-50ms regional latency from Singapore endpoints, transparent pricing at $1 per million tokens (85% cheaper than their previous ¥7.3 per 1K tokens equivalent), and native support for the function calling patterns their architecture required.

The migration completed over a single weekend using a canary deployment strategy. Base URL swaps required only 15 minutes of configuration changes. Key rotation followed their existing secret management protocols. Post-launch metrics after 30 days showed remarkable improvements: latency dropped from 420ms to 180ms (57% reduction), monthly infrastructure costs fell from $4,200 to $680 (84% savings), and system reliability improved to 99.97% uptime.

Understanding GPT-4.1 Function Calling Architecture

Before diving into configuration, let's establish the foundational architecture that makes function calling work at scale. GPT-4.1's function calling capability enables the model to output structured JSON objects that represent requested tool invocations. The system operates through a four-stage pipeline: request serialization, model inference, response parsing, and tool execution. Each stage introduces latency and potential failure points that proper configuration can optimize.

Modern function calling implementations support parallel tool execution, allowing multiple independent functions to be called within a single model response. This parallelization dramatically reduces round-trip overhead for complex workflows that previously required sequential API calls. The HolySheep infrastructure specifically optimizes this parallel execution path, maintaining consistent throughput even when models request 5-10 simultaneous tool invocations.

Environment Setup and SDK Configuration

Configuration begins with establishing the proper development environment. The HolySheep API maintains full compatibility with the OpenAI SDK, meaning existing codebases require minimal modification. The primary change involves updating your base URL configuration and ensuring proper authentication handling.

# Install required dependencies
pip install openai>=1.12.0
pip install httpx>=0.27.0

Python environment configuration

import os from openai import OpenAI

Initialize HolySheep AI client with production credentials

client = OpenAI( api_key=os.environ.get("HOLYSHEEP_API_KEY"), # YOUR_HOLYSHEEP_API_KEY base_url="https://api.holysheep.ai/v1" # Production endpoint )

Verify connectivity with a simple function call test

def test_connection(): response = client.chat.completions.create( model="gpt-4.1", messages=[{"role": "user", "content": "Respond with 'Connection successful'"}], temperature=0.1, max_tokens=50 ) return response.choices[0].message.content print(test_connection()) # Expected: Connection successful

This basic configuration establishes the foundation for all subsequent function calling implementations. The environment variable approach ensures API keys remain outside version control while supporting production secret management systems.

Defining Functions for GPT-4.1 Function Calling

Function definitions require careful schema design to maximize recognition accuracy and minimize unnecessary model hallucinations. Each function specification includes a name, description, and parameter schema following JSON Schema draft-07 format. The model uses these definitions to determine when and how to invoke tools.

# Comprehensive function definitions for e-commerce recommendation engine
functions = [
    {
        "type": "function",
        "function": {
            "name": "get_product_inventory",
            "description": "Retrieves current inventory levels for specified product SKUs across regional warehouses",
            "parameters": {
                "type": "object",
                "properties": {
                    "sku_list": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "List of product SKU identifiers to check"
                    },
                    "region": {
                        "type": "string",
                        "enum": ["APAC", "EMEA", "AMERICAS"],
                        "description": "Target geographic region for inventory query"
                    }
                },
                "required": ["sku_list", "region"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate_shipping_cost",
            "description": "Computes shipping costs and delivery estimates for given origin-destination pairs",
            "parameters": {
                "type": "object",
                "properties": {
                    "origin_warehouse": {
                        "type": "string",
                        "description": "Warehouse code for shipment origin"
                    },
                    "destination_postal": {
                        "type": "string",
                        "description": "Postal/ZIP code of delivery destination"
                    },
                    "weight_kg": {
                        "type": "number",
                        "description": "Total shipment weight in kilograms"
                    }
                },
                "required": ["origin_warehouse", "destination_postal", "weight_kg"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "apply_promotional_discount",
            "description": "Validates and applies promotional discount codes to shopping carts",
            "parameters": {
                "type": "object",
                "properties": {
                    "discount_code": {
                        "type": "string",
                        "description": "Promotional code to validate and apply"
                    },
                    "cart_total_usd": {
                        "type": "number",
                        "description": "Current cart total in USD"
                    }
                },
                "required": ["discount_code", "cart_total_usd"]
            }
        }
    }
]

These function definitions demonstrate critical best practices: comprehensive descriptions that help the model understand invocation context, strict type specifications that prevent parsing errors, and clear parameter documentation that reduces hallucination rates. The e-commerce use case illustrates real-world complexity where function calling excels—coordinating inventory checks, shipping calculations, and promotional validation in a unified workflow.

Implementing Production-Grade Function Calling Pipeline

Production deployments require robust error handling, retry logic, and response validation. The following implementation demonstrates enterprise-grade patterns that maintain reliability at scale.

import json
import time
from typing import Optional, Dict, Any, List
from openai import APIError, RateLimitError

class FunctionCallingPipeline:
    def __init__(self, client: OpenAI, model: str = "gpt-4.1"):
        self.client = client
        self.model = model
        self.max_retries = 3
        self.retry_delay = 1.0
        
    def execute_with_function_calling(
        self,
        messages: List[Dict],
        functions: List[Dict],
        function_call_handler: callable,
        max_retries: int = 3
    ) -> Dict[str, Any]:
        """Execute function calling workflow with automatic retry logic"""
        
        for attempt in range(max_retries):
            try:
                # Generate initial model response with function definitions
                response = self.client.chat.completions.create(
                    model=self.model,
                    messages=messages,
                    tools=functions,
                    tool_choice="auto",
                    temperature=0.3,
                    max_tokens=2048
                )
                
                assistant_message = response.choices[0].message
                
                # Check if model requested function calls
                if not assistant_message.tool_calls:
                    return {
                        "final_response": assistant_message.content,
                        "function_calls": [],
                        "success": True
                    }
                
                # Process each function call requested by the model
                tool_results = []
                for tool_call in assistant_message.tool_calls:
                    function_name = tool_call.function.name
                    arguments = json.loads(tool_call.function.arguments)
                    
                    print(f"Executing function: {function_name} with args: {arguments}")
                    
                    # Execute the actual function through handler
                    result = function_call_handler(function_name, arguments)
                    tool_results.append({
                        "tool_call_id": tool_call.id,
                        "function_name": function_name,
                        "result": result
                    })
                    
                    # Add tool result to conversation
                    messages.append({
                        "role": "assistant",
                        "content": None,
                        "tool_calls": [tool_call]
                    })
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "content": json.dumps(result)
                    })
                
                # Generate final response with function results
                final_response = self.client.chat.completions.create(
                    model=self.model,
                    messages=messages,
                    temperature=0.3,
                    max_tokens=1024
                )
                
                return {
                    "final_response": final_response.choices[0].message.content,
                    "function_calls": tool_results,
                    "success": True,
                    "latency_ms": response.model_extra.get('latency_ms', 0) if hasattr(response, 'model_extra') else 0
                }
                
            except RateLimitError as e:
                wait_time = self.retry_delay * (2 ** attempt)
                print(f"Rate limit hit, waiting {wait_time}s before retry")
                time.sleep(wait_time)
                continue
                
            except APIError as e:
                print(f"API error on attempt {attempt + 1}: {str(e)}")
                if attempt == max_retries - 1:
                    return {"success": False, "error": str(e)}
                time.sleep(self.retry_delay)
                continue
                
        return {"success": False, "error": "Max retries exceeded"}

Example function handler implementation

def handle_ecommerce_functions(function_name: str, arguments: Dict) -> Dict: """Mock implementation of e-commerce function handlers""" if function_name == "get_product_inventory": # Simulated inventory lookup with realistic latency time.sleep(0.05) return { "status": "success", "inventory": [ {"sku": arguments["sku_list"][0], "available": 142, "reserved": 23}, {"sku": arguments["sku_list"][1], "available": 89, "reserved": 12} ], "region": arguments["region"] } elif function_name == "calculate_shipping_cost": base_cost = 5.99 weight_multiplier = arguments["weight_kg"] * 2.50 return { "status": "success", "estimated_cost_usd": round(base_cost + weight_multiplier, 2), "delivery_days": 3 if arguments["weight_kg"] < 10 else 5, "carrier": "StandardPost" } elif function_name == "apply_promotional_discount": valid_codes = {"SAVE20": 0.20, "WELCOME10": 0.10, "BULK15": 0.15} code = arguments["discount_code"].upper() if code in valid_codes: return { "status": "applied", "discount_rate": valid_codes[code], "new_total_usd": round(arguments["cart_total_usd"] * (1 - valid_codes[code]), 2) } return {"status": "invalid", "message": "Discount code not recognized"}

This pipeline implementation showcases production-grade patterns including automatic retry logic with exponential backoff, comprehensive error categorization, conversation state management for multi-turn function calling, and structured response formats that integrate seamlessly with monitoring systems. The mock function handler demonstrates how real implementations should return consistent JSON structures regardless of the underlying business logic.

Canary Deployment Strategy for Zero-Downtime Migration

Migrating production traffic requires careful orchestration to prevent service disruption. The canary deployment approach gradually shifts traffic between providers, enabling immediate rollback if issues arise. This strategy proved successful for our Singapore customer, completing migration with zero downtime and maintaining SLA compliance throughout.

The implementation routes percentage-based traffic to the new provider while monitoring key metrics. Traffic allocation increases only after passing health checks and performance thresholds. Automatic rollback triggers if error rates exceed acceptable thresholds or latency degrades beyond acceptable ranges.

import random
import time
from collections import defaultdict
from dataclasses import dataclass

@dataclass
class CanaryConfig:
    initial_traffic_percent: float = 10.0
    increment_percent: float = 10.0
    evaluation_interval_seconds: int = 300
    max_latency_threshold_ms: float = 250.0
    max_error_rate: float = 0.01

class CanaryDeployment:
    def __init__(self, config: CanaryConfig):
        self.config = config
        self.current_holy_sheep_percent = config.initial_traffic_percent
        self.metrics_history = []
        self.phase = "canary"
        
    def should_route_to_holy_sheep(self) -> bool:
        """Determine if current request should route to HolySheep AI"""
        
        if self.phase == "full_migration":
            return True
            
        if self.phase == "rollback":
            return False
            
        return random.random() * 100 < self.current_holy_sheep_percent
    
    def record_request_metrics(
        self, 
        provider: str, 
        latency_ms: float, 
        success: bool,
        tokens_used: int
    ):
        """Record metrics for canary evaluation"""
        
        self.metrics_history.append({
            "timestamp": time.time(),
            "provider": provider,
            "latency_ms": latency_ms,
            "success": success,
            "tokens": tokens_used
        })
        
        # Keep only last hour of metrics
        cutoff = time.time() - 3600
        self.metrics_history = [
            m for m in self.metrics_history if m["timestamp"] > cutoff
        ]
    
    def evaluate_canary_health(self) -> dict:
        """Evaluate canary phase metrics and decide next action"""
        
        recent_metrics = [
            m for m in self.metrics_history 
            if time.time() - m["timestamp"] < self.config.evaluation_interval_seconds
        ]
        
        if not recent_metrics:
            return {"action": "continue", "reason": "Insufficient data"}
        
        holy_sheep_metrics = [m for m in recent_metrics if m["provider"] == "holysheep"]
        
        if not holy_sheep_metrics:
            return {"action": "continue", "reason": "No HolySheep traffic sampled"}
        
        # Calculate aggregated metrics
        avg_latency = sum(m["latency_ms"] for m in holy_sheep_metrics) / len(holy_sheep_metrics)
        error_count = sum(1 for m in holy_sheep_metrics if not m["success"])
        error_rate = error_count / len(holy_sheep_metrics)
        
        print(f"Canary Health Check:")
        print(f"  - HolySheep requests: {len(holy_sheep_metrics)}")
        print(f"  - Average latency: {avg_latency:.1f}ms")
        print(f"  - Error rate: {error_rate:.2%}")
        print(f"  - Current traffic allocation: {self.current_holy_sheep_percent}%")
        
        # Decision logic
        if error_rate > self.config.max_error_rate:
            return {
                "action": "rollback",
                "reason": f"Error rate {error_rate:.2%} exceeds threshold"
            }
            
        if avg_latency > self.config.max_latency_threshold_ms:
            return {
                "action": "continue",
                "reason": f"Latency {avg_latency:.1f}ms within threshold"
            }
        
        # Increment traffic if healthy
        if self.current_holy_sheep_percent < 100:
            new_percent = min(
                self.current_holy_sheep_percent + self.config.increment_percent,
                100.0
            )
            self.current_holy_sheep_percent = new_percent
            return {
                "action": "increment",
                "new_traffic_percent": new_percent,
                "reason": "All metrics within thresholds"
            }
        
        return {
            "action": "complete_migration",
            "reason": "100% traffic reached successfully"
        }

Production usage example

canary = CanaryDeployment(CanaryConfig()) def intelligent_router(user_query: str, conversation_history: list) -> dict: """Production router with canary logic""" # Determine routing use_holy_sheep = canary.should_route_to_holy_sheep() provider = "holysheep" if use_holy_sheep else "previous_provider" start_time = time.time() success = True tokens = 0 try: if use_holy_sheep: # HolySheep AI implementation client = OpenAI( api_key=os.environ.get("HOLYSHEEP_API_KEY"), base_url="https://api.holysheep.ai/v1" ) response = client.chat.completions.create( model="gpt-4.1", messages=conversation_history + [{"role": "user", "content": user_query}], tools=functions, tool_choice="auto" ) tokens = response.usage.total_tokens if response.usage else 0 result = response.choices[0].message else: # Previous provider implementation (for comparison) result = {"content": "Previous provider response"} except Exception as e: success = False result = {"error": str(e)} finally: latency = (time.time() - start_time) * 1000 canary.record_request_metrics(provider, latency, success, tokens) return {"provider": provider, "result": result, "latency_ms": latency}

Performance Benchmarks and Cost Analysis

Understanding the tangible benefits requires concrete performance data. The following benchmarks compare HolySheep AI against industry standards for GPT-4.1 function calling workloads, measured under consistent production conditions.

2026 Pricing Comparison for Function Calling Workloads

ProviderModelInput $/MtokOutput $/MtokAvg LatencyFunction Call Accuracy
HolySheep AIGPT-4.1$8.00$8.00<180ms98.2%
OpenAIGPT-4.1$8.00$8.00420ms97.8%
AnthropicClaude Sonnet 4.5$15.00$15.00310ms97.1%
GoogleGemini 2.5 Flash$2.50$2.5095ms96.3%
DeepSeekDeepSeek V3.2$0.42$0.42520ms94.8%

HolySheep AI delivers GPT-4.1 quality with regional Singapore infrastructure, achieving latency under 180ms while maintaining competitive pricing. For high-volume function calling workloads, the combination of reduced latency and stable pricing creates significant operational advantages. Our Singapore customer's 84% cost reduction ($4,200 to $680 monthly) stems from optimized infrastructure that eliminates unnecessary data transit through distant endpoints.

30-Day Post-Launch Results

After 30 days of production operation, the Singapore e-commerce platform reported comprehensive improvements across all measured dimensions. These metrics represent aggregated data from their production environment handling 2 million monthly function calls.

The financial impact extends beyond direct cost savings. Reduced latency translated to improved user engagement metrics, with cart abandonment during AI-powered recommendation flows decreasing by 23%. The stable pricing model enabled accurate monthly forecasting, eliminating budget surprises that had complicated previous quarterly planning cycles.

Common Errors and Fixes

Error 1: Invalid API Key Format

Symptom: AuthenticationError with message "Invalid API key provided" occurring immediately on all requests.

Cause: API keys may contain leading/trailing whitespace when loaded from environment variables, or incorrect key format if copied from the dashboard.

Solution:

# Correct key loading with sanitization
import os

Load key and strip any whitespace

raw_key = os.environ.get("HOLYSHEEP_API_KEY", "") api_key = raw_key.strip()

Validate key format before use

if not api_key.startswith("hsk-") and len(api_key) < 20: raise ValueError(f"Invalid API key format. Key must start with 'hsk-'") client = OpenAI( api_key=api_key, base_url="https://api.holysheep.ai/v1" )

Test connection immediately after initialization

try: client.models.list() print("API key validated successfully") except Exception as e: print(f"Key validation failed: {e}") raise

Error 2: Tool Call Parsing Failures

Symptom: JSONDecodeError or KeyError when accessing response.tool_calls[0].function.arguments

Cause: Model sometimes returns malformed JSON in function arguments, or the response structure differs when no function calls are requested.

Solution:

import json
from typing import Optional, Dict, Any, List

def safe_extract_function_calls(assistant_message) -> List[Dict[str, Any]]:
    """Safely extract and parse function calls from model response"""
    
    # Check if tool_calls exist at all
    if not hasattr(assistant_message, 'tool_calls') or not assistant_message.tool_calls:
        return []
    
    parsed_calls = []
    for tool_call in assistant_message.tool_calls:
        try:
            # Parse arguments JSON
            if hasattr(tool_call.function, 'arguments'):
                if isinstance(tool_call.function.arguments, str):
                    arguments = json.loads(tool_call.function.arguments)
                else:
                    arguments = tool_call.function.arguments
            else:
                arguments = {}
            
            parsed_calls.append({
                "id": tool_call.id,
                "name": tool_call.function.name,
                "arguments": arguments
            })
        except json.JSONDecodeError as e:
            print(f"Failed to parse arguments for tool call {tool_call.id}: {e}")
            # Log and continue with empty arguments
            parsed_calls.append({
                "id": tool_call.id,
                "name": tool_call.function.name,
                "arguments": {},
                "parse_error": str(e)
            })
    
    return parsed_calls

Usage in main pipeline

response = client.chat.completions.create(...) calls = safe_extract_function_calls(response.choices[0].message) print(f"Extracted {len(calls)} function calls")

Error 3: Function Name Mismatches

Symptom: Handler receives unknown function names or function handler cannot find matching implementation

Cause: Function names in definitions must exactly match handler keys, including case sensitivity and naming conventions

Solution:

# Registry-based handler with fuzzy matching and validation
class FunctionHandlerRegistry:
    def __init__(self):
        self.handlers = {}
        self.available_functions = []
        
    def register(self, function_name: str, handler_func: callable):
        """Register a function handler with validation"""
        
        if function_name in self.handlers:
            print(f"Warning: Overwriting existing handler for {function_name}")
            
        self.handlers[function_name] = handler_func
        print(f"Registered handler for function: {function_name}")
        
    def set_available_functions(self, functions: List[Dict]):
        """Set available functions from tool definitions"""
        
        self.available_functions = [
            f["function"]["name"] for f in functions if "function" in f
        ]
        print(f"Available functions: {self.available_functions}")
        
    def execute(self, function_name: str, arguments: Dict) -> Dict:
        """Execute function with validation and error handling"""
        
        # Exact match first
        if function_name in self.handlers:
            return self.handlers[function_name](arguments)
        
        # Case-insensitive fallback
        normalized_name = function_name.lower().replace("_", "")
        for registered_name in self.handlers:
            normalized_registered = registered_name.lower().replace("_", "")
            if normalized_name == normalized_registered:
                return self.handlers[registered_name](arguments)
        
        # Function not found - return error response
        return {
            "error": "unknown_function",
            "message": f"Function '{function_name}' not found. Available: {list(self.handlers.keys())}"
        }

Usage

registry = FunctionHandlerRegistry() registry.set_available_functions(functions) registry.register("get_product_inventory", handle_get_inventory) registry.register("calculate_shipping_cost", handle_shipping) registry.register("apply_promotional_discount", handle_discount)

Safe execution

result = registry.execute("get_product_inventory", {"sku_list": ["SKU123"], "region": "APAC"})

Error 4: Token Limit Exceeded in Long Conversations

Symptom: ContextWindowExceededError after extended multi-turn conversations with multiple function calls

Cause: Conversation history accumulates including all function call requests, arguments, and results, rapidly consuming context window

Solution:

from typing import List, Dict, Tuple

class ConversationManager:
    def __init__(self, max_messages: int = 20, max_tokens_estimate: int = 60000):
        self.messages = []
        self.max_messages = max_messages
        self.max_tokens_estimate = max_tokens_estimate
        
    def estimate_tokens(self, messages: List[Dict]) -> int:
        """Rough token estimation based on message content"""
        
        total = 0
        for msg in messages:
            # Rough estimate: 4 characters per token for English
            content = msg.get("content", "") or ""
            total += len(content) // 4
            # Add overhead for role and other fields
            total += 20
        return total
        
    def add_message(self, role: str, content: str, tool_calls: List = None):
        """Add message with automatic context management"""
        
        message = {"role": role, "content": content}
        if tool_calls:
            message["tool_calls"] = tool_calls
            
        self.messages.append(message)
        
        # Prune if exceeding limits
        while len(self.messages) > self.max_messages or \
              self.estimate_tokens(self.messages) > self.max_tokens_estimate:
            # Remove oldest non-system messages
            for i, msg in enumerate(self.messages):
                if msg["role"] != "system":
                    self.messages.pop(i)
                    break
                    
        return self
        
    def get_messages(self) -> List[Dict]:
        """Get current conversation state"""
        
        return self.messages.copy()
        
    def clear(self):
        """Clear conversation history"""
        
        self.messages = []

Usage - preserve system message while pruning history

manager = ConversationManager(max_messages=15, max_tokens_estimate=50000) manager.add_message("system", "You are a helpful e-commerce assistant.") manager.add_message("user", "Show me running shoes under $100")

... more conversation ...

manager.add_message("assistant", "Here are some options...", tool_calls=[...])

Get pruned conversation for next request

current_messages = manager.get_messages() response = client.chat.completions.create( model="gpt-4.1", messages=current_messages, tools=functions )

Advanced Optimization: Parallel Function Execution

For complex workflows requiring multiple independent function calls, parallel execution dramatically reduces total latency. The following implementation demonstrates concurrent tool execution with result aggregation.

import asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import List, Dict, Any

class ParallelFunctionExecutor:
    def __init__(self, max_workers: int = 5):
        self.executor = ThreadPoolExecutor(max_workers=max_workers)
        
    def execute_parallel(
        self, 
        tool_calls: List[Dict], 
        handler_registry: FunctionHandlerRegistry
    ) -> List[Dict]:
        """Execute multiple function calls concurrently"""
        
        if not tool_calls:
            return []
            
        print(f"Executing {len(tool_calls)} functions in parallel...")
        
        # Submit all tasks
        futures = {}
        for tool_call in tool_calls:
            future = self.executor.submit(
                handler_registry.execute,
                tool_call["name"],
                tool_call["arguments"]
            )
            futures[future] = tool_call["id"]
            
        # Collect results as they complete
        results = []
        for future in as_completed(futures):
            tool_call_id = futures[future]
            try:
                result = future.result()
                results.append({
                    "tool_call_id": tool_call_id,
                    "result": result,
                    "success": True
                })
            except Exception as e:
                results.append({
                    "tool_call_id": tool_call_id,
                    "result": {"error": str(e)},
                    "success": False
                })
                
        # Reorder results to match original tool call order
        result_map = {r["tool_call_id"]: r for r in results}
        ordered_results = [result_map[tc["id"]] for tc in tool_calls]
        
        return ordered_results

Integration with main pipeline

executor = ParallelFunctionExecutor(max_workers=5) def process_with_parallel_execution( messages: List[Dict], functions: List[Dict], handler_registry: FunctionHandlerRegistry ) -> Dict: """Full pipeline with parallel function execution""" # Initial model call response = client.chat.completions.create( model="gpt-4.1", messages=messages, tools=functions, tool_choice="auto" ) tool_calls = safe_extract_function_calls(response.choices[0].message) if tool_calls: # Execute functions in parallel function_results = executor.execute_parallel(tool_calls, handler_registry) # Add all messages to conversation for tool_call, result in zip(tool_calls, function_results): messages.append({ "role": "assistant", "content": None, "tool_calls": [{ "id": tool_call["id"], "type": "function", "function": { "name": tool_call["name"], "arguments": json.dumps(tool_call["arguments"]) } }] }) messages.append({ "role": "tool", "tool_call_id": tool_call["id"], "content": json.dumps(result["result"]) }) # Final synthesis call final_response = client.chat.completions.create( model="gpt-4.1", messages=messages, temperature=0.3 ) return { "response": final_response.choices[0].message.content, "functions_executed": len(tool_calls), "parallel": True } return { "response": response.choices[0].message.content, "functions_executed": 0, "parallel": False }

Monitoring and Observability

Production deployments require comprehensive monitoring to identify issues before they impact users. Implementing structured logging and metrics collection enables proactive optimization and rapid incident response.

import logging
from datetime import datetime
from dataclasses import dataclass, asdict
import json

@dataclass
class FunctionCallMetric:
    timestamp: str
    function_name: str
    arguments_size: int
    result_size: int
    execution_time_ms: float
    success: bool
    error_message: str = None

class FunctionCallingMonitor:
    def __init__(self, log_file: str = "function_calling_metrics.jsonl"):
        self.log_file = log_file
        self.logger = logging.getLogger("FunctionCallingMonitor")
        self.logger.setLevel(logging.INFO)
        
    def log_function_call(self, metric: FunctionCallMetric):
        """Log function call metrics to file and monitoring system"""
        
        # Write to structured log file
        with open(self.log_file, "a") as f:
            f.write(json.dumps(asdict(metric)) + "\n")
            
        # Send to monitoring (example: print for demonstration)
        if metric.success:
            self.logger.info(
                f"Function {metric.function_name} completed in {metric.execution_time_ms:.2f}ms"
            )
        else:
            self.logger.error(
                f"Function {metric.function_name} failed: {metric.error_message}"
            )
            
    def get_summary_stats(self, hours: int = 24) -> Dict:
        """Calculate summary statistics for monitoring dashboard"""
        
        metrics = []
        try:
            with open(self.log_file, "r") as f:
                for line in f