Skip to content
Scalekit Docs

Google ADK

Build a Google ADK agent with Scalekit-authenticated Gmail tools. Scalekit returns native ADK tool objects; no schema reshaping needed.

Build a Google ADK agent that reads a user’s Gmail inbox. Scalekit handles OAuth, token storage, and returns tools as native ADK tool objects compatible with any ADK agent.

Full code on GitHub
Terminal window
pip install "scalekit-sdk-python[google-adk]" "google-adk>=2,<3"
import os
import asyncio
import scalekit.client
scalekit_client = scalekit.client.ScalekitClient(
client_id=os.getenv("SCALEKIT_CLIENT_ID"),
client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
)
actions = scalekit_client.actions
# Connect the user's Gmail account, and wait until it's ACTIVE before calling tools
connection_name = "gmail"
identifier = "user_123" # your app's unique user ID
response = actions.get_or_create_connected_account(
connection_name=connection_name, identifier=identifier
)
if response.connected_account.status != "ACTIVE":
link = actions.get_authorization_link(
connection_name=connection_name, identifier=identifier
)
print("Authorize Gmail:", link.link)
input("Press Enter after authorizing...")
# Fetch the account again to pick up the new status
response = actions.get_or_create_connected_account(
connection_name=connection_name, identifier=identifier
)
if response.connected_account.status != "ACTIVE":
raise RuntimeError(
f"Gmail is {response.connected_account.status}, not ACTIVE. Authorize it and run again."
)

See Authorize a user for production auth handling.

actions.google.get_tools() returns native ADK tool objects. Pass them directly to a Google ADK Agent:

from google.adk.agents import Agent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
tools = actions.google.get_tools(
identifier="user_123",
connection_names=["gmail"],
page_size=100, # avoid missing tools when a connector has more than the default page
)
agent = Agent(
name="gmail_assistant",
model="gemini-2.0-flash",
instruction="You are a helpful Gmail assistant.",
tools=tools,
)
async def main():
session_service = InMemorySessionService()
runner = Runner(agent=agent, app_name="gmail_app", session_service=session_service)
session = await session_service.create_session(app_name="gmail_app", user_id="user_123")
message = types.Content(
role="user",
parts=[types.Part(text="Fetch my last 5 unread emails and summarize them")],
)
async for event in runner.run_async(
user_id="user_123",
session_id=session.id,
new_message=message,
):
if event.is_final_response() and event.content and event.content.parts:
print(event.content.parts[0].text)
asyncio.run(main())

Google ADK connects to MCP servers with McpToolset. Pass the Virtual MCP Server URL and a session token for this user:

import os
from datetime import timedelta
from google.adk.agents import Agent
from google.adk.tools.mcp_tool import McpToolset, StreamableHTTPConnectionParams
# Returned by create_config when you created the Virtual MCP Server (see Set up and connect)
config_id = os.environ["SCALEKIT_MCP_CONFIG_ID"]
mcp_url = os.environ["SCALEKIT_MCP_SERVER_URL"]
# Mint a fresh session token for this user before each agent run
mcp_token = actions.mcp.create_session_token(
mcp_config_id=config_id,
identifier="user_123",
expiry=timedelta(hours=1),
).token
agent = Agent(
name="gmail_assistant",
model="gemini-2.0-flash",
instruction="You are a helpful Gmail assistant.",
tools=[
McpToolset(
connection_params=StreamableHTTPConnectionParams(
url=mcp_url,
headers={"Authorization": f"Bearer {mcp_token}"},
)
)
],
)

Run this agent with the same Runner loop as above. See Set up and connect to create the server and check that the user’s connections are active before you mint a token.