使用 ADK 构建多智能体系统

1. 简介

概览

本实验将教您如何使用 Google 智能体开发套件 (Google ADK) 来编排复杂的多智能体系统。您将从简单的代理层次结构转变为构建自动化的协作式工作流。

构建内容

您将构建两个不同的多智能体系统:

  • 一个简单的旅游规划代理,可学习在“头脑风暴”代理和“景点规划”代理之间转移对话。
  • 一个更高级的电影推介生成器,它使用自动化智能体(如研究员、编剧和影评人)的“编剧室”以循环方式协同工作,从而创建完整的电影情节。

学习内容

  • 如何创建父代理和分代理关系。
  • 如何从工具将数据写入会话 state
  • 如何使用键模板(例如 {my_key?})从 state 读取数据。
  • 如何使用 SequentialAgent 创建分步工作流。
  • 如何使用 LoopAgent 创建迭代优化周期。
  • 如何使用 ParallelAgent 并发运行独立任务。

2. 多智能体系统

智能体开发套件 (ADK) 旨在赋能开发者,使其生成模型能够更可靠地执行复杂的多步骤任务。借助 ADK,您可以构建由多个更简单的智能体组成的流程,通过划分工作让它们协作解决问题,而不是使用一个复杂的提示。

与使用单个单体式提示相比,这种方法具有以下几项优势:

  • 更简单的设计:设计和组织小型专业化智能体的流程比设计一个大型复杂提示更简单。
  • 可靠性:与大型复杂智能体相比,专用智能体在特定任务方面更可靠。
  • 可维护性:修复或改进小型专用智能体,而不会破坏系统的其他部分。
  • 模块化:为一个工作流构建的智能体可以轻松在其他工作流中重复使用。

分层智能体树

显示分层智能体的树状结构

在 ADK 中,您可以采用树状结构来整理智能体。此层次结构对于控制对话流程至关重要,因为它限制了哪个代理可以将对话“传递”给哪个其他代理。这样可以使系统的行为更具可预测性,并更易于调试。福利包括:

  • 直观的设计:结构灵感源自现实世界中的团队,更易于推理。
  • 受控流程:此层次结构可让您精确控制任务委托,有助于进行调试。例如,即使您有两个说明相似的报告撰写智能体,树状结构也能确保调用正确的智能体。

整个结构以 root_agent 开头。此代理充当父代理,可以有一个或多个子代理,而子代理也可以是其自己的子代理的父代理,从而形成树状结构。

3. 项目设置

Google 账号

如果您还没有个人 Google 账号,则必须先创建一个 Google 账号

请改用个人账号,而不是工作账号或学校账号。

登录 Google Cloud 控制台

使用个人 Google 账号登录 Google Cloud 控制台

启用结算功能

兑换 Google Cloud 赠金(可选)

如需参加此研讨会,您需要拥有一个有一定信用额度的结算账号。使用本 Codelab 顶部横幅中的积分开始学习。如果您已关联结算账号,则可以跳过此步骤。

设置个人结算账号

如果您使用 Google Cloud 抵用金设置了结算,则可以跳过此步骤。

如需设置个人结算账号,请点击此处在 Cloud 控制台中启用结算功能

注意事项:

  • 完成本实验的 Cloud 资源费用应不到 1 美元。
  • 您可以按照本实验末尾的步骤删除资源,以避免产生更多费用。
  • 新用户符合参与 $300 USD 免费试用计划的条件。

创建项目(可选)

如果您没有要用于此实验的当前项目,请在此处创建一个新项目

4. 打开 Cloud Shell Editor

  1. 点击此链接可直接前往 Cloud Shell 编辑器
  2. 如果系统在今天任何时间提示您进行授权,请点击授权继续。点击以授权 Cloud Shell
  3. 如果终端未显示在屏幕底部,请打开它:
    • 点击查看
    • 点击终端在 Cloud Shell 编辑器中打开新终端
  4. 在终端中,使用以下命令设置项目:
    gcloud config set project [PROJECT_ID]
    
    • 示例:
      gcloud config set project lab-project-id-example
      
    • 如果您不记得自己的项目 ID,可以使用以下命令列出所有项目 ID:
      gcloud projects list
      
      在 Cloud Shell 编辑器终端中设置项目 ID
  5. 您应会看到以下消息:
    Updated property [core/project].
    

5. 启用 API

