◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/Dev Tools
⟐ Dev Tools/2026-03-11Intermediate

Gemini External Tool Integration — Grounding and Function Calling in Practice

How to connect Gemini to external services and your own data, covering both the in-app integrations and the API tools parameter: Google Search grounding, the full Function Calling round-trip, and the latency and cost trade-offs to plan for.

Gemini92Function Calling17IntegrationGrounding4Tools

I asked for the latest, and got a confident, stale answer

While drafting an app announcement with Gemini, I asked it to "account for the recent release status," but it answered based on how things stood months earlier. That makes sense: a model answers from what it learned up to its training cutoff.

The way past that wall — "doesn't know the latest" and "can't see my data" — is external tool integration. Gemini offers two paths: the integrations you toggle in the app, and the tools parameter you call from the API. Knowing both lets you pick the right one for the job.

In-app integrations

In the Gemini app (web and mobile), you can toggle connections to Google services from the settings screen. They are designed to fire automatically only when a question calls for them.

Google Search

Activates for news, current events, and real-time figures, folding search results into the answer.

  • "What's the weather in Tokyo today?"
  • "Summarize recent AI news in three lines"
  • "When was company X's latest earnings report?"

Google Maps

Searches places, directions, and store or hotel details.

  • "How do I get from Shibuya Station to Tokyo Tower?"
  • "Highly-rated Italian restaurants nearby"

YouTube

Searches videos and suggests related content.

  • "Find Python machine learning tutorial videos"

Google Flights & Hotels

Searches and compares flights and accommodations.

  • "Cheapest flights from Tokyo to Paris next month"

Each integration toggles independently. Turning off the ones you don't need avoids unintended external calls.

From the API: search grounding

To do the same thing from code, you use the tools parameter. Start with search grounding: the model runs a Google Search only when it judges one is needed, then builds the answer on top of those results.

from google import genai
from google.genai import types
 
client = genai.Client(api_key="YOUR_API_KEY")
 
response = client.models.generate_content(
    model="gemini-3.5-flash",
    contents="What's the current weather in Tokyo? Cite your sources.",
    config=types.GenerateContentConfig(
        tools=[types.Tool(google_search=types.GoogleSearch())],
    ),
)
 
print(response.text)
 
# Pull out the grounding sources
meta = response.candidates[0].grounding_metadata
if meta and meta.grounding_chunks:
    for chunk in meta.grounding_chunks:
        print("Source:", chunk.web.uri)
else:
    print("(No search was used for this request)")

The model searches only when it decides outside information is required. A weather question returns grounding_chunks; a question answerable from general knowledge skips search and leaves grounding_metadata empty. Always branch for the no-grounding case — that is the trick to keeping this stable in production. Code that never assumes grounding exists won't crash on the quieter requests.

From the API: the Function Calling round-trip

Search grounding is executed for you on Google's side. To reach your own database or internal API, you use Function Calling. Here is the step most introductions skip: once the model says it wants to call a function, who actually runs it? Your code does.

The flow has five stages: (1) declare the function, (2) the model requests a call, (3) you execute the function, (4) you return the result to the model, (5) the model produces the final answer.

from google import genai
from google.genai import types
 
client = genai.Client(api_key="YOUR_API_KEY")
 
# (1) Declare the function
get_weather = types.FunctionDeclaration(
    name="get_weather",
    description="Return the current weather for a given city",
    parameters={
        "type": "object",
        "properties": {
            "city": {"type": "string", "description": "City name"},
        },
        "required": ["city"],
    },
)
tools = [types.Tool(function_declarations=[get_weather])]
 
# The local implementation that actually runs (normally it hits an API)
def run_get_weather(city: str) -> dict:
    fake_db = {"Tokyo": "Clear, 24C", "Osaka": "Cloudy, 22C"}
    return {"city": city, "weather": fake_db.get(city, "no data")}
 
contents = [
    types.Content(role="user", parts=[types.Part(text="What's the weather in Tokyo?")]),
]
 
# (2) First call to the model
resp = client.models.generate_content(
    model="gemini-3.5-flash",
    contents=contents,
    config=types.GenerateContentConfig(tools=tools),
)
 
