Azure AI Foundry Tutorials - Function Calling Agent
Beyond Information Retrieval - Taking Actions
In previous tutorial we had created an agent with Bing web search capability. That agent could retrieve real-time information from the web, which solved the knowledge cutoff problem. But it could only provide information - it could not take any actions. Imagine you are building a customer service agent for an airline. A customer asks:"I need to change my seat to 12A on my flight tomorrow, confirmation number ABC123"An information-only agent would respond:
"To change your seat, please visit our website or call our customer service number..."

But what if the agent could actually change the seat for the customer? This is where Function Calling comes in.

Function Calling allows AI agents to execute custom Python functions, enabling them to take real actions like:
This transforms agents from passive information providers into active assistants that can accomplish tasks on behalf of users.
- Look up data from databases
- Modify records in systems
- Call external APIs
- Send emails or notifications
- Process transactions
- Interact with business logic
Video
This tutorial is explained in the below Youtube Video.Azure AI Agents - Table of Contents
Jump between Foundry tutorials, SDK builds, and grounded agent examples.
What is Function Calling?
Function calling (also called tool calling) is a capability that allows LLMs to:- Recognize when they need to execute a function to accomplish a task
- Determine which function to call based on the user's request
- Extract the appropriate parameters from the conversation
- Request the function execution with those parameters
- Use the function's return value to formulate a response

Use Case: Airline Booking Assistant
Let us build a realistic airline booking assistant that can help customers with their flight bookings. The agent will have access to these functions:- check_booking(confirmation_number) - Look up flight details using confirmation number
- modify_seat(booking_id, new_seat) - Change seat assignments
- process_refund(booking_id, amount) - Issue refunds for cancellations
- send_email(customer_email, message) - Send confirmation emails
Customer: "Can you check my booking ABC123?"
Agent: [Calls check_booking("ABC123")]
Agent: "Your flight is from New York to London on June 15th, seat 14B. How can I help you?"
Customer: "I'd like to change my seat to 12A"
Agent: [Calls modify_seat("ABC123", "12A")]
Agent: "Done! I've changed your seat to 12A and sent you a confirmation email."

