π§ Production Example 1 β Basic Tool Calling (Weather API)
π§ Use Case
User asks:
βWhatβs the weather in Delhi?β
LLM decides to call get_weather().
π¦ Step 1 β Define Tool Schema
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Fetch current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
}
}
]
π§ Step 2 β Define Backend Function
def get_weather(city: str) -> dict:
# In production, call real weather API here
return {
"city": city,
"temperature": "28Β°C",
"condition": "Sunny"
}
π Step 3 β Call LLM with Tools Enabled
from openai import OpenAI
import json
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "What is the weather in Delhi?"}
],
tools=tools,
tool_choice="auto"
)
π Step 4 β Detect Tool Call
message = response.choices[0].message
if message.tool_calls:
tool_call = message.tool_calls[0]
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
# Secure validation
if function_name == "get_weather" and "city" in arguments:
result = get_weather(arguments["city"])
π Step 5 β Send Tool Result Back to Model
second_response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "What is the weather in Delhi?"},
message,
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
}
]
)
print(second_response.choices[0].message.content)
π Production Enhancements (Critical)
In real systems, always:
- Validate arguments
- Apply rate limits
- Log tool usage
- Restrict allowed tools per user role
- Sanitize inputs
Never directly trust model-generated arguments.
π Production Example 2 β Database Query Tool
π§ Use Case
User asks:
βShow last 5 orders for customer ID 1024.β
π¦ Tool Definition
tools = [
{
"type": "function",
"function": {
"name": "get_recent_orders",
"description": "Fetch recent orders for a customer",
"parameters": {
"type": "object",
"properties": {
"customer_id": {"type": "integer"},
"limit": {"type": "integer"}
},
"required": ["customer_id"]
}
}
}
]
π§ Backend Implementation
def get_recent_orders(customer_id: int, limit: int = 5):
# Replace with actual database query
return [
{"order_id": 501, "amount": 1200},
{"order_id": 502, "amount": 850}
][:limit]
π‘οΈ Secure Execution Pattern
if function_name == "get_recent_orders":
customer_id = int(arguments["customer_id"])
limit = int(arguments.get("limit", 5))
# Security check example
if limit > 20:
raise ValueError("Limit exceeds maximum allowed")
result = get_recent_orders(customer_id, limit)
π§ Production Example 3 β ReAct-Style Tool Loop
For multi-step reasoning:
messages = [
{"role": "system", "content": "You are an enterprise AI assistant."},
{"role": "user", "content": "Calculate tax for order 501 and provide summary."}
]
while True:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
if not message.tool_calls:
print(message.content)
break
tool_call = message.tool_calls[0]
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
# Execute tool securely
result = execute_tool(function_name, arguments)
messages.append(message)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
This creates:
Think β Call Tool β Observe β Think β Respond
ποΈ Enterprise Architecture Pattern
Production systems include:
- Tool registry
- Execution controller
- Role-based access
- Logging layer
- Observability metrics
- Retry logic
- Failure handling
Never let the LLM directly execute code.
Always isolate execution layer.
π‘οΈ Security Best Practices
1οΈβ£ Strict Schema Validation
Use pydantic or JSON schema validation.
2οΈβ£ Input Sanitization
Prevent SQL injection or command injection.
3οΈβ£ Tool Permission Matrix
Not all users can access all tools.
4οΈβ£ Timeout & Fallback
Prevent hanging calls.
5οΈβ£ Audit Logging
Track every tool invocation.
π Why This Matters
Without tool calling:
- LLM hallucinates data
With tool calling:
- LLM retrieves real data
- Backend enforces control
- System becomes deterministic
This is the foundation of:
- Enterprise AI copilots
- Autonomous agents
- AI workflow systems
- RAG + Tools hybrid systems
π Final Thought
Prompt Engineering controls output.
Tool Calling controls action.
Together, they create real-world AI systems.