Skip to content

Hope to enhance BuiltInPlanner #4205

@WDEP-good

Description

@WDEP-good

** Please make sure you read the contribution guide and file the issues in the right place. **
Contribution guide.

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
I set up a main root Agent and two sub-agents, the weather Agent and the dice rolling Agent, using A2A. I asked the root Agent to roll a six-sided dice for me. If I hit 1, I would check the weather in Beijing; if I hit 2, I would check the weather in Shanghai; if I hit 3, I would check the weather in Shenzhen; if I hit 4, I would check the weather in Heilongjiang. If I hit 5, I can check the weather in Hunan. If I hit 6, I can check the weather in Guangxi. However, the root Agent only assigned the task to the dice-rolling Agent and then told me that I couldn't check the weather. In real time, I hope that after rolling the dice, it will be returned to the root Agent and then sent to the weather Agent to complete my request. The most fundamental thing is that I want the root Agent to selectively invoke sub-agents based on my semantics rather than a hardcoded workflow, and I want the root Agent to have full agentic capabilities

In fact, most of the time, the task ends after being dispatched to the dice-rolling Agent. There are also a small number of times when the dice-rolling Agent can think of returning the task to the main Agent to handle the weather issue, but this is extremely rare

Describe the solution you'd like
A clear and concise description of what you want to happen.
I hope the root Agent selectively invokes sub-agents based on my semantics rather than a hardcoded workflow, and I hope the root Agent has full agentic capabilities

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
I set the two sub-agents to each other as their own sub-agents to stably implement this function, but this still looks very much like a workflow. I hope it is automatically planned by the main Agent and sub-agents are dispatched according to the tasks
However, if this is done, the Event where the dice rolling Agent calls the weather Agent cannot be monitored in the event of the ADK Web page

Additional context
Add any other context or screenshots about the feature request here.
Dice Rolling Agent

from google.adk.agents.llm_agent import Agent
from google.adk.models import lite_llm
from dotenv import load_dotenv
from google.adk.a2a.utils.agent_to_a2a import to_a2a
from google.adk.tools.tool_context import ToolContext
from google.adk.planners.built_in_planner import BuiltInPlanner
from google.genai import types
from a2a.types import AgentCard
from google.adk.agents.remote_a2a_agent import AGENT_CARD_WELL_KNOWN_PATH
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
import os
import random

load_dotenv()

custom_model = lite_llm.LiteLlm(
    model='openai/gemini-3-flash-preview',
    api_base='https://sg.uiuiapi.com/v1',
    api_key=os.getenv("DEEPSEEK_API_KEY"),
)
def roll_die(sides: int, tool_context: ToolContext) -> int:
  """掷骰子并返回结果。

  参数:
    sides: 骰子的面数(整数)。
    tool_context: 工具上下文。
  返回:
    掷骰子的结果(整数)。
  """
  result = random.randint(1, sides)
  if not 'rolls' in tool_context.state:
    tool_context.state['rolls'] = []

  tool_context.state['rolls'] = tool_context.state['rolls'] + [result]
  return result

async def check_prime(nums: list[int]) -> str:
  """判断给定的数字列表哪些为质数。

  参数:
    nums: 要检查的数字列表。

  返回:
    一个说明哪些数字是质数的字符串。
  """
from google.adk.agents.llm_agent import Agent
from google.adk.models.lite_llm import LiteLlm
from dotenv import load_dotenv
from google.adk.a2a.utils.agent_to_a2a import to_a2a
from google.adk.planners.built_in_planner import BuiltInPlanner
from google.adk.agents.remote_a2a_agent import AGENT_CARD_WELL_KNOWN_PATH
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
from google.genai import types
import os
load_dotenv()  # 这行代码会读取 .env 文件中的环境变量

# @title 定义 get_weather 工具
def get_weather(city: str) -> dict:
    """获取指定城市的当前天气报告。

    参数:
        city (str): 城市名称(例如:"New York", "London", "Tokyo")。

    返回:
        dict: 包含天气信息的字典。
              包含'status'键('success'或'error')。
              如果'success',包括'report'键和天气详情。
              如果'error',包括'error_message'键。
    """
    print(f"--- 工具: get_weather 被调用,城市: {city} ---") # 记录工具执行
    city_normalized = city.lower().replace(" ", "") # 基本标准化

    # 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."},
        "北京": {"status": "success", "report": "北京天气晴朗,温度为 15°C。"},
        "beijing": {"status": "success", "report": "北京天气晴朗,温度为 15°C。"},
        "上海": {"status": "success", "report": "上海多云,温度为 18°C。"},
        "shanghai": {"status": "success", "report": "上海多云,温度为 18°C。"},
        "深圳": {"status": "success", "report": "深圳有小雨,温度为 22°C。"},
        "shenzhen": {"status": "success", "report": "深圳有小雨,温度为 22°C。"},
        "黑龙江": {"status": "success", "report": "黑龙江有雪,温度为 -10°C。"},
        "heilongjiang": {"status": "success", "report": "黑龙江有雪,温度为 -10°C。"},
        "湖南": {"status": "success", "report": "湖南阴天,温度为 12°C。"},
        "hunan": {"status": "success", "report": "湖南阴天,温度为 12°C。"},
        "广西": {"status": "success", "report": "广西晴天,温度为 20°C。"},
        "guangxi": {"status": "success", "report": "广西晴天,温度为 20°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}'."}

