Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
1baa5ad
Initial draft
takumiohym Apr 17, 2025
cc955da
updated langgraph solution nb
kylesteckler May 20, 2025
154079e
Fix typos in markdown cells of Docker and Kubernetes notebooks.
google-labs-jules[bot] Jun 3, 2025
1b04833
Add langgraph agent section
takumiohym Jun 3, 2025
280b93a
Merge pull request #613 from GoogleCloudPlatform/langgraph-agent-section
kylesteckler Jun 10, 2025
b9f928d
[pre-commit.ci] pre-commit autoupdate
pre-commit-ci[bot] Jul 7, 2025
037042e
Merge pull request #621 from GoogleCloudPlatform/pre-commit-ci-update…
takumiohym Jul 15, 2025
d89fc88
added adk deployment
olex-snk Jul 15, 2025
1cf2277
added adk deloyment
olex-snk Jul 15, 2025
dee08bb
cleaned
olex-snk Jul 16, 2025
347de54
style fixes
olex-snk Jul 16, 2025
378b928
cleaned
olex-snk Jul 16, 2025
82d23cf
cleaned
olex-snk Jul 16, 2025
cf3c428
cleaned
olex-snk Jul 16, 2025
5519f11
adding notebook for adk lab
sanjanalreddy Jul 17, 2025
754551e
minor formatting
sanjanalreddy Jul 17, 2025
9624bc6
removing hackernews loader
sanjanalreddy Jul 17, 2025
6d4f7d8
Replaced Tavily with Google Search with Gen AI SDK
takumiohym Jul 17, 2025
326fbd1
Merge pull request #636 from GoogleCloudPlatform/fix_langchain_compon…
takumiohym Jul 17, 2025
418aa14
Revert "removing hackernews loader"
sanjanalreddy Jul 17, 2025
becec16
Merge pull request #637 from GoogleCloudPlatform/revert-636-fix_langc…
sanjanalreddy Jul 17, 2025
883d441
removed hackernew loader
sanjanalreddy Jul 17, 2025
b9effab
removed hackernew loader
sanjanalreddy Jul 17, 2025
2014b25
reflect TODOs to .py files
takumiohym Jul 17, 2025
0b71d20
reflect the changes introduced in commit 0be79351deb55618fb03e8c2bd5d…
takumiohym Jul 17, 2025
6234414
Add essay writer agent
takumiohym Jul 17, 2025
2ba415e
Merge pull request #639 from GoogleCloudPlatform/fix_langchain_compon…
sanjanalreddy Jul 17, 2025
be3ce6b
Merge pull request #635 from GoogleCloudPlatform/adk_lab_nb
takumiohym Jul 17, 2025
b29cbaf
Add mkdir command before writing files
takumiohym Jul 17, 2025
03a5e29
Merge pull request #594 from GoogleCloudPlatform/langgraph_solution
takumiohym Jul 18, 2025
5661849
Merge pull request #640 from GoogleCloudPlatform/adk_mkdir
takumiohym Jul 18, 2025
c4c4f83
revert_style changes
olex-snk Jul 22, 2025
a6df3d2
fix comment
olex-snk Jul 22, 2025
e091d74
added update method
olex-snk Jul 22, 2025
067d916
refactored
olex-snk Jul 22, 2025
b0782f1
updated_description
olex-snk Jul 22, 2025
b06872e
reformatted_black
olex-snk Jul 22, 2025
b938420
reformatted wip
olex-snk Jul 22, 2025
aa117da
Remove Tavily
takumiohym Jul 30, 2025
e363d25
Merge pull request #643 from GoogleCloudPlatform/takumiohym-patch-1
takumiohym Jul 30, 2025
d60f5d4
removed redunant import
olex-snk Jul 31, 2025
d6d4450
cleaning_wip
olex-snk Aug 1, 2025
7b2d43b
fiext header size
olex-snk Aug 1, 2025
4cd6142
celaning_wip_v2
olex-snk Aug 1, 2025
0bad91d
style fix
olex-snk Aug 1, 2025
61e0464
added comment
olex-snk Aug 1, 2025
6ee2c4a
added comments
olex-snk Aug 1, 2025
73188ee
removed redunant import
olex-snk Aug 1, 2025
3dd550b
commented deletion call
olex-snk Aug 1, 2025
aa72282
removed redunant imports
olex-snk Aug 1, 2025
4332ff1
fix: adk agent 4 lab/solution flip
takumiohym Aug 1, 2025
f3570d4
Merge pull request #645 from GoogleCloudPlatform/fix_agent4
takumiohym Aug 4, 2025
54a2e85
fixed style
olex-snk Aug 5, 2025
15b6657
added Agent Engine Overview
olex-snk Aug 5, 2025
8ac1102
fixed description
olex-snk Aug 5, 2025
5fafa97
cleaned
olex-snk Aug 5, 2025
7d5e600
remamed
olex-snk Aug 5, 2025
9f66373
cleaned wip
olex-snk Aug 5, 2025
3acc746
cleaned and refactored
olex-snk Aug 5, 2025
385e7cf
cleaned
olex-snk Aug 5, 2025
ba883ef
reformatted
olex-snk Aug 5, 2025
d0f0d4a
removed SASSION_ID
olex-snk Aug 7, 2025
db11625
reformatted session output
olex-snk Aug 7, 2025
950d626
added_description
olex-snk Aug 7, 2025
2d0fe67
added more description
olex-snk Aug 7, 2025
c8b0b88
style fix
olex-snk Aug 7, 2025
6cc65ad
style fix
olex-snk Aug 7, 2025
47e0f37
fixed text
olex-snk Aug 7, 2025
87026b8
updated with hepler method
olex-snk Aug 7, 2025
d6c4d98
minor fixes
olex-snk Aug 7, 2025
3d45b2a
description fix
olex-snk Aug 7, 2025
8ca65dc
neming fix
olex-snk Aug 7, 2025
f40d493
reformatted
olex-snk Aug 7, 2025
f3199fc
Merge pull request #610 from GoogleCloudPlatform/fix/typos-docker-and…
takumiohym Aug 7, 2025
c195e25
review fixes
olex-snk Aug 11, 2025
84921f7
added link to ./building_agent_with_adk.ipynb
olex-snk Aug 11, 2025
9009696
Merge pull request #633 from GoogleCloudPlatform/adk_deployment
olex-snk Aug 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ __pycache__/
# IntelliJ IDEA
.idea/

