Documentation:https://googleapis.github.io/python-genai/
Google Gen AI Python SDK provides an interface for developers to integrate Google's generative models into their Python applications. It supports the Gemini Developer API and Gemini Enterprise Agent Platform APIs.
Warning
Updates to Automatic Function Calling (AFC) in upcoming SDK version:
We are changing AFC behavior in the next major version.
Specifically, users will not be able to
invoke AFC from direct calls to Models.generate_content or its stream and
async variants. Instead, users should invoke AFC from Chats modules.
| Methods/fields to be removed | migration guide |
|---|---|
Live.send | Use send_client_content, send_realtime_input, or send_tool_response instead |
Live.start_stream | Use receive and send_realtime_input instead |
LiveConnectConfig.generation_config | Set fields on LiveConnectConfig directly |
prompt/text/image arguments in Models.generate_videos (and async variants) | Use source argument instead |
GenerationConfigThinkingConfig | Use ThinkingConfig instead |
To avoid unexpected updates, pin the SDK version to < 3.0.0.
Large Language Models (LLMs) and generative AI coding assistants are often trained on static datasets. As a result, they may be unaware of recent updates and suggest outdated or legacy libraries.
To ensure your AI coding helper (such as Antigravity, Claude Code, Cursor, or other IDE extensions) generates up-to-date code using the correct SDK syntax and best practices, we recommend equipping your assistant with Gemini API Skills. Loading these skills injects the correct patterns and guidelines directly into your AI assistant's context.
Depending on your target platform, use the corresponding Agent Skill repository:
- Gemini Developer API: Use the google-gemini/gemini-skills repository.
- Gemini Enterprise Agent Platform (formerly Vertex AI): Use the google/skills repository.
pip install google-genaiWith uv:
uv pip install google-genaifromgoogleimportgenaifromgoogle.genaiimporttypesPlease run one of the following code blocks to create a client for different services (Gemini Developer API or Agent Platform).
fromgoogleimportgenai# Only run this block for Gemini Developer APIclient=genai.Client(api_key='GEMINI_API_KEY')fromgoogleimportgenai# Only run this block for Agent Platformclient=genai.Client(
enterprise=True, project='your-project-id', location='global'
)All API methods support Pydantic types and dictionaries, which you can access
from google.genai.types. You can import the types module with the following:
fromgoogle.genaiimporttypesBelow is an example generate_content() call using types from the types module:
response=client.models.generate_content(
model='gemini-2.5-flash',
contents=types.Part.from_text(text='Why is the sky blue?'),
config=types.GenerateContentConfig(
temperature=0,
top_p=0.95,
top_k=20,
),
)Alternatively, you can accomplish the same request using dictionaries instead of types:
response=client.models.generate_content(
model='gemini-2.5-flash',
contents={'text': 'Why is the sky blue?'},
config={
'temperature': 0,
'top_p': 0.95,
'top_k': 20,
},
)(Optional) Using environment variables:
You can create a client by configuring the necessary environment variables. Configuration setup instructions depends on whether you're using the Gemini Developer API or the Gemini API in the Gemini Enterprise Agent Platform.
Gemini Developer API: Set the GEMINI_API_KEY or GOOGLE_API_KEY.
It will automatically be picked up by the client. It's recommended that you
set only one of those variables, but if both are set, GOOGLE_API_KEY takes
precedence.
export GEMINI_API_KEY='your-api-key'Gemini API on Agent Platform: Set GOOGLE_GENAI_USE_ENTERPRISE,
GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION, as shown below:
export GOOGLE_GENAI_USE_ENTERPRISE=true
export GOOGLE_CLOUD_PROJECT='your-project-id'export GOOGLE_CLOUD_LOCATION='global'fromgoogleimportgenaiclient=genai.Client()Explicitly close the sync client to ensure that resources, such as the underlying HTTP connections, are properly cleaned up and closed.
fromgoogle.genaiimportClientclient=Client()
response_1=client.models.generate_content(
model=MODEL_ID,
contents='Hello',
)
response_2=client.models.generate_content(
model=MODEL_ID,
contents='Ask a question',
)
# Close the sync client to release resources.client.close()To explicitly close the async client:
fromgoogle.genaiimportClientaclient=Client(
enterprise=True, project='my-project-id', location='global'
).aioresponse_1=awaitaclient.models.generate_content(
model=MODEL_ID,
contents='Hello',
)
response_2=awaitaclient.models.generate_content(
model=MODEL_ID,
contents='Ask a question',
)
# Close the async client to release resources.awaitaclient.aclose()By using the sync client context manager, it will close the underlying sync client when exiting the with block and avoid httpx "client has been closed" error like issues#1763.
fromgoogle.genaiimportClientwithClient() asclient:
response_1=client.models.generate_content(
model=MODEL_ID,
contents='Hello',
)
response_2=client.models.generate_content(
model=MODEL_ID,
contents='Ask a question',
)By using the async client context manager, it will close the underlying async client when exiting the with block.
fromgoogle.genaiimportClientasyncwithClient().aioasaclient:
response_1=awaitaclient.models.generate_content(
model=MODEL_ID,
contents='Hello',
)
response_2=awaitaclient.models.generate_content(
model=MODEL_ID,
contents='Ask a question',
)By default, the SDK uses the beta API endpoints provided by Google to support
preview features in the APIs. The stable API endpoints can be selected by
setting the API version to v1.
To set the API version use http_options. For example, to set the API version
to v1 for Gemini Enterprise Agent Platform:
fromgoogleimportgenaifromgoogle.genaiimporttypesclient=genai.Client(
enterprise=True,
project='your-project-id',
location='global',
http_options=types.HttpOptions(api_version='v1')
)To set the API version to v1alpha for the Gemini Developer API:
fromgoogleimportgenaifromgoogle.genaiimporttypesclient=genai.Client(
api_key='GEMINI_API_KEY',
http_options=types.HttpOptions(api_version='v1alpha')
)By default we use httpx for both sync and async client implementations. In order
to have faster performance, you may install google-genai[aiohttp]. In Gen AI
SDK we configure trust_env=True to match with the default behavior of httpx.
Additional args of aiohttp.ClientSession.request() (see _RequestOptions args) can be passed
through the following way:
http_options=types.HttpOptions(
async_client_args={'cookies': ..., 'ssl': ...},
)
client=Client(..., http_options=http_options)Both httpx and aiohttp libraries use urllib.request.getproxies from
environment variables. Before client initialization, you may set proxy (and
optional SSL_CERT_FILE) by setting the environment variables:
export HTTPS_PROXY='http://username:password@proxy_uri:port'export SSL_CERT_FILE='client.pem'If you need socks5 proxy, httpx supportssocks5 proxy if you pass it via
args to httpx.Client(). You may install httpx[socks] to use it.
Then, you can pass it through the following way:
http_options=types.HttpOptions(
client_args={'proxy': 'socks5://user:pass@host:port'},
async_client_args={'proxy': 'socks5://user:pass@host:port'},
)
client=Client(..., http_options=http_options)In some cases you might need a custom base url (for example, API gateway proxy server) and bypass some authentication checks for project, location, or API key. You may pass the custom base url like this:
client=Client(
enterprise=True,
http_options=types.HttpOptionsDict(
base_url='https://test-api-gateway-proxy.com',
base_url_resource_scope=types.ResourceScope.COLLECTION,
),
)
response=client.models.generate_content(
model='gemini-3-pro-preview', contents='Why is the sky blue?'
)If base_url_resource_scope=types.ResourceScope.COLLECTION, the resource name
will not include api version, project, or location.
Expected request url will be: https://test-api-gateway-proxy.com/publishers/google/models/gemini-3-pro-preview
Parameter types can be specified as either dictionaries(TypedDict) or
Pydantic Models.
Pydantic model types are available in the types module.
The client.models module exposes model inferencing and model getters.
See the 'Create a client' section above to initialize a client.
response=client.models.generate_content(
model='gemini-3.5-flash', contents='Why is the sky blue?'
)
print(response.text)fromgoogle.genaiimporttypesresponse=client.models.generate_content(
model='gemini-3.1-flash-image',
contents='A cartoon infographic for flying sneakers',
config=types.GenerateContentConfig(
response_modalities=["IMAGE"],
image_config=types.ImageConfig(
aspect_ratio="9:16",
),
),
)
forpartinresponse.parts:
ifpart.inline_data:
generated_image=part.as_image()
generated_image.show()Download the file in console.
!wget -q https://storage.googleapis.com/generativeai-downloads/data/a11.txtpython code.
file=client.files.upload(file='a11.txt')
response=client.models.generate_content(
model='gemini-3.5-flash',
contents=['Could you summarize this file?', file]
)
print(response.text)The SDK always converts the inputs to the contents argument into
list[types.Content].
The following shows some common ways to provide your inputs.
This is the canonical way to provide contents, SDK will not do any conversion.
fromgoogle.genaiimporttypescontents=types.Content(
role='user',
parts=[types.Part.from_text(text='Why is the sky blue?')]
)SDK converts this to
[
types.Content(
role='user',
parts=[types.Part.from_text(text='Why is the sky blue?')]
)
]contents='Why is the sky blue?'The SDK will assume this is a text part, and it converts this into the following:
[
types.UserContent(
parts=[
types.Part.from_text(text='Why is the sky blue?')
]
)
]Where a types.UserContent is a subclass of types.Content, it sets the
role field to be user.
contents=['Why is the sky blue?', 'Why is the cloud white?']The SDK assumes these are 2 text parts, it converts this into a single content, like the following:
[
types.UserContent(
parts=[
types.Part.from_text(text='Why is the sky blue?'),
types.Part.from_text(text='Why is the cloud white?'),
]
)
]Where a types.UserContent is a subclass of types.Content, the
role field in types.UserContent is fixed to be user.
fromgoogle.genaiimporttypescontents=types.Part.from_function_call(
name='get_weather_by_location',
args={'location': 'Boston'}
)The SDK converts a function call part to a content with a model role:
[
types.ModelContent(
parts=[
types.Part.from_function_call(
name='get_weather_by_location',
args={'location': 'Boston'}
)
]
)
]Where a types.ModelContent is a subclass of types.Content, the
role field in types.ModelContent is fixed to be model.
fromgoogle.genaiimporttypescontents= [
types.Part.from_function_call(
name='get_weather_by_location',
args={'location': 'Boston'}
),
types.Part.from_function_call(
name='get_weather_by_location',
args={'location': 'New York'}
),
]The SDK converts a list of function call parts to a content with a model role:
[
types.ModelContent(
parts=[
types.Part.from_function_call(
name='get_weather_by_location',
args={'location': 'Boston'}
),
types.Part.from_function_call(
name='get_weather_by_location',
args={'location': 'New York'}
)
]
)
]Where a types.ModelContent is a subclass of types.Content, the
role field in types.ModelContent is fixed to be model.
fromgoogle.genaiimporttypescontents=types.Part.from_uri(
file_uri: 'gs://generativeai-downloads/images/scones.jpg',
mime_type: 'image/jpeg',
)The SDK converts all non function call parts into a content with a user role.
[
types.UserContent(parts=[
types.Part.from_uri(
file_uri: 'gs://generativeai-downloads/images/scones.jpg',
mime_type: 'image/jpeg',
)
])
]fromgoogle.genaiimporttypescontents= [
types.Part.from_text('What is this image about?'),
types.Part.from_uri(
file_uri: 'gs://generativeai-downloads/images/scones.jpg',
mime_type: 'image/jpeg',
)
]The SDK will convert the list of parts into a content with a user role
[
types.UserContent(
parts=[
types.Part.from_text('What is this image about?'),
types.Part.from_uri(
file_uri: 'gs://generativeai-downloads/images/scones.jpg',
mime_type: 'image/jpeg',
)
]
)
]You can also provide a list of types.ContentUnion. The SDK leaves items of
types.Content as is, it groups consecutive non function call parts into a
single types.UserContent, and it groups consecutive function call parts into
a single types.ModelContent.
If you put a list within a list, the inner list can only contain
types.PartUnion items. The SDK will convert the inner list into a single
types.UserContent.
The output of the model can be influenced by several optional settings
available in generate_content's config parameter. For example, increasing
max_output_tokens is essential for longer model responses. To make a model
more deterministic, lowering the temperature parameter reduces randomness,
with values near 0 minimizing variability. Capabilities and parameter defaults
for each model is shown in the
Gemini Enterprise Agent Platform docs
and Gemini API docs
respectively. Note that all API methods support Pydantic types and
dictionaries, which you can access from google.genai.types. In this example,
we use GenerateContentConfig to specify the desired behavior from the model.
fromgoogle.genaiimporttypesresponse=client.models.generate_content(
model='gemini-3.5-flash',
contents='high',
config=types.GenerateContentConfig(
system_instruction='I say high, you say low',
max_output_tokens=3,
temperature=0.3,
),
)
print(response.text)To retrieve tuned models, see list tuned models.
formodelinclient.models.list():
print(model)pager=client.models.list(config={'page_size': 10})
print(pager.page_size)
print(pager[0])
pager.next_page()
print(pager[0])asyncforjobinawaitclient.aio.models.list():
print(job)async_pager=awaitclient.aio.models.list(config={'page_size': 10})
print(async_pager.page_size)
print(async_pager[0])
awaitasync_pager.next_page()
print(async_pager[0])fromgoogle.genaiimporttypesresponse=client.models.generate_content(
model='gemini-3.5-flash',
contents='Say something bad.',
config=types.GenerateContentConfig(
safety_settings=[
types.SafetySetting(
category='HARM_CATEGORY_HATE_SPEECH',
threshold='BLOCK_ONLY_HIGH',
)
]
),
)
print(response.text)You can pass a Python function directly and it will be automatically called and responded by default.
fromgoogle.genaiimporttypesdefget_current_weather(location: str) ->str:
"""Returns the current weather. Args: location: The city and state, e.g. San Francisco, CA """return'sunny'response=client.models.generate_content(
model='gemini-3.5-flash',
contents='What is the weather like in Boston?',
config=types.GenerateContentConfig(tools=[get_current_weather]),
)
print(response.text)If you pass in a python function as a tool directly, and do not want automatic function calling, you can disable automatic function calling as follows:
fromgoogle.genaiimporttypesresponse=client.models.generate_content(
model='gemini-3.5-flash',
contents='What is the weather like in Boston?',
config=types.GenerateContentConfig(
tools=[get_current_weather],
automatic_function_calling=types.AutomaticFunctionCallingConfig(
disable=True
),
),
)With automatic function calling disabled, you will get a list of function call parts in the response:
function_calls: Optional[List[types.FunctionCall]] =response.function_callsIf you don't want to use the automatic function support, you can manually declare the function and invoke it.
The following example shows how to declare a function and pass it as a tool. Then you will receive a function call part in the response.
fromgoogle.genaiimporttypesfunction=types.FunctionDeclaration(
name='get_current_weather',
description='Get the current weather in a given location',
parameters_json_schema={
'type': 'object',
'properties': {
'location': {
'type': 'string',
'description': 'The city and state, e.g. San Francisco, CA',
}
},
'required': ['location'],
},
)
tool=types.Tool(function_declarations=[function])
response=client.models.generate_content(
model='gemini-3.5-flash',
contents='What is the weather like in Boston?',
config=types.GenerateContentConfig(tools=[tool]),
)
print(response.function_calls[0])After you receive the function call part from the model, you can invoke the function and get the function response. And then you can pass the function response to the model. The following example shows how to do it for a simple function invocation.
fromgoogle.genaiimporttypesuser_prompt_content=types.Content(
role='user',
parts=[types.Part.from_text(text='What is the weather like in Boston?')],
)
function_call_part=response.function_calls[0]
function_call_content=response.candidates[0].contenttry:
function_result=get_current_weather(
**function_call_part.function_call.args
)
function_response= {'result': function_result}
except (
Exception
) ase: # instead of raising the exception, you can let the model handle itfunction_response= {'error': str(e)}
function_response_part=types.Part.from_function_response(
name=function_call_part.name,
response=function_response,
)
function_response_content=types.Content(
role='tool', parts=[function_response_part]
)
response=client.models.generate_content(
model='gemini-3.5-flash',
contents=[
user_prompt_content,
function_call_content,
function_response_content,
],
config=types.GenerateContentConfig(
tools=[tool],
),
)
print(response.text)If you configure function calling mode to be ANY, then the model will always
return function call parts. If you also pass a python function as a tool, by
default the SDK will perform automatic function calling until the remote calls exceed the
maximum remote call for automatic function calling (default to 10 times).
If you'd like to disable automatic function calling in ANY mode:
fromgoogle.genaiimporttypesdefget_current_weather(location: str) ->str:
"""Returns the current weather. Args: location: The city and state, e.g. San Francisco, CA """return"sunny"response=client.models.generate_content(
model="gemini-3.5-flash",
contents="What is the weather like in Boston?",
config=types.GenerateContentConfig(
tools=[get_current_weather],
automatic_function_calling=types.AutomaticFunctionCallingConfig(
disable=True
),
tool_config=types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(mode='ANY')
),
),
)If you'd like to set x number of automatic function call turns, you can
configure the maximum remote calls to be x + 1.
Assuming you prefer 1 turn for automatic function calling.
fromgoogle.genaiimporttypesdefget_current_weather(location: str) ->str:
"""Returns the current weather. Args: location: The city and state, e.g. San Francisco, CA """return"sunny"response=client.models.generate_content(
model="gemini-3.5-flash",
contents="What is the weather like in Boston?",
config=types.GenerateContentConfig(
tools=[get_current_weather],
automatic_function_calling=types.AutomaticFunctionCallingConfig(
maximum_remote_calls=2
),
tool_config=types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(mode='ANY')
),
),
)See below for examples of how to use MCP for the Gemini Developer API and Gemini Enterprise Agent Platform.
Built-in MCP support is an experimental feature. You can pass a local MCP server as a tool directly.
importosimportasynciofromdatetimeimportdatetimefrommcpimportClientSession, StdioServerParametersfrommcp.client.stdioimportstdio_clientfromgoogleimportgenaiclient=genai.Client()
# Create server parameters for stdio connectionserver_params=StdioServerParameters(
command="npx", # Executableargs=["-y", "@philschmid/weather-mcp"], # MCP Serverenv=None, # Optional environment variables
)
asyncdefrun():
asyncwithstdio_client(server_params) as (read, write):
asyncwithClientSession(read, write) assession:
# Prompt to get the weather for the current day in London.prompt=f"What is the weather in London in {datetime.now().strftime('%Y-%m-%d')}?"# Initialize the connection between client and serverawaitsession.initialize()
# Send request to the model with MCP function declarationsresponse=awaitclient.aio.models.generate_content(
model="gemini-3.5-flash",
contents=prompt,
config=genai.types.GenerateContentConfig(
tools=[session], # uses the session, will automatically call the tool using automatic function calling
),
)
print(response.text)
# Start the asyncio event loop and run the main functionasyncio.run(run())To use MCP with Agent Platform, provide the MCP tool you want to use to
Tool.mcp_servers in your generate_content request. See
here
for a list of available MCP tools.
The mcp package is required to use Agent Platform MCP servers.
You can install it with pip install mcp.
importasynciofromgoogleimportgenaifromgoogle.genaiimporttypesPROJECT_ID="your-gcp-project"LOCATION="your-location"client=genai.Client(enterprise=True, project=PROJECT_ID, location=LOCATION)
asyncdefagent_platform_mcp():
response=awaitclient.aio.models.generate_content(
model="gemini-3.5-flash",
contents=f"List my endpoints in {LOCATION} for my {PROJECT_ID} project.",
config=types.GenerateContentConfig(
tools=[
types.Tool(
mcp_servers=[
types.McpServer(name='endpoints')
]
)
]
)
)
# Print the model responseifresponse.text:
print(response.text)
# Optionally, print the full conversation between the model and MCP serverifresponse.automatic_function_calling_history:
forturninresponse.automatic_function_calling_history:
print(f"Role: {turn.role}")
forpartinturn.parts:
ifpart.function_call:
print(f" Tool Called: {part.function_call.name}")
print(f" Arguments: {part.function_call.args}")
elifpart.function_response:
print(f" Tool Response: {part.function_response.response}")
print("-"*40)
asyncio.run(agent_platform_mcp())However you define your schema, don't duplicate it in your input prompt, including by giving examples of expected JSON output. If you do, the generated output might be lower in quality.
Schemas can be provided as standard JSON schema.
user_profile= {
'properties': {
'age': {
'anyOf': [
{'maximum': 20, 'minimum': 0, 'type': 'integer'},
{'type': 'null'},
],
'title': 'Age',
},
'username': {
'description': "User's unique name",
'title': 'Username',
'type': 'string',
},
},
'required': ['username', 'age'],
'title': 'User Schema',
'type': 'object',
}
response=client.models.generate_content(
model='gemini-3.5-flash',
contents='Give me a random user profile.',
config={
'response_mime_type': 'application/json',
'response_json_schema': user_profile
},
)
print(response.text)Schemas can be provided as Pydantic Models.
frompydanticimportBaseModelfromgoogle.genaiimporttypesclassCountryInfo(BaseModel):
name: strpopulation: intcapital: strcontinent: strgdp: intofficial_language: strtotal_area_sq_mi: intresponse=client.models.generate_content(
model='gemini-3.5-flash',
contents='Give me information for the United States.',
config=types.GenerateContentConfig(
response_mime_type='application/json',
response_json_schema=CountryInfo.model_json_schema(),
),
)
print(response.text)fromgoogle.genaiimporttypesresponse=client.models.generate_content(
model='gemini-3.5-flash',
contents='Give me information for the United States.',
config=types.GenerateContentConfig(
response_mime_type='application/json',
response_json_schema={
'required': [
'name',
'population',
'capital',
'continent',
'gdp',
'official_language',
'total_area_sq_mi',
],
'properties': {
'name': {'type': 'STRING'},
'population': {'type': 'INTEGER'},
'capital': {'type': 'STRING'},
'continent': {'type': 'STRING'},
'gdp': {'type': 'INTEGER'},
'official_language': {'type': 'STRING'},
'total_area_sq_mi': {'type': 'INTEGER'},
},
'type': 'OBJECT',
},
),
)
print(response.text)Generate content in a streaming format so that the model outputs streams back to you, rather than being returned as one chunk.
forchunkinclient.models.generate_content_stream(
model='gemini-3.5-flash', contents='Tell me a story in 300 words.'
):
print(chunk.text, end='')If your image is stored in Google Cloud Storage,
you can use the from_uri class method to create a Part object.
fromgoogle.genaiimporttypesforchunkinclient.models.generate_content_stream(
model='gemini-3.5-flash',
contents=[
'What is this image about?',
types.Part.from_uri(
file_uri='gs://generativeai-downloads/images/scones.jpg',
mime_type='image/jpeg',
),
],
):
print(chunk.text, end='')If your image is stored in your local file system, you can read it in as bytes
data and use the from_bytes class method to create a Part object.
fromgoogle.genaiimporttypesYOUR_IMAGE_PATH='your_image_path'YOUR_IMAGE_MIME_TYPE='your_image_mime_type'withopen(YOUR_IMAGE_PATH, 'rb') asf:
image_bytes=f.read()
forchunkinclient.models.generate_content_stream(
model='gemini-3.5-flash',
contents=[
'What is this image about?',
types.Part.from_bytes(data=image_bytes, mime_type=YOUR_IMAGE_MIME_TYPE),
],
):
print(chunk.text, end='')client.aio exposes all the analogous async methods
that are available on client. Note that it applies to all the modules.
For example, client.aio.models.generate_content is the async version
of client.models.generate_content
response=awaitclient.aio.models.generate_content(
model='gemini-3.5-flash', contents='Tell me a story in 300 words.'
)
print(response.text)asyncforchunkinawaitclient.aio.models.generate_content_stream(
model='gemini-3.5-flash', contents='Tell me a story in 300 words.'
):
print(chunk.text, end='')response=client.models.count_tokens(
model='gemini-3.5-flash',
contents='why is the sky blue?',
)
print(response)Compute tokens is only supported in Gemini Enterprise Agent Platform.
response=client.models.compute_tokens(
model='gemini-3.5-flash',
contents='why is the sky blue?',
)
print(response)response=awaitclient.aio.models.count_tokens(
model='gemini-3.5-flash',
contents='why is the sky blue?',
)
print(response)fromgoogle.genaiimportlocal_tokenizertokenizer=local_tokenizer.LocalTokenizer(model_name='gemini-3.5-flash')
result=tokenizer.count_tokens("What is your name?")fromgoogle.genaiimportlocal_tokenizertokenizer=local_tokenizer.LocalTokenizer(model_name='gemini-3.5-flash')
result=tokenizer.compute_tokens("What is your name?")response=client.models.embed_content(
model='gemini-embedding-001',
contents='why is the sky blue?',
)
print(response)fromgoogle.genaiimporttypesresponse=client.models.embed_content(
model='gemini-embedding-001',
contents=['why is the sky blue?', 'What is your age?'],
config=types.EmbedContentConfig(output_dimensionality=10),
)
print(response)fromgoogle.genaiimporttypesresponse1=client.models.generate_images(
model='imagen-4.0-generate-001',
prompt='An umbrella in the foreground, and a rainy night sky in the background',
config=types.GenerateImagesConfig(
number_of_images=1,
include_rai_reason=True,
output_mime_type='image/jpeg',
),
)
response1.generated_images[0].image.show()Upscale image is only supported in Gemini Enterprise Agent Platform.
fromgoogle.genaiimporttypesresponse2=client.models.upscale_image(
model='imagen-4.0-upscale-preview',
image=response1.generated_images[0].image,
upscale_factor='x2',
config=types.UpscaleImageConfig(
include_rai_reason=True,
output_mime_type='image/jpeg',
),
)
response2.generated_images[0].image.show()Edit image uses a separate model from generate and upscale.
Edit image is only supported in Gemini Enterprise Agent Platform.
# Edit the generated image from abovefromgoogle.genaiimporttypesfromgoogle.genai.typesimportRawReferenceImage, MaskReferenceImageraw_ref_image=RawReferenceImage(
reference_id=1,
reference_image=response1.generated_images[0].image,
)
# Model computes a mask of the backgroundmask_ref_image=MaskReferenceImage(
reference_id=2,
config=types.MaskReferenceConfig(
mask_mode='MASK_MODE_BACKGROUND',
mask_dilation=0,
),
)
response3=client.models.edit_image(
model='imagen-3.0-capability-001',
prompt='Sunlight and clear sky',
reference_images=[raw_ref_image, mask_ref_image],
config=types.EditImageConfig(
edit_mode='EDIT_MODE_INPAINT_INSERTION',
number_of_images=1,
include_rai_reason=True,
output_mime_type='image/jpeg',
),
)
response3.generated_images[0].image.show()fromgoogle.genaiimporttypes# Create operationoperation=client.models.generate_videos(
model='veo-3.1-generate-preview',
source=types.GenerateVideosSource(
prompt='A neon hologram of a cat driving at top speed',
),
config=types.GenerateVideosConfig(
number_of_videos=1,
duration_seconds=5,
enhance_prompt=True,
),
)
# Poll operationwhilenotoperation.done:
time.sleep(20)
operation=client.operations.get(operation)
video=operation.response.generated_videos[0].videovideo.show()fromgoogle.genaiimporttypes# Read local image (uses mimetypes.guess_type to infer mime type)image=types.Image.from_file(location="local/path/file.png")
# Create operationoperation=client.models.generate_videos(
model='veo-3.1-generate-preview',
source=types.GenerateVideosSource(
# Prompt is optional if image is providedprompt='Night sky',
image=image,
),
config=types.GenerateVideosConfig(
number_of_videos=1,
duration_seconds=5,
enhance_prompt=True,
# Can also pass an Image into last_frame for frame interpolation
),
)
# Poll operationwhilenotoperation.done:
time.sleep(20)
operation=client.operations.get(operation)
video=operation.response.generated_videos[0].videovideo.show()Currently, only Gemini Developer API supports video extension on Veo 3.1 for previously generated videos. Gemini Enterprise Agent Platform supports video extension on Veo 2.0.
fromgoogle.genaiimporttypes# Read local video (uses mimetypes.guess_type to infer mime type)video=types.Video.from_file("local/path/video.mp4")
# Create operationoperation=client.models.generate_videos(
model='veo-3.1-generate-preview',
source=types.GenerateVideosSource(
# Prompt is optional if Video is providedprompt='Night sky',
# Input video must be in GCS for Gemini Enterprise Agent Platform or a URI for Geminivideo=types.Video(
uri="gs://bucket-name/inputs/videos/cat_driving.mp4",
),
),
config=types.GenerateVideosConfig(
number_of_videos=1,
duration_seconds=5,
enhance_prompt=True,
),
)
# Poll operationwhilenotoperation.done:
time.sleep(20)
operation=client.operations.get(operation)
video=operation.response.generated_videos[0].videovideo.show()Create a chat session to start a multi-turn conversations with the model. Then,
use chat.send_message function multiple times within the same chat session so
that it can reflect on its previous responses (i.e., engage in an ongoing
conversation). See the 'Create a client' section above to initialize a client.
chat=client.chats.create(model='gemini-3.5-flash')
response=chat.send_message('tell me a story')
print(response.text)
response=chat.send_message('summarize the story you told me in 1 sentence')
print(response.text)chat=client.chats.create(model='gemini-3.5-flash')
forchunkinchat.send_message_stream('tell me a story'):
print(chunk.text)chat=client.aio.chats.create(model='gemini-3.5-flash')
response=awaitchat.send_message('tell me a story')
print(response.text)chat=client.aio.chats.create(model='gemini-3.5-flash')
asyncforchunkinawaitchat.send_message_stream('tell me a story'):
print(chunk.text)Files are only supported in Gemini Developer API. See the 'Create a client' section above to initialize a client.
!gcloud storage cp gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf .!gcloud storage cp gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf .file1=client.files.upload(file='2312.11805v3.pdf')
file2=client.files.upload(file='2403.05530.pdf')
print(file1)
print(file2)file1=client.files.upload(file='2312.11805v3.pdf')
file_info=client.files.get(name=file1.name)file3=client.files.upload(file='2312.11805v3.pdf')
client.files.delete(name=file3.name)client.caches contains the control plane APIs for cached content. See the
'Create a client' section above to initialize a client.
fromgoogle.genaiimporttypesifclient.enterprise:
file_uris= [
'gs://cloud-samples-data/generative-ai/pdf/2312.11805v3.pdf',
'gs://cloud-samples-data/generative-ai/pdf/2403.05530.pdf',
]
else:
file_uris= [file1.uri, file2.uri]
cached_content=client.caches.create(
model='gemini-3.5-flash',
config=types.CreateCachedContentConfig(
contents=[
types.Content(
role='user',
parts=[
types.Part.from_uri(
file_uri=file_uris[0], mime_type='application/pdf'
),
types.Part.from_uri(
file_uri=file_uris[1],
mime_type='application/pdf',
),
],
)
],
system_instruction='What is the sum of the two pdfs?',
display_name='test cache',
ttl='3600s',
),
)cached_content=client.caches.get(name=cached_content.name)fromgoogle.genaiimporttypesresponse=client.models.generate_content(
model='gemini-3.5-flash',
contents='Summarize the pdfs',
config=types.GenerateContentConfig(
cached_content=cached_content.name,
),
)
print(response.text)The Interactions API is a unified interface for interacting with Gemini models and agents. It simplifies state management, tool orchestration, and long-running tasks.
See the documentation site for more details.
interaction=client.interactions.create(
model='gemini-3.5-flash',
input='Tell me a short joke about programming.'
)
print(interaction.outputs[-1].text)The Interactions API supports server-side state management. You can continue a conversation by referencing the previous_interaction_id.
# 1. First turninteraction1=client.interactions.create(
model='gemini-3.5-flash',
input='Hi, my name is Amir.'
)
print(f"Model: {interaction1.outputs[-1].text}")
# 2. Second turn (passing previous_interaction_id)interaction2=client.interactions.create(
model='gemini-3.5-flash',
input='What is my name?',
previous_interaction_id=interaction1.id
)
print(f"Model: {interaction2.outputs[-1].text}")You can use specialized agents like deep-research-pro-preview-12-2025 for complex tasks.
importtime# 1. Start the Deep Research Agentinitial_interaction=client.interactions.create(
input='Research the history of the Google TPUs with a focus on 2025 and 2026.',
agent='deep-research-pro-preview-12-2025',
background=True
)
print(f"Research started. Interaction ID: {initial_interaction.id}")
# 2. Poll for resultswhileTrue:
interaction=client.interactions.get(id=initial_interaction.id)
print(f"Status: {interaction.status}")
ifinteraction.status=="completed":
print("\nFinal Report:\n", interaction.outputs[-1].text)
breakelifinteraction.statusin ["failed", "cancelled"]:
print(f"Failed with status: {interaction.status}")
breaktime.sleep(10)You can provide multimodal data (text, images, audio, etc.) in the input list.
importbase64# Assuming you have an image loaded as bytes# base64_image = ...interaction=client.interactions.create(
model='gemini-3.5-flash',
input=[
{'type': 'text', 'text': 'Describe the image.'},
{'type': 'image', 'data': base64_image, 'mime_type': 'image/png'}
]
)
print(interaction.outputs[-1].text)You can define custom functions for the model to use. The Interactions API handles the tool selection, and you provide the execution result back to the model.
# 1. Define the tooldefget_weather(location: str):
"""Gets the weather for a given location."""returnf"The weather in {location} is sunny."weather_tool= {
'type': 'function',
'name': 'get_weather',
'description': 'Gets the weather for a given location.',
'parameters': {
'type': 'object',
'properties': {
'location': {'type': 'string', 'description': 'The city and state, e.g. San Francisco, CA'}
},
'required': ['location']
}
}
# 2. Send the request with toolsinteraction=client.interactions.create(
model='gemini-3.5-flash',
input='What is the weather in Mountain View, CA?',
tools=[weather_tool]
)
# 3. Handle the tool callforoutputininteraction.outputs:
ifoutput.type=='function_call':
print(f"Tool Call: {output.name}({output.arguments})")
# Execute your actual function hereresult=get_weather(**output.arguments)
# Send result back to the modelinteraction=client.interactions.create(
model='gemini-3.5-flash',
previous_interaction_id=interaction.id,
input=[{
'type': 'function_result',
'name': output.name,
'call_id': output.id,
'result': result
}]
)
print(f"Response: {interaction.outputs[-1].text}")You can also use Google's built-in tools, such as Google Search or Code Execution.
interaction=client.interactions.create(
model='gemini-3.5-flash',
input='Who won the last Super Bowl?',
tools=[{'type': 'google_search'}]
)
# Find the text output (not the GoogleSearchResultContent)text_output=next((oforoininteraction.outputsifo.type=='text'), None)
iftext_output:
print(text_output.text)interaction=client.interactions.create(
model='gemini-3.5-flash',
input='Calculate the 50th Fibonacci number.',
tools=[{'type': 'code_execution'}]
)
print(interaction.outputs[-1].text)The Interactions API can generate multimodal outputs, such as images. You must specify the response_modalities.
importbase64interaction=client.interactions.create(
model='gemini-3-pro-image-preview',
input='Generate an image of a futuristic city.',
response_modalities=['IMAGE']
)
foroutputininteraction.outputs:
ifoutput.type=='image':
print(f"Generated image with mime_type: {output.mime_type}")
# Save the imagewithopen("generated_city.png", "wb") asf:
f.write(base64.b64decode(output.data))client.tunings contains tuning job APIs and supports supervised fine
tuning through tune. Only supported in Gemini Enterprise Agent Platform. See the 'Create a client'
section above to initialize a client.
- Gemini Enterprise Agent Platform supports tuning from GCS source or from a Gemini Enterprise Agent Platform Multimodal Dataset
fromgoogle.genaiimporttypesmodel='gemini-3.5-flash'training_dataset=types.TuningDataset(
# or gcs_uri=my_enterprise_multimodal_datasetgcs_uri='gs://your-gcs-bucket/your-tuning-data.jsonl',
)fromgoogle.genaiimporttypestuning_job=client.tunings.tune(
base_model=model,
training_dataset=training_dataset,
config=types.CreateTuningJobConfig(
epoch_count=1, tuned_model_display_name='test_dataset_examples model'
),
)
print(tuning_job)tuning_job=client.tunings.get(name=tuning_job.name)
print(tuning_job)importtimecompleted_states=set(
[
'JOB_STATE_SUCCEEDED',
'JOB_STATE_FAILED',
'JOB_STATE_CANCELLED',
]
)
whiletuning_job.statenotincompleted_states:
print(tuning_job.state)
tuning_job=client.tunings.get(name=tuning_job.name)
time.sleep(10)response=client.models.generate_content(
model=tuning_job.tuned_model.endpoint,
contents='why is the sky blue?',
)
print(response.text)tuned_model=client.models.get(model=tuning_job.tuned_model.model)
print(tuned_model)To retrieve base models, see list base models.
formodelinclient.models.list(config={'page_size': 10, 'query_base': False}):
print(model)pager=client.models.list(config={'page_size': 10, 'query_base': False})
print(pager.page_size)
print(pager[0])
pager.next_page()
print(pager[0])asyncforjobinawaitclient.aio.models.list(config={'page_size': 10, 'query_base': False}):
print(job)async_pager=awaitclient.aio.models.list(config={'page_size': 10, 'query_base': False})
print(async_pager.page_size)
print(async_pager[0])
awaitasync_pager.next_page()
print(async_pager[0])fromgoogle.genaiimporttypesmodel=pager[0]
model=client.models.update(
model=model.name,
config=types.UpdateModelConfig(
display_name='my tuned model', description='my tuned model description'
),
)
print(model)forjobinclient.tunings.list(config={'page_size': 10}):
print(job)pager=client.tunings.list(config={'page_size': 10})
print(pager.page_size)
print(pager[0])
pager.next_page()
print(pager[0])asyncforjobinawaitclient.aio.tunings.list(config={'page_size': 10}):
print(job)async_pager=awaitclient.aio.tunings.list(config={'page_size': 10})
print(async_pager.page_size)
print(async_pager[0])
awaitasync_pager.next_page()
print(async_pager[0])Only supported in Gemini Enterprise Agent Platform. See the 'Create a client' section above to initialize a client.
Gemini Enterprise Agent Platform:
# Specify model and source file only, destination and job display name will be auto-populatedjob=client.batches.create(
model='gemini-3.5-flash',
src='bq://my-project.my-dataset.my-table', # or "gs://path/to/input/data"
)
print(job)Gemini Developer API:
# Create a batch job with inlined requestsbatch_job=client.batches.create(
model="gemini-3.5-flash",
src=[{
"contents": [{
"parts": [{
"text": "Hello!",
}],
"role": "user",
}],
"config": {"response_modalities": ["text"]},
}],
)
jobIn order to create a batch job with file name. Need to upload a json file.
For example myrequests.json:
{"key":"request_1", "request": {"contents": [{"parts": [{"text":
"Explain how AI works in a few words"}]}], "generation_config": {"response_modalities": ["TEXT"]}}}
{"key":"request_2", "request": {"contents": [{"parts": [{"text": "Explain how Crypto works in a few words"}]}]}}Then upload the file.
# Upload the filefile=client.files.upload(
file='myrequests.json',
config=types.UploadFileConfig(display_name='test-json')
)
# Create a batch job with file namebatch_job=client.batches.create(
model="gemini-3.5-flash",
src="files/test-json",
)# Get a job by namejob=client.batches.get(name=job.name)
job.statecompleted_states=set(
[
'JOB_STATE_SUCCEEDED',
'JOB_STATE_FAILED',
'JOB_STATE_CANCELLED',
'JOB_STATE_PAUSED',
]
)
whilejob.statenotincompleted_states:
print(job.state)
job=client.batches.get(name=job.name)
time.sleep(30)
jobforjobinclient.batches.list(config=types.ListBatchJobsConfig(page_size=10)):
print(job)pager=client.batches.list(config=types.ListBatchJobsConfig(page_size=10))
print(pager.page_size)
print(pager[0])
pager.next_page()
print(pager[0])asyncforjobinawaitclient.aio.batches.list(
config=types.ListBatchJobsConfig(page_size=10)
):
print(job)async_pager=awaitclient.aio.batches.list(
config=types.ListBatchJobsConfig(page_size=10)
)
print(async_pager.page_size)
print(async_pager[0])
awaitasync_pager.next_page()
print(async_pager[0])# Delete the job resourcedelete_job=client.batches.delete(name=job.name)
delete_jobTo handle errors raised by the model service, the SDK provides this APIError class.
fromgoogle.genaiimporterrorstry:
client.models.generate_content(
model="invalid-model-name",
contents="What is your name?",
)
excepterrors.APIErrorase:
print(e.code) # 404print(e.message)The extra_body field in HttpOptions accepts a dictionary of additional JSON
properties to include in the request body. This can be used to access new or
experimental backend features that are not yet formally supported in the SDK.
The structure of the dictionary must match the backend API's request structure.
- Gemini Enterprise Agent Platform backend API docs: https://docs.cloud.google.com/gemini-enterprise-agent-platform/reference/rest
- Gemini API backend API docs: https://ai.google.dev/api/rest
response=client.models.generate_content(
model="gemini-2.5-pro",
contents="What is the weather in Boston? and how about Sunnyvale?",
config=types.GenerateContentConfig(
tools=[get_current_weather],
http_options=types.HttpOptions(extra_body={'tool_config': {'function_calling_config': {'mode': 'COMPOSITIONAL'}}}),
),
)