Your chatbot replies with text but never does anything — no bookings, no product lookups, no database updates. As long as your AI models only generate words, they remain spectators. Function calling with Gemini API turns your model into an operational agent: it knows when to call a function, which parameters to pass, and how to process the result. At Meteora Web, we use it to automate real workflows (reservations, orders, CRM queries). This guide shows you how to make it work, with copy-paste code you can adapt immediately.
Why use function calling with Gemini instead of generating free text?
A language model that only outputs natural language cannot act. You ask "find the cheapest flight to Rome", and it gives you a generic paragraph, not a real booking. With function calling, Gemini returns a structured request: it wants to call search_flights(destination='Rome', budget=150). You execute the call and send the result back. It's like giving the model a phone — it can do things.
Sponsored Protocol
Concrete benefits:
- Reliability: functions produce real data, not hallucinations.
- Integration: the model connects to databases, external APIs, ERP systems.
- Cost control: you pay only for necessary API calls, no wasted prompt loops.
How to declare functions in Gemini API?
Functions are described with a JSON schema, similar to OpenAPI. Gemini uses these definitions to understand existence, parameters, and return types. Here's a Python example:
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_API_KEY")
# Function definition
search_tools = types.Tool(
function_declarations=[
types.FunctionDeclaration(
name="search_hotel",
description="Search available hotels in a city for specific dates",
parameters=types.Schema(
type=types.Type.OBJECT,
properties={
"city": types.Schema(type=types.Type.STRING, description="City name, e.g. 'Palermo'"),
"checkin": types.Schema(type=types.Type.STRING, description="Check-in date YYYY-MM-DD"),
"checkout": types.Schema(type=types.Type.STRING, description="Check-out date YYYY-MM-DD"),
"max_price": types.Schema(type=types.Type.NUMBER, description="Maximum price per night in euros")
},
required=["city", "checkin", "checkout"]
)
)
]
)
Note: function names must be unique and descriptive. Required parameters go in the required list. If omitted, Gemini might not pass them.
Sponsored Protocol
How to handle the model's response and actually call functions?
The flow is a two-step loop:
Sponsored Protocol
- Send prompt + tool list. Gemini responds with a
function_callor text. - If
function_call, execute the real function (e.g., SQL query, REST API call) and return the result asfunction_response. - The model receives the response and produces final text.
Here's Python code implementing the loop for search_hotel:
# Real function that queries a database (simulated)
def search_hotel(city, checkin, checkout, max_price=None):
# Here you do a real API or DB call
mock_results = [
{"name": "Sole e Mare Hotel", "price": 120, "city": city},
{"name": "Central B&B", "price": 85, "city": city}
]
if max_price:
mock_results = [h for h in mock_results if h["price"] <= max_price]
return mock_results
# Function calling loop
model = "gemini-2.0-flash"
tools = [search_tools]
messages = [
types.Content(role="user", parts=[types.Part(text="Find cheap hotels in Palermo from 2026-06-01 to 2026-06-05")])
]
while True:
response = client.models.generate_content(
model=model,
contents=messages,
config=types.GenerateContentConfig(tools=tools)
)
if response.candidates[0].content.parts[0].function_call:
fc = response.candidates[0].content.parts[0].function_call
if fc.name == "search_hotel":
result = search_hotel(**fc.args)
function_resp = types.Part(
function_response=types.FunctionResponse(
name=fc.name,
response={"hotels": result}
)
)
messages.append(response.candidates[0].content)
messages.append(types.Content(role="function", parts=[function_resp]))
else:
final_text = response.text
break
print(final_text)
Error handling: if the real function fails (API down, timeout), return a function_response with an error field and let the model handle it gracefully.
Practical example: an agent that searches and books hotels
A real scenario: user says "I'd like to book a room at the Sole e Mare Hotel in Palermo from June 1 to 5 for 2 adults". The model must first search availability, then make the booking. Define two functions: search_hotel (already shown) and book_hotel.
# Add book_hotel to the list
book_tool = types.Tool(
function_declarations=[
types.FunctionDeclaration(
name="book_hotel",
description="Book a reservation at a specific hotel",
parameters=types.Schema(
type=types.Type.OBJECT,
properties={
"hotel_name": types.Schema(type=types.Type.STRING),
"checkin": types.Schema(type=types.Type.STRING),
"checkout": types.Schema(type=types.Type.STRING),
"guests": types.Schema(type=types.Type.INTEGER)
},
required=["hotel_name", "checkin", "checkout", "guests"]
)
)
]
)
all_tools = [search_tools, book_tool]
In the loop, when the model calls book_hotel, execute the function and return a confirmation ID. The agent becomes a composite tool: it autonomously decides the sequence of actions.
Safety: set a maximum iteration limit (e.g., 5) to prevent infinite loops if the model keeps calling functions.
How to avoid common mistakes in tool use?
We've seen projects arrive with these recurring issues:
- Timeouts and retries: if the real function takes over 30 seconds, Gemini may cut off. Set a timeout and return a manageable error.
- Missing parameters: the model often omits optional parameters. Provide default values in the real function.
- Security: never expose API keys or sensitive data in function descriptions. Gemini will read them verbatim.
- Logging: log every function call and response for debugging and auditing.
- Costs: each function call turn consumes input/output tokens. Monitor with
response.usage_metadata.
We recommend testing with a set of example prompts before going to production. Use Google AI Studio playground to validate your schemas.
What to do next
1. Get your API key from Google AI Studio (or Google Cloud Vertex AI) and enable Gemini 2.0 Flash (supports function calling out of the box).
2. Write your first function — start with a dummy database or a public API (e.g., weather, currency exchange).
3. Implement the loop as shown above. Handle the case where there is no function_call.
4. Add logging and iteration limits for safety.
5. Read the official documentation on Function Calling Gemini API for details on supported models and limits.
For a complete overview of Gemini API for developers, check our Pillar Guide. There you'll find context, comparisons, and broader use cases.