custom_model = LiteLlm(
    model="openai/gemini-3-flash-preview",  # 使用 openai/ 前缀指定为 OpenAI 兼容接口
    api_base="https://sg.uiuiapi.com/v1",  # 第三方 API 端点(不要包含 /chat/completions,LiteLLM 会自动添加)
    api_key=os.getenv("DEEPSEEK_API_KEY"),
)


hello_world_agent = RemoteA2aAgent(
    name="hello_world_agent",
    description="专门负责掷骰子(任意面数)、判断质数和计算数字总和的代理。当需要掷骰子或判断质数时,调用此代理。",
    agent_card=f"http://localhost:8001/{AGENT_CARD_WELL_KNOWN_PATH}",
)



root_agent = Agent(
    name="weather_agent",
    model=custom_model,
    description="为特定城市提供天气信息。",
    instruction="你是一名乐于助人的天气助手。"
                "当用户询问某个城市的天气时,"
                "请使用 'get_weather' 工具获取相关信息。"
                "如果工具返回错误,请礼貌地告知用户。"
                "如果工具调用成功,请清晰地展示天气报告。",
    tools=[get_weather],
    # sub_agents=[
    #     hello_world_agent,
    # ],
    planner=BuiltInPlanner(
        thinking_config=types.ThinkingConfig(
            include_thoughts=True,
        ),
    ),
)


a2a_app = to_a2a(root_agent, port=8002)

root Agent

from google.adk.agents.llm_agent import Agent
from google.adk.models import lite_llm
from dotenv import load_dotenv
from google.adk.agents.remote_a2a_agent import AGENT_CARD_WELL_KNOWN_PATH
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
from google.adk.planners.built_in_planner import BuiltInPlanner
from google.genai import types
import os

load_dotenv()



custom_model = lite_llm.LiteLlm(
    model='openai/gemini-3-flash-preview',
    api_base='https://sg.uiuiapi.com/v1',
    api_key=os.getenv("DEEPSEEK_API_KEY"),
)

hello_world_agent = RemoteA2aAgent(
    name="hello_world_agent",
    description="专门负责掷骰子(任意面数)、判断质数和计算数字总和的代理。当需要掷骰子或判断质数时,调用此代理。",
    agent_card=f"http://localhost:8001/{AGENT_CARD_WELL_KNOWN_PATH}",
)

weather_agent = RemoteA2aAgent(
    name="weather_agent",
    description="专门负责查询城市天气信息的代理,支持中文和英文城市名(如:北京、上海、湖南、Beijing、Shanghai等)。当需要查询天气时,调用此代理。",
    agent_card=f"http://localhost:8002/{AGENT_CARD_WELL_KNOWN_PATH}",
)


root_agent = Agent(
    model=custom_model,
    name='root_agent',
    sub_agents=[
        weather_agent,
        hello_world_agent,
    ],
    description='一个智能助手,可以协调多个专业代理来完成用户的请求。',
instruction="""你是一个智能协调员,负责分析用户请求并调度合适的专业代理完成任务。

**核心工作原则:**
1.  **理解任务链**:当用户请求包含明显的顺序或条件关系时(例如“先掷骰子,再根据结果查天气”),你必须规划一个多步骤任务。
2.  **代理调度**:
    *   专长于掷骰子、判断质数或数字计算的任务,请调用 `hello_world_agent`。
    *   专长于查询天气的任务,请调用 `weather_agent`。
3.  **工作流执行**:对于条件性任务,标准流程是:**执行第一个任务 → 提取关键结果(如骰子点数) → 将结果映射为参数 → 发起第二个任务**。例如,收到当前这类请求时,你应能自动推断出需要先获得骰子点数,再根据点数映射到城市,最后查询该城市天气。

请基于以上原则,智能地协调子代理来完成用户的完整请求。
""",
    planner=BuiltInPlanner(
        thinking_config=types.ThinkingConfig(
            include_thoughts=True,
        ),
    ),
)

Inquiry result

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    core[Component] This issue is related to the core interface and implementation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions