
For developers seasoned in the Google Workspace ecosystem, the promise of agentic AI is not just about automating tasks, but about creating intelligent, nuanced interactions with the services we know so well. Google’s Agent Development Kit (ADK) provides the foundation, but integrating the familiar, user-centric OAuth 2.0 flow into this new world requires a deliberate architectural approach.
This article explores the patterns for building a sophisticated, multi-capability agent. It explores why you might choose a custom tool implementation (ADK’s “Journey 2”) over auto-generation, and presents a reusable authentication pattern that you can apply to any Workspace API.
The full source code for this project is available in the companion GitHub repository. It’s designed as a high-fidelity local workbench, perfect for development, debugging, and rapid iteration.
The Architectural Crossroads: Journey 1 vs. Journey 2
When integrating a REST API with the ADK, you face a choice, as detailed in the official ADK authentication documentation:
- Journey 1: The “Auto-Toolify” Approach. This involves using components like
OpenAPIToolsetor the pre-builtGoogleApiToolSetsets. You provide an API specification, and the ADK instantly generates tools for the entire API surface. This is incredibly fast for prototyping but can lead to an agent that is “noisy” (has too many tools and scopes) and lacks the robustness to handle API-specific complexities like pagination. - Journey 2: The “Crafted Tool” Approach. This involves using
FunctionToolto wrap your own Python functions. This is the path taken in this project. It requires more initial effort but yields a far superior agent for several reasons:- Control: This approach exposes only the high-level capabilities needed (e.g.,
search_all_chat_spaces), not every raw API endpoint. - Robustness: Logic can be built directly into the tools to handle real-world challenges like pagination, abstracting this complexity away from the LLM.
- Efficiency: The tool can pre-process data from the API, returning a concise summary to the LLM and preserving its valuable context window.
- Control: This approach exposes only the high-level capabilities needed (e.g.,
Journey 2 was chosen because the goal is not just to call an API, but to provide the agent with a reliable, intelligent capability.
The Core Implementation: A Reusable Pattern
The cornerstone of this integration is a single, centralised function: get_credentials. This function lives in agent.py and is called by every tool that needs to access a protected resource.
It elegantly manages the entire lifecycle of an OAuth token within the ADK session by following a clear, four-step process:
- Check Cache: It first looks in the session state (
tool_context.state) for a valid, cached token. - Refresh: If a token exists but is expired, it uses the refresh token to get a new one and updates the cache.
- Check for Auth Response: If no token is found, it checks if the user has just completed the OAuth consent flow using
tool_context.get_auth_response(). - Request Credentials: If all else fails, it formally requests credentials via
tool_context.request_credential(), which signals the ADK runtime to pause and trigger the interactive user flow.
This pattern is completely generic. You can see in the agent.py file how, by simply changing the SCOPES constant, you could reuse this exact function for Google Drive, Calendar, Sheets, or any other Workspace API.
Defining the Agent and Tools
With the authentication pattern defined, building the agent becomes a matter of composition. The agent.py file also defines the “Orchestrator/Worker” structure—a best practice that uses a fast, cheap model (gemini-2.5-flash) for routing and a more powerful, specialised model (gemini-2.5-pro) for analysis.
The Other Half: The Client-Side Auth Flow
The get_credentials function is only half the story. When it calls tool_context.request_credential(), it signals to the runtime that it needs user authentication. The cli.py script acts as that runtime, or “Agent Client.”
The cli.py script is responsible for the user-facing interaction. As you can see in the handle_agent_run function within cli.py, the script’s main loop does two key things:
- It iterates through agent events and uses a helper to check for the specific
adk_request_credentialfunction call. - When it detects this request, it pauses, prints the authorisation URL for the user, and waits to receive the callback URL.
- It then bundles this callback URL into a
FunctionResponseand sends it back to the agent, which can then resume the tool call, this time successfully.
This client-side loop is the essential counterpart to the get_credentials pattern.
Production Considerations: Moving Beyond the Workbench
This entire setup is designed as a high-fidelity local workbench. Before moving to a production environment, several changes are necessary:
- Persistent Sessions: The
InMemorySessionServiceis ephemeral. For production, you must switch to a persistent service likeDatabaseSessionService(backed by a database like PostgreSQL) orVertexAiSessionService. This is critical for remembering conversation history and, most importantly, for securely storing the user’s OAuth tokens. - Secure Credential Storage: While caching tokens in the session state is acceptable for local testing, production systems should encrypt the token data in the database or use a dedicated secret manager.
- Runtime Environment: The
cli.pywould be replaced by a web server framework (like FastAPI or Flask) if you are deploying this as a web application, or adapted to the specific requirements of a platform like Vertex AI Agent Engine.
By building with this modular, Journey 2 approach, you create agents that are not only more capable and robust but are also well-architected for the transition from local development to a production-grade deployment.
Explore the Code
Explore the full source code in the GitHub repository to see these concepts in action. The README.md file provides all the necessary steps to get the agent up and running on your local machine. By combining the conceptual overview in this article with the hands-on code, you’ll be well-equipped to build your own robust, production-ready agents with the Google ADK.