#Added to avoid exposeing Env configuration files
.env

# OS generated files
.DS_Store
.DS_Store?
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ repos:
- id: black-jupyter
args: [-l 80]
- repo: https://github.com/asottile/pyupgrade
rev: v3.19.1
rev: v3.20.0
hooks:
- id: pyupgrade
args: [--py36-plus]
- repo: https://github.com/pycqa/pylint
rev: v3.3.6
rev: v3.3.7
hooks:
- id: pylint
args: ["--disable", "unexpected-keyword-arg,no-value-for-parameter,too-many-function-args"]
8 changes: 4 additions & 4 deletions notebooks/docker_and_kubernetes/labs/1_intro_docker.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"There are no running containers. **Note. If you are running this in at AI Notebook, you'll see one container running.**\n",
"There are no running containers. **Note. If you are running this in an AI Notebook, you'll see one container running.**\n",
"\n",
"The `hello-world` containers you ran previously already exited. In order to see all containers, including ones that have finished executing, run docker `ps -a`:"
]
Expand Down Expand Up @@ -167,7 +167,7 @@
"Your dockerfile should have the following steps\n",
"\n",
" 1. use `FROM` to inherit an official Node runtime as the parent image; e.g. node:6\n",
" 2. use `WORKDIR` to seet the working directory to /app\n",
" 2. use `WORKDIR` to set the working directory to /app\n",
" 3. use `ADD` to copy the current directory to the container at /app\n",
" 4. use `EXPOSE` to make the containers port 80 available to the outside world\n",
" 5. use `CMD` to run the command `node ./src/app.js`"
Expand Down Expand Up @@ -443,7 +443,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"You can check that both container are running using `docker ps`."
"You can check that both containers are running using `docker ps`."
]
},
{
Expand All @@ -459,7 +459,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"And let's test boht containers using `curl` as before:"
"And let's test both containers using `curl` as before:"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion notebooks/docker_and_kubernetes/labs/2_intro_k8s.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Get authentication credentials and deploy and application\n",
"## Get authentication credentials and deploy an application\n",
"\n",
"After creating your cluster, you need authentication credentials to interact with it. Use `get-credentials` to authenticate the cluster.\n",
"\n",
Expand Down
8 changes: 4 additions & 4 deletions notebooks/docker_and_kubernetes/labs/3_k8s_hello_node.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"You should see the output `\"Hello World!\"`. Once you've verfied this, interupt the above running cell by hitting the stop button."
"You should see the output `\"Hello World!\"`. Once you've verified this, interrupt the above running cell by hitting the stop button."
]
},
{
Expand All @@ -92,7 +92,7 @@
"\n",
"Now we will create a docker image called `hello_node.docker` that will do the following:\n",
"\n",
" 1. Start from the node image found on the Docker hub by inhereting from `node:6.9.2`\n",
" 1. Start from the node image found on the Docker hub by inheriting from `node:6.9.2`\n",
" 2. Expose port 8000\n",
" 3. Copy the `./src/server.js` file to the image\n",
" 4. Start the node server as we previously did manually using `CMD`\n",
Expand Down Expand Up @@ -219,7 +219,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that the image is working as intended, push it to the Google Artifact Registry, a private repository for your Docker images, accessible from your Google Cloud projects. First, configure docker uisng your local config file. The initial push may take a few minutes to complete. You'll see the progress bars as it builds."
"Now that the image is working as intended, push it to the Google Artifact Registry, a private repository for your Docker images, accessible from your Google Cloud projects. First, configure docker using your local config file. The initial push may take a few minutes to complete. You'll see the progress bars as it builds."
]
},
{
Expand Down Expand Up @@ -371,7 +371,7 @@
"\n",
"By default, the pod is only accessible by its internal IP within the cluster. In order to make the hello-node container accessible from outside the Kubernetes virtual network, you have to expose the pod as a Kubernetes service.\n",
"\n",
"You can expose the pod to the public internet with the `kubectl expose` command. The `--type=\"LoadBalancer\"` flag is required for the creation of an externally accessible IP. This flag specifies that are using the load-balancer provided by the underlying infrastructure (in this case the Compute Engine load balancer). Note that you expose the deployment, and not the pod, directly. This will cause the resulting service to load balance traffic across all pods managed by the deployment (in this case only 1 pod, but you will add more replicas later).\n",
"You can expose the pod to the public internet with the `kubectl expose` command. The `--type=\"LoadBalancer\"` flag is required for the creation of an externally accessible IP. This flag specifies that you are using the load-balancer provided by the underlying infrastructure (in this case the Compute Engine load balancer). Note that you expose the deployment, and not the pod, directly. This will cause the resulting service to load balance traffic across all pods managed by the deployment (in this case only 1 pod, but you will add more replicas later).\n",
"\n",
"**Exercise**\n",
"\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"There are no running containers. **Note. If you are running this in at AI Notebook, you'll see one container running.**\n",
"There are no running containers. **Note. If you are running this in an AI Notebook, you'll see one container running.**\n",
"\n",
"The `hello-world` containers you ran previously already exited. In order to see all containers, including ones that have finished executing, run docker `ps -a`:"
]
Expand Down Expand Up @@ -428,7 +428,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"You can check that both container are running using `docker ps`."
"You can check that both containers are running using `docker ps`."
]
},
{
Expand All @@ -446,7 +446,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"And let's test boht containers using `curl` as before:"
"And let's test both containers using `curl` as before:"
]
},
{
Expand Down
4 changes: 2 additions & 2 deletions notebooks/docker_and_kubernetes/solutions/2_intro_k8s.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Get authentication credentials and deploy and application\n",
"## Get authentication credentials and deploy an application\n",
"\n",
"After creating your cluster, you need authentication credentials to interact with it. Use `get-credentials` to authenticate the cluster."
]
Expand Down Expand Up @@ -150,7 +150,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Use the `kubectl create` command to create a new Deployment `hello-server` from the `hello-app` container image. The `--image` flag to specify a container image to deploy. The `kubectl create` command pulls the example image from a Artifact Registry bucket. Here, use [us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0](https://us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0) to indicate the specific image version to pull. If a version is not specified, the latest version is used."
"Use the `kubectl create` command to create a new Deployment `hello-server` from the `hello-app` container image. The `--image` flag to specify a container image to deploy. The `kubectl create` command pulls the example image from an Artifact Registry bucket. Here, use [us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0](https://us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0) to indicate the specific image version to pull. If a version is not specified, the latest version is used."
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"You should see the output `\"Hello World!\"`. Once you've verfied this, interupt the above running cell by hitting the stop button."
"You should see the output `\"Hello World!\"`. Once you've verified this, interrupt the above running cell by hitting the stop button."
]
},
{
Expand All @@ -92,7 +92,7 @@
"\n",
"Now we will create a docker image called `hello_node.docker` that will do the following:\n",
"\n",
" 1. Start from the node image found on the Docker hub by inhereting from `node:6.9.2`\n",
" 1. Start from the node image found on the Docker hub by inheriting from `node:6.9.2`\n",
" 2. Expose port 8000\n",
" 3. Copy the `./src/server.js` file to the image\n",
" 4. Start the node server as we previously did manually\n",
Expand Down Expand Up @@ -217,7 +217,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that the image is working as intended, push it to the Google Artifact Registry, a private repository for your Docker images, accessible from your Google Cloud projects. First, configure docker uisng your local config file. The initial push may take a few minutes to complete. You'll see the progress bars as it builds."
"Now that the image is working as intended, push it to the Google Artifact Registry, a private repository for your Docker images, accessible from your Google Cloud projects. First, configure docker using your local config file. The initial push may take a few minutes to complete. You'll see the progress bars as it builds."
]
},
{
Expand Down Expand Up @@ -349,7 +349,7 @@
"\n",
"By default, the pod is only accessible by its internal IP within the cluster. In order to make the hello-node container accessible from outside the Kubernetes virtual network, you have to expose the pod as a Kubernetes service.\n",
"\n",
"You can expose the pod to the public internet with the `kubectl expose` command. The `--type=\"LoadBalancer\"` flag is required for the creation of an externally accessible IP. This flag specifies that we are using the load-balancer provided by the underlying infrastructure (in this case the Compute Engine load balancer). Note that you expose the deployment, and not the pod, directly. This will cause the resulting service to load balance traffic across all pods managed by the deployment (in this case only 1 pod, but you will add more replicas later)."
"You can expose the pod to the public internet with the `kubectl expose` command. The `--type=\"LoadBalancer\"` flag is required for the creation of an externally accessible IP. This flag specifies that you are using the load-balancer provided by the underlying infrastructure (in this case the Compute Engine load balancer). Note that you expose the deployment, and not the pod, directly. This will cause the resulting service to load balance traffic across all pods managed by the deployment (in this case only 1 pod, but you will add more replicas later)."
]
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pylint: skip-file
from . import agent
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# pylint: skip-file
from google.adk.agents import Agent

