diff --git a/README.md b/README.md index 0439d6e..b3ae224 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ A curated collection of **Awesome LLM apps built with RAG, AI Agents, Multi-agen * [๐ŸŽจ AI Game Design Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/ai_game_design_agent_team/) * [๐Ÿ‘จโ€โš–๏ธ AI Legal Agent Team (Cloud & Local)](advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/) * [๐Ÿ’ผ AI Recruitment Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/ai_recruitment_agent_team/) +* [๐Ÿ  AI Real Estate Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/ai_real_estate_agent_team) * [๐Ÿ‘จโ€๐Ÿ’ผ AI Services Agency (CrewAI)](advanced_ai_agents/multi_agent_apps/agent_teams/ai_services_agency/) * [๐Ÿ‘จโ€๐Ÿซ AI Teaching Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/ai_teaching_agent_team/) * [๐Ÿ’ป Multimodal Coding Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_coding_agent_team/) diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/creative_writing_agent/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/creative_writing_agent/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/creative_writing_agent/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/creative_writing_agent/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/creative_writing_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/creative_writing_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/creative_writing_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/creative_writing_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/creative_writing_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/creative_writing_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/creative_writing_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/creative_writing_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/requirements.txt similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/1_starter_agent/requirements.txt rename to ai_agent_framework_crash_course/google_adk_crash_course/1_starter_agent/requirements.txt diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_1_openai_adk_agent/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_1_openai_adk_agent/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_1_openai_adk_agent/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_1_openai_adk_agent/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_1_openai_adk_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_1_openai_adk_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_1_openai_adk_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_1_openai_adk_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_1_openai_adk_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_1_openai_adk_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_1_openai_adk_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_1_openai_adk_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_2_anthropic_adk_agent/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_2_anthropic_adk_agent/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_2_anthropic_adk_agent/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_2_anthropic_adk_agent/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_2_anthropic_adk_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_2_anthropic_adk_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_2_anthropic_adk_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_2_anthropic_adk_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_2_anthropic_adk_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_2_anthropic_adk_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/2_2_anthropic_adk_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/2_2_anthropic_adk_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/requirements.txt similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/2_model_agnostic_agent/requirements.txt rename to ai_agent_framework_crash_course/google_adk_crash_course/2_model_agnostic_agent/requirements.txt diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/customer_support_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/requirements.txt similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_1_customer_support_ticket_agent/requirements.txt rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_1_customer_support_ticket_agent/requirements.txt diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/email_generator_agent/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/email_generator_agent/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/email_generator_agent/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/email_generator_agent/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/email_generator_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/email_generator_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/email_generator_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/email_generator_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/email_generator_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/email_generator_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/email_generator_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/email_generator_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/requirements.txt similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/3_2_email_agent/requirements.txt rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/3_2_email_agent/requirements.txt diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/3_structured_output_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/3_structured_output_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/code_exec_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/code_exec_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/code_exec_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/code_exec_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/code_exec_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/code_exec_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/code_exec_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/code_exec_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/requirements.txt similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/requirements.txt rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/requirements.txt diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/search_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/search_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/search_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/search_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/search_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/search_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_1_builtin_tools/search_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_1_builtin_tools/search_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/calculator_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/calculator_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/calculator_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/calculator_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/calculator_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/calculator_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/calculator_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/calculator_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/calculator_agent/tools.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/calculator_agent/tools.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/calculator_agent/tools.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/calculator_agent/tools.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/requirements.txt similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/requirements.txt rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/requirements.txt diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/utility_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/utility_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/utility_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/utility_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/utility_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/utility_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/utility_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/utility_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/utility_agent/tools.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/utility_agent/tools.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_2_function_tools/utility_agent/tools.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_2_function_tools/utility_agent/tools.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/crewai_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/crewai_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/crewai_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/crewai_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/crewai_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/crewai_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/crewai_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/crewai_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/langchain_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/langchain_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/langchain_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/langchain_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/langchain_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/langchain_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/langchain_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/langchain_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/requirements.txt similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_3_thirdparty_tools/requirements.txt rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_3_thirdparty_tools/requirements.txt diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/filesystem_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/__init__.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/__init__.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/__init__.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/__init__.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/firecrawl_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/requirements.txt similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/4_4_mcp_tools/requirements.txt rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/4_4_mcp_tools/requirements.txt diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/4_tool_using_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/4_tool_using_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/app.py b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/app.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/app.py rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/app.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/requirements.txt similarity index 72% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/requirements.txt rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/requirements.txt index 0a14da2..2debdf7 100644 --- a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_1_in_memory_conversation_agent/requirements.txt +++ b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_1_in_memory_conversation_agent/requirements.txt @@ -1,4 +1,4 @@ -google-adk==1.9.0 +google-adk>=1.9.0 streamlit>=1.47.1 python-dotenv>=1.1.1 asyncio \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/.env.example similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/.env.example rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/.env.example diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/agent.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/agent.py rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/agent.py diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/app.py b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/app.py similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/app.py rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/app.py diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/requirements.txt new file mode 100644 index 0000000..b4f2fb1 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/5_2_persistent_conversation_agent/requirements.txt @@ -0,0 +1,5 @@ +google-adk>=1.9.0 +streamlit>=1.47.1 +python-dotenv>=1.1.1 +sqlalchemy>=2.0.0 +asyncio \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/README.md similarity index 100% rename from ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/5_memory_agent/README.md diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/.env.example new file mode 100644 index 0000000..f5cfcfb --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/.env.example @@ -0,0 +1,3 @@ +# If using Gemini via Google AI Studio +GOOGLE_GENAI_USE_VERTEXAI=False +GOOGLE_API_KEY="your-api-key" \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/README.md new file mode 100644 index 0000000..d8cda71 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/README.md @@ -0,0 +1,233 @@ +# 6.1 Agent Lifecycle Callbacks + +This tutorial demonstrates how to use `before_agent_callback` and `after_agent_callback` to monitor agent execution lifecycle. + +## ๐ŸŽฏ Learning Objectives + +- Understand agent lifecycle callbacks +- Learn how to monitor agent execution timing +- See how to share state between callbacks +- Practice implementing performance monitoring + +## ๐Ÿ“ Project Structure + +``` +6_1_agent_lifecycle_callbacks/ +โ”œโ”€โ”€ agent.py # Agent with lifecycle callbacks +โ”œโ”€โ”€ app.py # Streamlit web interface +โ”œโ”€โ”€ requirements.txt # Python dependencies +โ””โ”€โ”€ README.md # This file +``` + +## ๐Ÿ”ง Setup + +1. **Install dependencies:** + ```bash + pip install -r requirements.txt + ``` + +2. **Set up API key:** + ```bash + # Create .env file + echo "GOOGLE_API_KEY=your_api_key_here" > .env + ``` + +## ๐Ÿš€ Running the Demo + +### Command Line Demo +```bash +python agent.py +``` + +### Web Interface +```bash +streamlit run app.py +``` + +## ๐Ÿง  Core Concept: Agent Lifecycle Monitoring + +Agent lifecycle callbacks allow you to monitor the beginning and end of agent execution, providing visibility into when agents start and complete their tasks. + +### **Agent Lifecycle Flow** + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ User Input โ”‚โ”€โ”€โ”€โ–ถโ”‚ Agent Start โ”‚โ”€โ”€โ”€โ–ถโ”‚ Agent End โ”‚ +โ”‚ โ”‚ โ”‚ Callback โ”‚ โ”‚ Callback โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ โ”‚ + โ–ผ โ–ผ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ Agent Logic โ”‚ โ”‚ Performance โ”‚ + โ”‚ Execution โ”‚ โ”‚ Metrics โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### **Callback Execution Timeline** + +``` +Timeline: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ + +User Message + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ before_agent โ”‚ โ† Records start time, agent info +โ”‚ _callback โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Agent Logic โ”‚ โ† Core agent processing +โ”‚ Execution โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ after_agent โ”‚ โ† Calculates duration, logs completion +โ”‚ _callback โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ–ผ +Response to User +``` + +## ๐Ÿ“– Code Walkthrough + +### **1. Callback Functions** + +The callbacks work in pairs to monitor the complete agent lifecycle: + +**Before Callback (`before_agent_callback`):** +- Records execution start timestamp +- Stores start time in session state for after callback +- Logs agent execution start (agent name, time) +- Returns `None` to allow normal execution + +**After Callback (`after_agent_callback`):** +- Retrieves start time from session state +- Calculates total execution duration +- Logs completion with performance metrics +- Returns `None` to use original result + +### **2. State Management Between Callbacks** + +``` +Session State Flow: +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ before_callback โ”‚โ”€โ”€โ”€โ–ถโ”‚ Session State โ”‚โ”€โ”€โ”€โ–ถโ”‚ after_callback โ”‚ +โ”‚ stores: โ”‚ โ”‚ โ”‚ โ”‚ retrieves: โ”‚ +โ”‚ - start_time โ”‚ โ”‚ - request_start โ”‚ โ”‚ - start_time โ”‚ +โ”‚ โ”‚ โ”‚ _time โ”‚ โ”‚ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### **3. Agent Setup** + +The agent is configured with both lifecycle callbacks: +- `before_agent_callback`: Monitors agent execution start +- `after_agent_callback`: Monitors agent execution completion +- Uses `InMemoryRunner` for proper callback triggering + +## ๐Ÿงช Testing Examples + +### **Example Output Format** + +``` +๐Ÿš€ Agent LifecycleDemoAgent started at 19:15:30 +โฐ Start time: 2024-01-15 19:15:30 + +โœ… Agent LifecycleDemoAgent completed +โฑ๏ธ Duration: 1.23s +โฐ End time: 2024-01-15 19:15:31 +๐Ÿ“Š Performance: 1.23s | LifecycleDemoAgent + +``` + +### **What Each Metric Tells You** + +- **๐Ÿš€ Start time**: When the agent began processing +- **โœ… Completion time**: When the agent finished processing +- **โฑ๏ธ Duration**: Total execution time in seconds +- **๐Ÿ“Š Performance**: Formatted performance summary + +## ๐Ÿ” Key Concepts + +### **Agent Lifecycle Monitoring** +- **Execution Start**: Track when agents begin processing +- **Execution End**: Track when agents complete their tasks +- **Performance Timing**: Calculate total execution duration +- **State Sharing**: Pass timing data between callbacks + +### **CallbackContext** +- **agent_name**: Name of the agent being executed +- **invocation_id**: Unique identifier for this execution +- **state**: Session state that persists between callbacks + +### **State Management** +- Use `callback_context.state.to_dict()` to get current state +- Use `callback_context.state.update()` to modify state +- State is shared between before and after callbacks + +## ๐ŸŽฏ Use Cases + +- **Performance Monitoring**: Track execution times +- **Logging**: Record agent activities +- **Analytics**: Collect usage statistics +- **Debugging**: Monitor agent behavior +- **Custom Logic**: Add pre/post processing + +## ๐Ÿšจ Common Mistakes + +1. **Forgetting to await session creation:** + ```python + # โŒ Wrong + session_service.create_session(...) + + # โœ… Correct + await session_service.create_session(...) + ``` + +2. **Using wrong callback signature:** + ```python + # โŒ Wrong + def after_agent_callback(context, result): + + # โœ… Correct + def after_agent_callback(callback_context: CallbackContext): + ``` + +3. **Not using InMemoryRunner:** + ```python + # โŒ Wrong - callbacks won't trigger + agent.run(message) + + # โœ… Correct + runner.run_async(...) + ``` + +## โš ๏ธ Critical Implementation Note + +**Event Loop Completion**: The `after_agent_callback` will not trigger if you break the event loop immediately upon receiving `is_final_response()`. + +**Correct Pattern**: Allow the event loop to complete naturally: +```python +# โŒ Wrong - breaks loop early, after_agent_callback won't run +if event.is_final_response() and event.content: + response_text = event.content.parts[0].text.strip() + break # This prevents after_agent_callback from running + +# โœ… Correct - let loop complete naturally +if event.is_final_response() and event.content: + response_text = event.content.parts[0].text.strip() + # Don't break - let the loop complete to ensure callbacks run +``` + +This is a known ADK behavior where breaking the loop early prevents cleanup callbacks from executing. + +## ๐Ÿ”— Next Steps + +- Try Tutorial 6.2: LLM Interaction Callbacks +- Experiment with state management between callbacks +- Add custom logging or analytics +- Implement performance alerts for slow responses \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/agent.py new file mode 100644 index 0000000..fee9d2a --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/agent.py @@ -0,0 +1,122 @@ +import os +import asyncio +from datetime import datetime +from typing import Optional +from google.adk.agents import LlmAgent +from google.adk.agents.callback_context import CallbackContext +from google.adk.runners import InMemoryRunner +from google.genai import types +from dotenv import load_dotenv + +# Load environment variables +load_dotenv() + + +# --- 1. Define the Callback Functions --- +def before_agent_callback(callback_context: CallbackContext) -> Optional[types.Content]: + """Callback before agent execution starts""" + agent_name = callback_context.agent_name + start_time = datetime.now() + + print(f"๐Ÿš€ Agent {agent_name} started at {start_time.strftime('%H:%M:%S')}") + print(f"โฐ Start time: {start_time.strftime('%Y-%m-%d %H:%M:%S')}") + print() # Add spacing + + # Store start time in state for after callback + current_state = callback_context.state.to_dict() + current_state["start_time"] = start_time.isoformat() + callback_context.state.update(current_state) + + return None + +def after_agent_callback(callback_context: CallbackContext) -> Optional[types.Content]: + """Callback after agent execution completes""" + agent_name = callback_context.agent_name + current_state = callback_context.state.to_dict() + + # Get start time from state + start_time_str = current_state.get("start_time") + if start_time_str: + start_time = datetime.fromisoformat(start_time_str) + end_time = datetime.now() + duration = end_time - start_time + duration_seconds = duration.total_seconds() + + print(f"โœ… Agent {agent_name} completed") + print(f"โฑ๏ธ Duration: {duration_seconds:.2f}s") + print(f"โฐ End time: {end_time.strftime('%Y-%m-%d %H:%M:%S')}") + print(f"๐Ÿ“Š Performance: {duration_seconds:.2f}s | {agent_name}") + print() # Add spacing + + return None + +# --- 2. Setup Agent with Callbacks --- +llm_agent_with_callbacks = LlmAgent( + name="agent_lifecycle_demo_agent", + model="gemini-2.5-flash", + instruction="You are a helpful assistant. Respond to user questions clearly and concisely.", + description="An LLM agent demonstrating lifecycle callbacks for monitoring", + before_agent_callback=before_agent_callback, + after_agent_callback=after_agent_callback +) + +# --- 3. Setup Runner and Sessions --- +runner = InMemoryRunner(agent=llm_agent_with_callbacks, app_name="agent_lifecycle_callback_demo") + +async def run_agent(message: str) -> str: + """Run the agent with the given message""" + user_id = "demo_user" + session_id = "demo_session" + + # Get the bundled session service + session_service = runner.session_service + + # Get or create session + session = await session_service.get_session( + app_name="agent_lifecycle_callback_demo", + user_id=user_id, + session_id=session_id + ) + if not session: + session = await session_service.create_session( + app_name="agent_lifecycle_callback_demo", + user_id=user_id, + session_id=session_id, + state={"conversation_history": []} + ) + + # Create user content + user_content = types.Content( + role='user', + parts=[types.Part(text=message)] + ) + + # Run agent and get response + response_text = "" + async for event in runner.run_async( + user_id=user_id, + session_id=session_id, + new_message=user_content + ): + if event.is_final_response() and event.content: + response_text = event.content.parts[0].text.strip() + # Don't break here - let the loop complete naturally to ensure after_agent_callback runs + + return response_text + +# --- 4. Execute --- +if __name__ == "__main__": + print("\n" + "="*50 + " Agent Lifecycle Callbacks Demo " + "="*50) + + # Test messages + test_messages = [ + "Hello, how are you?" + ] + + async def test_agent(): + for i, message in enumerate(test_messages, 1): + print(f"\n--- Test {i}: {message} ---") + response = await run_agent(message) + print(f"๐Ÿค– Response: {response}") + + asyncio.run(test_agent()) \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/app.py b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/app.py new file mode 100644 index 0000000..98c2fcf --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/app.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python3 +""" +Streamlit App for Agent Lifecycle Callbacks Demo +""" + +import streamlit as st +import asyncio +from agent import llm_agent_with_callbacks, runner +from google.genai import types + +# Page configuration +st.set_page_config( + page_title="Agent Lifecycle Callbacks Demo", + page_icon="๐Ÿ”„", + layout="wide" +) + +# Title and description +st.title("๐Ÿ”„ Agent Lifecycle Callbacks Demo") +st.markdown(""" +This demo shows how to use `before_agent_callback` and `after_agent_callback` to monitor agent execution. +Watch the console output to see the callback timing information. +""") + +# Sidebar +with st.sidebar: + st.header("๐Ÿ“Š Callback Information") + st.markdown(""" + **Before Callback:** + - Records start time + - Logs agent execution start + + **After Callback:** + - Calculates execution duration + - Logs completion time + """) + + st.header("๐Ÿ”ง Technical Details") + st.markdown(""" + - Uses `InMemoryRunner` for session management + - Callbacks receive `CallbackContext` with agent info + - State is shared between callbacks via session + """) + +# Main chat interface +st.header("๐Ÿ’ฌ Chat with Agent") + +# Define the get_response function +async def get_response(prompt_text: str) -> str: + """Run agent with the given prompt""" + user_id = "demo_user" + session_id = "demo_session" + + # Get the bundled session service + session_service = runner.session_service + + # Get or create session + session = await session_service.get_session( + app_name="agent_lifecycle_callback_demo", + user_id=user_id, + session_id=session_id + ) + if not session: + session = await session_service.create_session( + app_name="agent_lifecycle_callback_demo", + user_id=user_id, + session_id=session_id + ) + + # Create user content + user_content = types.Content( + role='user', + parts=[types.Part(text=prompt_text)] + ) + + # Run agent and get response + response_text = "" + async for event in runner.run_async( + user_id=user_id, + session_id=session_id, + new_message=user_content + ): + if event.is_final_response() and event.content: + response_text = event.content.parts[0].text.strip() + # Don't break - let the loop complete to ensure callbacks run + + return response_text + +# Initialize chat history +if "messages" not in st.session_state: + st.session_state.messages = [] + +# Display chat messages +for message in st.session_state.messages: + with st.chat_message(message["role"]): + st.markdown(message["content"]) + +# Chat input +if prompt := st.chat_input("Ask me anything..."): + # Add user message to chat history + st.session_state.messages.append({"role": "user", "content": prompt}) + with st.chat_message("user"): + st.markdown(prompt) + + # Add assistant response to chat history + with st.chat_message("assistant"): + message_placeholder = st.empty() + + # Show loading message + message_placeholder.markdown("๐Ÿค” Thinking...") + + # Get response + response = asyncio.run(get_response(prompt)) + + # Update placeholder with response + message_placeholder.markdown(response) + + # Add assistant response to chat history + st.session_state.messages.append({"role": "assistant", "content": response}) + +# Quick test buttons +st.markdown("---") +st.header("โšก Quick Tests") + +col1, col2, col3 = st.columns(3) + +with col1: + if st.button("๐Ÿ‘‹ Greeting Test"): + with st.chat_message("user"): + st.markdown("Hello, how are you?") + with st.chat_message("assistant"): + with st.spinner("๐Ÿค– Agent is processing..."): + response = asyncio.run(get_response("Hello, how are you?")) + st.markdown(response) + +with col2: + if st.button("๐Ÿงฎ Math Test"): + with st.chat_message("user"): + st.markdown("What's 2 + 2?") + with st.chat_message("assistant"): + with st.spinner("๐Ÿค– Agent is processing..."): + response = asyncio.run(get_response("What's 2 + 2?")) + st.markdown(response) + +with col3: + if st.button("๐Ÿ˜„ Joke Test"): + with st.chat_message("user"): + st.markdown("Tell me a short joke") + with st.chat_message("assistant"): + with st.spinner("๐Ÿค– Agent is processing..."): + response = asyncio.run(get_response("Tell me a short joke")) + st.markdown(response) + +# Clear chat button +if st.button("๐Ÿ—‘๏ธ Clear Chat"): + st.session_state.messages = [] + st.rerun() + +# Footer +st.markdown("---") +st.markdown(""" +
+

