Skip to main content
Function Calling allows AI models to call external functions and APIs, greatly expanding the capability boundaries of intelligent agents, enabling them to perform specific operations and obtain real-time data.

Features

Function calling provides AI models with the ability to interact with external systems, supporting various complex application scenarios and integration requirements.

Core Parameter Description

  • tools: Defines the list of callable functions, including function names, descriptions, and parameter specifications
  • tool_choice: Controls function calling strategy, can be set to auto, none, or specify a function name
  • model: Uses models that support function calling, such as glm-4-plus, glm-4.6, etc.

Response Parameter Description

Key fields in function calling responses:
  • tool_calls: Contains information about functions the model decides to call
  • function.name: Name of the called function
  • function.arguments: Function call parameters (JSON format string)
  • id: Unique identifier for the tool call

Features

Structured Output

  • Automatic function parameter parsing
  • Type validation and conversion
  • Error handling and retry
  • Result formatting

Multi-function Support

  • Define multiple functions simultaneously
  • Function chaining calls
  • Conditional function selection
  • Parallel function execution

Flexible Integration

  • RESTful API integration
  • Database operations
  • File system access
  • Third-party service calls

Code Examples

By defining function tools and handling function calls, AI models can perform various external operations:
  • Python SDK
Install SDK
# Install latest version
pip install zai-sdk

# Or specify version
pip install zai-sdk==0.0.4
Verify Installation
import zai
print(zai.__version__)
Complete Example
import json
from zai import ZaiClient

# Initialize client
client = ZaiClient(api_key='your_api_key')

# Define weather query function
def get_weather(city: str) -> dict:
    """Get weather information for specified city"""
    # This should call a real weather API
    weather_data = {
        "city": city,
        "temperature": "22Β°C",
        "condition": "Sunny",
        "humidity": "65%",
        "wind_speed": "5 km/h"
    }
    return weather_data

# Define function tools
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get current weather information for specified city",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "City name, e.g.: Beijing, Shanghai"
                    }
                },
                "required": ["city"]
            }
        }
    }
]

# Make conversation request
response = client.chat.completions.create(
    model="glm-4-plus",  # Use model that supports function calling
    messages=[
        {"role": "user", "content": "How's the weather in Beijing today?"}
    ],
    tools=tools,         # Pass function tools
    tool_choice="auto"   # Automatically choose whether to call functions
)

# Handle function calls
message = response.choices[0].message
messages = [{"role": "user", "content": "How's the weather in Beijing today?"}]
messages.append(message.model_dump())

if message.tool_calls:
    for tool_call in message.tool_calls:
        if tool_call.function.name == "get_weather":
            # Parse parameters and call function
            args = json.loads(tool_call.function.arguments)
            weather_result = get_weather(args.get("city"))
            
            # Return function result to model
            messages.append({
                "role": "tool",
                "content": json.dumps(weather_result, ensure_ascii=False),
                "tool_call_id": tool_call.id
            })
    
    # Get final answer
    final_response = client.chat.completions.create(
        model="glm-4-plus",
        messages=messages,
        tools=tools
    )
    
    print(final_response.choices[0].message.content)
else:
    print(message.content)

Scenario Examples

When using function calling, please ensure proper security validation and permission control for external APIs and database operations.
import json
import requests
from datetime import datetime
from zai import ZaiClient