MODEL = "gemini-2.0-flash"

from .tools import get_weather

root_agent = None # TODO - define the weather agent

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The root_agent is initialized to None with a TODO to define the weather agent. This file seems incomplete and the agent is not functional.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# pylint: skip-file
def get_weather(city: str) -> dict:
"""TODO:Write a docstring for the
get_weather agent with a description of what the tool is
supposed to do and also the arguments that are needed.
"""
Comment on lines +3 to +6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The docstring for the get_weather function is incomplete and contains a TODO. A detailed docstring is crucial for the LLM to understand how to use this tool effectively. Please complete the docstring with a description of the tool's purpose and its arguments.

    """Retrieves the current weather report for a specified city.

    Args:
        city (str): The name of the city (e.g., "New York", "London", "Tokyo").
    """

print(
f"--- Tool: get_weather called for city: {city} ---"
) # Log tool execution
city_normalized = city.lower().replace(" ", "") # Basic normalization

# Mock weather data
mock_weather_db = {
"newyork": {
"status": "success",
"report": "The weather in New York is sunny with a temperature of 25°C.",
},
"london": {
"status": "success",
"report": "It's cloudy in London with a temperature of 15°C.",
},
"tokyo": {
"status": "success",
"report": "Tokyo is experiencing light rain and a temperature of 18°C.",
},
}