如需使用 Vertex AI API 并与 Gemini 模型互动,您需要在 Google Cloud 项目中启用 Vertex AI API。

  1. 在终端中,启用该 API:
    gcloud services enable aiplatform.googleapis.com
    

Python 版 Vertex AI SDK 简介

如需通过 Python 应用与 Vertex AI 上托管的模型进行交互,您需要使用 Vertex AI SDK for Python。此 SDK 简化了发送提示、指定模型参数和接收响应的过程,无需直接处理底层 API 调用的复杂性。

您可以在以下位置找到有关 Vertex AI SDK for Python 的全面文档:Vertex AI SDK for Python 简介 | Google Cloud

6. 设置项目环境

克隆代码库

  1. 终端中,克隆包含起始文件的代码库。
    git clone --depth 1 https://github.com/GoogleCloudPlatform/devrel-demos.git devrel-demos-multiagent-lab
    
    --depth 1 标志仅克隆最新版本,速度更快。
  2. 终端中,将特定于实验的文件夹移至您的主目录,并将其重命名为与实验的预期结构相匹配。
    mv devrel-demos-multiagent-lab/ai-ml/build-multiagent-systems-with-adk/adk_multiagent_systems ~
    
  3. 终端中,前往本实验的正确工作目录 (adk_multiagent_systems)。
    cd ~/adk_multiagent_systems
    

查看文件结构

现在,所有文件都已创建完毕,请在资源管理器中打开 adk_multiagent_systems 文件夹,查看完整结构。

  1. 在 Cloud Shell 编辑器菜单中,依次选择文件 > 打开文件夹…
    Cloud Shell 编辑器的“文件”菜单,其中“打开文件夹”处于选中状态
  2. 在随即显示的框中,在您的用户名后添加以下文件夹信息:adk_multiagent_systems/。点击确定
    结果应如下所示:
    打开包含项目路径的“打开文件夹”对话框
  3. 左侧的探索器面板将刷新。现在,您应该会看到完整的项目结构,其中包含 parent_and_subagentsworkflow_agents 子目录,可以开始执行后续步骤了。
    显示打开的 adk_multiagent_systems 文件夹的探索器面板

激活虚拟环境

  1. 终端中,使用 uv 创建并激活虚拟环境。这样可确保项目依赖项不会与系统 Python 或其他项目发生冲突。
    uv venv
    source .venv/bin/activate
    
  2. 终端中,安装 google-adkrequirements.txt 文件中的其他依赖项:
    uv pip install -r requirements.txt
    