How Function Calling Works
Here is the complete flow when a user makes a request that requires function calling: Step 1: User makes a requestUser: "Change my seat to 12A for booking ABC123"Step 2: Agent analyzes the request and decides a function is needed
Agent thinks: "The user wants to modify a seat. I should use the modify_seat function."Step 3: Agent extracts parameters from the conversation
Agent identifies: - booking_id: "ABC123" - new_seat: "12A"Step 4: Agent requests function execution (run status becomes "requires_action")
Agent requests: modify_seat(booking_id="ABC123", new_seat="12A")Step 5: Your code executes the function and returns the result
Function returns: {"success": true, "message": "Seat changed to 12A"}
Step 6: Agent uses the result to formulate a natural language response
Agent responds: "I've successfully changed your seat to 12A. You'll receive a confirmation email shortly."This entire orchestration happens automatically once you define the functions!
Prerequisites
Before implementing function calling, make sure you have:- Completed the previous tutorial on Azure AI Foundry SDK
- An Azure AI Foundry project with a deployed GPT-4o model
- Python environment with azure-ai-agents package installed
- Understanding of Python functions and dictionaries
Implementation - Defining Functions
Let us start by implementing the Python functions that our agent will call. These functions simulate an airline booking system. Create a new file calledairline_functions.py:
# airline_functions.py
"""
Simulated airline booking system functions.
In a real system, these would connect to actual databases and APIs.
"""
# Simulated database of bookings
bookings_db = {
"ABC123": {
"booking_id": "ABC123",
"passenger_name": "John Doe",
"flight_number": "AA101",
"route": "New York (JFK) to London (LHR)",
"date": "2026-06-15",
"seat": "14B",
"status": "confirmed",
"email": "john.doe@email.com"
},
"XYZ789": {
"booking_id": "XYZ789",
"passenger_name": "Jane Smith",
"flight_number": "AA202",
"route": "Los Angeles (LAX) to Tokyo (NRT)",
"date": "2026-07-20",
"seat": "23A",
"status": "confirmed",
"email": "jane.smith@email.com"
}
}
def check_booking(confirmation_number: str) -> dict:
"""
Look up flight booking details by confirmation number.
Args:
confirmation_number: The booking confirmation number
Returns:
Dictionary with booking details or error message
"""
print(f"[FUNCTION CALLED] check_booking('{confirmation_number}')")
if confirmation_number in bookings_db:
booking = bookings_db[confirmation_number]
return {
"success": True,
"booking": booking
}
else:
return {
"success": False,
"error": f"No booking found with confirmation number {confirmation_number}"
}
def modify_seat(booking_id: str, new_seat: str) -> dict:
"""
Change the seat assignment for a booking.
Args:
booking_id: The booking confirmation number
new_seat: The new seat number (e.g., "12A")
Returns:
Dictionary with success status and message
"""
print(f"[FUNCTION CALLED] modify_seat('{booking_id}', '{new_seat}')")
if booking_id not in bookings_db:
return {
"success": False,
"error": f"No booking found with ID {booking_id}"
}
# Validate seat format (basic validation)
if not new_seat or len(new_seat) < 2:
return {
"success": False,
"error": "Invalid seat number format"
}
# Update the seat
old_seat = bookings_db[booking_id]["seat"]
bookings_db[booking_id]["seat"] = new_seat
return {
"success": True,
"message": f"Seat changed from {old_seat} to {new_seat}",
"new_seat": new_seat
}
def process_refund(booking_id: str, amount: float) -> dict:
"""
Process a refund for a booking cancellation.
Args:
booking_id: The booking confirmation number
amount: The refund amount in USD
Returns:
Dictionary with refund confirmation
"""
print(f"[FUNCTION CALLED] process_refund('{booking_id}', {amount})")
if booking_id not in bookings_db:
return {
"success": False,
"error": f"No booking found with ID {booking_id}"
}
# Update booking status
bookings_db[booking_id]["status"] = "refunded"
return {
"success": True,
"message": f"Refund of ${amount:.2f} processed successfully",
"refund_amount": amount,
"booking_id": booking_id
}
def send_email(customer_email: str, message: str) -> dict:
"""
Send an email to the customer.
Args:
customer_email: Customer's email address
message: Email message content
Returns:
Dictionary with send confirmation
"""
print(f"[FUNCTION CALLED] send_email('{customer_email}', message_length={len(message)})")
# In a real system, this would integrate with an email service
# For now, we just simulate it
print(f" EMAIL TO: {customer_email}")
print(f" SUBJECT: Booking Update")
print(f" MESSAGE: {message}")
return {
"success": True,
"message": f"Email sent to {customer_email}",
"email": customer_email
}
Let us break down what we just created:
1. Simulated Database
bookings_db = {
"ABC123": {...},
"XYZ789": {...}
}
This dictionary simulates a database of flight bookings. In a real system, this would be an actual database.
2. Python Functions
Each function (check_booking, modify_seat, process_refund, send_email) is a regular Python function that performs an action and returns a dictionary with the result.3. Function Definitions
The llm does not know anything about the python functions that we have defined above. So how do let the llm know which function calls are at its disposal. For this we make use offunction_definitions.
The function_definitions list describes each function in a format the LLM can understand. This includes:
- name - Function name
- description - What the function does (the LLM uses this to decide when to call it)
- parameters - What arguments the function accepts, their types, and descriptions
- required - Which parameters are mandatory
functions = FunctionTool(function_definitions)FunctionTool will automatically create a function definition like this from the python code on the fly and this is then passed to the llm. So now the llm knows which function it can call for a specific scenario.
{
"type": "function",
"function": {
"name": "check_booking", # <- From function.__name__
"description": "Look up flight booking details by confirmation number.", # <- From docstring (first line)
"parameters": {
"type": "object",
"properties": {
"confirmation_number": {
"type": "string", # <- From type hint: str
"description": "The booking confirmation number" # <- From Args section in docstring
}
},
"required": ["confirmation_number"] # <- Inferred from function signature (no default value)
}
}
}
So similar to above below function definitions will be created by functionTool and sent to llm.
# Function definitions for the agent (in OpenAI function calling format)
# LLM metadata
function_definitions = [
{
"type": "function",
"function": {
"name": "check_booking",
"description": "Look up flight booking details using the confirmation number",
"parameters": {
"type": "object",
"properties": {
"confirmation_number": {
"type": "string",
"description": "The booking confirmation number (e.g., ABC123)"
}
},
"required": ["confirmation_number"]
}
}
},
{
"type": "function",
"function": {
"name": "modify_seat",
"description": "Change the seat assignment for an existing booking",
"parameters": {
"type": "object",
"properties": {
"booking_id": {
"type": "string",
"description": "The booking confirmation number"
},
"new_seat": {
"type": "string",
"description": "The new seat number (e.g., 12A, 23B)"
}
},
"required": ["booking_id", "new_seat"]
}
}
},
{
"type": "function",
"function": {
"name": "process_refund",
"description": "Process a refund for a cancelled booking",
"parameters": {
"type": "object",
"properties": {
"booking_id": {
"type": "string",
"description": "The booking confirmation number"
},
"amount": {
"type": "number",
"description": "The refund amount in USD"
}
},
"required": ["booking_id", "amount"]
}
}
},
{
"type": "function",
"function": {
"name": "send_email",
"description": "Send an email notification to the customer",
"parameters": {
"type": "object",
"properties": {
"customer_email": {
"type": "string",
"description": "Customer's email address"
},
"message": {
"type": "string",
"description": "The email message content"
}
},
"required": ["customer_email", "message"]
}
}
}
]
4. Function Mapping
Now the llm only knows the function definition name. So it returns this function definition name when it needs to call one. But the name of the function definition and the actual python code function may not always be the same. So we create a mapping of function definition and python definition. When function definition is returned by llm, indicating to execute a python function. We check this mapping to get the corresponding python function and execute it.
# Mapping of function names to actual Python functions
available_functions = {
"check_booking": check_booking,
"modify_seat": modify_seat,
"process_refund": process_refund,
"send_email": send_email
}
This maps function names (strings) to actual Python function objects, so we can call them dynamically. Add this to the airline_function.py.
In previous tutorial we had created an azure foundry project. We will be making use of this project.