class FunctionAgent:
    def __init__(self, api_key):
        self.client = ZaiClient(api_key=api_key)
        self.tools = self._define_tools()
    
    def _define_tools(self):
        return [
            {
                "type": "function",
                "function": {
                    "name": "get_current_time",
                    "description": "Get current time",
                    "parameters": {
                        "type": "object",
                        "properties": {},
                        "required": []
                    }
                }
            },
            {
                "type": "function",
                "function": {
                    "name": "calculate",
                    "description": "Perform mathematical calculations",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "expression": {
                                "type": "string",
                                "description": "Mathematical expression, e.g.: 2+3*4"
                            }
                        },
                        "required": ["expression"]
                    }
                }
            },
            {
                "type": "function",
                "function": {
                    "name": "search_web",
                    "description": "Search web information",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "query": {
                                "type": "string",
                                "description": "Search keywords"
                            }
                        },
                        "required": ["query"]
                    }
                }
            }
        ]
    
    def get_current_time(self):
        """Get current time"""
        return {
            "current_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "timezone": "Asia/Shanghai"
        }
    
    def calculate(self, expression: str):
        """Safe mathematical calculation"""
        try:
            # Simple security check
            allowed_chars = set('0123456789+-*/().')
            if not all(c in allowed_chars or c.isspace() for c in expression):
                return {"error": "Expression contains disallowed characters"}
            
            result = eval(expression)
            return {
                "expression": expression,
                "result": result
            }
        except Exception as e:
            return {"error": f"Calculation error: {str(e)}"}
    
    def search_web(self, query: str):
        """Simulate web search"""
        # This should call a real search API
        return {
            "query": query,
            "results": [
                {"title": f"Search result 1 about {query}", "url": "https://example1.com"},
                {"title": f"Search result 2 about {query}", "url": "https://example2.com"}
            ]
        }
    
    def execute_function(self, function_name: str, arguments: dict):
        """Execute function call"""
        if function_name == "get_current_time":
            return self.get_current_time()
        elif function_name == "calculate":
            return self.calculate(arguments.get("expression", ""))
        elif function_name == "search_web":
            return self.search_web(arguments.get("query", ""))
        else:
            return {"error": f"Unknown function: {function_name}"}
    
    def chat(self, user_message: str):
        """Handle user message"""
        messages = [{"role": "user", "content": user_message}]
        
        response = self.client.chat.completions.create(
            model="glm-4-plus",
            messages=messages,
            tools=self.tools,
            tool_choice="auto"
        )
        
        message = response.choices[0].message
        messages.append(message.model_dump())
        
        # Handle function calls
        if message.tool_calls:
            for tool_call in message.tool_calls:
                function_name = tool_call.function.name
                arguments = json.loads(tool_call.function.arguments)
                
                # Execute function
                result = self.execute_function(function_name, arguments)
                
                # Add function result
                messages.append({
                    "role": "tool",
                    "content": json.dumps(result, ensure_ascii=False),
                    "tool_call_id": tool_call.id
                })
            
            # Get final answer
            final_response = self.client.chat.completions.create(
                model="glm-4-plus",
                messages=messages,
                tools=self.tools
            )
            
            return final_response.choices[0].message.content
        else:
            return message.content

# Usage example
agent = FunctionAgent("your_api_key")

# Test different types of requests
print(agent.chat("What time is it now?"))
print(agent.chat("Help me calculate 15 * 23 + 7"))
print(agent.chat("Search for the latest developments in artificial intelligence"))
import sqlite3

def query_database(sql: str) -> dict:
    """Execute database query"""
    try:
        conn = sqlite3.connect('example.db')
        cursor = conn.cursor()
        cursor.execute(sql)
        results = cursor.fetchall()
        conn.close()
        
        return {
            "success": True,
            "data": results,
            "row_count": len(results)
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e)
        }

# Function definition
db_tool = {
    "type": "function",
    "function": {
        "name": "query_database",
        "description": "Execute SQL query",
        "parameters": {
            "type": "object",
            "properties": {
                "sql": {
                    "type": "string",
                    "description": "SQL query statement"
                }
            },
            "required": ["sql"]
        }
    }
}
import os
import json

def file_operations(operation: str, file_path: str, content: str = None) -> dict:
    """File operation function"""
    try:
        if operation == "read":
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            return {"success": True, "content": content}
        
        elif operation == "write":
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(content)
            return {"success": True, "message": "File written successfully"}
        
        elif operation == "list":
            files = os.listdir(file_path)
            return {"success": True, "files": files}
        
        else:
            return {"success": False, "error": "Unsupported operation"}
    
    except Exception as e:
        return {"success": False, "error": str(e)}

# Function definition
file_tool = {
    "type": "function",
    "function": {
        "name": "file_operations",
        "description": "Execute file operations",
        "parameters": {
            "type": "object",
            "properties": {
                "operation": {
                    "type": "string",
                    "enum": ["read", "write", "list"],
                    "description": "Operation type"
                },
                "file_path": {
                    "type": "string",
                    "description": "File path"
                },
                "content": {
                    "type": "string",
                    "description": "Content to write (only required for write operation)"
                }
            },
            "required": ["operation", "file_path"]
        }
    }
}
import requests

