How to Combine Google Search, Google Maps, and Custom Functions in a Single Gemini API Call With Context Circulation, Parallel Tool IDs, and Multi-Step Agentic Chains

by CryptoExpert
aistudios


import subprocess, sys

subprocess.check_call(
[sys.executable, “-m”, “pip”, “install”, “-qU”, “google-genai”],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)

import getpass, json, textwrap, os, time
from google import genai
from google.genai import types

if “GOOGLE_API_KEY” not in os.environ:
os.environ[“GOOGLE_API_KEY”] = getpass.getpass(“Enter your Gemini API key: “)

aistudios

client = genai.Client(api_key=os.environ[“GOOGLE_API_KEY”])

TOOL_COMBO_MODEL = “gemini-3-flash-preview”
MAPS_MODEL = “gemini-2.5-flash”

DIVIDER = “=” * 72

def heading(title: str):
print(f”\n{DIVIDER}”)
print(f” {title}”)
print(DIVIDER)

def wrap(text: str, width: int = 80):
for line in text.splitlines():
print(textwrap.fill(line, width=width) if line.strip() else “”)

def describe_parts(response):
parts = response.candidates[0].content.parts
fc_ids = {}
for i, part in enumerate(parts):
prefix = f” Part {i:2d}:”
if hasattr(part, “tool_call”) and part.tool_call:
tc = part.tool_call
print(f”{prefix} [toolCall] type={tc.tool_type} id={tc.id}”)
if hasattr(part, “tool_response”) and part.tool_response:
tr = part.tool_response
print(f”{prefix} [toolResponse] type={tr.tool_type} id={tr.id}”)
if hasattr(part, “executable_code”) and part.executable_code:
code = part.executable_code.code[:90].replace(“\n”, ” ↵ “)
print(f”{prefix} [executableCode] {code}…”)
if hasattr(part, “code_execution_result”) and part.code_execution_result:
out = (part.code_execution_result.output or “”)[:90]
print(f”{prefix} [codeExecResult] {out}”)
if hasattr(part, “function_call”) and part.function_call:
fc = part.function_call
fc_ids[fc.name] = fc.id
print(f”{prefix} [functionCall] name={fc.name} id={fc.id}”)
print(f” └─ args: {dict(fc.args)}”)
if hasattr(part, “text”) and part.text:
snippet = part.text[:110].replace(“\n”, ” “)
print(f”{prefix} [text] {snippet}…”)
if hasattr(part, “thought_signature”) and part.thought_signature:
print(f” └─ thought_signature present ✓”)
return fc_ids

heading(“DEMO 1: Combine Google Search + Custom Function in One Request”)

print(“””
This demo shows the flagship new feature: passing BOTH a built-in tool
(Google Search) and a custom function declaration in a single API call.

Gemini will:
Turn 1 → Search the web for real-time info, then request our custom
function to get weather data.
Turn 2 → We supply the function response; Gemini synthesizes everything.

Key points:
• google_search and function_declarations go in the SAME Tool object
• include_server_side_tool_invocations must be True (on ToolConfig)
• Return ALL parts (incl. thought_signatures) in subsequent turns
“””)

get_weather_func = types.FunctionDeclaration(
name=”getWeather”,
description=”Gets the current weather for a requested city.”,
parameters=types.Schema(
type=”OBJECT”,
properties={
“city”: types.Schema(
type=”STRING”,
description=”The city and state, e.g. Utqiagvik, Alaska”,
),
},
required=[“city”],
),
)

print(“▶ Turn 1: Sending prompt with Google Search + getWeather tools…\n”)

response_1 = client.models.generate_content(
model=TOOL_COMBO_MODEL,
contents=(
“What is the northernmost city in the United States? ”
“What’s the weather like there today?”
),
config=types.GenerateContentConfig(
tools=[
types.Tool(
google_search=types.GoogleSearch(),
function_declarations=[get_weather_func],
),
],
tool_config=types.ToolConfig(
include_server_side_tool_invocations=True,
),
),
)

print(” Parts returned by the model:\n”)
fc_ids = describe_parts(response_1)

function_call_id = fc_ids.get(“getWeather”)
print(f”\n ✅ Captured function_call id for getWeather: {function_call_id}”)

print(“\n▶ Turn 2: Returning function result & requesting final synthesis…\n”)

history = [
types.Content(
role=”user”,
parts=[
types.Part(
text=(
“What is the northernmost city in the United States? ”
“What’s the weather like there today?”
)
)
],
),
response_1.candidates[0].content,
types.Content(
role=”user”,
parts=[
types.Part(
function_response=types.FunctionResponse(
name=”getWeather”,
response={“response”: “Very cold. 22°F / -5.5°C with strong Arctic winds.”},
id=function_call_id,
)
)
],
),
]

response_2 = client.models.generate_content(
model=TOOL_COMBO_MODEL,
contents=history,
config=types.GenerateContentConfig(
tools=[
types.Tool(
google_search=types.GoogleSearch(),
function_declarations=[get_weather_func],
),
],
tool_config=types.ToolConfig(
include_server_side_tool_invocations=True,
),
),
)

print(” ✅ Final synthesized response:\n”)
for part in response_2.candidates[0].content.parts:
if hasattr(part, “text”) and part.text:
wrap(part.text)



Source link

heygen

You may also like

Subscribe To Our Newsletter

Join our mailing list to receive the latest news and updates from our team.

You have Successfully Subscribed!

Verified by MonsterInsights