Also we had already deployed a gpt-4o model. We will make use of this.

Do remember, that azure foundry sdk there gets updated quite regularly. So do take reference of the documentation - Azure Python SDK Documentation
Configuration - Setting Up Environment Variables
We need to configure two important pieces of information: the Azure AI endpoint and the model deployment name. Create a.env file in your project directory:
MODEL_DEPLOYMENT_NAME="gpt-4o" AZURE_AI_ENDPOINT="https://new-foundry-ai-project--resource.services.ai.azure.com/api/projects/new-foundry-ai-project-1"
Creating the Agent with Functions
Now let us create an agent that can use these functions. Createagent.py:
import os
import time
import json
from azure.ai.agents import AgentsClient
from azure.ai.agents.models import ListSortOrder, FunctionTool, ToolSet, RequiredAction
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv
# Import our airline functions
from airline_functions import available_functions, check_booking, modify_seat, process_refund, send_email
# Load environment variables
load_dotenv()
# Get configuration
endpoint = os.getenv("AZURE_AI_ENDPOINT")
model_deployment = os.getenv("MODEL_DEPLOYMENT_NAME")
# Validate configuration
if not all([endpoint, model_deployment]):
raise ValueError("Missing required environment variables")
# Create AgentsClient
agents_client = AgentsClient(
endpoint=endpoint,
credential=DefaultAzureCredential(exclude_environment_credential=True)
)
print("Connected to Azure AI Foundry")
# Create FunctionTool with actual Python functions
functions = FunctionTool(functions=[check_booking, modify_seat, process_refund, send_email])
# Create agent with function calling capability
with agents_client:
agent = agents_client.create_agent(
model=model_deployment,
name="airline-booking-agent",
instructions="""You are a helpful airline customer service agent.
You can help customers with their flight bookings by:
- Looking up booking details
- Changing seat assignments
- Processing refunds
- Sending confirmation emails
Always be polite and professional. When you successfully complete an action,
confirm what you did for the customer.""",
tools=functions.definitions
)
print(f"Created agent: {agent.id}")
# Create thread
thread = agents_client.threads.create()
print(f"Created thread: {thread.id}")
# Customer request
user_message = "Hi, can you check my booking ABC123 and then change my seat to 12A?"
message = agents_client.messages.create(
thread_id=thread.id,
role="user",
content=user_message
)
print(f"\nUser: {user_message}")
# Run agent
run = agents_client.runs.create(
thread_id=thread.id,
agent_id=agent.id
)
# Poll and handle function calls
while run.status in ["queued", "in_progress", "requires_action"]:
time.sleep(1)
run = agents_client.runs.get(thread_id=thread.id, run_id=run.id)
print(f"Run status: {run.status}")
# Handle function calling
if run.status == "requires_action":
print("\n[AGENT REQUESTING FUNCTION CALLS]")
# Get the required actions
tool_calls = run.required_action.submit_tool_outputs.tool_calls
tool_outputs = []
for tool_call in tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f"\nFunction: {function_name}")
print(f"Arguments: {function_args}")
# Execute the function
if function_name in available_functions:
function_to_call = available_functions[function_name]
function_response = function_to_call(**function_args)
print(f"Response: {function_response}")
# Add the function output
tool_outputs.append({
"tool_call_id": tool_call.id,
"output": json.dumps(function_response)
})
else:
print(f"Unknown function: {function_name}")
# Submit all function outputs back to the agent
if tool_outputs:
print("\n[SUBMITTING FUNCTION OUTPUTS TO AGENT]")
run = agents_client.runs.submit_tool_outputs(
thread_id=thread.id,
run_id=run.id,
tool_outputs=tool_outputs
)
print(f"\nRun completed with status: {run.status}")
# Check for errors
if run.status == "failed":
print(f"Run failed: {run.last_error}")
# Get messages
messages = agents_client.messages.list(
thread_id=thread.id,
order=ListSortOrder.ASCENDING
)
# Display conversation
print("\n" + "="*60)
print("CONVERSATION")
print("="*60)
for msg in messages:
if msg.text_messages:
last_text = msg.text_messages[-1]
print(f"\n{msg.role.upper()}: {last_text.text.value}")
print("="*60)
Understanding the Function Calling Code
Let us break down the key parts of the agent code:1. Create FunctionTool
functions = FunctionTool(function_definitions)This creates a tool object from our function definitions. The
FunctionTool class wraps our function definitions in the format Azure AI Agents expects.
2. Create Agent with Tools
agent = agents_client.create_agent(
model=model_deployment,
name="airline-booking-agent",
instructions="...",
tools=functions.definitions
)
We pass functions.definitions to the tools parameter, giving the agent access to all our airline functions.
3. Handle requires_action Status
if run.status == "requires_action":
tool_calls = run.required_action.submit_tool_outputs.tool_calls
When the agent wants to call a function, the run status becomes "requires_action". We need to execute the requested functions and submit the outputs back.
4. Execute Functions
for tool_call in tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
function_to_call = available_functions[function_name]
function_response = function_to_call(**function_args)
tool_outputs.append({
"tool_call_id": tool_call.id,
"output": json.dumps(function_response)
})
For each function the agent wants to call:
- Extract the function name and arguments
- Look up the actual Python function from our
available_functionsdict - Execute the function with the provided arguments
- Store the result to send back to the agent
5. Submit Function Outputs
run = agents_client.runs.submit_tool_outputs(
thread_id=thread.id,
run_id=run.id,
tool_outputs=tool_outputs
)
Send all function results back to the agent so it can continue processing and formulate a response.
Running the Airline Agent
Now let us run the agent and see function calling in action!python agent_functions.pyYou should see output like:
Connected to Azure AI Foundry
Created agent: asst_abc123
Created thread: thread_xyz789
User: Hi, can you check my booking ABC123 and then change my seat to 12A?
Run status: in_progress
[AGENT REQUESTING FUNCTION CALLS]
Function: check_booking
Arguments: {'confirmation_number': 'ABC123'}
[FUNCTION CALLED] check_booking('ABC123')
Response: {'success': True, 'booking': {'booking_id': 'ABC123', ...}}
Function: modify_seat
Arguments: {'booking_id': 'ABC123', 'new_seat': '12A'}
[FUNCTION CALLED] modify_seat('ABC123', '12A')
Response: {'success': True, 'message': 'Seat changed from 14B to 12A', 'new_seat': '12A'}
[SUBMITTING FUNCTION OUTPUTS TO AGENT]
Run status: in_progress
Run completed with status: completed
============================================================
CONVERSATION
============================================================
USER: Hi, can you check my booking ABC123 and then change my seat to 12A?
ASSISTANT: I've checked your booking ABC123. You're booked on flight AA101 from
New York (JFK) to London (LHR) on June 15th, 2026. Your original seat was 14B.
I've successfully changed your seat to 12A as requested. Is there anything else
I can help you with?
============================================================
Look at what happened! The agent:
- Understood the user wanted to check a booking AND change a seat
- Called
check_booking()first to get the booking details - Called
modify_seat()to change the seat to 12A - Used the results to formulate a natural, helpful response
Testing More Complex Scenarios
Let us test the agent with different types of requests:Scenario 1: Refund Request
user_message = "I need to cancel my booking XYZ789 and get a refund of $450"
message = agents_client.messages.create(
thread_id=thread.id,
role="user",
content=user_message
)
The agent will:
- Call
process_refund("XYZ789", 450) - Confirm the refund was processed
- Optionally call
send_email()to send confirmation
Scenario 2: Just Information Lookup
user_message = "What's on my booking ABC123?"
message = agents_client.messages.create(
thread_id=thread.id,
role="user",
content=user_message
)
The agent will:
- Call
check_booking("ABC123") - Present the booking details in a user-friendly way
Scenario 3: Invalid Booking
user_message = "Change my seat to 10C for booking INVALID999"
message = agents_client.messages.create(
thread_id=thread.id,
role="user",
content=user_message
)
The agent will:
- Try to call
modify_seat("INVALID999", "10C") - Get an error response from the function
- Politely inform the user that the booking was not found
Function Calling Flow Diagram
Here is the complete flow when function calling is involved:
1. User sends message
2. Agent analyzes message
3. Agent decides it needs to call function(s)
4. Run status becomes "requires_action"
5. Your code extracts function calls
6. Your code executes Python functions
7. Your code submits function outputs
8. Agent processes outputs
9. Agent formulates response
10. Run status becomes "completed"
11. User receives response
Multiple Function Calls in Sequence
One powerful aspect of function calling is that the agent can chain multiple functions together. For example:User: "Check my booking ABC123, change my seat to 12A, and send me a confirmation email"The agent will:
- Call
check_booking("ABC123")to get booking details and email - Call
modify_seat("ABC123", "12A")to change the seat - Call
send_email(email, "Your seat has been changed to 12A") - Respond to the user confirming all actions
Function Definition Best Practices
When defining functions for your agent, follow these best practices:1. Clear Descriptions
"description": "Change the seat assignment for an existing booking"The description should clearly explain what the function does. The LLM uses this to decide when to call it.
2. Detailed Parameter Descriptions
"new_seat": {
"type": "string",
"description": "The new seat number (e.g., 12A, 23B)"
}
Include examples in parameter descriptions to help the LLM understand the expected format.
3. Specify Required Parameters
"required": ["booking_id", "new_seat"]Mark which parameters are mandatory so the LLM knows it must extract them.
4. Return Structured Data
return {
"success": True,
"message": "Seat changed successfully",
"new_seat": "12A"
}
Always return a dictionary with a clear structure. Include a success field and descriptive messages.
5. Handle Errors Gracefully
if booking_id not in bookings_db:
return {
"success": False,
"error": f"No booking found with ID {booking_id}"
}
Return error information in the same format as success responses, so the agent can communicate errors to users.
Security Considerations
When implementing function calling, security is critical:1. Validate All Inputs
def modify_seat(booking_id: str, new_seat: str) -> dict:
# Validate seat format
if not new_seat or len(new_seat) < 2:
return {"success": False, "error": "Invalid seat format"}
# Validate booking exists
if booking_id not in bookings_db:
return {"success": False, "error": "Booking not found"}
Never trust that the LLM will provide valid input. Always validate.
2. Implement Authorization
In a real system, you would verify the user has permission to modify the booking:
def modify_seat(booking_id: str, new_seat: str, user_email: str) -> dict:
booking = bookings_db.get(booking_id)
# Check if user owns this booking
if booking["email"] != user_email:
return {"success": False, "error": "Unauthorized"}
3. Limit Dangerous Operations
Some operations should require additional confirmation:
def process_refund(booking_id: str, amount: float, confirmed: bool = False) -> dict:
if not confirmed:
return {
"success": False,
"requires_confirmation": True,
"message": f"Please confirm refund of ${amount}"
}
4. Log All Function Calls
def modify_seat(booking_id: str, new_seat: str) -< dict:
print(f"[AUDIT] Seat change: {booking_id} -< {new_seat}")
# Log to database/file for auditing
Maintain an audit trail of all actions taken by the agent.
Comparison: Bing Search vs Function Calling
| Aspect | Bing Search Tool | Function Calling |
|---|---|---|
| Purpose | Retrieve public web information | Execute custom business logic |
| Data Source | Public internet (via Bing) | Your databases, APIs, systems |
| Can Take Actions? | No (read-only) | Yes (can modify data, trigger workflows) |
| Setup Complexity | Low (just add connection) | Medium (write and define functions) |
| Customization | Limited (searches Bing) | Complete (you write the code) |
| Use Cases | News, weather, stock prices, general info | Bookings, orders, CRM, database operations |
| Cost | Per Bing search API call | Your infrastructure costs |
Real-World Integration Examples
Here are examples of how to integrate function calling with real systems:Example 1: Database Integration
import psycopg2
def check_booking(confirmation_number: str) -> dict:
conn = psycopg2.connect("dbname=airline user=postgres")
cur = conn.cursor()
cur.execute(
"SELECT * FROM bookings WHERE confirmation_number = %s",
(confirmation_number,)
)
result = cur.fetchone()
conn.close()
if result:
return {"success": True, "booking": dict(result)}
else:
return {"success": False, "error": "Booking not found"}
Example 2: REST API Integration
import requests
def send_email(customer_email: str, message: str) -> dict:
# Call SendGrid API
response = requests.post(
"https://api.sendgrid.com/v3/mail/send",
headers={"Authorization": f"Bearer {SENDGRID_API_KEY}"},
json={
"personalizations": [{"to": [{"email": customer_email}]}],
"from": {"email": "noreply@airline.com"},
"subject": "Booking Update",
"content": [{"type": "text/plain", "value": message}]
}
)
if response.status_code == 202:
return {"success": True, "message": "Email sent"}
else:
return {"success": False, "error": "Failed to send email"}
Example 3: Payment Processing
import stripe
def process_refund(booking_id: str, amount: float) -> dict:
booking = get_booking_from_db(booking_id)
try:
refund = stripe.Refund.create(
payment_intent=booking["payment_intent_id"],
amount=int(amount * 100) # Stripe uses cents
)
update_booking_status(booking_id, "refunded")
return {
"success": True,
"message": f"Refund of ${amount} processed",
"refund_id": refund.id
}
except stripe.error.StripeError as e:
return {"success": False, "error": str(e)}
Error Handling in Function Calling
Proper error handling is crucial. Here is a robust pattern:
while run.status in ["queued", "in_progress", "requires_action"]:
time.sleep(1)
run = agents_client.runs.get(thread_id=thread.id, run_id=run.id)
if run.status == "requires_action":
tool_calls = run.required_action.submit_tool_outputs.tool_calls
tool_outputs = []
for tool_call in tool_calls:
try:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
if function_name not in available_functions:
raise ValueError(f"Unknown function: {function_name}")
function_to_call = available_functions[function_name]
function_response = function_to_call(**function_args)
tool_outputs.append({
"tool_call_id": tool_call.id,
"output": json.dumps(function_response)
})
except Exception as e:
# Return error to agent
error_response = {
"success": False,
"error": f"Function execution failed: {str(e)}"
}
tool_outputs.append({
"tool_call_id": tool_call.id,
"output": json.dumps(error_response)
})
# Submit outputs (including errors)
run = agents_client.runs.submit_tool_outputs(
thread_id=thread.id,
run_id=run.id,
tool_outputs=tool_outputs
)
This ensures that even if a function fails, the agent can handle it gracefully and inform the user.
Limitations and Considerations
1. Function Execution Timeout
Functions should execute quickly (under 30 seconds). Long-running operations should be handled asynchronously:
def start_refund_process(booking_id: str) -> dict:
# Start async task
task_id = queue_refund_task(booking_id)
return {
"success": True,
"message": "Refund processing started",
"task_id": task_id,
"status": "pending"
}
2. Cost Implications
Each function call adds to the token count and processing time. Design functions to be efficient.3. Context Window Limits
Large function outputs consume tokens. Return only essential data:
# Bad - returns too much data
return {"success": True, "all_bookings": list_of_1000_bookings}
# Good - returns summary
return {"success": True, "total_bookings": 1000, "active_bookings": 50}
4. Agent Reliability
The LLM might not always call the right function or extract parameters correctly. Validate everything and provide clear feedback.What We Have Learned
In this tutorial, we learned:- What function calling is and why it is powerful
- How to define Python functions for agents to call
- How to create function definitions in the correct format
- How to handle the
requires_actionstatus - How to execute functions and submit outputs back to the agent
- How agents orchestrate multiple function calls
- Best practices for security and error handling
- How to integrate with real databases and APIs
Next Steps
In upcoming tutorials, we will explore:- RAG (Retrieval Augmented Generation) - Give agents access to your document knowledge bases
- Code Interpreter - Let agents write and execute Python code for data analysis
- File Upload and Processing - Work with user-uploaded documents
- MCP (Model Context Protocol) - Connect to external systems
- Multi-Agent Workflows - Coordinate specialized agents for complex tasks
Complete Code
airline_functions.py - [See the complete function definitions above] agent_functions.py - [See the complete agent code above] .env:MODEL_DEPLOYMENT_NAME="gpt-4o" AZURE_AI_ENDPOINT="https://new-foundry-ai-project--resource.services.ai.azure.com/api/projects/new-foundry-ai-project-1"
Download Source Code
Download it -Azure AI Agent Function Calling
Azure AI Agents - Table of Contents
Jump between Foundry tutorials, SDK builds, and grounded agent examples.
Popular Posts
1Z0-830 Java SE 21 Developer Certification
Azure AI Foundry Hello World
Azure AI Agent Hello World
Foundry vs Hub Projects
Build Agents with SDK
Bing Web Search Agent
Function Calling Agent
Spring Boot + Azure Key Vault Hello World Example
Spring Boot + Elasticsearch + Azure Key Vault Example
Spring Boot Azure AD (Entra ID) OAuth 2.0 Authentication
Deploy Spring Boot App to Azure App Service
Secure Azure App Service using Azure API Management
Deploy Spring Boot JAR to Azure App Service
Deploy Spring Boot + MySQL to Azure App Service
Spring Boot + Azure Managed Identity Example
Secure Spring Boot Azure Web App with Managed Identity + App Registration
Elasticsearch 8 Security - Integrate Azure AD OIDC