def call_external_api(url: str, method: str = "GET", headers: dict = None, data: dict = None) -> dict:
    """Call external API"""
    try:
        if method.upper() == "GET":
            response = requests.get(url, headers=headers, params=data)
        elif method.upper() == "POST":
            response = requests.post(url, headers=headers, json=data)
        else:
            return {"success": False, "error": "Unsupported HTTP method"}
        
        return {
            "success": True,
            "status_code": response.status_code,
            "data": response.json() if response.headers.get('content-type', '').startswith('application/json') else response.text
        }
    
    except Exception as e:
        return {"success": False, "error": str(e)}

# Function definition
api_tool = {
    "type": "function",
    "function": {
        "name": "call_external_api",
        "description": "Call external API",
        "parameters": {
            "type": "object",
            "properties": {
                "url": {
                    "type": "string",
                    "description": "API endpoint URL"
                },
                "method": {
                    "type": "string",
                    "enum": ["GET", "POST"],
                    "description": "HTTP method"
                },
                "headers": {
                    "type": "object",
                    "description": "Request headers"
                },
                "data": {
                    "type": "object",
                    "description": "Request data"
                }
            },
            "required": ["url"]
        }
    }
}

Best Practices

Function Design Principles

  • Single responsibility: Each function should do one thing
  • Clear naming: Function and parameter names should be meaningful
  • Complete description: Provide detailed function and parameter descriptions

Security Considerations

  • Input validation: Strictly validate all input parameters
  • Permission control: Limit function access permissions
  • Logging: Record function call logs

Parameter Design

# Good parameter design
{
    "type": "object",
    "properties": {
        "city": {
            "type": "string",
            "description": "City name, supports Chinese and English, e.g.: Beijing, Shanghai, New York",
            "examples": ["Beijing", "Shanghai", "New York"]
        },
        "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"],
            "description": "Temperature unit",
            "default": "celsius"
        }
    },
    "required": ["city"]
}

Error Handling

def robust_function(param: str) -> dict:
    """Robust function implementation"""
    try:
        # Parameter validation
        if not param or not isinstance(param, str):
            return {
                "success": False,
                "error": "Invalid parameter",
                "error_code": "INVALID_PARAM"
            }
        
        # Business logic
        result = process_data(param)
        
        return {
            "success": True,
            "data": result,
            "timestamp": datetime.now().isoformat()
        }
    
    except ValueError as e:
        return {
            "success": False,
            "error": f"Data error: {str(e)}",
            "error_code": "DATA_ERROR"
        }
    except Exception as e:
        return {
            "success": False,
            "error": f"System error: {str(e)}",
            "error_code": "SYSTEM_ERROR"
        }

Input Validation

def secure_function(user_input: str) -> dict:
    """Secure function implementation"""
    # Input length limit
    if len(user_input) > 1000:
        return {"error": "Input too long"}
    
    # Dangerous character filtering
    dangerous_chars = ['<', '>', '&', '"', "'"]
    if any(char in user_input for char in dangerous_chars):
        return {"error": "Input contains dangerous characters"}
    
    # SQL injection protection
    sql_keywords = ['DROP', 'DELETE', 'UPDATE', 'INSERT']
    if any(keyword in user_input.upper() for keyword in sql_keywords):
        return {"error": "Input contains dangerous keywords"}
    
    return {"success": True, "processed_input": user_input}

Permission Control

def check_permissions(user_id: str, operation: str) -> bool:
    """Check user permissions"""
    user_permissions = get_user_permissions(user_id)
    return operation in user_permissions

def protected_function(user_id: str, operation: str, data: dict) -> dict:
    """Function requiring permission validation"""
    if not check_permissions(user_id, operation):
        return {
            "success": False,
            "error": "Insufficient permissions",
            "error_code": "PERMISSION_DENIED"
        }
    
    # Execute operation
    return perform_operation(operation, data)
It is recommended to provide detailed documentation and examples for each function to help the model better understand the function’s purpose and usage.
Function calling involves code execution. Please ensure appropriate security measures are implemented, including input validation, permission control, and error handling.
⌘I