part = resp.candidates[0].content.parts[0]
if part.function_call:
    call = part.function_call
    # (3) Run the function on our side
    result = run_get_weather(**dict(call.args))
 
    # (4) Append both the model's call and our result to the history
    contents.append(resp.candidates[0].content)
    contents.append(
        types.Content(
            role="tool",
            parts=[types.Part(
                function_response=types.FunctionResponse(
                    name=call.name, response=result,
                )
            )],
        )
    )
 
    # (5) Get the final answer grounded in the result
    final = client.models.generate_content(
        model="gemini-3.5-flash",
        contents=contents,
        config=types.GenerateContentConfig(tools=tools),
    )
    print(final.text)

The key is step (4): append both the model's call (function_call) and your execution result (function_response) to the history before asking for the final answer. Return only the result, and the model loses track of what was asked and what came back, producing an off-target reply. I once spent half a day on a bug caused by appending just one of the two.

Four things I watch in production

Inserting an external tool adds concerns that plain text generation never had. Here is what I check every time while running these in my own indie projects.

  • Latency: tool calls involve a network round-trip, so responses slow down. On user-facing screens, an interim "searching…" indicator changes the perceived speed dramatically.
  • Cost: grounding searches and multiple round-trips each add charges. Estimating on the free tier before designing your production rate limits keeps things safe.
  • Citations: the source URLs in grounding_chunks are your material for showing readers that an answer is trustworthy. If you display them, account for dead links.
  • Preventing stray calls: pass only the tools you actually need. Declaring too many raises the odds the model picks an unintended function.

Choosing between them in indie development

For drafts where factual freshness matters — app announcements, release notes — I reach for search grounding. When the answer depends on data that lives only on my side, such as internal metrics or inventory, I use Function Calling. Feeding in app revenue figures (an AdMob report, say) for summarization is another job for the latter.

The in-app integrations are best for getting a feel for the behavior by hand. The API tools come into their own once you fold that behavior into automation.

Which model should call the tools

When you build tool integration, the model you pick shapes the outcome too. In my own setup, I lean on gemini-3.5-flash for the lighter round-trips — search grounding or a single Function Calling hop — where speed matters, and only reach for a higher-tier model when I want to chain several tools and have it reason step by step.

Flash models respond quickly and stay cheaper, which suits features that run in sync with a user's action. For work that keeps no one waiting — a nightly batch, say — where you want precision in picking the right tool and assembling its arguments, switching up is worth it. Build on Flash first; if you see wrong-function picks or dropped arguments, move up. That order wastes the least effort.

One more thing: calling the API without naming a model uses the default, and that default can shift with updates. In automation, pin model explicitly so behavior doesn't change out from under you one day.

Your next step

With your own Gemini API key, run the search-grounding snippet above as-is, and try one question that returns grounding_chunks and one that doesn't. Experiencing the empty case first makes the design decisions far easier when you wire up the Function Calling round-trip.

Thank you for reading. I hope it gives you a solid foothold as you start building.

Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

⟐ Dev Tools2026-08-21
How Many Assistant-Dependent Lines Are Still in Your App?
On September 4th, Google Assistant on Android begins its replacement by Gemini. Here is how to grep your own project for every entry point an assistant can open, and how to turn that list into utterances you can actually test on a device.
◈ API / SDK2026-04-26
Production-Ready Function Calling with Gemini 2.5 Pro API — Realistic Patterns for Failures, Timeouts, and Hallucinations
Gemini 2.5 Pro's Function Calling is powerful, but it tends to land in 'works, but does odd things sometimes' territory in production. Here are the design patterns I arrived at running search, reservation, and notification agents.
⟐ Dev Tools2026-10-17
Hung Jobs Fail Quietly — Wrapping a Scheduled Gemini Call With a Timeout, an Empty-Output Check, and a Lock
An outer shell script that protects a cron-driven `gemini -p` call from three quiet failures: hanging on a response, exiting 0 with empty output, and overlapping with the previous run. Includes exit codes and timings measured with stand-in commands, and how far `timeout` reaches into child processes.