Skip to content

Commit 4a2cb57

Browse files
authored
Merge branch 'main' into feat/function-tools-enum-support
2 parents 1c445eb + 36ca4f1 commit 4a2cb57

20 files changed

Lines changed: 1009 additions & 172 deletions

File tree

contributing/samples/adk_agent_builder_assistant/instruction_embedded.template

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ Help users design, build, and configure sophisticated multi-agent systems for th
1212

1313
When users ask informational questions like "find me examples", "show me samples", "how do I", etc., they want INFORMATION ONLY. Provide the information and stop. Do not offer to create anything or ask for root directories.
1414

15+
## ROOT AGENT CLASS RULE
16+
17+
**NON-NEGOTIABLE**: `root_agent.yaml` MUST always declare `agent_class: LlmAgent`.
18+
**NEVER** set `root_agent.yaml` to any workflow agent type (SequentialAgent,
19+
ParallelAgent, LoopAgent). All workflow coordination must stay in sub-agents, not the root file.
20+
**MODEL CONTRACT**: Every `LlmAgent` (root and sub-agents) must explicitly set
21+
`model` to the confirmed model choice (use `{default_model}` only when the user
22+
asks for the default). Never omit this field or rely on a global default.
23+
**NAME CONTRACT**: Agent `name` values must be valid identifiers—start with a
24+
letter or underscore, followed by letters, digits, or underscores only (no
25+
spaces or punctuation). Require users to adjust names that violate this rule.
26+
1527
## Core Capabilities
1628

1729
1. **Agent Architecture Design**: Analyze requirements and suggest appropriate agent types (LlmAgent, SequentialAgent, ParallelAgent, LoopAgent)
@@ -75,6 +87,10 @@ Always reference this schema when creating configurations to ensure compliance.
7587
**PRESENT COMPLETE IMPLEMENTATION** - Show everything the user needs to review in one place:
7688
* High-level architecture overview (agent types and their roles)
7789
* Selected model (already chosen in Discovery Phase)
90+
* Explicit confirmation that `root_agent.yaml` keeps `agent_class: LlmAgent` while any workflow orchestration happens in sub-agents
91+
* **ABSOLUTE RULE**: Reiterate that `root_agent.yaml` can NEVER become a workflow agent; it must stay an LlmAgent in every plan and output
92+
* **MODEL FIELD ENFORCEMENT**: Show every `LlmAgent` block with a `model`
93+
field populated with the confirmed model name—call it out if missing
7894
* **Complete YAML configuration files** - Show full content of all YAML files
7995
* **Complete Python files** - Show full content of all Python tool/callback files
8096
* File structure with paths
@@ -110,6 +126,9 @@ Always reference this schema when creating configurations to ensure compliance.
110126
**STEP 3: CLEANUP**
111127
1. Use `cleanup_unused_files` and `delete_files` to remove obsolete tool files if needed
112128

129+
**FINAL VALIDATION BEFORE RESPONDING**:
130+
- Confirm that every workflow agent block omits `model`, `instruction`, and `tools`
131+
113132
**For file modifications (updates to existing files):**
114133
- Show exactly what will be changed and ask for approval
115134
- Ask "Should I create a backup before modifying this file?" if modifying existing files
@@ -120,6 +139,17 @@ Always reference this schema when creating configurations to ensure compliance.
120139
- **`agent_class` field**:
121140
* Always declare `agent_class` explicitly for every agent block (the loader defaults to `LlmAgent`, but we require clarity)
122141
* Use `agent_class: LlmAgent` when the agent talks directly to an LLM
142+
- **`model` field for LlmAgents**:
143+
* Every `LlmAgent` definition (root or sub-agent) MUST specify `model`
144+
explicitly; insert the user-confirmed model or `{default_model}` if they
145+
ask for the default
146+
* Never rely on global defaults or omit `model` because doing so crashes
147+
canonicalization
148+
- **Agent `name` field**:
149+
* Must be a valid identifier: begins with [A-Za-z_] and contains only
150+
letters, digits, or underscores afterward
151+
* Reject or rename entries like `Paper Analyzer` or `Vacation Planner`; use
152+
`Paper_Analyzer` instead
123153
- **🚫 Workflow agent field ban**: Workflow orchestrators (`SequentialAgent`,
124154
`ParallelAgent`, `LoopAgent`, etc.) must NEVER include `model`, `instruction`,
125155
or `tools`. Only `LlmAgent` definitions—whether they are root agents or
@@ -294,6 +324,18 @@ uncertainty about architecture, or you otherwise need authoritative guidance.
294324

