TutorialsApr 13, 20267 min read

Code execution for Google Gemini function calling in a hardware-isolated sandbox

Gemini's function-calling API is the right shape for giving the model a Python interpreter — if you bring your own execution layer. Here's the full pattern with Podflare, for both Python and TypeScript SDKs.

Robel TegegnePodflare, founder

Google Gemini’s function-calling API (FunctionDeclaration + FunctionCall, exposed via @google/genai in TS and google-genai in Python) is structurally similar to OpenAI’s tool-use and Anthropic’s tool_use: you declare schemas, the model emits a call, you execute it, you return the result, the model continues.

Gemini does ship a built-in code_execution tool. It’s fine for demos. It’s not fine for production: you don’t control the environment, data passes through Google’s infra, and there’s no persistence across calls. For real work you wire in your own hardware-isolated sandbox. Here’s how.

Install

# Python
pip install google-genai podflare

# or TypeScript
npm install @google/genai podflare

Python: wire a Podflare sandbox into Gemini

import os
from google import genai
from google.genai import types
from podflare import Sandbox
from podflare.gemini import podflare_function_declaration, run_function_call

client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
sandbox = Sandbox()

# podflare_function_declaration() returns the FunctionDeclaration
# Gemini expects, with the right schema for the code argument and
# a description that tells the model state persists across calls.
tools = types.Tool(function_declarations=[podflare_function_declaration()])

config = types.GenerateContentConfig(tools=[tools])

contents = [types.Content(role="user", parts=[types.Part(text=(
    "Fetch the current weather in Nairobi, Lagos, and Accra via "
    "wttr.in, and tell me which city is warmest right now."
))])]

while True:
    resp = client.models.generate_content(
        model="gemini-2.5-pro",
        contents=contents,
        config=config,
    )

    # Record the model's turn in history.
    contents.append(resp.candidates[0].content)

    fn_calls = [
        p.function_call for p in resp.candidates[0].content.parts
        if p.function_call
    ]
    if not fn_calls:
        print(resp.text)  # final answer
        break

    # Execute every function call via Podflare, return tool results.
    tool_parts = []
    for call in fn_calls:
        result = run_function_call(call, sandbox)
        tool_parts.append(types.Part(
            function_response=types.FunctionResponse(
                name=call.name,
                response={"result": result},
            ),
        ))
    contents.append(types.Content(role="user", parts=tool_parts))

sandbox.close()

podflare_function_declaration() is pre-built so you don’t have to write the FunctionDeclaration boilerplate. If you want to customize the description or add auth scoping, the adapter is ~40 lines — fork it.

TypeScript

import { GoogleGenAI } from "@google/genai";
import { Sandbox } from "podflare";
import { podflareFunctionDeclaration, runFunctionCall } from "podflare/gemini";

const genai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const sandbox = new Sandbox();
await sandbox.open();

const tools = [{
  functionDeclarations: [podflareFunctionDeclaration()],
}];

let contents = [{
  role: "user",
  parts: [{
    text: "Compute 100 days of SPY daily returns. Report stdev."
  }],
}];

while (true) {
  const resp = await genai.models.generateContent({
    model: "gemini-2.5-pro",
    contents,
    config: { tools },
  });

  contents.push(resp.candidates[0].content);

  const fnCalls = (resp.candidates[0].content.parts ?? [])
    .map((p) => p.functionCall)
    .filter(Boolean);

  if (fnCalls.length === 0) {
    console.log(resp.text);
    break;
  }

  const toolParts = await Promise.all(
    fnCalls.map(async (call) => ({
      functionResponse: {
        name: call.name,
        response: { result: await runFunctionCall(call, sandbox) },
      },
    })),
  );
  contents.push({ role: "user", parts: toolParts });
}

await sandbox.close();

Why you want this over Gemini’s built-in code_execution

  • Real environment control. pip install matplotlib plotly scikit-learn polars — whatever. Gemini’s built-in has a fixed library set you can’t extend.
  • Persistent state across function calls. The sandbox’s Python REPL keeps globals() alive between every function_call. Gemini’s built-in drops state between turns.
  • Data stays in your perimeter. Gemini runs its built-in inside Google. Podflare runs in a region you chose.
  • Fork for parallel hypotheses. sandbox.fork(n=5) in ~80 ms server-side. Not available in the built-in.
  • Full-Linux access. Run shell commands, compile C, call ffmpeg, whatever. The built-in is sandbox-restricted.

Multimodal bonus

Gemini is particularly strong at multimodal reasoning (images, audio, video). Combining that with a Python sandbox is powerful: the model can describe what it sees in an image, then run code to process the numbers it extracted. Upload an image to the sandbox first via sandbox.upload(bytes, "/tmp/chart.png"), then let the model generate Python to parse + analyze it.

Streaming

If you want the model’s reasoning + tool calls to stream to your UI as they emerge, swap to generateContentStream. The loop structure is the same — you just collect parts as they arrive.

Performance

From Vertex’s us-central1 or any Gemini region that’s near a Podflare region (us-central Dallas, us-east Ashburn), expect ~40 ms p50 round-trip from Gemini’s edge to a Podflare sandbox. The Gemini inference + Podflare exec latency are additive, but both are fast enough that interactive agent UX stays snappy.

Ship it

Free Podflare account. Full Gemini + Podflare example: Python | TypeScript.

Related reading

#gemini function calling#gemini code execution#google genai sdk#gemini python sandbox#gemini ai agent#gemini tool use

Keep reading

Ship an AI agent on Podflare in under a minute.

Hardware-isolated microVM per sandbox, ~190 ms round-trip, 80 ms fork(), full Python REPL persistence. Free tier includes $200 credit.

Get started free
Code execution for Google Gemini function calling in a hardware-isolated sandbox — Podflare