From 6a90f3fb52cd683a6972ff883e3b8682f34a45cc Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Wed, 4 Feb 2026 13:41:08 +0530 Subject: [PATCH] add adk samples --- .../pre_post_processing/python/adk/agent.py | 124 ++++++++++++++++++ .../python/adk/requirements.txt | 2 + 2 files changed, 126 insertions(+) create mode 100644 docs/en/samples/pre_post_processing/python/adk/agent.py create mode 100644 docs/en/samples/pre_post_processing/python/adk/requirements.txt diff --git a/docs/en/samples/pre_post_processing/python/adk/agent.py b/docs/en/samples/pre_post_processing/python/adk/agent.py new file mode 100644 index 0000000000..7977c1f3c6 --- /dev/null +++ b/docs/en/samples/pre_post_processing/python/adk/agent.py @@ -0,0 +1,124 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import asyncio +from datetime import datetime +from typing import Any, Dict, Optional, Awaitable + +from google.adk import Agent +from google.adk.apps import App +from google.adk.agents import InvocationContext +from toolbox_adk import ToolboxToolset, CredentialStrategy + +system_prompt = """ + You're a helpful hotel assistant. You handle hotel searching, booking and + cancellations. When the user searches for a hotel, mention it's name, id, + location and price tier. Always mention hotel ids while performing any + searches. This is very important for any operations. For any bookings or + cancellations, please provide the appropriate confirmation. Be sure to + update checkin or checkout dates if mentioned by the user. + Don't ask for confirmations from the user. +""" + +async def before_tool_callback(context: Any, args: Dict[str, Any]): + """ + Callback fired before a tool is executed. + Enforces business logic: Max stay duration is 14 days. + """ + tool_name = getattr(context, "name", "unknown_tool") + + print(f"POLICY CHECK: Intercepting '{tool_name}'") + if tool_name == "update-hotel" or ("checkin_date" in args and "checkout_date" in args): + try: + start = datetime.fromisoformat(args["checkin_date"]) + end = datetime.fromisoformat(args["checkout_date"]) + duration = (end - start).days + + if duration > 14: + print("BLOCKED: Stay too long") + raise ValueError("Error: Maximum stay duration is 14 days.") + except ValueError as e: + if "Maximum stay duration" in str(e): + raise + pass + + return args + +async def after_tool_callback(context: Any, args: Dict[str, Any], result: Any, error: Optional[Exception]) -> Awaitable[Any]: + """ + Callback fired after a tool execution. + Enriches response for successful bookings. + """ + tool_name = getattr(context, "name", "unknown_tool") + + if error: + print(f"[Tool-Level] after_tool_callback: Tool '{tool_name}' failed with error: {error}") + return None + if isinstance(result, str) and "Error" not in result: + is_booking = tool_name == "book-hotel" or "booking" in str(result).lower() or "confirmed" in str(result).lower() + + if is_booking: + loyalty_bonus = 500 + return f"Booking Confirmed!\n You earned {loyalty_bonus} Loyalty Points with this stay.\n\nSystem Details: {result}" + return result + +async def main(): + print("🚀 Initializing ADK Agent with Toolbox...") + + toolset = ToolboxToolset( + server_url="http://127.0.0.1:5000", + toolset_name="my-toolset", + credentials=CredentialStrategy.toolbox_identity(), + pre_hook=before_tool_callback, + post_hook=after_tool_callback + ) + + root_agent = Agent( + name='root_agent', + model='gemini-2.5-flash', + instruction=system_prompt, + tools=[toolset], + ) + + app = App(root_agent=root_agent, name="my_agent") + user_input = "Book hotel with id 3." + print(f"\nUSER: '{user_input}'") + + # Note: run_async expects an InvocationContext and returns an async generator + context = InvocationContext(text=user_input) + response_text = "" + async for chunk in root_agent.run_async(context): + # Accumulate text from chunks + text_chunk = getattr(chunk, 'text', str(chunk)) + if text_chunk: + response_text += text_chunk + + print(f"AI: {response_text}") + + # Test Pre-processing + print("-" * 50) + user_input_2 = "Update my hotel with id 3 with checkin date 2025-01-18 and checkout date 2025-02-10" # > 14 days + print(f"USER: '{user_input_2}'") + + context_2 = InvocationContext(text=user_input_2) + response_text = "" + async for chunk in root_agent.run_async(context_2): + text_chunk = getattr(chunk, 'text', str(chunk)) + if text_chunk: + response_text += text_chunk + + print(f"AI: {response_text}") + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/docs/en/samples/pre_post_processing/python/adk/requirements.txt b/docs/en/samples/pre_post_processing/python/adk/requirements.txt new file mode 100644 index 0000000000..b67361ecfd --- /dev/null +++ b/docs/en/samples/pre_post_processing/python/adk/requirements.txt @@ -0,0 +1,2 @@ +google-adk[toolbox]==1.23.0 +pytest==9.0.2 \ No newline at end of file