{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install google-adk nltk google-generativeai\nprint(\"✅ All libraries installed successfully!\")","metadata":{"_uuid":"a567696f-9567-4b52-b689-26ace9449319","_cell_guid":"e50a3856-e14b-4d49-a8ef-4af3c6444fab","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-12-04T06:40:07.184220Z","iopub.execute_input":"2025-12-04T06:40:07.184625Z","iopub.status.idle":"2025-12-04T06:40:15.670360Z","shell.execute_reply.started":"2025-12-04T06:40:07.184595Z","shell.execute_reply":"2025-12-04T06:40:15.668869Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nfrom kaggle_secrets import UserSecretsClient\nimport nltk\nfrom nltk.tokenize import sent_tokenize\nfrom google.adk.tools import AgentTool, ToolContext, load_memory\nfrom google.adk.models.google_llm import Gemini\nfrom google.genai import types\nfrom google.adk.agents import Agent, SequentialAgent\nfrom google.adk.runners import InMemoryRunner\nfrom google.adk.tools import google_search\n\nprint(\"✅ ADK components imported successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:40:15.672546Z","iopub.execute_input":"2025-12-04T06:40:15.672856Z","iopub.status.idle":"2025-12-04T06:41:20.026344Z","shell.execute_reply.started":"2025-12-04T06:40:15.672826Z","shell.execute_reply":"2025-12-04T06:41:20.024328Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"try:\n    GOOGLE_API_KEY = UserSecretsClient().get_secret(\"GOOGLE_API_KEY\")\n    os.environ[\"GOOGLE_API_KEY\"] = GOOGLE_API_KEY\n    print(\"✅ Gemini API key setup complete.\")\nexcept Exception as e:\n    print(\n        f\"🔑 Authentication Error: Please make sure you have added 'GOOGLE_API_KEY' to your Kaggle secrets. Details: {e}\"\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:41:20.027600Z","iopub.execute_input":"2025-12-04T06:41:20.029310Z","iopub.status.idle":"2025-12-04T06:41:20.175069Z","shell.execute_reply.started":"2025-12-04T06:41:20.029276Z","shell.execute_reply":"2025-12-04T06:41:20.174142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from IPython.core.display import display, HTML\nfrom jupyter_server.serverapp import list_running_servers\ndef get_adk_proxy_url():\n    PROXY_HOST = \"https://kkb-production.jupyter-proxy.kaggle.net\"\n    ADK_PORT = \"8000\"\n\n    servers = list(list_running_servers())\n    if not servers:\n        raise Exception(\"No running Jupyter servers found.\")\n\n    baseURL = servers[0][\"base_url\"]\n\n    try:\n        path_parts = baseURL.split(\"/\")\n        kernel = path_parts[2]\n        token = path_parts[3]\n    except IndexError:\n        raise Exception(f\"Could not parse kernel/token from base URL: {baseURL}\")\n\n    url_prefix = f\"/k/{kernel}/{token}/proxy/proxy/{ADK_PORT}\"\n    url = f\"{PROXY_HOST}{url_prefix}\"\n\n    styled_html = f\"\"\"\n    <div style=\"padding: 15px; border: 2px solid #f0ad4e; border-radius: 8px; background-color: #fef9f0; margin: 20px 0;\">\n        <div style=\"font-family: sans-serif; margin-bottom: 12px; color: #333; font-size: 1.1em;\">\n            <strong>⚠️ IMPORTANT: Action Required</strong>\n        </div>\n        <div style=\"font-family: sans-serif; margin-bottom: 15px; color: #333; line-height: 1.5;\">\n            The ADK web UI is <strong>not running yet</strong>. You must start it in the next cell.\n            <ol style=\"margin-top: 10px; padding-left: 20px;\">\n                <li style=\"margin-bottom: 5px;\"><strong>Run the next cell</strong> (the one with <code>!adk web ...</code>) to start the ADK web UI.</li>\n                <li style=\"margin-bottom: 5px;\">Wait for that cell to show it is \"Running\" (it will not \"complete\").</li>\n                <li>Once it's running, <strong>return to this button</strong> and click it to open the UI.</li>\n            </ol>\n            <em style=\"font-size: 0.9em; color: #555;\">(If you click the button before running the next cell, you will get a 500 error.)</em>\n        </div>\n        <a href='{url}' target='_blank' style=\"\n            display: inline-block; background-color: #1a73e8; color: white; padding: 10px 20px;\n            text-decoration: none; border-radius: 25px; font-family: sans-serif; font-weight: 500;\n            box-shadow: 0 2px 5px rgba(0,0,0,0.2); transition: all 0.2s ease;\">\n            Open ADK Web UI (after running cell below) ↗\n        </a>\n    </div>\n    \"\"\"\n\n    display(HTML(styled_html))\n\n    return url_prefix\n\n\nprint(\"✅ Helper functions defined.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:41:20.177577Z","iopub.execute_input":"2025-12-04T06:41:20.177881Z","iopub.status.idle":"2025-12-04T06:41:20.389985Z","shell.execute_reply.started":"2025-12-04T06:41:20.177856Z","shell.execute_reply":"2025-12-04T06:41:20.388907Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"retry_config = types.HttpRetryOptions(\n    attempts=5,  # Maximum retry attempts\n    exp_base=7,  # Delay multiplier\n    initial_delay=1,  # Initial delay before first retry (in seconds)\n    http_status_codes=[429, 500, 503, 504]  # Retry on these HTTP errors\n)\n\n\nasync def auto_save_to_memory(callback_context):\n    \"\"\"Automatically persists session data to long-term memory.\"\"\"\n    if hasattr(callback_context._invocation_context, 'memory_service'):\n        await callback_context._invocation_context.memory_service.add_session_to_memory(\n            callback_context._invocation_context.session\n        )\n\n\n# Tool to save user preferences into Session State\ndef set_user_context(tool_context: ToolContext, role: str, focus_area: str):\n    \"\"\"\n    Saves the user's role and focus area to the current session state.\n    Use this when the user introduces themselves (e.g., \"I am a Product Manager\").\n    \"\"\"\n    tool_context.state[\"user:role\"] = role\n    tool_context.state[\"user:focus\"] = focus_area\n    return f\"Context saved: Role={role}, Focus={focus_area}\"\n\n\nprint(\"✅ Retry config and callbacks defined.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:41:20.391270Z","iopub.execute_input":"2025-12-04T06:41:20.391896Z","iopub.status.idle":"2025-12-04T06:41:20.402074Z","shell.execute_reply.started":"2025-12-04T06:41:20.391867Z","shell.execute_reply":"2025-12-04T06:41:20.400569Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- FALLBACK TOOLS ---\ndef offline_meeting_fallback(text: str):\n    sentences = sent_tokenize(text)\n    actions = [s for s in sentences if any(w in s.lower() for w in ['todo', 'action', 'deadline'])]\n    return f\"[OFFLINE FALLBACK] Actions detected: {len(actions)}\"\n\n\ndef offline_research_fallback(text: str):\n    sentences = sent_tokenize(text)\n    tldr = sentences[0] if sentences else \"No text\"\n    return f\"[OFFLINE FALLBACK] TL;DR: {tldr}\"\n\n\nprint(\"✅ Fallback tools defined.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:41:20.404026Z","iopub.execute_input":"2025-12-04T06:41:20.404574Z","iopub.status.idle":"2025-12-04T06:41:20.437462Z","shell.execute_reply.started":"2025-12-04T06:41:20.404531Z","shell.execute_reply":"2025-12-04T06:41:20.436213Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = Gemini(model=\"gemini-2.5-flash-lite\", retry_options=retry_config)\n\nprint(\"✅ Model initialized.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:41:20.438683Z","iopub.execute_input":"2025-12-04T06:41:20.439013Z","iopub.status.idle":"2025-12-04T06:41:20.458537Z","shell.execute_reply.started":"2025-12-04T06:41:20.438989Z","shell.execute_reply":"2025-12-04T06:41:20.456978Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# [A] Meeting Agent\nmeeting_agent = Agent(\n    name=\"MeetingPrepAgent\",\n    model=model,\n    instruction=\"Analyze the transcript. Output: Pre-Brief, Agenda, and Action Items.\",\n    tools=[offline_meeting_fallback]\n)\n\nprint(\"✅ Meeting Agent defined.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:41:20.459693Z","iopub.execute_input":"2025-12-04T06:41:20.460034Z","iopub.status.idle":"2025-12-04T06:41:20.482918Z","shell.execute_reply.started":"2025-12-04T06:41:20.460001Z","shell.execute_reply":"2025-12-04T06:41:20.481749Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# [B] Research Pipeline\nextractor = Agent(\n    name=\"FactExtractor\",\n    model=model,\n    instruction=\"Extract Top 5 Key Findings and Sources from the provided content.\",\n    output_key=\"facts\"\n)\n\nwriter = Agent(\n    name=\"BriefWriter\",\n    model=model,\n    instruction=\"Using the previous agent's extracted findings, write a Decision-Ready Brief with TL;DR, Findings, and Next Steps.\",\n)\n\nresearch_pipeline = SequentialAgent(\n    name=\"ResearchSummaryAgent\",\n    sub_agents=[extractor, writer]\n)\n\nprint(\"✅ Research Pipeline defined.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:41:20.484078Z","iopub.execute_input":"2025-12-04T06:41:20.484540Z","iopub.status.idle":"2025-12-04T06:41:20.508313Z","shell.execute_reply.started":"2025-12-04T06:41:20.484508Z","shell.execute_reply":"2025-12-04T06:41:20.507249Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Web Searching pipeline\nsearch_web = Agent(\n    name=\"SearchingAgent\",\n    model=model,\n    instruction=\"General -> Answer directly using Google Search if needed to weather, current time, real world related question.\",\n    tools=[google_search]\n)\n\nprint(\"✅ Searching Agent defined.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:41:20.512148Z","iopub.execute_input":"2025-12-04T06:41:20.512564Z","iopub.status.idle":"2025-12-04T06:41:20.544252Z","shell.execute_reply.started":"2025-12-04T06:41:20.512538Z","shell.execute_reply":"2025-12-04T06:41:20.542906Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# [C] Orchestrator (Router with Memory)\nroot_agent = Agent(\n    name=\"AgentAssist_Orchestrator\",\n    model=model,\n    instruction=\"\"\"You are the AgentAssist Orchestrator.\n    \n    1. CHECK CONTEXT: Use 'load_memory' to see if you know the user's preferences.\n    2. SAVE CONTEXT: If the user states their role/job, use 'set_user_context'.\n    3. ROUTE:\n       - Meeting notes -> 'MeetingPrepAgent'\n       - Documents -> 'ResearchSummaryAgent'\n       - General -> Answer directly using Google Search if needed to weather, current time, real world related question\n    \"\"\",\n    tools=[AgentTool(meeting_agent), AgentTool(research_pipeline), AgentTool(search_web), load_memory, set_user_context],\n    after_agent_callback=auto_save_to_memory  # Enables auto-memory storage\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:43:33.896163Z","iopub.execute_input":"2025-12-04T06:43:33.896580Z","iopub.status.idle":"2025-12-04T06:43:33.902034Z","shell.execute_reply.started":"2025-12-04T06:43:33.896555Z","shell.execute_reply":"2025-12-04T06:43:33.901182Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"runner = InMemoryRunner(agent=root_agent)\n\nprint(\"✅ Runner created.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:43:37.779075Z","iopub.execute_input":"2025-12-04T06:43:37.780035Z","iopub.status.idle":"2025-12-04T06:43:37.786126Z","shell.execute_reply.started":"2025-12-04T06:43:37.780002Z","shell.execute_reply":"2025-12-04T06:43:37.784913Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Test query\nresponse = await runner.run_debug(\n    \"What is Agent Development Kit from Google? What languages is the SDK available in?\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:43:41.426454Z","iopub.execute_input":"2025-12-04T06:43:41.426796Z","iopub.status.idle":"2025-12-04T06:43:45.536652Z","shell.execute_reply.started":"2025-12-04T06:43:41.426771Z","shell.execute_reply":"2025-12-04T06:43:45.535633Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!adk create Ai-agent --model gemini-2.5-flash-lite --api_key $GOOGLE_API_KEY","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:48:51.398423Z","iopub.execute_input":"2025-12-04T06:48:51.398800Z","iopub.status.idle":"2025-12-04T06:49:20.909459Z","shell.execute_reply.started":"2025-12-04T06:48:51.398776Z","shell.execute_reply":"2025-12-04T06:49:20.908227Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"url_prefix = get_adk_proxy_url()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:49:20.911360Z","iopub.execute_input":"2025-12-04T06:49:20.911731Z","iopub.status.idle":"2025-12-04T06:49:20.922001Z","shell.execute_reply.started":"2025-12-04T06:49:20.911702Z","shell.execute_reply":"2025-12-04T06:49:20.921031Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!adk web --url_prefix {url_prefix}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T06:49:20.923071Z","iopub.execute_input":"2025-12-04T06:49:20.923492Z","iopub.status.idle":"2025-12-04T06:58:22.394444Z","shell.execute_reply.started":"2025-12-04T06:49:20.923454Z","shell.execute_reply":"2025-12-04T06:58:22.393102Z"}},"outputs":[],"execution_count":null}]}