agent-starter-pack 0.18.2__py3-none-any.whl → 0.21.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. agent_starter_pack/agents/{langgraph_base_react → adk_a2a_base}/.template/templateconfig.yaml +5 -12
  2. agent_starter_pack/agents/adk_a2a_base/README.md +37 -0
  3. agent_starter_pack/{frontends/streamlit/frontend/style/app_markdown.py → agents/adk_a2a_base/app/__init__.py} +3 -23
  4. agent_starter_pack/agents/adk_a2a_base/app/agent.py +70 -0
  5. agent_starter_pack/agents/adk_a2a_base/notebooks/adk_a2a_app_testing.ipynb +583 -0
  6. agent_starter_pack/agents/{crewai_coding_crew/notebooks/evaluating_crewai_agent.ipynb → adk_a2a_base/notebooks/evaluating_adk_agent.ipynb} +163 -199
  7. agent_starter_pack/agents/adk_a2a_base/tests/integration/test_agent.py +58 -0
  8. agent_starter_pack/agents/adk_base/app/__init__.py +2 -2
  9. agent_starter_pack/agents/adk_base/app/agent.py +3 -0
  10. agent_starter_pack/agents/adk_base/notebooks/adk_app_testing.ipynb +13 -28
  11. agent_starter_pack/agents/adk_live/app/__init__.py +17 -0
  12. agent_starter_pack/agents/adk_live/app/agent.py +3 -0
  13. agent_starter_pack/agents/agentic_rag/app/__init__.py +2 -2
  14. agent_starter_pack/agents/agentic_rag/app/agent.py +3 -0
  15. agent_starter_pack/agents/agentic_rag/notebooks/adk_app_testing.ipynb +13 -28
  16. agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/.template/templateconfig.yaml +12 -9
  17. agent_starter_pack/agents/langgraph_base/README.md +30 -0
  18. agent_starter_pack/agents/langgraph_base/app/__init__.py +17 -0
  19. agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/app/agent.py +4 -4
  20. agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/tests/integration/test_agent.py +1 -1
  21. agent_starter_pack/base_template/.gitignore +4 -2
  22. agent_starter_pack/base_template/Makefile +110 -16
  23. agent_starter_pack/base_template/README.md +97 -12
  24. agent_starter_pack/base_template/deployment/terraform/dev/apis.tf +4 -6
  25. agent_starter_pack/base_template/deployment/terraform/dev/providers.tf +5 -1
  26. agent_starter_pack/base_template/deployment/terraform/dev/variables.tf +5 -3
  27. agent_starter_pack/base_template/deployment/terraform/dev/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +193 -0
  28. agent_starter_pack/base_template/deployment/terraform/github.tf +16 -9
  29. agent_starter_pack/base_template/deployment/terraform/locals.tf +7 -7
  30. agent_starter_pack/base_template/deployment/terraform/providers.tf +5 -1
  31. agent_starter_pack/base_template/deployment/terraform/sql/completions.sql +138 -0
  32. agent_starter_pack/base_template/deployment/terraform/storage.tf +0 -9
  33. agent_starter_pack/base_template/deployment/terraform/variables.tf +15 -19
  34. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} +20 -22
  35. agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +206 -0
  36. agent_starter_pack/base_template/pyproject.toml +5 -17
  37. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +19 -4
  38. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +36 -11
  39. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml +24 -5
  40. agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml +44 -9
  41. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/telemetry.py +96 -0
  42. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/typing.py +4 -6
  43. agent_starter_pack/{agents/crewai_coding_crew/app/crew/config/agents.yaml → base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/__init__.py } +9 -23
  44. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/part_converter.py +138 -0
  45. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/__init__.py +13 -0
  46. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/a2a_agent_executor.py +265 -0
  47. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/task_result_aggregator.py +152 -0
  48. agent_starter_pack/cli/commands/create.py +40 -4
  49. agent_starter_pack/cli/commands/enhance.py +1 -1
  50. agent_starter_pack/cli/commands/register_gemini_enterprise.py +1070 -0
  51. agent_starter_pack/cli/main.py +2 -0
  52. agent_starter_pack/cli/utils/cicd.py +20 -4
  53. agent_starter_pack/cli/utils/template.py +257 -25
  54. agent_starter_pack/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +113 -16
  55. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/README.md +2 -2
  56. agent_starter_pack/deployment_targets/agent_engine/tests/load_test/load_test.py +178 -9
  57. agent_starter_pack/deployment_targets/agent_engine/tests/{% if cookiecutter.is_a2a %}helpers.py{% else %}unused_helpers.py{% endif %} +138 -0
  58. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py +193 -307
  59. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/app_utils/deploy.py +414 -0
  60. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/{utils → app_utils}/{% if cookiecutter.is_adk_live %}expose_app.py{% else %}unused_expose_app.py{% endif %} +13 -14
  61. agent_starter_pack/deployment_targets/cloud_run/Dockerfile +4 -1
  62. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +85 -86
  63. agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/service.tf +139 -107
  64. agent_starter_pack/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +228 -12
  65. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/README.md +4 -4
  66. agent_starter_pack/deployment_targets/cloud_run/tests/load_test/load_test.py +92 -12
  67. agent_starter_pack/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/{server.py → fast_api_app.py} +194 -121
  68. agent_starter_pack/frontends/adk_live_react/frontend/package-lock.json +18 -18
  69. agent_starter_pack/frontends/adk_live_react/frontend/src/multimodal-live-types.ts +5 -3
  70. agent_starter_pack/resources/docs/adk-cheatsheet.md +198 -41
  71. agent_starter_pack/resources/locks/uv-adk_a2a_base-agent_engine.lock +4966 -0
  72. agent_starter_pack/resources/locks/uv-adk_a2a_base-cloud_run.lock +5011 -0
  73. agent_starter_pack/resources/locks/uv-adk_base-agent_engine.lock +1443 -709
  74. agent_starter_pack/resources/locks/uv-adk_base-cloud_run.lock +1058 -874
  75. agent_starter_pack/resources/locks/uv-adk_live-agent_engine.lock +1443 -709
  76. agent_starter_pack/resources/locks/uv-adk_live-cloud_run.lock +1058 -874
  77. agent_starter_pack/resources/locks/uv-agentic_rag-agent_engine.lock +1568 -749
  78. agent_starter_pack/resources/locks/uv-agentic_rag-cloud_run.lock +1123 -929
  79. agent_starter_pack/resources/locks/{uv-langgraph_base_react-agent_engine.lock → uv-langgraph_base-agent_engine.lock} +1714 -1689
  80. agent_starter_pack/resources/locks/{uv-langgraph_base_react-cloud_run.lock → uv-langgraph_base-cloud_run.lock} +1285 -2374
  81. agent_starter_pack/utils/watch_and_rebuild.py +1 -1
  82. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/METADATA +3 -6
  83. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/RECORD +89 -93
  84. agent_starter_pack-0.21.0.dist-info/entry_points.txt +2 -0
  85. llm.txt +4 -5
  86. agent_starter_pack/agents/crewai_coding_crew/README.md +0 -34
  87. agent_starter_pack/agents/crewai_coding_crew/app/agent.py +0 -47
  88. agent_starter_pack/agents/crewai_coding_crew/app/crew/config/tasks.yaml +0 -37
  89. agent_starter_pack/agents/crewai_coding_crew/app/crew/crew.py +0 -71
  90. agent_starter_pack/agents/crewai_coding_crew/tests/integration/test_agent.py +0 -47
  91. agent_starter_pack/agents/langgraph_base_react/README.md +0 -9
  92. agent_starter_pack/agents/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb +0 -1574
  93. agent_starter_pack/base_template/deployment/terraform/dev/log_sinks.tf +0 -69
  94. agent_starter_pack/base_template/deployment/terraform/log_sinks.tf +0 -79
  95. agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/utils/tracing.py +0 -155
  96. agent_starter_pack/cli/utils/register_gemini_enterprise.py +0 -406
  97. agent_starter_pack/deployment_targets/agent_engine/deployment/terraform/{% if not cookiecutter.is_adk_live %}service.tf{% else %}unused_service.tf{% endif %} +0 -82
  98. agent_starter_pack/deployment_targets/agent_engine/notebooks/intro_agent_engine.ipynb +0 -1025
  99. agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/utils/deployment.py +0 -99
  100. agent_starter_pack/frontends/streamlit/frontend/side_bar.py +0 -214
  101. agent_starter_pack/frontends/streamlit/frontend/streamlit_app.py +0 -265
  102. agent_starter_pack/frontends/streamlit/frontend/utils/chat_utils.py +0 -67
  103. agent_starter_pack/frontends/streamlit/frontend/utils/local_chat_history.py +0 -127
  104. agent_starter_pack/frontends/streamlit/frontend/utils/message_editing.py +0 -59
  105. agent_starter_pack/frontends/streamlit/frontend/utils/multimodal_utils.py +0 -217
  106. agent_starter_pack/frontends/streamlit/frontend/utils/stream_handler.py +0 -310
  107. agent_starter_pack/frontends/streamlit/frontend/utils/title_summary.py +0 -94
  108. agent_starter_pack/resources/locks/uv-crewai_coding_crew-agent_engine.lock +0 -6650
  109. agent_starter_pack/resources/locks/uv-crewai_coding_crew-cloud_run.lock +0 -7825
  110. agent_starter_pack-0.18.2.dist-info/entry_points.txt +0 -3
  111. /agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/notebooks/evaluating_langgraph_agent.ipynb +0 -0
  112. /agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/gcs.py +0 -0
  113. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/WHEEL +0 -0
  114. {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/licenses/LICENSE +0 -0
@@ -13,6 +13,7 @@ This document serves as a long-form, comprehensive reference for building, orche
13
13
  * 2.1 Basic `LlmAgent` Setup
14
14
  * 2.2 Advanced `LlmAgent` Configuration
15
15
  * 2.3 LLM Instruction Crafting
16
+ * 2.4 Production Wrapper (`App`)
16
17
  3. [Orchestration with Workflow Agents](#3-orchestration-with-workflow-agents)
17
18
  * 3.1 `SequentialAgent`: Linear Execution
18
19
  * 3.2 `ParallelAgent`: Concurrent Execution
@@ -34,16 +35,18 @@ This document serves as a long-form, comprehensive reference for building, orche
34
35
  * 7.1 Defining Function Tools: Principles & Best Practices
35
36
  * 7.2 The `ToolContext` Object: Accessing Runtime Information
36
37
  * 7.3 All Tool Types & Their Usage
38
+ * 7.4 Tool Confirmation (Human-in-the-Loop)
37
39
  8. [Context, State, and Memory Management](#8-context-state-and-memory-management)
38
40
  * 8.1 The `Session` Object & `SessionService`
39
41
  * 8.2 `State`: The Conversational Scratchpad
40
42
  * 8.3 `Memory`: Long-Term Knowledge & Retrieval
41
43
  * 8.4 `Artifacts`: Binary Data Management
42
44
  9. [Runtime, Events, and Execution Flow](#9-runtime-events-and-execution-flow)
43
- * 9.1 The `Runner`: The Orchestrator
44
- * 9.2 The Event Loop: Core Execution Flow
45
- * 9.3 `Event` Object: The Communication Backbone
46
- * 9.4 Asynchronous Programming (Python Specific)
45
+ * 9.1 Runtime Configuration (`RunConfig`)
46
+ * 9.2 The `Runner`: The Orchestrator
47
+ * 9.3 The Event Loop: Core Execution Flow
48
+ * 9.4 `Event` Object: The Communication Backbone
49
+ * 9.5 Asynchronous Programming (Python Specific)
47
50
  10. [Control Flow with Callbacks](#10-control-flow-with-callbacks)
48
51
  * 10.1 Callback Mechanism: Interception & Control
49
52
  * 10.2 Types of Callbacks
@@ -230,7 +233,7 @@ Agent Config agents can be deployed using:
230
233
  * **Model Support**: Only Gemini models currently supported
231
234
  * **Language Support**: Custom tools must be written in Python
232
235
  * **Unsupported Agent Types**: `LangGraphAgent`, `A2aAgent`
233
- * **Unsupported Tools**: `AgentTool`, `LongRunningFunctionTool`, `VertexAiSearchTool`, `MCPToolset`, `CrewaiTool`, `LangchainTool`, `ExampleTool`
236
+ * **Unsupported Tools**: `AgentTool`, `LongRunningFunctionTool`, `VertexAiSearchTool`, `MCPToolset`, `LangchainTool`, `ExampleTool`
234
237
 
235
238
  For complete examples and reference, see the [ADK samples repository](https://github.com/search?q=repo%3Agoogle%2Fadk-python+path%3A%2F%5Econtributing%5C%2Fsamples%5C%2F%2F+.yaml&type=code).
236
239
 
@@ -385,7 +388,7 @@ The `instruction` is critical. It guides the LLM's behavior, persona, and tool u
385
388
 
386
389
  * **Be Specific & Concise**: Avoid ambiguity.
387
390
  * **Define Persona & Role**: Give the LLM a clear role.
388
- * **Constrain Behavior & Tool Use**: Explicitly state what the LLM should *and should not* do.
391
+ * **Constrain Behavior & Tool Use**: Explicitly state what the LLM *and should not* do.
389
392
  * **Define Output Format**: Tell the LLM *exactly* what its output should look like, especially when not using `output_schema`.
390
393
  * **Dynamic Injection**: Use `{state_key}` to inject runtime data from `session.state` into the prompt.
391
394
  * **Iteration**: Test, observe, and refine instructions.
@@ -449,6 +452,30 @@ report_composer = LlmAgent(
449
452
  )
450
453
  ```
451
454
 
455
+ ### 2.4 Production Wrapper (`App`)
456
+ Wraps the `root_agent` to enable production-grade runtime features that an `Agent` cannot handle alone.
457
+
458
+ ```python
459
+ from google.adk.apps.app import App
460
+ from google.adk.agents.context_cache_config import ContextCacheConfig
461
+ from google.adk.apps.events_compaction_config import EventsCompactionConfig
462
+ from google.adk.apps.resumability_config import ResumabilityConfig
463
+
464
+ production_app = App(
465
+ name="my_app",
466
+ root_agent=my_agent,
467
+ # 1. Reduce costs/latency for long contexts
468
+ context_cache_config=ContextCacheConfig(min_tokens=2048, ttl_seconds=600),
469
+ # 2. Allow resuming crashed workflows from last state
470
+ resumability_config=ResumabilityConfig(is_resumable=True),
471
+ # 3. Manage long conversation history automatically
472
+ events_compaction_config=EventsCompactionConfig(compaction_interval=5, overlap_size=1)
473
+ )
474
+
475
+ # Usage: Pass 'app' instead of 'agent' to the Runner
476
+ # runner = Runner(app=production_app, ...)
477
+ ```
478
+
452
479
  ---
453
480
 
454
481
  ## 3. Orchestration with Workflow Agents
@@ -615,6 +642,19 @@ A hierarchical (tree-like) structure of parent-child relationships defined by th
615
642
  * **Mechanism**: Wrap the target agent (`target_agent`) in `AgentTool(agent=target_agent)` and add it to the calling `LlmAgent`'s `tools` list. The `AgentTool` generates a `FunctionDeclaration` for the LLM. When called, `AgentTool` runs the target agent and returns its final response as the tool result.
616
643
  * **Best for**: Hierarchical task decomposition, where a higher-level agent needs a specific output from a lower-level agent.
617
644
 
645
+ **Delegation vs. Agent-as-a-Tool**
646
+ * **Delegation (`sub_agents`)**: The parent agent *transfers control*. The sub-agent interacts directly with the user for subsequent turns until it finishes.
647
+ * **Agent-as-a-Tool (`AgentTool`)**: The parent agent *calls* another agent like a function. The parent remains in control, receives the sub-agent's entire interaction as a single tool result, and summarizes it for the user.
648
+
649
+ ```python
650
+ # Delegation: "I'll let the specialist handle this conversation."
651
+ root = Agent(name="root", sub_agents=[specialist])
652
+
653
+ # Agent-as-a-Tool: "I need the specialist to do a task and give me the results."
654
+ from google.adk.tools import AgentTool
655
+ root = Agent(name="root", tools=[AgentTool(specialist)])
656
+ ```
657
+
618
658
  ### 4.3 Common Multi-Agent Patterns
619
659
 
620
660
  * **Coordinator/Dispatcher**: A central agent routes requests to specialized sub-agents (often via LLM-driven delegation).
@@ -896,14 +936,15 @@ Tools extend an agent's abilities beyond text generation.
896
936
 
897
937
  2. **Built-in Tools**: Ready-to-use tools provided by ADK.
898
938
  * `google_search`: Provides Google Search grounding.
899
- * `BuiltInCodeExecutor`: Enables sandboxed code execution.
939
+ * **Code Execution**:
940
+ * `BuiltInCodeExecutor`: Local, convenient for development. **Not** for untrusted production use.
941
+ * `GkeCodeExecutor`: Production-grade. Executes code in ephemeral, sandboxed pods on Google Kubernetes Engine (GKE) using gVisor for isolation. Requires GKE cluster setup.
900
942
  * `VertexAiSearchTool`: Provides grounding from your private Vertex AI Search data stores.
901
943
  * `BigQueryToolset`: A collection of tools for interacting with BigQuery (e.g., `list_datasets`, `execute_sql`).
902
944
  > **Warning**: An agent can only use one type of built-in tool at a time and they cannot be used in sub-agents.
903
945
 
904
946
  3. **Third-Party Tool Wrappers**: For seamless integration with other frameworks.
905
947
  * `LangchainTool`: Wraps a tool from the LangChain ecosystem.
906
- * `CrewaiTool`: Wraps a tool from the CrewAI library.
907
948
 
908
949
  4. **OpenAPI & Protocol Tools**: For interacting with APIs and services.
909
950
  * **`OpenAPIToolset`**: Automatically generates a set of `RestApiTool`s from an OpenAPI (Swagger) v3 specification.
@@ -914,6 +955,51 @@ Tools extend an agent's abilities beyond text generation.
914
955
  * **`ApplicationIntegrationToolset`**: Turns Application Integration workflows and Integration Connectors (e.g., Salesforce, SAP) into callable tools.
915
956
  * **Toolbox for Databases**: An open-source MCP server that ADK can connect to for database interactions.
916
957
 
958
+ 6. **Dynamic Toolsets (`BaseToolset`)**: Instead of a static list of tools, use a `Toolset` to dynamically determine which tools an agent can use based on the current context (e.g., user permissions).
959
+ ```python
960
+ from google.adk.tools.base_toolset import BaseToolset
961
+
962
+ class AdminAwareToolset(BaseToolset):
963
+ async def get_tools(self, context: ReadonlyContext) -> list[BaseTool]:
964
+ # Check state to see if user is admin
965
+ if context.state.get('user:role') == 'admin':
966
+ return [admin_delete_tool, standard_query_tool]
967
+ return [standard_query_tool]
968
+
969
+ # Usage:
970
+ agent = Agent(tools=[AdminAwareToolset()])
971
+ ```
972
+
973
+ ### 7.4 Tool Confirmation (Human-in-the-Loop)
974
+ ADK can pause tool execution to request human or system confirmation before proceeding, essential for sensitive actions.
975
+
976
+ * **Boolean Confirmation**: Simple yes/no via `FunctionTool(..., require_confirmation=True)`.
977
+ * **Dynamic Confirmation**: Pass a function to `require_confirmation` to decide at runtime based on arguments.
978
+ * **Advanced/Payload Confirmation**: Use `tool_context.request_confirmation()` inside the tool for structured feedback.
979
+
980
+ ```python
981
+ from google.adk.tools import FunctionTool, ToolContext
982
+
983
+ # 1. Simple Boolean Confirmation
984
+ # Pauses execution until a 'confirmed': True/False event is received.
985
+ sensitive_tool = FunctionTool(delete_database, require_confirmation=True)
986
+
987
+ # 2. Dynamic Threshold Confirmation
988
+ def needs_approval(amount: float, **kwargs) -> bool:
989
+ return amount > 10000
990
+
991
+ transfer_tool = FunctionTool(wire_money, require_confirmation=needs_approval)
992
+
993
+ # 3. Advanced Payload Confirmation (inside tool definition)
994
+ def book_flight(destination: str, price: float, tool_context: ToolContext):
995
+ # Pause and ask user to select a seat class before continuing
996
+ tool_context.request_confirmation(
997
+ hint="Please confirm booking and select seat class.",
998
+ payload={"seat_class": ["economy", "business", "first"]} # Expected structure
999
+ )
1000
+ return {"status": "pending_confirmation"}
1001
+ ```
1002
+
917
1003
  ---
918
1004
 
919
1005
  ## 8. Context, State, and Memory Management
@@ -935,7 +1021,7 @@ A mutable dictionary within `session.state` for short-term, dynamic data.
935
1021
  * **(No prefix)**: Session-specific (e.g., `session.state['booking_step']`).
936
1022
  * `user:`: Persistent for a `user_id` across all their sessions (e.g., `session.state['user:preferred_currency']`).
937
1023
  * `app:`: Persistent for `app_name` across all users and sessions.
938
- * `temp:`: Volatile, for the current `Invocation` turn only.
1024
+ * `temp:`: Ephemeral state that only exists for the current **invocation** (one user request -> final agent response cycle). It is discarded afterwards.
939
1025
 
940
1026
  ### 8.3 `Memory`: Long-Term Knowledge & Retrieval
941
1027
 
@@ -959,12 +1045,38 @@ For named, versioned binary data (files, images).
959
1045
 
960
1046
  The `Runner` is the central orchestrator of an ADK application.
961
1047
 
962
- ### 9.1 The `Runner`: The Orchestrator
1048
+ ### 9.1 Runtime Configuration (`RunConfig`)
1049
+ Passed to `run` or `run_live` to control execution limits and output formats.
1050
+
1051
+ ```python
1052
+ from google.adk.agents.run_config import RunConfig
1053
+ from google.genai import types
1054
+
1055
+ config = RunConfig(
1056
+ # Safety limits
1057
+ max_llm_calls=100, # Prevent infinite agent loops
1058
+
1059
+ # Streaming & Modality
1060
+ response_modalities=["AUDIO", "TEXT"], # Request specific output formats
1061
+
1062
+ # Voice configuration (for AUDIO modality)
1063
+ speech_config=types.SpeechConfig(
1064
+ voice_config=types.VoiceConfig(
1065
+ prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Kore")
1066
+ )
1067
+ ),
1068
+
1069
+ # Debugging
1070
+ save_input_blobs_as_artifacts=True # Save uploaded files to ArtifactService
1071
+ )
1072
+ ```
1073
+
1074
+ ### 9.2 The `Runner`: The Orchestrator
963
1075
 
964
1076
  * **Role**: Manages the agent's lifecycle, the event loop, and coordinates with services.
965
1077
  * **Entry Point**: `runner.run_async(user_id, session_id, new_message)`.
966
1078
 
967
- ### 9.2 The Event Loop: Core Execution Flow
1079
+ ### 9.3 The Event Loop: Core Execution Flow
968
1080
 
969
1081
  1. User input becomes a `user` `Event`.
970
1082
  2. `Runner` calls `agent.run_async(invocation_context)`.
@@ -972,7 +1084,7 @@ The `Runner` is the central orchestrator of an ADK application.
972
1084
  4. `Runner` processes the `Event` (applies state changes, etc.) and yields it to the client.
973
1085
  5. Execution resumes. This cycle repeats until the agent is done.
974
1086
 
975
- ### 9.3 `Event` Object: The Communication Backbone
1087
+ ### 9.4 `Event` Object: The Communication Backbone
976
1088
 
977
1089
  `Event` objects carry all information and signals.
978
1090
 
@@ -981,7 +1093,7 @@ The `Runner` is the central orchestrator of an ADK application.
981
1093
  * `Event.actions`: Signals side effects (`state_delta`, `transfer_to_agent`, `escalate`).
982
1094
  * `Event.is_final_response()`: Helper to identify the complete, displayable message.
983
1095
 
984
- ### 9.4 Asynchronous Programming (Python Specific)
1096
+ ### 9.5 Asynchronous Programming (Python Specific)
985
1097
 
986
1098
  ADK is built on `asyncio`. Use `async def`, `await`, and `async for` for all I/O-bound operations.
987
1099
 
@@ -1086,22 +1198,28 @@ Plugins are stateful, reusable modules for implementing cross-cutting concerns t
1086
1198
  * **Execution Order**: Plugin callbacks run **before** their corresponding agent-level callbacks. If a plugin callback returns a value, the agent-level callback is skipped.
1087
1199
  * **Defining a Plugin**: Inherit from `BasePlugin` and implement callback methods.
1088
1200
  ```python
1089
- from google.adk.plugins.base_plugin import BasePlugin
1201
+ from google.adk.plugins import BasePlugin
1090
1202
  from google.adk.agents.callback_context import CallbackContext
1203
+ from google.adk.models.llm_request import LlmRequest
1091
1204
 
1092
- class InvocationCounterPlugin(BasePlugin):
1205
+ class AuditLoggingPlugin(BasePlugin):
1093
1206
  def __init__(self):
1094
- super().__init__(name="invocation_counter")
1095
- self.agent_runs = 0
1207
+ super().__init__(name="audit_logger")
1208
+
1209
+ async def before_model_callback(self, callback_context: CallbackContext, llm_request: LlmRequest):
1210
+ # Log every prompt sent to any LLM
1211
+ print(f"[AUDIT] Agent {callback_context.agent_name} calling LLM with: {llm_request.contents[-1]}")
1096
1212
 
1097
- async def before_agent_callback(self, callback_context: CallbackContext, **kwargs):
1098
- self.agent_runs += 1
1099
- print(f"[Plugin] Total agent runs: {self.agent_runs}")
1213
+ async def on_tool_error_callback(self, tool, error, **kwargs):
1214
+ # Global error handler for all tools
1215
+ print(f"[ALERT] Tool {tool.name} failed: {error}")
1216
+ # Optionally return a dict to suppress the exception and provide fallback
1217
+ return {"status": "error", "message": "An internal error occurred, handled by plugin."}
1100
1218
  ```
1101
1219
  * **Registering a Plugin**:
1102
1220
  ```python
1103
1221
  from google.adk.runners import Runner
1104
- # runner = Runner(agent=root_agent, ..., plugins=[InvocationCounterPlugin()])
1222
+ # runner = Runner(agent=root_agent, ..., plugins=[AuditLoggingPlugin()])
1105
1223
  ```
1106
1224
  * **Error Handling Callbacks**: Plugins support unique error hooks like `on_model_error_callback` and `on_tool_error_callback` for centralized error management.
1107
1225
  * **Limitation**: Plugins are not supported by the `adk web` interface.
@@ -1333,19 +1451,18 @@ Multi-layered defense against harmful content, misalignment, and unsafe actions.
1333
1451
  ```
1334
1452
  * **Tool/Callback `print` statements**: Simple logging directly within your functions.
1335
1453
  * **Logging**: Use Python's standard `logging` module. Control verbosity with `adk web --log_level DEBUG` or `adk web -v`.
1336
- * **Observability Integrations**: ADK supports OpenTelemetry, enabling integration with platforms like:
1337
- * Google Cloud Trace
1338
- * AgentOps
1339
- * Arize AX
1340
- * Phoenix
1341
- * Weave by WandB
1342
- ```python
1343
- # Example using Comet Opik integration (conceptual)
1344
- # pip install comet_opik_adk
1345
- # from comet_opik_adk import enable_opik_tracing
1346
- # enable_opik_tracing() # Call at app startup
1347
- # Then run your ADK app, traces appear in Comet workspace.
1348
- ```
1454
+ * **One-Line Observability Integrations**: ADK has native hooks for popular tracing platforms.
1455
+ * **AgentOps**:
1456
+ ```python
1457
+ import agentops
1458
+ agentops.init(api_key="...") # Automatically instruments ADK agents
1459
+ ```
1460
+ * **Arize Phoenix**:
1461
+ ```python
1462
+ from phoenix.otel import register
1463
+ register(project_name="my_agent", auto_instrument=True)
1464
+ ```
1465
+ * **Google Cloud Trace**: Enable via flag during deployment: `adk deploy [cloud_run|agent_engine] --trace_to_cloud ...`
1349
1466
  * **Session History (`session.events`)**: Persisted for detailed post-mortem analysis.
1350
1467
 
1351
1468
  ---
@@ -1354,11 +1471,52 @@ Multi-layered defense against harmful content, misalignment, and unsafe actions.
1354
1471
 
1355
1472
  ADK supports real-time, bidirectional communication for interactive experiences like live voice conversations.
1356
1473
 
1357
- * **Bidirectional Streaming**: Enables low-latency, two-way data flow (text, audio, video) between the client and agent, allowing for interruptions.
1358
- * **Core Components**:
1359
- * **`Runner.run_live()`**: The entry point for starting a streaming session.
1360
- * **`LiveRequestQueue`**: A queue for sending data (e.g., audio chunks) from the client to the agent during a live session.
1361
- * **`RunConfig`**: A configuration object passed to `run_live()` to specify modalities (`['TEXT', 'AUDIO']`), speech synthesis options, etc.
1474
+ #### Bidirectional Streaming Loop (`run_live`)
1475
+ For real-time voice/video, use `run_live` with a `LiveRequestQueue`. This enables low-latency, two-way communication where the user can interrupt the agent.
1476
+
1477
+ ```python
1478
+ import asyncio
1479
+ from google.adk.agents import LiveRequestQueue
1480
+ from google.adk.agents.run_config import RunConfig
1481
+
1482
+ async def start_streaming_session(runner, session, user_id):
1483
+ # 1. Configure modalities (e.g., AUDIO output for voice agents)
1484
+ run_config = RunConfig(response_modalities=["AUDIO"])
1485
+
1486
+ # 2. Create input queue for client data (audio chunks, text)
1487
+ live_queue = LiveRequestQueue()
1488
+
1489
+ # 3. Start the bidirectional stream
1490
+ live_events = runner.run_live(
1491
+ session=session,
1492
+ live_request_queue=live_queue,
1493
+ run_config=run_config
1494
+ )
1495
+
1496
+ # 4. Process events (simplified loop)
1497
+ try:
1498
+ async for event in live_events:
1499
+ # Handle agent output (text or audio bytes)
1500
+ if event.content and event.content.parts:
1501
+ part = event.content.parts[0]
1502
+ if part.inline_data and part.inline_data.mime_type.startswith("audio/"):
1503
+ # Send audio bytes to client
1504
+ await client.send_audio(part.inline_data.data)
1505
+ elif part.text:
1506
+ # Send text to client
1507
+ await client.send_text(part.text)
1508
+
1509
+ # Handle turn signals
1510
+ if event.turn_complete:
1511
+ pass # Signal client that agent finished speaking
1512
+ finally:
1513
+ live_queue.close()
1514
+
1515
+ # To send user input to agent during the stream:
1516
+ # await live_queue.send_content(Content(role="user", parts=[Part(text="Hello")]))
1517
+ # await live_queue.send_realtime(Blob(mime_type="audio/pcm", data=audio_bytes))
1518
+ ```
1519
+
1362
1520
  * **Streaming Tools**: A special type of `FunctionTool` that can stream intermediate results back to the agent.
1363
1521
  * **Definition**: Must be an `async` function with a return type of `AsyncGenerator`.
1364
1522
  ```python
@@ -1384,7 +1542,6 @@ ADK supports real-time, bidirectional communication for interactive experiences
1384
1542
  ]
1385
1543
  )
1386
1544
  ```
1387
- * **Streaming Modalities**: `RunConfig.response_modalities=['TEXT', 'AUDIO']`.
1388
1545
 
1389
1546
  ---
1390
1547
 
@@ -1423,7 +1580,7 @@ ADK supports real-time, bidirectional communication for interactive experiences
1423
1580
  ### Testing the output of an agent
1424
1581
 
1425
1582
  The following script demonstrates how to programmatically test an agent's output. This approach is extremely useful when an LLM or coding agent needs to interact with a work-in-progress agent, as well as for automated testing, debugging, or when you need to integrate agent execution into other workflows:
1426
- ```
1583
+ ```python
1427
1584
  import asyncio
1428
1585
 
1429
1586
  from google.adk.runners import Runner