Code execution vs function calling
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.
Explanation
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
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
| Field | Description |
|---|---|
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'ValueError: tool name not recognizedKeyError accessing function argsgoogle.api_core.exceptions.ResourceExhaustedExperienced 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.