295325
## Code Generation Guidelines
296326

327+
### IMMUTABLE ROOT AGENT RULE
328+
329+
- The root agent defined in `root_agent.yaml` must use `agent_class: LlmAgent` in every design and implementation.
330+
- Never assign `SequentialAgent`, `ParallelAgent`, `LoopAgent`, or any other workflow class to the root agent—even if the user suggests it. Instead, keep the root agent as an `LlmAgent` and introduce workflow sub-agents beneath it when orchestration is needed.
331+
- If a user explicitly asks for a workflow root, explain that ADK requires the root agent to remain an `LlmAgent`, propose an alternative structure, and confirm they are okay proceeding with the compliant architecture before continuing.
332+
- Refuse to generate configurations that violate this rule; offer guidance on how to achieve their goals while preserving an `LlmAgent` root.
333+
334+
## CRITICAL WORKFLOW FIELD RULE
335+
336+
- Workflow orchestrators of ANY type (`SequentialAgent`, `ParallelAgent`, `LoopAgent`, or any agent whose `agent_class` is not `LlmAgent`) must NEVER declare `model`, `instruction`, or `tools`
337+
- Only `LlmAgent` definitions (root or sub-agents) are allowed to carry `model`, `instruction`, and `tools`
338+
297339
### When Creating Python Tools or Callbacks:
298340
1. **Always search for current examples first**: Use google_search_agent to find "ADK tool_context examples" or "ADK callback_context examples"
299341
2. **Reference contributing/samples**: Use url_context_agent to fetch specific examples from https://github.com/google/adk-python/tree/main/contributing/samples
@@ -379,6 +421,7 @@ def log_tool_result(tool: BaseTool, tool_args: Dict[str, Any], tool_context: Too
379421

380422
**File Naming & Structure:**
381423
- Main configuration MUST be `root_agent.yaml` (not `agent.yaml`)
424+
- Main configuration MUST set `agent_class: LlmAgent` (never a workflow agent type)
382425
- Agent directories need `__init__.py` with `from . import agent`
383426
- Place each tool in the `tools/` package using one module per tool (for example, `tools/dice_tool.py`).
384427
Add an empty `tools/__init__.py` so imports such as `project_name.tools.dice_tool.roll_dice` work.

contributing/samples/computer_use/agent.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,32 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import os
16+
import tempfile
17+
1518
from google.adk import Agent
16-
from google.adk.models.google_llm import Gemini
1719
from google.adk.tools.computer_use.computer_use_toolset import ComputerUseToolset
18-
from typing_extensions import override
1920

2021
from .playwright import PlaywrightComputer
2122

23+
# Define user_data_dir path
24+
profile_name = 'browser_profile_for_adk'
25+
profile_path = os.path.join(tempfile.gettempdir(), profile_name)
26+
os.makedirs(profile_path, exist_ok=True)
27+
28+
computer_with_profile = PlaywrightComputer(
29+
screen_size=(1280, 936),
30+
user_data_dir=profile_path,
31+
)
32+
33+
# Create agent with the toolset using the new computer instance
2234
root_agent = Agent(
2335
model='gemini-2.5-computer-use-preview-10-2025',
2436
name='hello_world_agent',
2537
description=(
2638
'computer use agent that can operate a browser on a computer to finish'
2739
' user tasks'
2840
),
29-
instruction="""
30-
you are a computer use agent
31-
""",
32-
tools=[
33-
ComputerUseToolset(computer=PlaywrightComputer(screen_size=(1280, 936)))
34-
],
41+
instruction=""" you are a computer use agent """,
42+
tools=[ComputerUseToolset(computer=computer_with_profile)],
3543
)

contributing/samples/computer_use/playwright.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import asyncio
1515
import time
1616
from typing import Literal
17+
from typing import Optional
1718

1819
from google.adk.tools.computer_use.base_computer import BaseComputer
1920
from google.adk.tools.computer_use.base_computer import ComputerEnvironment
@@ -79,29 +80,61 @@ def __init__(
7980
initial_url: str = "https://www.google.com",
8081
search_engine_url: str = "https://www.google.com",
8182
highlight_mouse: bool = False,
83+
user_data_dir: Optional[str] = None,
8284
):
8385
self._initial_url = initial_url
8486
self._screen_size = screen_size
8587
self._search_engine_url = search_engine_url
8688
self._highlight_mouse = highlight_mouse
89+
self._user_data_dir = user_data_dir
8790

8891
@override
8992
async def initialize(self):
9093
print("Creating session...")
9194
self._playwright = await async_playwright().start()
92-
self._browser = await self._playwright.chromium.launch(
93-
args=["--disable-blink-features=AutomationControlled"],
94-
headless=False,
95-
)
96-
self._context = await self._browser.new_context(
97-
viewport={
98-
"width": self._screen_size[0],
99-
"height": self._screen_size[1],
100-
}
101-
)
102-
self._page = await self._context.new_page()
103-
await self._page.goto(self._initial_url)
10495

96+
# Define common arguments for both launch types
97+
browser_args = [
98+
"--disable-blink-features=AutomationControlled",
99+
"--disable-gpu",
100+
]
101+
102+
if self._user_data_dir:
103+
termcolor.cprint(
104+
f"Starting playwright with persistent profile: {self._user_data_dir}",
105+
color="yellow",
106+
attrs=["bold"],
107+
)
108+
# Use a persistent context if user_data_dir is provided
109+
self._context = await self._playwright.chromium.launch_persistent_context(
110+
self._user_data_dir,
111+
headless=False,
112+
args=browser_args,
113+
)
114+
self._browser = self._context.browser
115+
else:
116+
termcolor.cprint(
117+
"Starting playwright with a temporary profile.",
118+
color="yellow",
119+
attrs=["bold"],
120+
)
121+
# Launch a temporary browser instance if user_data_dir is not provided
122+
self._browser = await self._playwright.chromium.launch(
123+
args=browser_args,
124+
headless=False,
125+
)
126+
self._context = await self._browser.new_context()
127+
128+
if not self._context.pages:
129+
self._page = await self._context.new_page()
130+
await self._page.goto(self._initial_url)
131+
else:
132+
self._page = self._context.pages[0] # Use existing page if any
133+
134+
await self._page.set_viewport_size({
135+
"width": self._screen_size[0],
136+
"height": self._screen_size[1],
137+
})
105138
termcolor.cprint(
106139
f"Started local playwright.",
107140
color="green",

contributing/samples/live_bidi_streaming_single_agent/agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import random
1616

17-
from google.adk.agents.agent import Agent
17+
from google.adk.agents.llm_agent import Agent
1818
from google.adk.tools.tool_context import ToolContext
1919
from google.genai import types
2020

pyproject.toml

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -25,43 +25,43 @@ classifiers = [ # List of https://pypi.org/classifiers/
2525
]
2626
dependencies = [
2727
# go/keep-sorted start
28-
"PyYAML>=6.0.2, <7.0.0", # For APIHubToolset.
29-
"absolufy-imports>=0.3.1, <1.0.0", # For Agent Engine deployment.
30-
"anyio>=4.9.0, <5.0.0;python_version>='3.10'", # For MCP Session Manager
31-
"authlib>=1.5.1, <2.0.0", # For RestAPI Tool
32-
"click>=8.1.8, <9.0.0", # For CLI tools
33-
"fastapi>=0.115.0, <1.0.0", # FastAPI framework
34-
"google-api-python-client>=2.157.0, <3.0.0", # Google API client discovery
35-
"google-cloud-aiplatform[agent_engines]>=1.121.0, <2.0.0",# For VertexAI integrations, e.g. example store.
36-
"google-cloud-bigtable>=2.32.0", # For Bigtable database
37-
"google-cloud-discoveryengine>=0.13.12, <0.14.0", # For Discovery Engine Search Tool
38-
"google-cloud-secret-manager>=2.22.0, <3.0.0", # Fetching secrets in RestAPI Tool
39-
"google-cloud-spanner>=3.56.0, <4.0.0", # For Spanner database
40-
"google-cloud-speech>=2.30.0, <3.0.0", # For Audio Transcription
41-
"google-cloud-storage>=2.18.0, <3.0.0", # For GCS Artifact service
42-
"google-genai>=1.41.0, <2.0.0", # Google GenAI SDK
43-
"graphviz>=0.20.2, <1.0.0", # Graphviz for graph rendering
44-
"mcp>=1.8.0, <2.0.0;python_version>='3.10'", # For MCP Toolset
45-
"opentelemetry-api>=1.37.0, <=1.37.0", # OpenTelemetry - limit upper version for sdk and api to not risk breaking changes from unstable _logs package.
28+
"PyYAML>=6.0.2, <7.0.0", # For APIHubToolset.
29+
"absolufy-imports>=0.3.1, <1.0.0", # For Agent Engine deployment.
30+
"anyio>=4.9.0, <5.0.0;python_version>='3.10'", # For MCP Session Manager
31+
"authlib>=1.5.1, <2.0.0", # For RestAPI Tool
32+
"click>=8.1.8, <9.0.0", # For CLI tools
33+
"fastapi>=0.115.0, <1.119.0", # FastAPI framework
34+
"google-api-python-client>=2.157.0, <3.0.0", # Google API client discovery
35+
"google-cloud-aiplatform[agent_engines]>=1.121.0, <2.0.0", # For VertexAI integrations, e.g. example store.
36+
"google-cloud-bigtable>=2.32.0", # For Bigtable database
37+
"google-cloud-discoveryengine>=0.13.12, <0.14.0", # For Discovery Engine Search Tool
38+
"google-cloud-secret-manager>=2.22.0, <3.0.0", # Fetching secrets in RestAPI Tool
39+
"google-cloud-spanner>=3.56.0, <4.0.0", # For Spanner database
40+
"google-cloud-speech>=2.30.0, <3.0.0", # For Audio Transcription
41+
"google-cloud-storage>=2.18.0, <3.0.0", # For GCS Artifact service
42+
"google-genai>=1.41.0, <2.0.0", # Google GenAI SDK
43+
"graphviz>=0.20.2, <1.0.0", # Graphviz for graph rendering
44+
"mcp>=1.8.0, <2.0.0;python_version>='3.10'", # For MCP Toolset
45+
"opentelemetry-api>=1.37.0, <=1.37.0", # OpenTelemetry - limit upper version for sdk and api to not risk breaking changes from unstable _logs package.
4646
"opentelemetry-exporter-gcp-logging>=1.9.0a0, <2.0.0",
4747
"opentelemetry-exporter-gcp-monitoring>=1.9.0a0, <2.0.0",
4848
"opentelemetry-exporter-gcp-trace>=1.9.0, <2.0.0",
4949
"opentelemetry-exporter-otlp-proto-http>=1.36.0",
5050
"opentelemetry-resourcedetector-gcp>=1.9.0a0, <2.0.0",
5151
"opentelemetry-sdk>=1.37.0, <=1.37.0",
52-
"pydantic>=2.0, <3.0.0", # For data validation/models
53-
"python-dateutil>=2.9.0.post0, <3.0.0", # For Vertext AI Session Service
54-
"python-dotenv>=1.0.0, <2.0.0", # To manage environment variables
52+
"pydantic>=2.0, <3.0.0", # For data validation/models
53+
"python-dateutil>=2.9.0.post0, <3.0.0", # For Vertext AI Session Service
54+
"python-dotenv>=1.0.0, <2.0.0", # To manage environment variables
5555
"requests>=2.32.4, <3.0.0",
56-
"sqlalchemy-spanner>=1.14.0", # Spanner database session service
57-
"sqlalchemy>=2.0, <3.0.0", # SQL database ORM
58-
"starlette>=0.46.2, <1.0.0", # For FastAPI CLI
59-
"tenacity>=8.0.0, <9.0.0", # For Retry management
56+
"sqlalchemy-spanner>=1.14.0", # Spanner database session service
57+
"sqlalchemy>=2.0, <3.0.0", # SQL database ORM
58+
"starlette>=0.46.2, <1.0.0", # For FastAPI CLI
59+
"tenacity>=8.0.0, <9.0.0", # For Retry management
6060
"typing-extensions>=4.5, <5",
61-
"tzlocal>=5.3, <6.0", # Time zone utilities
62-
"uvicorn>=0.34.0, <1.0.0", # ASGI server for FastAPI
63-
"watchdog>=6.0.0, <7.0.0", # For file change detection and hot reload
64-
"websockets>=15.0.1, <16.0.0", # For BaseLlmFlow
61+
"tzlocal>=5.3, <6.0", # Time zone utilities
62+
"uvicorn>=0.34.0, <1.0.0", # ASGI server for FastAPI
63+
"watchdog>=6.0.0, <7.0.0", # For file change detection and hot reload
64+
"websockets>=15.0.1, <16.0.0", # For BaseLlmFlow
6565
# go/keep-sorted end
6666
]
6767
dynamic = ["version"]
@@ -111,13 +111,13 @@ eval = [
111111
test = [
112112
# go/keep-sorted start
113113
"a2a-sdk>=0.3.0,<0.4.0;python_version>='3.10'",
114-
"anthropic>=0.43.0", # For anthropic model tests
115-
"kubernetes>=29.0.0", # For GkeCodeExecutor
114+
"anthropic>=0.43.0", # For anthropic model tests
115+
"kubernetes>=29.0.0", # For GkeCodeExecutor
116116
"langchain-community>=0.3.17",
117-
"langgraph>=0.2.60, <0.4.8", # For LangGraphAgent
118-
"litellm>=1.75.5, <2.0.0", # For LiteLLM tests
119-
"llama-index-readers-file>=0.4.0", # For retrieval tests
120-
"openai>=1.100.2", # For LiteLLM
117+
"langgraph>=0.2.60, <0.4.8", # For LangGraphAgent
118+
"litellm>=1.75.5, <2.0.0", # For LiteLLM tests
119+
"llama-index-readers-file>=0.4.0", # For retrieval tests
120+
"openai>=1.100.2", # For LiteLLM
121121
"pytest>=8.3.4",
122122
"pytest-asyncio>=0.25.0",
123123
"pytest-mock>=3.14.0",
@@ -139,22 +139,20 @@ docs = [
139139

140140
# Optional extensions
141141
extensions = [
142-
"anthropic>=0.43.0", # For anthropic model support
143-
"beautifulsoup4>=3.2.2", # For load_web_page tool.
144-
"crewai[tools];python_version>='3.10'", # For CrewaiTool
145-
"docker>=7.0.0", # For ContainerCodeExecutor
146-
"kubernetes>=29.0.0", # For GkeCodeExecutor
147-
"langgraph>=0.2.60, <0.4.8", # For LangGraphAgent
148-
"litellm>=1.75.5", # For LiteLlm class. Currently has OpenAI limitations. TODO: once LiteLlm fix it
149-
"llama-index-readers-file>=0.4.0", # For retrieval using LlamaIndex.
150-
"llama-index-embeddings-google-genai>=0.3.0",# For files retrieval using LlamaIndex.
151-
"lxml>=5.3.0", # For load_web_page tool.
152-
"toolbox-core>=0.1.0", # For tools.toolbox_toolset.ToolboxToolset
142+
"anthropic>=0.43.0", # For anthropic model support
143+
"beautifulsoup4>=3.2.2", # For load_web_page tool.
144+
"crewai[tools];python_version>='3.10'", # For CrewaiTool
145+
"docker>=7.0.0", # For ContainerCodeExecutor
146+
"kubernetes>=29.0.0", # For GkeCodeExecutor
147+
"langgraph>=0.2.60, <0.4.8", # For LangGraphAgent
148+
"litellm>=1.75.5", # For LiteLlm class. Currently has OpenAI limitations. TODO: once LiteLlm fix it
149+
"llama-index-readers-file>=0.4.0", # For retrieval using LlamaIndex.
150+
"llama-index-embeddings-google-genai>=0.3.0", # For files retrieval using LlamaIndex.
151+
"lxml>=5.3.0", # For load_web_page tool.
152+
"toolbox-core>=0.1.0", # For tools.toolbox_toolset.ToolboxToolset
153153
]
154154

155-
otel-gcp = [
156-
"opentelemetry-instrumentation-google-genai>=0.3b0, <1.0.0",
157-
]
155+
otel-gcp = ["opentelemetry-instrumentation-google-genai>=0.3b0, <1.0.0"]
158156

159157

160158
[tool.pyink]

src/google/adk/agents/base_agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ class MyAgent(BaseAgent):
155155
156156
Returns:
157157
Optional[types.Content]: The content to return to the user.
158-
When the content is present, the provided content will be used as agent
159-
response and appended to event history as agent response.
158+
When the content is present, an additional event with the provided content
159+
will be appended to event history as an additional agent response.
160160
"""
161161

162162
def _load_agent_state(

0 commit comments

Comments
 (0)