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.
- agent_starter_pack/agents/{langgraph_base_react → adk_a2a_base}/.template/templateconfig.yaml +5 -12
- agent_starter_pack/agents/adk_a2a_base/README.md +37 -0
- agent_starter_pack/{frontends/streamlit/frontend/style/app_markdown.py → agents/adk_a2a_base/app/__init__.py} +3 -23
- agent_starter_pack/agents/adk_a2a_base/app/agent.py +70 -0
- agent_starter_pack/agents/adk_a2a_base/notebooks/adk_a2a_app_testing.ipynb +583 -0
- agent_starter_pack/agents/{crewai_coding_crew/notebooks/evaluating_crewai_agent.ipynb → adk_a2a_base/notebooks/evaluating_adk_agent.ipynb} +163 -199
- agent_starter_pack/agents/adk_a2a_base/tests/integration/test_agent.py +58 -0
- agent_starter_pack/agents/adk_base/app/__init__.py +2 -2
- agent_starter_pack/agents/adk_base/app/agent.py +3 -0
- agent_starter_pack/agents/adk_base/notebooks/adk_app_testing.ipynb +13 -28
- agent_starter_pack/agents/adk_live/app/__init__.py +17 -0
- agent_starter_pack/agents/adk_live/app/agent.py +3 -0
- agent_starter_pack/agents/agentic_rag/app/__init__.py +2 -2
- agent_starter_pack/agents/agentic_rag/app/agent.py +3 -0
- agent_starter_pack/agents/agentic_rag/notebooks/adk_app_testing.ipynb +13 -28
- agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/.template/templateconfig.yaml +12 -9
- agent_starter_pack/agents/langgraph_base/README.md +30 -0
- agent_starter_pack/agents/langgraph_base/app/__init__.py +17 -0
- agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/app/agent.py +4 -4
- agent_starter_pack/agents/{langgraph_base_react → langgraph_base}/tests/integration/test_agent.py +1 -1
- agent_starter_pack/base_template/.gitignore +4 -2
- agent_starter_pack/base_template/Makefile +110 -16
- agent_starter_pack/base_template/README.md +97 -12
- agent_starter_pack/base_template/deployment/terraform/dev/apis.tf +4 -6
- agent_starter_pack/base_template/deployment/terraform/dev/providers.tf +5 -1
- agent_starter_pack/base_template/deployment/terraform/dev/variables.tf +5 -3
- agent_starter_pack/base_template/deployment/terraform/dev/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +193 -0
- agent_starter_pack/base_template/deployment/terraform/github.tf +16 -9
- agent_starter_pack/base_template/deployment/terraform/locals.tf +7 -7
- agent_starter_pack/base_template/deployment/terraform/providers.tf +5 -1
- agent_starter_pack/base_template/deployment/terraform/sql/completions.sql +138 -0
- agent_starter_pack/base_template/deployment/terraform/storage.tf +0 -9
- agent_starter_pack/base_template/deployment/terraform/variables.tf +15 -19
- 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
- agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +206 -0
- agent_starter_pack/base_template/pyproject.toml +5 -17
- agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +19 -4
- agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +36 -11
- agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml +24 -5
- agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml +44 -9
- agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/telemetry.py +96 -0
- agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/typing.py +4 -6
- 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
- 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
- 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
- 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
- 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
- agent_starter_pack/cli/commands/create.py +40 -4
- agent_starter_pack/cli/commands/enhance.py +1 -1
- agent_starter_pack/cli/commands/register_gemini_enterprise.py +1070 -0
- agent_starter_pack/cli/main.py +2 -0
- agent_starter_pack/cli/utils/cicd.py +20 -4
- agent_starter_pack/cli/utils/template.py +257 -25
- agent_starter_pack/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +113 -16
- agent_starter_pack/deployment_targets/agent_engine/tests/load_test/README.md +2 -2
- agent_starter_pack/deployment_targets/agent_engine/tests/load_test/load_test.py +178 -9
- agent_starter_pack/deployment_targets/agent_engine/tests/{% if cookiecutter.is_a2a %}helpers.py{% else %}unused_helpers.py{% endif %} +138 -0
- agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py +193 -307
- agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/app_utils/deploy.py +414 -0
- 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
- agent_starter_pack/deployment_targets/cloud_run/Dockerfile +4 -1
- agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +85 -86
- agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/service.tf +139 -107
- agent_starter_pack/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +228 -12
- agent_starter_pack/deployment_targets/cloud_run/tests/load_test/README.md +4 -4
- agent_starter_pack/deployment_targets/cloud_run/tests/load_test/load_test.py +92 -12
- agent_starter_pack/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/{server.py → fast_api_app.py} +194 -121
- agent_starter_pack/frontends/adk_live_react/frontend/package-lock.json +18 -18
- agent_starter_pack/frontends/adk_live_react/frontend/src/multimodal-live-types.ts +5 -3
- agent_starter_pack/resources/docs/adk-cheatsheet.md +198 -41
- agent_starter_pack/resources/locks/uv-adk_a2a_base-agent_engine.lock +4966 -0
- agent_starter_pack/resources/locks/uv-adk_a2a_base-cloud_run.lock +5011 -0
- agent_starter_pack/resources/locks/uv-adk_base-agent_engine.lock +1443 -709
- agent_starter_pack/resources/locks/uv-adk_base-cloud_run.lock +1058 -874
- agent_starter_pack/resources/locks/uv-adk_live-agent_engine.lock +1443 -709
- agent_starter_pack/resources/locks/uv-adk_live-cloud_run.lock +1058 -874
- agent_starter_pack/resources/locks/uv-agentic_rag-agent_engine.lock +1568 -749
- agent_starter_pack/resources/locks/uv-agentic_rag-cloud_run.lock +1123 -929
- agent_starter_pack/resources/locks/{uv-langgraph_base_react-agent_engine.lock → uv-langgraph_base-agent_engine.lock} +1714 -1689
- agent_starter_pack/resources/locks/{uv-langgraph_base_react-cloud_run.lock → uv-langgraph_base-cloud_run.lock} +1285 -2374
- agent_starter_pack/utils/watch_and_rebuild.py +1 -1
- {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/METADATA +3 -6
- {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/RECORD +89 -93
- agent_starter_pack-0.21.0.dist-info/entry_points.txt +2 -0
- llm.txt +4 -5
- agent_starter_pack/agents/crewai_coding_crew/README.md +0 -34
- agent_starter_pack/agents/crewai_coding_crew/app/agent.py +0 -47
- agent_starter_pack/agents/crewai_coding_crew/app/crew/config/tasks.yaml +0 -37
- agent_starter_pack/agents/crewai_coding_crew/app/crew/crew.py +0 -71
- agent_starter_pack/agents/crewai_coding_crew/tests/integration/test_agent.py +0 -47
- agent_starter_pack/agents/langgraph_base_react/README.md +0 -9
- agent_starter_pack/agents/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb +0 -1574
- agent_starter_pack/base_template/deployment/terraform/dev/log_sinks.tf +0 -69
- agent_starter_pack/base_template/deployment/terraform/log_sinks.tf +0 -79
- agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/utils/tracing.py +0 -155
- agent_starter_pack/cli/utils/register_gemini_enterprise.py +0 -406
- agent_starter_pack/deployment_targets/agent_engine/deployment/terraform/{% if not cookiecutter.is_adk_live %}service.tf{% else %}unused_service.tf{% endif %} +0 -82
- agent_starter_pack/deployment_targets/agent_engine/notebooks/intro_agent_engine.ipynb +0 -1025
- agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/utils/deployment.py +0 -99
- agent_starter_pack/frontends/streamlit/frontend/side_bar.py +0 -214
- agent_starter_pack/frontends/streamlit/frontend/streamlit_app.py +0 -265
- agent_starter_pack/frontends/streamlit/frontend/utils/chat_utils.py +0 -67
- agent_starter_pack/frontends/streamlit/frontend/utils/local_chat_history.py +0 -127
- agent_starter_pack/frontends/streamlit/frontend/utils/message_editing.py +0 -59
- agent_starter_pack/frontends/streamlit/frontend/utils/multimodal_utils.py +0 -217
- agent_starter_pack/frontends/streamlit/frontend/utils/stream_handler.py +0 -310
- agent_starter_pack/frontends/streamlit/frontend/utils/title_summary.py +0 -94
- agent_starter_pack/resources/locks/uv-crewai_coding_crew-agent_engine.lock +0 -6650
- agent_starter_pack/resources/locks/uv-crewai_coding_crew-cloud_run.lock +0 -7825
- agent_starter_pack-0.18.2.dist-info/entry_points.txt +0 -3
- /agent_starter_pack/agents/{crewai_coding_crew → langgraph_base}/notebooks/evaluating_langgraph_agent.ipynb +0 -0
- /agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/{utils → app_utils}/gcs.py +0 -0
- {agent_starter_pack-0.18.2.dist-info → agent_starter_pack-0.21.0.dist-info}/WHEEL +0 -0
- {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
|
|
44
|
-
* 9.2 The
|
|
45
|
-
* 9.3
|
|
46
|
-
* 9.4
|
|
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`, `
|
|
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
|
|
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
|
-
*
|
|
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:`:
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
1205
|
+
class AuditLoggingPlugin(BasePlugin):
|
|
1093
1206
|
def __init__(self):
|
|
1094
|
-
super().__init__(name="
|
|
1095
|
-
|
|
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
|
|
1098
|
-
|
|
1099
|
-
print(f"[
|
|
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=[
|
|
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
|
|
1337
|
-
*
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
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
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
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
|