设置环境变量

  1. 您已位于 adk_multiagent_systems 目录中。在终端中,创建一个 .env 文件来存储环境变量:
    cloudshell edit .env
    
  2. 将以下内容粘贴到编辑器中打开的 .env 文件中:
    GOOGLE_GENAI_USE_VERTEXAI=TRUE
    GOOGLE_CLOUD_PROJECT="[YOUR-PROJECT-ID]"
    GOOGLE_CLOUD_LOCATION=global
    MODEL="gemini-2.5-flash"
    
  3. [YOUR-PROJECT-ID] 替换为您的实际 Google Cloud 项目 ID。(例如 PROJECT_ID = "google-cloud-labs"
    如果您忘记了项目 ID,请在终端中运行以下命令。系统会显示您的所有项目及其 ID 的列表。
    gcloud projects list
    
  4. 终端中,将此 .env 文件复制到分代理目录中,以便它们也能访问这些变量:
    cp .env parent_and_subagents/.env
    cp .env workflow_agents/.env
    
    文件结构现在应如下所示:
    显示打开的 adk_multiagent_systems 文件夹的探索器面板

7. 了解父智能体、分代理和同级智能体之间的转移

对话始终从 root_agent 开始。默认情况下,父代理会使用其子代理的 description 来决定何时转移对话。您还可以在父智能体的 instruction 中使用子智能体的 name 明确引导这些控制权转移。

我们来测试一下。

  1. 在 Cloud Shell 编辑器中,打开 adk_multiagent_systems/parent_and_subagents/agent.py。请注意 agent.py 文件中的三个代理:
    • root_agent(命名为 steering:向用户提出问题,以确定要转移到哪个分代理。最初,它仅依赖于子代理的 description
    • travel_brainstormer:帮助用户集思广益,寻找目的地。
    • attractions_planner:帮助用户列出特定国家/地区的推荐活动。
  2. 通过在创建 root_agent 时添加以下代码行,使 travel_brainstormerattractions_planner 成为 root_agent 的子智能体:
        sub_agents=[travel_brainstormer, attractions_planner]
    
  3. 终端中,与您的代理聊天:
    cd ~/adk_multiagent_systems
    adk run parent_and_subagents
    
  4. 终端中的 [user]: 提示符处,输入:
    hello
    
    输出示例(您的输出可能略有不同):
    [steering]: Hi there! Do you already have a country in mind for your trip, or would you like some help deciding where to go?
    
  5. 现在,在终端中告诉智能体:
    I could use some help deciding.
    
    输出示例(您的输出可能略有不同):
    [travel_brainstormer]: Okay! To give you the best recommendations, I need to understand what you're looking for in a trip.
    ...
    
    请注意 [travel_brainstormer] 标记。root_agent 转移控制权仅基于子代理的 description
  6. 终端中的 user: 提示处,输入 exit,然后按 Enter 键结束对话。
  7. 现在,我们来更明确地说明一下。在 agent.py 中,将以下内容添加到 root_agentinstruction 中:
            If they need help deciding, send them to 'travel_brainstormer'.
            If they know what country they'd like to visit, send them to the 'attractions_planner'.
    
  8. 终端中,再次运行代理:
    adk run parent_and_subagents
    
  9. 终端中的 [user]: 提示符处,输入:
    hello
    
  10. 用以下内容回复:
    I would like to go to Japan.
    
    输出示例(您的输出可能略有不同):
    [attractions_planner]: Okay, I can help you with that! Here are some popular attractions in Japan:
    ...
    
    按照新说明,将数据转移到 attractions_planner
  11. 现在,请回复以下内容:
    Actually I don't know what country to visit.
    
    输出示例(您的输出可能略有不同):
    [travel_brainstormer]: Okay! I can help you brainstorm some countries for travel...
    
    请注意,您已转移到 attractions_planner同级智能体 travel_brainstormer。默认情况下允许转移到同级智能体。
  12. 在用户提示处,输入 exit 以结束会话。

回顾

在本部分中,您学习了代理层次结构和对话流程的基础知识:

  • 对话始终从 root_agent 开始。
  • 父代理可以根据其 description 自动转移给分代理。
  • 您可以明确控制此流程,方法是向父代理提供 instruction 以通过其 name 转移到分代理。
  • 默认情况下,智能体可以将对话转移给其 peer 智能体(层次结构中的同级智能体)。

8. 使用会话状态存储和检索信息

每个 ADK 对话都有一个 Session,其中包括一个会话状态字典。所有代理都可以访问此状态,因此它是代理之间传递信息或在整个对话过程中维护数据(例如列表)的理想方式。

如需了解如何向状态添加内容以及如何从状态读取内容,请执行以下操作:

  1. 返回到文件 adk_multiagent_systems/parent_and_subagents/agent.py
  2. 将以下函数定义粘贴到 # Tools 标题后面:
    def save_attractions_to_state(
    tool_context: ToolContext,
    attractions: List[str]
    ) -> dict[str, str]:
        """Saves the list of attractions to state["attractions"].
    
        Args:
            attractions [str]: a list of strings to add to the list of attractions
    
        Returns:
            None
        """
        # Load existing attractions from state. If none exist, start an empty list
        existing_attractions = tool_context.state.get("attractions", [])
    
        # Update the 'attractions' key with a combo of old and new lists.
        # When the tool is run, ADK will create an event and make
        # corresponding updates in the session's state.
        tool_context.state["attractions"] = existing_attractions + attractions
    
        # A best practice for tools is to return a status message in a return dict
        return {"status": "success"}
    
    在此代码中,请注意:
    • 该函数接收 tool_context: ToolContext。此对象是会话的网关。
    • tool_context.state["attractions"] = ... 行直接从会话的状态字典中读取数据并向其中写入数据。其余工作由 ADK 处理。
  3. 添加 tools 参数,将该工具添加到 attractions_planner 代理:
        tools=[save_attractions_to_state]
    
  4. 将以下要点添加到 attractions_planner 代理的现有 instruction 中:
            - When they reply, use your tool to save their selected attraction and then provide more possible attractions.
            - If they ask to view the list, provide a bulleted list of { attractions? } and then suggest some more.
    
  5. 终端中使用以下命令启动智能体开发套件网页界面
    adk web
    
    输出
    INFO:     Started server process [2434]
    INFO:     Waiting for application startup.
    +-------------------------------------------------------+
    | ADK Web Server started                                |
    |                                                       |
    | For local testing, access at http://localhost:8000.   |
    +-------------------------------------------------------+
    
    INFO:     Application startup complete.
    INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
    
  6. 在 Cloud Shell 终端中,点击网页预览按钮,然后选择更改端口,即可在新标签页中查看网页界面。
    “网页预览”菜单
  7. 输入端口号 8000,然后点击更改并预览。系统即会在一个新浏览器标签页中打开 ADK 开发者界面。
    “更改端口”弹出式框,文本框中输入了 8000
  8. 从左侧的选择智能体下拉菜单中,选择 parent_and_subagents
  9. 输入 hello 开始对话
  10. 在智能体向您问好后,回复以下内容:
    I'd like to go to Egypt.
    
    您应该会被转移到 attractions_planner,并获得景点列表。
  11. 选择一个景点,例如:
    I'll go to the Sphinx
    
  12. 您应该会收到类似如下的回答:Okay, I've saved The Sphinx to your list...
  13. 点击回答工具箱(带有对勾标记),查看根据工具的回答创建的事件。
    请注意,它包含一个 actions 字段,该字段内的 stateDelta 描述了状态的更改情况。
  14. 回复代理列表中的另一个景点。
  15. 在左侧导航菜单中,点击“X”以退出之前查看的事件聚焦状态。
  16. 在左侧边栏中,点击标签页。您现在可以在会话的状态中看到 attractions 数组,其中应包含您选择的两个商品。网页界面中的会话状态预览
  17. 向智能体发送以下消息:
    What is on my list?
    
    代理现在应从状态读取并返回您的列表。
  18. 试用智能体后,关闭网络浏览器标签页,然后在 Cloud Shell 终端中按 CTRL + C 停止服务器。

部分总结

在本部分中,您学习了如何使用 Session 状态来共享数据:

  • 写入状态:您可以在工具内使用 tool_context.state 对象(例如 tool_context.state["my_list"] = [...])写入状态字典。
  • 读取状态:您可以使用键模板(例如 Here is your list: {my_list?})将状态数据直接注入到智能体的 instruction 中。
  • 检查状态:您可以使用“状态”标签页在 ADK 开发者界面中实时监控会话状态。

9. 工作流智能体

到目前为止,您已经了解了父代理如何转移到分代理,然后等待用户。工作流智能体则不同:它们会在自动化流程中依次执行其子智能体,而无需等待用户输入。

这非常适合自动化多步骤任务,例如“规划和执行”或“起草和修订”流水线。ADK 提供 3 个内置工作流智能体来管理此流程:

  • SequentialAgent
  • LoopAgent
  • ParallelAgent

本实验的剩余部分将重点介绍如何使用这三个工作流代理构建多智能体系统

您将构建一个智能体,用于为一部关于历史人物的新电影撰写宣传文案。智能体将负责研究、迭代式写作和报告生成。

最后,您的系统将如下所示:

film_concept_team 多智能体系统示意图

您将逐步构建此系统,首先从最简单的工作流开始。

10. 使用 SequentialAgent 构建多智能体系统

SequentialAgent 是一种工作流代理,可按简单的线性序列执行其子代理。其 sub_agents 列表中的各个代理会按顺序依次运行。这非常适合必须按特定顺序执行任务的流水线,例如您现在要构建的电影推介代理。

第一个版本将采用以下结构:

构建 Film_concept_team 多智能体系统的第 1 步

  • root_agent (greeter) 将欢迎用户并获取电影主题。
  • 然后,它将转移到名为 film_concept_teamSequentialAgent,该 SequentialAgent 将:
    1. 运行 researcher 代理,从维基百科获取事实信息。
    2. 运行 screenwriter 代理,以使用这些事实来撰写情节。
    3. 运行 file_writer 代理,将最终图表保存到文件中。

我们来运行一下。

  1. Cloud Shell 编辑器中,打开 adk_multiagent_systems/workflow_agents/agent.py
    通读此智能体定义文件。由于必须先定义子智能体,然后才能将其分配给父智能体,因此若要按照对话流程的顺序读取该文件,您可以从文件底部往上读取智能体。
  2. 请注意 append_to_state 工具。借助此辅助函数,代理可以将会话状态中的数据附加到列表中,researcherscreenwriter 将通过这种方式传递其工作。
  3. 试用代理。在终端中,启动已启用实时重新加载功能的 Web 界面:
    cd ~/adk_multiagent_systems
    adk web --reload_agents
    
  4. 在 Cloud Shell 终端中,点击网页预览按钮,然后选择更改端口,即可在新标签页中查看网页界面。
    “网页预览”菜单
  5. 输入端口号 8000,然后点击更改并预览。系统即会在一个新浏览器标签页中打开 ADK 开发者界面。
    “更改端口”弹出式框,文本框中输入了 8000
  6. 选择智能体下拉菜单中,选择 workflow_agents
  7. 输入 hello 开始对话。greeter 代理会做出响应。
  8. 出现提示时,输入一位历史人物。您可以使用以下任一选项,也可以使用自己的选项:
    • 张仲景
    • Ada Lovelace
    • 马可·奥勒留
  9. 现在,SequentialAgent 将接管。您不会看到任何中间消息。researcherscreenwriterfile_writer 将依次运行。只有在整个序列完成时,代理才会做出响应。
    如果失败,您可以点击右上角的 + 新建会话,然后重试。
  10. 当代理确认文件已写入后,在 Cloud Shell 编辑器中的 movie_pitches 目录中找到并打开新的 .txt 文件,即可查看输出。
  11. 在 ADK 开发者界面中,点击对话记录中的最后一个智能体图标,打开事件视图
  12. 事件视图显示了智能体树的直观图表。您可以看到 greeter 如何调用 film_concept_team,然后 film_concept_team 按顺序调用每个子代理。ADK 网页图表
  13. 您可以点击图表中任何代理的请求响应标签页,检查传递的确切数据(包括会话状态)。

部分总结

在本部分中,您学习了如何使用工作流代理

  • SequentialAgent 会按顺序逐个执行其子智能体,而无需在各个步骤之间等待用户输入。
  • 这是一个“工作流”,因为用户与 root_agent 对话,然后 root_agent工作交给 SequentialAgent 完成。
  • 序列中的子代理使用会话状态(例如 { PLOT_OUTLINE? })来访问之前代理的工作。
  • 您可以使用开发者界面中的事件图来直观呈现并调试整个代理到代理的工作流。

11. 添加 LoopAgent 以进行迭代工作

LoopAgent 是一种工作流代理,它会按顺序运行其子代理,然后从头开始重复运行。这个“循环”会一直持续,直到满足某个条件,例如达到 max_iterations 次数或分代理调用内置的 exit_loop 工具。

这对于需要迭代优化的任务非常有用。您将添加此 LoopAgent,为电影推介智能体创建一个“编剧室”。这样一来,researcherscreenwriter 和新的 critic 代理就可以循环工作,每次通过时都会改进情节,直到 critic 认为情节已准备就绪。这还有助于智能体通过研究和完善创意来处理更模糊的用户输入(例如“一位古代医生”)。

构建 Film_concept_team 多智能体系统的第 2 步

如需进行这些更改,请执行以下操作:

  1. adk_multiagent_systems/workflow_agents/agent.py 中,添加 exit_loop 的导入项(在其他 google.adk 导入项附近):
    from google.adk.tools import exit_loop
    
  2. 添加新的 critic 代理。该代理会审核剧情。如果结果良好,则调用 exit_loop。如果不是,则将反馈添加到状态中,以供下一个循环使用。
    将以下智能体定义粘贴到 # Agents 部分下:
    critic = Agent(
        name="critic",
        model=model_name,
        description="Reviews the outline so that it can be improved.",
        instruction="""
        INSTRUCTIONS:
        Consider these questions about the PLOT_OUTLINE:
        - Does it meet a satisfying three-act cinematic structure?
        - Do the characters' struggles seem engaging?
        - Does it feel grounded in a real time period in history?
        - Does it sufficiently incorporate historical details from the RESEARCH?
    
        If the PLOT_OUTLINE does a good job with these questions, exit the writing loop with your 'exit_loop' tool.
        If significant improvements can be made, use the 'append_to_state' tool to add your feedback to the field 'CRITICAL_FEEDBACK'.
        Explain your decision and briefly summarize the feedback you have provided.
    
        PLOT_OUTLINE:
        { PLOT_OUTLINE? }
    
        RESEARCH:
        { research? }
        """,
        before_model_callback=log_query_to_model,
        after_model_callback=log_model_response,
        tools=[append_to_state, exit_loop]
    )
    
  3. 创建 writers_room LoopAgent。此变量将包含在循环中运行的三个代理。
    将以下代码粘贴到 film_concept_team 代理定义上方
    writers_room = LoopAgent(
        name="writers_room",
        description="Iterates through research and writing to improve a movie plot outline.",
        sub_agents=[
            researcher,
            screenwriter,
            critic
        ],
        max_iterations=5,
    )
    
  4. 更新 film_concept_team SequentialAgent 以使用新的 writers_room 循环。将 researcherscreenwriter 替换为单个 writers_room 代理。将您现有的 film_concept_team 定义替换为以下内容:
    film_concept_team = SequentialAgent(
        name="film_concept_team",
        description="Write a film plot outline and save it as a text file.",
        sub_agents=[
            writers_room,
            file_writer
        ],
    )
    
  5. 返回 ADK 开发者界面标签页,然后点击右上角的 + 新建会话
  6. 输入 hello 发起新对话
  7. 在系统提示时,这次给代理提供一个更宽泛的主题。以下是一些建议:
    • 一位为大众设计产品的工业设计师
    • 制图师(地图制作者)
    • that guy who made crops yield more food
    代理现在将遍历该循环。在 ADK 开发者界面中,您会看到日志,因为智能体运行了多次(例如“[研究员]”“[编剧]”“[影评人]”“[研究员]”“[编剧]”“[影评人]...”)。
  8. 当循环完成时,代理将写入文件。查看 adk_multiagent_systems/movie_pitches 目录中生成的文件。
  9. 在开发者界面中检查事件图,查看循环结构。

部分总结

在本部分中,您学习了如何使用 LoopAgent

  • LoopAgent 是一种工作流代理,可重复执行其子代理序列,从而为迭代任务创建“内循环”。
  • 循环中的智能体使用会话状态在后续传递中相互传递工作(例如 PLOT_OUTLINE)和反馈(例如 CRITICAL_FEEDBACK)。
  • 循环可以通过达到 max_iterations 限制或通过代理调用 exit_loop 工具来停止。

12. 使用 ParallelAgent 进行“扇出和收集”

ParallelAgent 是一种工作流代理,可同时(并发)执行其所有子代理。这对于可拆分为多个独立子任务的任务(例如运行两个不同的研究作业)非常有用。

您将使用 ParallelAgent 创建一个并行工作的“预制作团队”。一个智能体将研究票房潜力,而另一个智能体同时集思广益,提出演员阵容创意。这通常称为“扇出和收集”模式:ParallelAgent“扇出”工作,而后续智能体(我们的 file_writer)“收集”结果。

构建 Film_concept_team 多智能体系统的第 3 步

最终的智能体流程将如下所示:

  1. greeter(根)开始聊天。
  2. 它会转移到 film_concept_team (SequentialAgent),后者会运行:
    • 用于创建图表的 writers_room (LoopAgent)。
    • 新的 preproduction_team (ParallelAgent) 可用于同时研究票房和演员阵容。
    • 用于收集所有结果并保存文件的 file_writer

如需进行这些更改,请执行以下操作:

  1. adk_multiagent_systems/workflow_agents/agent.py 中,将新的 ParallelAgent 及其子代理粘贴到 # Agents 标题下。
    box_office_researcher = Agent(
        name="box_office_researcher",
        model=model_name,
        description="Considers the box office potential of this film",
        instruction="""
        PLOT_OUTLINE:
        { PLOT_OUTLINE? }
    
        INSTRUCTIONS:
        Write a report on the box office potential of a movie like that described in PLOT_OUTLINE based on the reported box office performance of other recent films.
        """,
        output_key="box_office_report"
    )
    
    casting_agent = Agent(
        name="casting_agent",
        model=model_name,
        description="Generates casting ideas for this film",
        instruction="""
        PLOT_OUTLINE:
        { PLOT_OUTLINE? }
    
        INSTRUCTIONS:
        Generate ideas for casting for the characters described in PLOT_OUTLINE
        by suggesting actors who have received positive feedback from critics and/or
        fans when they have played similar roles.
        """,
        output_key="casting_report"
    )
    
    preproduction_team = ParallelAgent(
        name="preproduction_team",
        sub_agents=[
            box_office_researcher,
            casting_agent
        ]
    )
    
  2. 更新 film_concept_team SequentialAgentsub_agents 列表,以包含新的 preproduction_team(介于 writers_roomfile_writer 之间)。将现有 film_concept_team 定义替换为以下内容:
    film_concept_team = SequentialAgent(
        name="film_concept_team",
        description="Write a film plot outline and save it as a text file.",
        sub_agents=[
            writers_room,
            preproduction_team,
            file_writer
        ],
    )
    
  3. 更新 file_writer 代理的 instruction,使其从状态中“收集”新报告并将其添加到文件中。
    file_writerinstruction 字符串替换为以下内容:
        instruction="""
        INSTRUCTIONS:
        - Create a marketable, contemporary movie title suggestion for the movie described in the PLOT_OUTLINE.
        If a title has been suggested in PLOT_OUTLINE, you can use it, or replace it with a better one.
        - Use your 'write_file' tool to create a new txt file with the following arguments:
        - for a filename, use the movie title
        - Write to the 'movie_pitches' directory.
        - For the 'content' to write, include:
        - The PLOT_OUTLINE
        - The BOX_OFFICE_REPORT
        - The CASTING_REPORT
    
        PLOT_OUTLINE:
        { PLOT_OUTLINE? }
    
        BOX_OFFICE_REPORT:
        { box_office_report? }
    
        CASTING_REPORT:
        { casting_report? }
        """,
    
  4. 返回到 ADK 开发者界面标签页,然后点击 + 新建会话
  5. 输入 hello 以开始对话。
  6. 当系统提示时,输入一个新人物想法。以下是一些建议:
    • 发明了 Wi-Fi 技术的那个女演员
    • 一位出色的厨师
    • 世博会展览中的主要参与者
  7. 当智能体完成工作后,检查 adk_multiagent_systems/movie_pitches 目录中的最终文件。现在,它应该包含剧情、票房报告和演员阵容报告,所有内容都在一个文档中。

部分总结

在本部分中,您学习了如何使用 ParallelAgent

  • ParallelAgent“扇出”工作,同时运行所有子代理,而不是按顺序运行。
  • 对于不相互依赖的任务(例如研究两个不同的主题),这种方式非常高效。
  • 并行代理的结果由后续代理“收集”。为此,您可以让并行代理将其工作保存到会话状态(使用 output_key),并让最终代理(例如 file_writer)读取这些键。

13. 自定义工作流智能体

如果预定义工作流智能体 SequentialAgentLoopAgentParallelAgent 无法满足您的需求,CustomAgent 可让您灵活地实现新的工作流逻辑。

您可以定义子智能体之间的流控制、条件执行或状态管理模式。这适用于复杂的工作流、有状态的编排,或将自定义业务逻辑集成到框架的编排层中。

创建 CustomAgent 不在本实验范围内,不过了解其存在以备不时之需也是很有益处的!

14. 恭喜!

您已使用 Google 智能体开发套件 (ADK) 成功构建了一个复杂多智能体系统。您已经从简单的父级-子级智能体关系发展到编排复杂的自动化工作流,这些工作流可以研究、撰写和完善创意项目。

回顾

在本实验中,您完成了以下操作:

  • 分层树状结构组织智能体,并建立父智能体与分代理关系。
  • 受控的代理到代理转移,包括自动转移(使用 description)和显式转移(使用 instruction)。
  • 使用工具将数据写入 tool_context.state 字典。
  • 使用键模板(例如 { PLOT_OUTLINE? })从会话状态读取数据并引导智能体的提示。
  • 实现了 SequentialAgent,以创建简单的分步工作流(研究 -> 撰写 -> 保存)。
  • 使用 critic 代理和 exit_loop 工具创建迭代优化周期。LoopAgent
  • 使用 ParallelAgent 将独立任务(例如演员阵容和票房研究)“分发”以并发运行。

持续进行实验

您可以利用所学知识以多种方式继续深造。以下是一些建议:

  • 添加更多智能体:尝试向 preproduction_team ParallelAgent 添加新的智能体。例如,您可以创建一个 marketing_agent,用于根据 PLOT_OUTLINE 为电影撰写宣传语。
  • 添加更多工具:为 researcher 代理添加更多工具。您可以创建一个使用 Google 搜索 API 的工具,以查找 Wikipedia 上没有的信息。
  • 探索 CustomAgent:实验中提到了不适合标准模板的工作流的 CustomAgent。尝试构建一个智能体,例如,仅当会话状态中存在特定键时才以条件方式运行该智能体。