Check the console/terminal for callback timing information

+
+""", unsafe_allow_html=True) \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/requirements.txt new file mode 100644 index 0000000..9669354 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_1_agent_lifecycle_callbacks/requirements.txt @@ -0,0 +1,3 @@ +google-adk>=1.9.0 +streamlit>=1.47.1 +python-dotenv>=1.1.1 \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/.env.example new file mode 100644 index 0000000..f5cfcfb --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/.env.example @@ -0,0 +1,3 @@ +# If using Gemini via Google AI Studio +GOOGLE_GENAI_USE_VERTEXAI=False +GOOGLE_API_KEY="your-api-key" \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/README.md new file mode 100644 index 0000000..354b240 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/README.md @@ -0,0 +1,218 @@ +# 6.2 LLM Interaction Callbacks + +This tutorial demonstrates how to use `before_model_callback` and `after_model_callback` to monitor LLM requests and responses. + +## ๐ŸŽฏ Learning Objectives + +- Understand LLM interaction callbacks +- Learn how to monitor LLM requests and responses +- Track token usage and response times +- Estimate API costs +- Monitor LLM performance metrics + +## ๐Ÿ“ Project Structure + +``` +6_2_llm_interaction_callbacks/ +โ”œโ”€โ”€ agent.py # Agent with LLM interaction callbacks +โ”œโ”€โ”€ app.py # Streamlit web interface +โ”œโ”€โ”€ requirements.txt # Python dependencies +โ””โ”€โ”€ README.md # This file +``` + +## ๐Ÿ”ง Setup + +1. **Install dependencies:** + ```bash + pip install -r requirements.txt + ``` + +2. **Set up API key:** + ```bash + # Create .env file + echo "GOOGLE_API_KEY=your_api_key_here" > .env + ``` + +## ๐Ÿš€ Running the Demo + +### Command Line Demo +```bash +python agent.py +``` + +### Web Interface +```bash +streamlit run app.py +``` + +## ๐Ÿง  Core Concept: LLM Interaction Monitoring + +LLM interaction callbacks allow you to monitor the communication between your agent and the underlying language model, providing insights into requests, responses, and performance metrics. + +### **LLM Interaction Flow** + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ User Input โ”‚โ”€โ”€โ”€โ–ถโ”‚ LLM Request โ”‚โ”€โ”€โ”€โ–ถโ”‚ LLM Response โ”‚ +โ”‚ โ”‚ โ”‚ Callback โ”‚ โ”‚ Callback โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ โ”‚ + โ–ผ โ–ผ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ Model API โ”‚ โ”‚ Token Usage โ”‚ + โ”‚ (Gemini) โ”‚ โ”‚ & Performance โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### **Callback Execution Timeline** + +``` +Timeline: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ + +User Message + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ before_model โ”‚ โ† Records start time, model info +โ”‚ _callback โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ LLM API Call โ”‚ โ† Actual request to Gemini +โ”‚ (Gemini 2.5) โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ after_model โ”‚ โ† Calculates duration, tokens, cost +โ”‚ _callback โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ–ผ +Response to User +``` + +## ๐Ÿ“– Code Walkthrough + +### **1. Callback Functions** + +The callbacks work in pairs to monitor the complete LLM interaction: + +**Before Callback (`before_model_callback`):** +- Extracts model information from `llm_request` +- Records request timestamp +- Stores data in session state for after callback +- Logs request details (model, time, agent) + +**After Callback (`after_model_callback`):** +- Retrieves stored request data from session state +- Calculates response duration +- Extracts token usage from `llm_response.usage_metadata` +- Estimates API costs based on token count +- Logs performance metrics + +### **2. State Management Between Callbacks** + +``` +Session State Flow: +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ before_callback โ”‚โ”€โ”€โ”€โ–ถโ”‚ Session State โ”‚โ”€โ”€โ”€โ–ถโ”‚ after_callback โ”‚ +โ”‚ stores: โ”‚ โ”‚ โ”‚ โ”‚ retrieves: โ”‚ +โ”‚ - start_time โ”‚ โ”‚ - llm_request_ โ”‚ โ”‚ - start_time โ”‚ +โ”‚ - model โ”‚ โ”‚ time โ”‚ โ”‚ - model โ”‚ +โ”‚ - prompt_length โ”‚ โ”‚ - llm_model โ”‚ โ”‚ - prompt_length โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### **3. Agent Setup** + +The agent is configured with both callbacks: +- `before_model_callback`: Monitors request initiation +- `after_model_callback`: Monitors response completion +- Uses `InMemoryRunner` for proper callback triggering + +## ๐Ÿงช Testing Examples + +### **Example Output Format** + +``` +๐Ÿค– LLM Request to gemini-2.5-flash +โฐ Request time: 19:15:30 +๐Ÿ“‹ Agent: llm_monitor_agent + +๐Ÿ“ LLM Response from gemini-2.5-flash +โฑ๏ธ Duration: 1.45s +๐Ÿ”ข Tokens: 156 +๐Ÿ’ฐ Estimated cost: $0.0004 + +``` + +### **What Each Metric Tells You** + +- **โฐ Request time**: When the LLM request was initiated +- **โฑ๏ธ Duration**: Total time from request to response +- **๐Ÿ”ข Tokens**: Total tokens consumed (input + output) +- **๐Ÿ’ฐ Estimated cost**: Approximate API cost based on token usage + +## ๐Ÿ” Key Concepts + +### **LLM Request Monitoring** +- **Model Information**: Track which model is being used +- **Timing**: Record request timestamps +- **State Management**: Store request data for response analysis + +### **LLM Response Monitoring** +- **Response Time**: Calculate duration from request to response +- **Token Usage**: Track total tokens consumed +- **Cost Estimation**: Approximate API costs + +### **Usage Metadata** +- **Token Count**: `llm_response.usage_metadata.total_token_count` +- **Model Information**: Available in request and response +- **Timing Data**: Stored in session state between callbacks + +## ๐ŸŽฏ Use Cases + +- **Performance Monitoring**: Track LLM response times +- **Cost Management**: Monitor API usage and costs +- **Quality Assurance**: Analyze prompt and response patterns +- **Debugging**: Troubleshoot LLM interaction issues +- **Analytics**: Collect usage statistics and metrics + +## ๐Ÿšจ Common Mistakes + +1. **Incorrect callback signatures:** + ```python + # โŒ Wrong + def before_model_callback(context, model, prompt): + + # โœ… Correct + def before_model_callback(callback_context: CallbackContext, llm_request): + ``` + +2. **Wrong token extraction:** + ```python + # โŒ Wrong + tokens = llm_response.usage_metadata.get('total_token_count') + + # โœ… Correct + tokens = getattr(llm_response.usage_metadata, 'total_token_count', 0) + ``` + +3. **Not using InMemoryRunner:** + ```python + # โŒ Wrong - callbacks won't trigger + agent.run(message) + + # โœ… Correct + runner.run_async(...) + ``` + +## ๐Ÿ”— Next Steps + +- Try Tutorial 6.3: Tool Execution Callbacks +- Experiment with different cost estimation models +- Add response quality metrics +- Implement rate limiting and quota management +- Create custom analytics dashboards \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/agent.py new file mode 100644 index 0000000..41c4d76 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/agent.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +""" +LLM Interaction Callbacks Demo +Simple agent that demonstrates LLM request/response monitoring +""" + +import os +from datetime import datetime +from typing import Optional +from google.adk.agents import LlmAgent +from google.adk.agents.callback_context import CallbackContext +from google.adk.runners import InMemoryRunner +from google.genai import types +from dotenv import load_dotenv + +# Load environment variables +load_dotenv() + +def before_model_callback(callback_context: CallbackContext, llm_request) -> Optional[types.Content]: + """Callback before LLM request is made""" + agent_name = callback_context.agent_name + request_time = datetime.now() + + # Extract model and prompt from llm_request + model = getattr(llm_request, 'model', 'unknown') + + # Extract full prompt text from llm_request contents + prompt_text = "unknown" + if hasattr(llm_request, 'contents') and llm_request.contents: + for content in llm_request.contents: + if hasattr(content, 'parts') and content.parts: + for part in content.parts: + if hasattr(part, 'text') and part.text: + prompt_text = part.text + break + if prompt_text != "unknown": + break + + print(f"๐Ÿค– LLM Request to {model}") + print(f"โฐ Request time: {request_time.strftime('%H:%M:%S')}") + print(f"๐Ÿ“‹ Agent: {agent_name}") + print() # Add spacing + + # Store request info in state for after callback + current_state = callback_context.state.to_dict() + current_state["llm_request_time"] = request_time.isoformat() + current_state["llm_model"] = model + current_state["llm_prompt_length"] = len(prompt_text) + callback_context.state.update(current_state) + + # Return None to allow normal execution + return None + +def after_model_callback(callback_context: CallbackContext, llm_response) -> Optional[types.Content]: + """Callback after LLM response is received""" + agent_name = callback_context.agent_name + current_state = callback_context.state.to_dict() + + # Extract response info + response_text = str(llm_response) if llm_response else 'unknown' + model = current_state.get("llm_model", "unknown") + + # Extract token count from usage_metadata + tokens = 0 + if llm_response and hasattr(llm_response, 'usage_metadata') and llm_response.usage_metadata: + tokens = getattr(llm_response.usage_metadata, 'total_token_count', 0) + + # Get request time from state + request_time_str = current_state.get("llm_request_time") + if request_time_str: + request_time = datetime.fromisoformat(request_time_str) + duration = datetime.now() - request_time + duration_seconds = duration.total_seconds() + else: + duration_seconds = 0 + + print(f"๐Ÿ“ LLM Response from {model}") + print(f"โฑ๏ธ Duration: {duration_seconds:.2f}s") + print(f"๐Ÿ”ข Tokens: {tokens}") + + # Calculate estimated cost for Gemini 2.5 Flash + # Pricing: $2.50 per 1M output tokens (including thinking tokens) + cost_per_1k_output = 0.0025 # $2.50 per 1M = $0.0025 per 1K + estimated_cost = (tokens / 1000) * cost_per_1k_output + print(f"๐Ÿ’ฐ Estimated cost: ${estimated_cost:.4f}") + print() # Add spacing + + # Return None to use the original response + return None + +# Create agent with LLM callbacks +root_agent = LlmAgent( + name="llm_monitor_agent", + model="gemini-2.5-flash", + description="Agent with LLM interaction monitoring", + instruction=""" + You are a helpful assistant with LLM monitoring. + + Your role is to: + - Provide clear, informative responses + - Keep responses concise but comprehensive + - Demonstrate the LLM callback system + + The system will automatically track: + - Your requests to the LLM model + - Response times and token usage + - Estimated API costs + + Focus on being helpful while showing the monitoring capabilities. + """, + before_model_callback=before_model_callback, + after_model_callback=after_model_callback +) + +# Create runner for agent execution +runner = InMemoryRunner(agent=root_agent, app_name="llm_monitor_app") + +async def run_agent(message: str) -> str: + """Run the agent with the given message""" + user_id = "demo_user" + session_id = "demo_session" + + # Get the bundled session service + session_service = runner.session_service + + # Get or create session + session = await session_service.get_session( + app_name="llm_monitor_app", + user_id=user_id, + session_id=session_id + ) + if not session: + session = await session_service.create_session( + app_name="llm_monitor_app", + user_id=user_id, + session_id=session_id, + state={"conversation_history": []} + ) + + # Create user content + user_content = types.Content( + role='user', + parts=[types.Part(text=message)] + ) + + # Run agent and get response + response_text = "" + async for event in runner.run_async( + user_id=user_id, + session_id=session_id, + new_message=user_content + ): + if event.is_final_response() and event.content: + response_text = event.content.parts[0].text.strip() + # Don't break here - let the loop complete naturally to ensure callbacks run + + return response_text + +if __name__ == "__main__": + import asyncio + + # Test the agent + print("๐Ÿงช Testing LLM Interaction Callbacks") + print("=" * 50) + + test_messages = [ + "Explain quantum computing in simple terms", + "Write a short poem about AI", + "What are the benefits of renewable energy?" + ] + + async def test_agent(): + for message in test_messages: + print(f"\n๐Ÿค– User: {message}") + response = await run_agent(message) + print(f"๐Ÿค– Agent: {response}") + print("-" * 50) + + asyncio.run(test_agent()) \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/app.py b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/app.py new file mode 100644 index 0000000..658d060 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/app.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +""" +Streamlit App for LLM Interaction Callbacks Demo +""" + +import streamlit as st +import sys +import os +import asyncio +from agent import run_agent + +# Page configuration +st.set_page_config( + page_title="LLM Interaction Callbacks", + page_icon="๐Ÿค–", + layout="wide" +) + +# Title and description +st.title("๐Ÿค– LLM Interaction Callbacks Demo") +st.markdown(""" +This demo shows how to monitor LLM requests and responses using callbacks. +Watch the console output to see detailed LLM interaction tracking! +""") + +# Sidebar with information +with st.sidebar: + st.header("๐Ÿ“Š LLM Monitoring") + st.markdown(""" + **Request Callback**: Triggered when LLM request is sent + - Logs model name and prompt + - Records request timestamp + - Tracks prompt length + + **Response Callback**: Triggered when LLM response is received + - Calculates response duration + - Tracks token usage + - Estimates API costs + """) + +# Main chat interface +st.header("๐Ÿ’ฌ Chat with LLM Monitor") + +# Initialize chat history +if "messages" not in st.session_state: + st.session_state.messages = [] + +# Display chat messages +for message in st.session_state.messages: + with st.chat_message(message["role"]): + st.markdown(message["content"]) + +# Chat input +if prompt := st.chat_input("Ask me something..."): + # Add user message to chat + st.session_state.messages.append({"role": "user", "content": prompt}) + with st.chat_message("user"): + st.markdown(prompt) + + # Get agent response + with st.chat_message("assistant"): + with st.spinner("๐Ÿค– LLM is processing..."): + response = asyncio.run(run_agent(prompt)) + st.markdown(response) + + # Add assistant response to chat + st.session_state.messages.append({"role": "assistant", "content": response}) + +# Quick test buttons +st.markdown("---") +st.header("โšก Quick Tests") + +col1, col2, col3 = st.columns(3) + +with col1: + if st.button("๐Ÿ”ฌ Science Test"): + with st.chat_message("user"): + st.markdown("Explain quantum computing in simple terms") + with st.chat_message("assistant"): + with st.spinner("๐Ÿค– LLM is processing..."): + response = asyncio.run(run_agent("Explain quantum computing in simple terms")) + st.markdown(response) + +with col2: + if st.button("๐Ÿ“ Poetry Test"): + with st.chat_message("user"): + st.markdown("Write a short poem about AI") + with st.chat_message("assistant"): + with st.spinner("๐Ÿค– LLM is processing..."): + response = asyncio.run(run_agent("Write a short poem about AI")) + st.markdown(response) + +with col3: + if st.button("๐ŸŒ Environment Test"): + with st.chat_message("user"): + st.markdown("What are the benefits of renewable energy?") + with st.chat_message("assistant"): + with st.spinner("๐Ÿค– LLM is processing..."): + response = asyncio.run(run_agent("What are the benefits of renewable energy?")) + st.markdown(response) + +# Clear chat button +if st.button("๐Ÿ—‘๏ธ Clear Chat History"): + st.session_state.messages = [] + st.rerun() + +# Information about callbacks +st.markdown("---") +st.header("๐Ÿ“‹ LLM Callback Output") +st.markdown(""" +**Check your console/terminal** to see the LLM interaction output: + +``` +๐Ÿค– LLM Request to gemini-2.5-flash +โฐ Request time: 10:30:15 +๐Ÿ“‹ Agent: llm_monitor_agent + +๐Ÿ“ LLM Response from gemini-2.5-flash +โฑ๏ธ Duration: 1.45s +๐Ÿ”ข Tokens: 156 +๐Ÿ’ฐ Estimated cost: $0.0004 +``` +""") + +# Footer +st.markdown("---") +st.markdown("*Watch the console output to see LLM interaction callbacks in action!*") \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/requirements.txt new file mode 100644 index 0000000..9669354 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_2_llm_interaction_callbacks/requirements.txt @@ -0,0 +1,3 @@ +google-adk>=1.9.0 +streamlit>=1.47.1 +python-dotenv>=1.1.1 \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/.env.example b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/.env.example new file mode 100644 index 0000000..f5cfcfb --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/.env.example @@ -0,0 +1,3 @@ +# If using Gemini via Google AI Studio +GOOGLE_GENAI_USE_VERTEXAI=False +GOOGLE_API_KEY="your-api-key" \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/README.md new file mode 100644 index 0000000..1001142 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/README.md @@ -0,0 +1,254 @@ +# ๐ŸŽฏ Tutorial 6.3: Tool Execution Callbacks + +## ๐ŸŽฏ What You'll Learn +- **Before Tool Callbacks**: Monitor when tools begin execution +- **After Tool Callbacks**: Track tool completion and results +- **Tool Context**: Understand how tool execution is monitored + +## ๐Ÿง  Core Concept: Tool Execution Monitoring + +Tool execution callbacks allow you to monitor when agents use tools, track their execution lifecycle, and analyze the results. This provides visibility into how agents interact with external systems and APIs. + +### **Tool Execution Flow** +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Tool Call โ”‚โ”€โ”€โ”€โ–ถโ”‚ Before Tool โ”‚โ”€โ”€โ”€โ–ถโ”‚ Tool Execution โ”‚ +โ”‚ (Agent) โ”‚ โ”‚ Callback โ”‚ โ”‚ (External) โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ โ”‚ + โ–ผ โ–ผ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ After Tool โ”‚ โ”‚ Tool Result โ”‚ + โ”‚ Callback โ”‚ โ”‚ (Agent) โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### **Callback Execution Timeline** +``` +Time โ†’ 0ms 5ms 10ms 15ms 20ms 25ms + โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ + โ–ผ โ–ผ โ–ผ โ–ผ โ–ผ โ–ผ + [Tool] [Before] [Exec] [After] [Result] + Call Callback Start Callback Return +``` + +### **Use Cases** +- **Execution Monitoring**: Track when tools start and complete +- **Parameter Validation**: Check tool inputs before execution +- **Result Logging**: Record tool outputs and errors +- **Debugging**: Understand tool execution patterns +- **Analytics**: Monitor which tools are used most + +## ๐Ÿš€ Tutorial Overview + +In this tutorial, we'll create an agent with tool execution callbacks that: +- Uses a simple calculator tool +- Monitors tool execution start and end +- Tracks tool parameters and results +- Provides detailed tool usage visibility + +## ๐Ÿ“ Project Structure + +``` +6_3_tool_execution_callbacks/ +โ”œโ”€โ”€ README.md # This file +โ”œโ”€โ”€ requirements.txt # Dependencies +โ”œโ”€โ”€ agent.py # Agent with tool callbacks +โ””โ”€โ”€ app.py # Streamlit interface +``` + +## ๐ŸŽฏ Learning Objectives + +By the end of this tutorial, you'll understand: + +- โœ… **Before Tool Callbacks**: How to monitor tool execution start +- โœ… **After Tool Callbacks**: How to track tool completion +- โœ… **Tool Context**: How to access tool and agent information +- โœ… **FunctionTool**: How to properly register tools with callbacks +- โœ… **Callback Integration**: How to integrate callbacks with agents + +## ๐Ÿš€ Getting Started + +### **Setup** +1. **Install dependencies**: `pip install -r requirements.txt` +2. **Set up environment**: Create `.env` with `GOOGLE_API_KEY=your_key` +3. **Run the app**: `streamlit run app.py` + +### **Test the Agent** +```bash +# Run the Streamlit app +streamlit run app.py + +# Try these test messages: +- "Calculate 15 + 27" +- "What is 100 divided by 4?" +- "Multiply 8 by 12" +``` + +## ๐Ÿ”ง Key Concepts + +### **1. Before Tool Callback** +- **Trigger**: When tool execution begins +- **Parameters**: `tool`, `args`, `tool_context` +- **Use Cases**: Log tool usage, validate parameters, record start + +### **2. After Tool Callback** +- **Trigger**: When tool execution completes +- **Parameters**: `tool`, `args`, `tool_context`, `tool_response` +- **Use Cases**: Log results, handle errors, provide feedback + +### **3. Tool Context** +- **Agent Information**: Access `tool_context.agent_name` +- **State Management**: Use `tool_context.state` for data sharing +- **Tool Details**: Access tool information via `tool.name` + +## ๐Ÿ” Testing Examples + +### **Basic Tool Usage** +``` +User: "Calculate 15 + 27" + +๐Ÿ”ง Tool calculator_tool started +๐Ÿ“ Parameters: {'operation': 'add', 'a': 15.0, 'b': 27.0} +๐Ÿ“‹ Agent: tool_execution_demo_agent + +โœ… Tool calculator_tool completed +โฑ๏ธ Duration: 0.0012s +๐Ÿ“„ Result: 15 + 27 = 42 +``` + +### **Error Handling** +``` +User: "What is 10 divided by 0?" + +๐Ÿ”ง Tool calculator_tool started +๐Ÿ“ Parameters: {'operation': 'divide', 'a': 10.0, 'b': 0.0} +๐Ÿ“‹ Agent: tool_execution_demo_agent + +โœ… Tool calculator_tool completed +โฑ๏ธ Duration: 0.0008s +๐Ÿ“„ Result: Error: Division by zero +``` + +## ๐ŸŽฏ What Each Metric Tells You + +### **Before Tool Callback Output** +- **๐Ÿ”ง Tool Name**: Which tool is being executed +- **๐Ÿ“ Parameters**: Input parameters passed to the tool +- **๐Ÿ“‹ Agent**: Which agent is using the tool + +### **After Tool Callback Output** +- **โœ… Completion Status**: Tool execution completed successfully +- **โฑ๏ธ Duration**: How long the tool took to execute +- **๐Ÿ“„ Result**: The output or result from the tool + +## ๐ŸŽฏ Critical Implementation Notes + +### **FunctionTool Requirement** +Tools must be wrapped with `FunctionTool` for callbacks to work: + +```python +# โœ… Correct - Use FunctionTool +calculator_function_tool = FunctionTool(func=calculator_tool) +agent = LlmAgent(tools=[calculator_function_tool], ...) + +# โŒ Incorrect - Raw function won't trigger callbacks +agent = LlmAgent(tools=[calculator_tool], ...) +``` + +### **Callback Signatures** +Use the correct parameter order for tool callbacks: + +```python +# โœ… Correct signatures +def before_tool_callback(tool: BaseTool, args: dict, tool_context: ToolContext): + pass + +def after_tool_callback(tool: BaseTool, args: dict, tool_context: ToolContext, tool_response: any): + pass +``` + +### **Event Loop Completion** +Don't break the event loop immediately after `is_final_response()`: + +```python +# โœ… Do this - allows callbacks to complete +if event.is_final_response() and event.content: + response_text = event.content.parts[0].text.strip() + # Don't break - let the loop complete naturally +``` + +## ๐ŸŽฏ Advanced Patterns + +### **Multiple Tools** +Register multiple tools with the same callbacks: + +```python +def weather_tool(city: str) -> str: + return f"Weather in {city}: Sunny, 25ยฐC" + +def calculator_tool(operation: str, a: float, b: float) -> str: + # ... implementation + +# Register multiple tools +weather_function_tool = FunctionTool(func=weather_tool) +calculator_function_tool = FunctionTool(func=calculator_tool) + +agent = LlmAgent( + name="multi_tool_agent", + model="gemini-2.5-flash", + tools=[calculator_function_tool, weather_function_tool], + before_tool_callback=before_tool_callback, + after_tool_callback=after_tool_callback +) +``` + +### **Parameter Validation** +Implement validation in before_tool_callback: + +```python +def before_tool_callback(tool: BaseTool, args: dict, tool_context: ToolContext): + tool_name = tool.name + + # Validate calculator tool parameters + if tool_name == "calculator_tool": + if "operation" not in args: + print("โš ๏ธ Warning: Missing operation parameter") + if "a" not in args or "b" not in args: + print("โš ๏ธ Warning: Missing numeric parameters") + + print(f"๐Ÿ”ง Tool {tool_name} started") + print(f"๐Ÿ“ Parameters: {args}") + return None +``` + +### **Result Modification** +Modify tool results in after_tool_callback: + +```python +def after_tool_callback(tool: BaseTool, args: dict, tool_context: ToolContext, tool_response: any): + tool_name = tool.name + + # Add context to calculator results + if tool_name == "calculator_tool" and "result" in tool_response: + operation = args.get("operation", "unknown") + tool_response["context"] = f"Performed {operation} operation" + + print(f"โœ… Tool {tool_name} completed") + print(f"๐Ÿ“„ Result: {tool_response}") + return tool_response # Return modified response +``` + +## ๐Ÿ”— Next Steps + +After completing this tutorial, you'll be ready for: + +- **[Advanced Tool Patterns](../advanced_tool_patterns/README.md)** - Complex tool architectures +- **[Custom Tool Development](../custom_tools/README.md)** - Building custom tools +- **[Tool Integration](../tool_integration/README.md)** - Integrating external APIs + +## ๐Ÿ“š Additional Resources + +- [Google ADK Tool Callbacks](https://google.github.io/adk-docs/callbacks/types-of-callbacks/#tool-execution-callbacks) +- [Tool Development Guide](https://google.github.io/adk-docs/tools/) +- [FunctionTool Documentation](https://google.github.io/adk-docs/tools/function-tools/) \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/__pycache__/agent.cpython-311.pyc b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/__pycache__/agent.cpython-311.pyc new file mode 100644 index 0000000..6f7cecb Binary files /dev/null and b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/__pycache__/agent.cpython-311.pyc differ diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/agent.py b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/agent.py new file mode 100644 index 0000000..5525419 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/agent.py @@ -0,0 +1,150 @@ +import os +import asyncio +import time +from datetime import datetime +from typing import Optional, Dict, Any +from google.adk.agents import LlmAgent +from google.adk.runners import InMemoryRunner +from google.adk.tools import BaseTool, FunctionTool +from google.adk.tools.tool_context import ToolContext +from google.genai import types +from dotenv import load_dotenv + +# Load environment variables +load_dotenv() + +def calculator_tool(operation: str, a: float, b: float) -> str: + """Simple calculator tool with basic operations""" + if operation == "add": + return f"{a} + {b} = {a + b}" + elif operation == "subtract": + return f"{a} - {b} = {a - b}" + elif operation == "multiply": + return f"{a} ร— {b} = {a * b}" + elif operation == "divide": + if b == 0: + return "Error: Division by zero" + return f"{a} รท {b} = {a / b}" + else: + return f"Unknown operation: {operation}" + +# Create FunctionTool from the calculator function +calculator_function_tool = FunctionTool(func=calculator_tool) + +def before_tool_callback(tool: BaseTool, args: Dict[str, Any], tool_context: ToolContext) -> Optional[Dict[str, Any]]: + """Callback before tool execution starts""" + agent_name = tool_context.agent_name + tool_name = tool.name + start_time = time.time() + + print(f"๐Ÿ”ง Tool {tool_name} started") + print(f"๐Ÿ“ Parameters: {args}") + print(f"๐Ÿ“‹ Agent: {agent_name}") + print() # Add spacing + + # Store start time in tool_context state for after callback + current_state = tool_context.state.to_dict() + current_state["tool_start_time"] = start_time + tool_context.state.update(current_state) + + # Return None to allow normal execution + return None + +def after_tool_callback(tool: BaseTool, args: Dict[str, Any], tool_context: ToolContext, tool_response: Any) -> Optional[Any]: + """Callback after tool execution completes""" + agent_name = tool_context.agent_name + tool_name = tool.name + current_state = tool_context.state.to_dict() + + # Get start time from state and calculate duration + start_time = current_state.get("tool_start_time") + if start_time: + end_time = time.time() + duration_seconds = end_time - start_time + + print(f"โœ… Tool {tool_name} completed") + print(f"โฑ๏ธ Duration: {duration_seconds:.4f}s") + print(f"๐Ÿ“„ Result: {tool_response}") + print() # Add spacing + else: + print(f"โœ… Tool {tool_name} completed") + print(f"๐Ÿ“„ Result: {tool_response}") + print() # Add spacing + + # Return None to use the original tool response + return None + +# --- 2. Setup Agent with Tool Callbacks --- +llm_agent_with_tool_callbacks = LlmAgent( + name="tool_execution_demo_agent", + model="gemini-2.5-flash", + instruction="You are a helpful assistant with calculator tools. When users ask for calculations, use the calculator_tool with appropriate parameters and provide clear explanations of the results.", + description="An LLM agent demonstrating tool execution callbacks for monitoring", + tools=[calculator_function_tool], + before_tool_callback=before_tool_callback, + after_tool_callback=after_tool_callback +) + +# --- 3. Setup Runner and Sessions --- +runner = InMemoryRunner(agent=llm_agent_with_tool_callbacks, app_name="tool_execution_callback_demo") + +async def run_agent(message: str) -> str: + """Run the agent with the given message""" + user_id = "demo_user" + session_id = "demo_session" + + # Get the bundled session service + session_service = runner.session_service + + # Get or create session + session = await session_service.get_session( + app_name="tool_execution_callback_demo", + user_id=user_id, + session_id=session_id + ) + if not session: + session = await session_service.create_session( + app_name="tool_execution_callback_demo", + user_id=user_id, + session_id=session_id, + state={"conversation_history": []} + ) + + # Create user content + user_content = types.Content( + role='user', + parts=[types.Part(text=message)] + ) + + # Run agent and get response + response_text = "" + async for event in runner.run_async( + user_id=user_id, + session_id=session_id, + new_message=user_content + ): + if event.is_final_response() and event.content: + response_text = event.content.parts[0].text.strip() + # Don't break - let the loop complete naturally to ensure callbacks run + + return response_text + +# --- 4. Execute --- +if __name__ == "__main__": + print("\n" + "="*50 + " Tool Execution Callbacks Demo " + "="*50) + + # Test messages + test_messages = [ + "Calculate 15 + 27", + "What is 100 divided by 4?", + "Multiply 8 by 12", + "What is 50 minus 23?" + ] + + async def test_agent(): + for i, message in enumerate(test_messages, 1): + print(f"\n--- Test {i}: {message} ---") + response = await run_agent(message) + print(f"๐Ÿค– Response: {response}") + + asyncio.run(test_agent()) \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/app.py b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/app.py new file mode 100644 index 0000000..9b8a309 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/app.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +""" +Streamlit App for Tool Execution Callbacks Demo +""" + +import streamlit as st +import sys +import os +import asyncio +from agent import run_agent + +# Page configuration +st.set_page_config( + page_title="Tool Execution Callbacks", + page_icon="๐Ÿ”ง", + layout="wide" +) + +# Title and description +st.title("๐Ÿ”ง Tool Execution Callbacks Demo") +st.markdown(""" +This demo shows how to monitor tool execution using callbacks. +Watch the console output to see detailed tool execution tracking! +""") + +# Sidebar with information +with st.sidebar: + st.header("๐Ÿ“Š Tool Execution Monitoring") + st.markdown(""" + **Before Tool Callback** + - Triggered when a tool starts execution + - Logs tool name and input parameters + - Records agent name + - Stores start time for duration tracking + + **After Tool Callback** + - Triggered when a tool finishes execution + - Logs tool result + - Calculates and displays execution duration + - Handles errors (e.g., division by zero) + """) + + st.markdown("---") + st.markdown("### ๐Ÿงฎ Available Tools") + st.markdown(""" + **Calculator Tool**: + - Addition: `add` + - Subtraction: `subtract` + - Multiplication: `multiply` + - Division: `divide` + """) + +# Main chat interface +st.header("๐Ÿ’ฌ Chat with Tool Monitor") + +# Initialize chat history +if "messages" not in st.session_state: + st.session_state.messages = [] + +# Display chat messages +for message in st.session_state.messages: + with st.chat_message(message["role"]): + st.markdown(message["content"]) + +# Chat input +if prompt := st.chat_input("Ask me to calculate something..."): + # Add user message to chat + st.session_state.messages.append({"role": "user", "content": prompt}) + with st.chat_message("user"): + st.markdown(prompt) + + # Get agent response + with st.chat_message("assistant"): + with st.spinner("๐Ÿ”ง Tool is executing..."): + response = asyncio.run(run_agent(prompt)) + st.markdown(response) + + # Add assistant response to chat + st.session_state.messages.append({"role": "assistant", "content": response}) + +# Quick test buttons +st.markdown("---") +st.header("โšก Quick Tests") + +col1, col2, col3 = st.columns(3) + +with col1: + if st.button("โž• Addition Test"): + test_message = "Calculate 15 + 27" + st.session_state.messages.append({"role": "user", "content": test_message}) + with st.chat_message("user"): + st.markdown(test_message) + with st.chat_message("assistant"): + with st.spinner("๐Ÿ”ง Tool is executing..."): + response = asyncio.run(run_agent(test_message)) + st.markdown(response) + st.session_state.messages.append({"role": "assistant", "content": response}) + +with col2: + if st.button("โž— Division Test"): + test_message = "What is 100 divided by 4?" + st.session_state.messages.append({"role": "user", "content": test_message}) + with st.chat_message("user"): + st.markdown(test_message) + with st.chat_message("assistant"): + with st.spinner("๐Ÿ”ง Tool is executing..."): + response = asyncio.run(run_agent(test_message)) + st.markdown(response) + st.session_state.messages.append({"role": "assistant", "content": response}) + +with col3: + if st.button("โŒ Error Test"): + test_message = "Calculate 10 divided by 0" + st.session_state.messages.append({"role": "user", "content": test_message}) + with st.chat_message("user"): + st.markdown(test_message) + with st.chat_message("assistant"): + with st.spinner("๐Ÿ”ง Tool is executing..."): + response = asyncio.run(run_agent(test_message)) + st.markdown(response) + st.session_state.messages.append({"role": "assistant", "content": response}) + +# Clear chat button +if st.button("๐Ÿ—‘๏ธ Clear Chat History"): + st.session_state.messages = [] + st.rerun() + +# Information about callbacks +st.markdown("---") +st.header("๐Ÿ“‹ Tool Callback Output") +st.markdown(""" +**Check your console/terminal** to see the tool execution output: + +``` +๐Ÿ”ง Tool calculator_tool started +๐Ÿ“ Parameters: {'operation': 'add', 'a': 15.0, 'b': 27.0} +๐Ÿ“‹ Agent: tool_execution_demo_agent + +โœ… Tool calculator_tool completed +โฑ๏ธ Duration: 0.0012s +๐Ÿ“„ Result: 15 + 27 = 42 +``` +""") + +# Footer +st.markdown("---") +st.markdown("*Watch the console output to see tool execution callbacks in action!*") \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/requirements.txt b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/requirements.txt new file mode 100644 index 0000000..9669354 --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/6_3_tool_execution_callbacks/requirements.txt @@ -0,0 +1,3 @@ +google-adk>=1.9.0 +streamlit>=1.47.1 +python-dotenv>=1.1.1 \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/README.md new file mode 100644 index 0000000..76256ba --- /dev/null +++ b/ai_agent_framework_crash_course/google_adk_crash_course/6_callbacks/README.md @@ -0,0 +1,189 @@ +# ๐ŸŽฏ Tutorial 6: Callbacks + +## ๐ŸŽฏ What You'll Learn +- **Agent Lifecycle Callbacks**: Monitor agent creation, initialization, and cleanup +- **LLM Interaction Callbacks**: Track model requests, responses, and token usage +- **Tool Execution Callbacks**: Monitor tool calls, parameters, and results + +## ๐Ÿง  Core Concept: Callbacks + +Callbacks are functions that get executed at specific points during agent execution, allowing you to monitor, log, and control the agent's behavior without modifying the core logic. + +### **Callback Flow Diagram** +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Agent Start โ”‚โ”€โ”€โ”€โ–ถโ”‚ LLM Request โ”‚โ”€โ”€โ”€โ–ถโ”‚ Tool Execution โ”‚ +โ”‚ Callback โ”‚ โ”‚ Callback โ”‚ โ”‚ Callback โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ โ”‚ โ”‚ + โ–ผ โ–ผ โ–ผ +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Agent End โ”‚ โ”‚ LLM Response โ”‚ โ”‚ Tool Result โ”‚ +โ”‚ Callback โ”‚ โ”‚ Callback โ”‚ โ”‚ Callback โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### **Why Use Callbacks?** +- **Monitoring**: Track agent performance and behavior +- **Logging**: Record interactions for debugging and analysis +- **Control**: Modify behavior based on specific events +- **Integration**: Connect agents to external systems +- **Debugging**: Understand what's happening inside the agent + +## ๐Ÿš€ Tutorial Overview + +This tutorial covers three essential callback patterns in Google ADK: + +1. **Agent Lifecycle Callbacks**: Monitor agent creation, initialization, and cleanup events +2. **LLM Interaction Callbacks**: Track model requests, responses, and token usage +3. **Tool Execution Callbacks**: Monitor tool calls, parameters, and execution results + +Each sub-tutorial provides simple, focused examples that demonstrate specific callback patterns. + +## ๐Ÿ“ Project Structure + +``` +6_callbacks/ +โ”œโ”€โ”€ README.md # This file - concept explanation +โ”œโ”€โ”€ 6_1_agent_lifecycle_callbacks/ # Agent lifecycle monitoring +โ”‚ โ”œโ”€โ”€ README.md # Lifecycle callback patterns +โ”‚ โ”œโ”€โ”€ agent.py # Agent with lifecycle callbacks +โ”‚ โ”œโ”€โ”€ app.py # Streamlit interface +โ”‚ โ””โ”€โ”€ requirements.txt # Dependencies +โ”œโ”€โ”€ 6_2_llm_interaction_callbacks/ # LLM request/response tracking +โ”‚ โ”œโ”€โ”€ README.md # LLM callback patterns +โ”‚ โ”œโ”€โ”€ agent.py # Agent with LLM callbacks +โ”‚ โ”œโ”€โ”€ app.py # Streamlit interface +โ”‚ โ””โ”€โ”€ requirements.txt # Dependencies +โ””โ”€โ”€ 6_3_tool_execution_callbacks/ # Tool execution monitoring + โ”œโ”€โ”€ README.md # Tool callback patterns + โ”œโ”€โ”€ agent.py # Agent with tool callbacks + โ”œโ”€โ”€ app.py # Streamlit interface + โ””โ”€โ”€ requirements.txt # Dependencies +``` + +## ๐ŸŽฏ Learning Objectives + +By the end of this tutorial, you'll understand: + +- โœ… **Callback Fundamentals**: How callbacks work in Google ADK +- โœ… **Lifecycle Monitoring**: Track agent creation, initialization, and cleanup +- โœ… **LLM Tracking**: Monitor model requests, responses, and performance +- โœ… **Tool Monitoring**: Track tool execution and results +- โœ… **Practical Applications**: Real-world use cases for callbacks +- โœ… **Debugging Techniques**: Use callbacks for troubleshooting + +## ๐Ÿš€ Getting Started + +### **Prerequisites** +- Python 3.11+ +- Google AI Studio API key +- Basic understanding of Google ADK (Tutorials 1-5) + +### **Setup** +1. **Get API Key**: Visit [Google AI Studio](https://aistudio.google.com/) +2. **Create .env file**: Add `GOOGLE_API_KEY=your_key_here` +3. **Install dependencies**: `pip install -r requirements.txt` + +### **Run Tutorials** +```bash +# Agent Lifecycle Callbacks +cd 6_1_agent_lifecycle_callbacks +streamlit run app.py + +# LLM Interaction Callbacks +cd ../6_2_llm_interaction_callbacks +streamlit run app.py + +# Tool Execution Callbacks +cd ../6_3_tool_execution_callbacks +streamlit run app.py +``` + +## ๐Ÿ”ง Callback Patterns + +### **1. Agent Lifecycle Callbacks** +```python +def on_agent_start(agent_name: str): + print(f"๐Ÿš€ Agent {agent_name} started") + +def on_agent_end(agent_name: str, result: str): + print(f"โœ… Agent {agent_name} completed: {result}") + +# Register callbacks +agent = LlmAgent( + name="my_agent", + model="gemini-2.5-flash", + on_start=on_agent_start, + on_end=on_agent_end +) +``` + +### **2. LLM Interaction Callbacks** +```python +def on_llm_request(model: str, prompt: str): + print(f"๐Ÿค– LLM Request to {model}: {prompt[:50]}...") + +def on_llm_response(model: str, response: str, tokens: int): + print(f"๐Ÿ“ LLM Response from {model}: {tokens} tokens") + +# Register callbacks +agent = LlmAgent( + name="my_agent", + model="gemini-2.5-flash", + on_llm_request=on_llm_request, + on_llm_response=on_llm_response +) +``` + +### **3. Tool Execution Callbacks** +```python +def on_tool_start(tool_name: str, params: dict): + print(f"๐Ÿ”ง Tool {tool_name} started with params: {params}") + +def on_tool_end(tool_name: str, result: str): + print(f"โœ… Tool {tool_name} completed: {result}") + +# Register callbacks +agent = LlmAgent( + name="my_agent", + model="gemini-2.5-flash", + tools=[my_tool], + on_tool_start=on_tool_start, + on_tool_end=on_tool_end +) +``` + +## ๐ŸŽฏ Use Cases + +### **Monitoring & Analytics** +- Track agent performance metrics +- Monitor token usage and costs +- Analyze tool usage patterns +- Debug agent behavior + +### **Logging & Debugging** +- Log all agent interactions +- Debug tool execution issues +- Monitor LLM response quality +- Track error patterns + +### **Integration & Control** +- Connect to external monitoring systems +- Implement custom error handling +- Add authentication and validation +- Control agent behavior dynamically + +## ๐Ÿ”— Next Steps + +After completing this tutorial, you'll be ready for: + +- **[Advanced Agent Patterns](../advanced_patterns/README.md)** - Complex agent architectures +- **[Production Deployment](../deployment/README.md)** - Deploying agents to production +- **[Custom Tools](../custom_tools/README.md)** - Building custom tools and integrations + +## ๐Ÿ“š Additional Resources + +- [Google ADK Documentation](https://google.github.io/adk-docs/) +- [Callback API Reference](https://google.github.io/adk-docs/api-reference/python/) +- [Best Practices Guide](https://google.github.io/adk-docs/best-practices/) \ No newline at end of file diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/README.md b/ai_agent_framework_crash_course/google_adk_crash_course/README.md similarity index 89% rename from ai_agent_framework_crash_course/google_adk_tutorials/README.md rename to ai_agent_framework_crash_course/google_adk_crash_course/README.md index 120d8e1..b4a3af0 100644 --- a/ai_agent_framework_crash_course/google_adk_tutorials/README.md +++ b/ai_agent_framework_crash_course/google_adk_crash_course/README.md @@ -43,7 +43,12 @@ This crash course covers the essential concepts of Google ADK through hands-on t - **[5.1 In-Memory Conversation](./5_memory_agent/5_1_in_memory_conversation/README.md)** - Basic session management - **[5.2 Persistent Conversation](./5_memory_agent/5_2_persistent_conversation/README.md)** - Database storage with SQLite -6. **More tutorials coming soon!** +6. **[6_callbacks](./6_callbacks/README.md)** - Callback patterns and monitoring + - **[6.1 Agent Lifecycle Callbacks](./6_callbacks/6_1_agent_lifecycle_callbacks/README.md)** - Monitor agent creation and cleanup + - **[6.2 LLM Interaction Callbacks](./6_callbacks/6_2_llm_interaction_callbacks/README.md)** - Track model requests and responses + - **[6.3 Tool Execution Callbacks](./6_callbacks/6_3_tool_execution_callbacks/README.md)** - Monitor tool calls and results + +7. **More tutorials coming soon!** ## ๐Ÿ› ๏ธ Prerequisites diff --git a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/requirements.txt b/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/requirements.txt deleted file mode 100644 index f33c212..0000000 --- a/ai_agent_framework_crash_course/google_adk_tutorials/5_memory_agent/5_2_persistent_conversation_agent/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -google-adk>=0.1.0 -streamlit>=1.28.0 -python-dotenv>=1.0.0 -sqlalchemy>=2.0.0 -asyncio \ No newline at end of file