if city_normalized in mock_weather_db:
return mock_weather_db[city_normalized]
else:
return {
"status": "error",
"error_message": f"Sorry, I don't have weather information for '{city}'.",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pylint: skip-file
from . import agent
39 changes: 39 additions & 0 deletions notebooks/vertex_genai/labs/adk_agents/agent2_sub_agent/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# pylint: skip-file
from google.adk.agents import Agent

MODEL = "gemini-2.0-flash"

from .tools import get_weather, say_goodbye, say_hello

# --- Greeting Agent ---
greeting_agent = Agent(
# TODO - Define the greeting agent
)
Comment on lines +9 to +11

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The greeting_agent is not defined and contains a TODO. This part of the implementation is incomplete.


# --- Farewell Agent ---
farewell_agent = Agent(
model=MODEL,
name="farewell_agent",
instruction="You are the Farewell Agent. Your ONLY task is to provide a polite goodbye message. "
"Use the 'say_goodbye' tool when the user indicates they are leaving or ending the conversation "
"(e.g., using words like 'bye', 'goodbye', 'thanks bye', 'see you'). "
"Do not perform any other actions.",
description="Handles simple farewells and goodbyes using the 'say_goodbye' tool.", # Crucial for delegation
tools=[say_goodbye],
)

root_agent = Agent(
name="weather_agent_v2", # Give it a new version name
model=MODEL,
description="The main coordinator agent. Handles weather requests and delegates greetings/farewells to specialists.",
instruction="You are the main Weather Agent coordinating a team. Your primary responsibility is to provide weather information. "
"Use the 'get_weather' tool ONLY for specific weather requests (e.g., 'weather in London'). "
"You have specialized sub-agents: "
"1. 'greeting_agent': Handles simple greetings like 'Hi', 'Hello'. Delegate to it for these. "
"2. 'farewell_agent': Handles simple farewells like 'Bye', 'See you'. Delegate to it for these. "
"Analyze the user's query. If it's a greeting, delegate to 'greeting_agent'. If it's a farewell, delegate to 'farewell_agent'. "
"If it's a weather request, handle it yourself using 'get_weather'. "
"For anything else, respond appropriately or state you cannot handle it.",
tools=[get_weather],
sub_agents=[greeting_agent, farewell_agent],
)
62 changes: 62 additions & 0 deletions notebooks/vertex_genai/labs/adk_agents/agent2_sub_agent/tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# pylint: skip-file
def get_weather(city: str) -> dict:
"""Retrieves the current weather report for a specified city.

Args:
city (str): The name of the city (e.g., "New York", "London", "Tokyo").

Returns:
dict: A dictionary containing the weather information.
Includes a 'status' key ('success' or 'error').
If 'success', includes a 'report' key with weather details.
If 'error', includes an 'error_message' key.
"""
print(
f"--- Tool: get_weather called for city: {city} ---"
) # Log tool execution
city_normalized = city.lower().replace(" ", "") # Basic normalization

# Mock weather data
mock_weather_db = {
"newyork": {
"status": "success",
"report": "The weather in New York is sunny with a temperature of 25°C.",
},
"london": {
"status": "success",
"report": "It's cloudy in London with a temperature of 15°C.",
},
"tokyo": {
"status": "success",
"report": "Tokyo is experiencing light rain and a temperature of 18°C.",
},
}

if city_normalized in mock_weather_db:
return mock_weather_db[city_normalized]
else:
return {
"status": "error",
"error_message": f"Sorry, I don't have weather information for '{city}'.",
}


def say_hello(name: str = "there") -> str:
"""Provides a simple greeting, optionally addressing the user by name.

Args:
name (str, optional): The name of the person to greet. Defaults to "there".

Returns:
str: A friendly greeting message.
"""
if name is None or name.strip() == "":
name = "there"
print(f"--- Tool: say_hello called with name: {name} ---")
return f"Hello, {name}!"


def say_goodbye() -> str:
"""Provides a simple farewell message to conclude the conversation."""
print(f"--- Tool: say_goodbye called ---")
return "Goodbye! Have a great day."
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pylint: skip-file
from . import agent
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# pylint: skip-file
from google.adk.agents import Agent

MODEL = "gemini-2.0-flash"

from .tools import (
get_weather_stateful,
say_goodbye,
say_hello,
set_user_preference,
)

greeting_agent = Agent(
model=MODEL,
name="greeting_agent",
instruction="You are the Greeting Agent. Your ONLY task is to provide a friendly greeting using the 'say_hello' tool. Do nothing else.",
description="Handles simple greetings and hellos using the 'say_hello' tool.",
tools=[say_hello],
)

farewell_agent = Agent(
model=MODEL,
name="farewell_agent",
instruction="You are the Farewell Agent. Your ONLY task is to provide a polite goodbye message using the 'say_goodbye' tool. Do not perform any other actions.",
description="Handles simple farewells and goodbyes using the 'say_goodbye' tool.",
tools=[say_goodbye],
)

root_agent = Agent(
name="weather_agent_v3_stateful", # New version name
model=MODEL,
description="Main agent: Provides weather (state-aware unit), delegates greetings/farewells, saves report to state.",
instruction="You are the main Weather Agent. Your job is to provide weather using 'get_weather_stateful'. "
"If user want to change prefered temperature unit (Celsius/Fahrenheit), use 'set_user_preference' and and change 'user:temperature_unit' state."
"The tool will format the temperature based on user preference stored in state. "
"Delegate simple greetings to 'greeting_agent' and farewells to 'farewell_agent'. "
"Handle only weather requests, greetings, and farewells.",
tools=[
get_weather_stateful,
set_user_preference,
], # Use the state-aware tool
sub_agents=[greeting_agent, farewell_agent], # Include sub-agents
output_key="last_weather_report", # <<< Auto-save agent's final weather response
)
Loading
Loading