Function calling

The model can't look up your data or change anything in your systems. It can only ask. Follow one function call through the Gemini API with no framework, from declaration to final answer.

10 min Free

A model knows a lot, but it doesn’t know where your customer’s parcel is right now. That fact lives in your database. Function calling connects the two without giving the model any access to your systems.

It works in four steps, and only one of them happens inside the model:

  1. Declare the function: its name, what it does, and a schema for its parameters.
  2. Call the model with the user’s question and the declaration.
  3. Run the function yourself. The model returns a function_call with the arguments it chose. Your code decides whether to run it.
  4. Send the result back. The model uses it to write the final answer.

This lesson uses the Gemini API directly, with no agent framework, so you can see every message. Press Play for a single lookup, then switch the Try it selector to see two calls at once, and a question that needs no call at all.

  1. Model asks
  2. Your code runs
  3. Result goes back
  4. Answer
Customersupport chatYour codeorder_status.pyDeclarationget_order_statusGeminiInteractions APIYour functionget_order_status()Orders DByour system

Press Play to watch it run, or step through with ← →.

00/11
import json

from google import genai

# 1. Describe the function to the model: name, purpose, parameters.
get_order_status_declaration = {
    "type": "function",
    "name": "get_order_status",
    "description": "Gets the live delivery status of a customer's order.",
    "parameters": {
        "type": "object",
        "properties": {
            "order_id": {"type": "string", "description": "Order ID, e.g. ORD-4417"},
        },
        "required": ["order_id"],
    },
}


def get_order_status(order_id: str) -> dict:
    """Your real code: a database query or an internal API call."""
    return {"order_id": order_id, "status": "out_for_delivery", "eta": "today 6 pm"}


client = genai.Client()

# 2. Turn 1: send the question together with the declaration.
interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input="Where is my order ORD-4417?",
    tools=[get_order_status_declaration],
)

# 3. Your code runs every function the model asked for.
results = []
for step in interaction.steps:
    if step.type == "function_call" and step.name == "get_order_status":
        result = get_order_status(**step.arguments)
        results.append({
            "type": "function_result",
            "name": step.name,
            "call_id": step.id,
            "result": [{"type": "text", "text": json.dumps(result)}],
        })

# 4. Turn 2: send the results back, linked to turn 1.
if results:
    interaction = client.interactions.create(
        model="gemini-3.8-flash",
        input=results,
        tools=[get_order_status_declaration],
        previous_interaction_id=interaction.id,
    )

print(interaction.output_text)

Interaction steps

No steps yet. Press Play.

What to notice

  1. The model only asks. A function_call is a structured request: a name, arguments and an id. Running it, validating it or refusing it is your code’s job. Google’s best practices include validating function calls before you execute them.
  2. Two API calls, linked together. Turn 1 returns the function_call. Turn 2 sends a function_result with the matching call_id, plus previous_interaction_id so the model sees turn 1. (If you set store=False, you resend the full history yourself instead.)
  3. The declaration is the model’s only view of your function. A clear description and strong types (string, integer, enum) lead to better calls. Google suggests keeping the active set to around 10 to 20 tools.
  4. One turn can hold several calls. Independent lookups come back together as parallel calls. Calls that depend on each other (find the city, then get its weather) come back one after another. This is called compositional calling.
  5. You can control when it calls. tool_choice in generation_config sets the mode:
ModeBehaviour
auto (default)The model decides: call a function or answer directly
anyThe model must call a function
noneThe model can’t call functions
validatedThe model makes sure its calls match the function schema

From here to agents
Wrap this in a loop that keeps calling the model until it stops asking for functions, and you have an agent. Frameworks like ADK run that loop and your Python functions for you: see What an AI agent really is. If you only need the final answer in a fixed format, use structured output instead.

Check your understanding

1. Where does get_order_status actually run?
2. In turn 2, how does the model know which result answers which call?
3. A user asks “What does UPI stand for?” and your only tool is get_order_status. With the default mode, what happens?