API Intermediate medium · 7 min

Code execution vs function calling

What you will learn
Understand when to use Gemini's code execution feature for computation versus function calling for tool integration.

Why this matters

Both code execution and function calling let you extend Gemini's capabilities, but they solve different problems: code execution runs arbitrary Python inline, while function calling orchestrates external tools. Choosing wrong means wasted API calls, security risks, or architectural complexity.

Skip if: Use code execution only for lightweight computation or debugging. Don't use it for production workflows requiring audit logs, error handling, or persistent state: use function calling instead. Don't use function calling for simple math or string operations: use code execution.

Explanation

Code execution allows Gemini to run Python code directly and see the results inline. The model writes code, you execute it, and Gemini receives the output to continue reasoning. Function calling is a structured protocol where Gemini requests a specific function be called with specific arguments: you implement and execute the function on your side, then return results to Gemini.

Under the hood, code execution is stateful within a single conversation: variables persist across turns. Function calling is stateless per call: each invocation is independent, but you maintain the actual tool implementation. Code execution trades security and control for simplicity; function calling trades simplicity for control and auditability.

Use code execution for exploratory analysis, quick calculations, or when you want Gemini to directly execute trusted code. Use function calling for production integrations, external APIs, database queries, or any operation where you need to validate, log, or modify requests before execution.

Request code

python
import google.generativeai as genai
import os

genai.configure(api_key=os.environ['GOOGLE_API_KEY'])
model = genai.GenerativeModel('gemini-2.0-flash')

# Example 1: Code execution
response_code_exec = model.generate_content(
    "Calculate the 10th Fibonacci number using Python code."
)
print("Code Execution Response:")
print(response_code_exec.text)

# Example 2: Function calling
tools = [
    {
        "type": "function",
        "function": {
            "name": "fibonacci",
            "description": "Calculate the nth Fibonacci number",
            "parameters": {
                "type": "object",
                "properties": {
                    "n": {
                        "type": "integer",
                        "description": "The position in the Fibonacci sequence"
                    }
                },
                "required": ["n"]
            }
        }
    }
]

response_func_call = model.generate_content(
    "What is the 10th Fibonacci number?",
    tools=tools
)

print("\nFunction Calling Response:")
if response_func_call.candidates[0].content.parts:
    for part in response_func_call.candidates[0].content.parts:
        if hasattr(part, 'function_call'):
            print(f"Function called: {part.function_call.name}")
            print(f"Arguments: {part.function_call.args}")

# Now execute the function yourself
def fibonacci(n):
    if n <= 1:
        return n
    a, b = 0, 1
    for _ in range(2, n + 1):
        a, b = b, a + b
    return b

func_args = response_func_call.candidates[0].content.parts[0].function_call.args
result = fibonacci(func_args['n'])
print(f"\nActual result from your function: {result}")

Authentication

Set your Google API key before instantiation: `export GOOGLE_API_KEY='your-key-here'` then `genai.configure(api_key=os.environ['GOOGLE_API_KEY'])`

Response shape

FieldDescription
text The model's text response: for code execution, includes the code written and results; for function calling, describes the intent
candidates List of response options (usually 1)
candidates[0].content.parts Array of content parts: may include text, code_execution_result, or function_call objects
candidates[0].content.parts[i].function_call.name The name of the function Gemini wants to call
candidates[0].content.parts[i].function_call.args Dictionary of arguments passed to the function
candidates[0].content.parts[i].executable_code The Python code Gemini wrote (code execution only)

Field guide

function_call

Only present when Gemini decides a tool is needed: check this to decide whether to invoke your function or continue

executable_code

Less common: Gemini may write code that gets executed in a sandbox, but function calling is the preferred pattern for production

candidates[0].content.parts

Iterate through this to find all actions Gemini took in a single response: don't assume single action per response

Setup trap

Forgetting that code execution is a client-side convenience feature in older patterns: modern Gemini API doesn't auto-execute your code. You must handle execution yourself or use a specialized code execution service. Function calling explicitly returns structured requests that you handle, which is clearer for production systems.

Cost

Code execution and function calling both count as regular API tokens. Function calling adds 1-2 extra API calls (call request + result callback), so for simple operations, inline code execution is cheaper. For complex workflows with many function calls, the overhead is negligible compared to the value of structured tool integration.

Rate limits

Function calling doesn't increase rate limits, but orchestrating multiple functions in sequence (call → implement → callback → call again) can hit limits faster if you're not batching. Code execution within a single request is cheaper rate-limit-wise.

Common gotcha

Assuming function_call is always present in the response. Gemini may choose not to call a function even if tools are defined: always check if `function_call` exists before accessing `.name` or `.args`, or you'll get an AttributeError.

Error recovery

AttributeError: 'NoneType' object has no attribute 'function_call'
Gemini didn't call a function: check if tools were provided and if the prompt was clear enough. The `function_call` attribute only exists when Gemini decides to invoke a tool.
ValueError: tool name not recognized
The function name in the response doesn't match your tool definition. Ensure tool names in your function definitions exactly match what Gemini will request: typos break the contract.
KeyError accessing function args
Function args weren't provided or the key name doesn't match the schema. Always validate that all required parameters are present before calling your function implementation.
google.api_core.exceptions.ResourceExhausted
Rate limit hit during function calling sequence. Implement exponential backoff or batch function calls into fewer API requests.

Experienced dev note

Function calling is not just for calling external APIs: it's a design pattern for explicit, auditable control flow. Even for internal Python functions, using function calling lets you log every invocation, validate arguments before execution, and implement caching/memoization transparently. Code execution feels faster but you lose auditability. In production, the 1-2 extra API calls for function calling are worth the clarity and observability.

Check your understanding

Your team's security policy requires logging every external API call Gemini makes with timestamps and arguments. Which approach (code execution or function calling) makes this requirement easier to implement, and why?

Show answer hint

Code execution happens in Gemini's sandbox and you only see the output: no visibility into intermediate steps. Function calling returns explicit structured requests that you log before execution. This is why function calling is the production-safe choice when auditability matters.

VERSION google-generativeai 0.8.x uses LCEL-compatible function calling. Older 0.1.x versions used different tool syntax (tool_use instead of function_call). Always pin genai.GenerativeModel to 'gemini-2.0-flash' or 'gemini-2.5-pro': older model names don't support full function calling capabilities.

Community Notes

No notes yetBe the first to share a version-specific fix or tip.