コンテンツにスキップ

並列エージェント

ADKでサポートPython v0.1.0Go v0.1.0Java v0.2.0

ParallelAgentは、サブエージェントを並列(concurrently)で実行するワークフローエージェントです。これにより、タスクが独立して実行可能なワークフローを劇的に高速化します。

ParallelAgentは次の場合に使用します:速度を優先し、独立したリソース集約型のタスクを伴うシナリオでは、ParallelAgentが効率的な並列実行を促進します。サブエージェントが依存関係なしで動作する場合、タスクを並列に実行でき、全体の処理時間を大幅に短縮できます。

他のワークフローエージェントと同様に、ParallelAgentはLLMによって駆動されないため、その実行方法は決定論的(deterministic)です。ただし、ワークフローエージェントが関与するのはその実行(つまり、サブエージェントを並列実行すること)のみであり、内部ロジックではありません。ワークフローエージェントのツールやサブエージェントは、LLMを利用する場合もあれば、しない場合もあります。

このアプローチは、複数ソースからのデータ取得や重い計算処理のような操作に特に有益で、並列化によって大幅なパフォーマンス向上が得られます。重要なのは、この戦略では、並列実行されるエージェント間で共有ステートや直接的な情報交換が本質的に不要であると想定している点です。

仕組み

ParallelAgentrun_async()メソッドが呼び出されると:

  1. 並列実行: sub_agentsリストに存在するサブエージェントのrun_async()メソッドを並列で開始します。これは、すべてのエージェントが(ほぼ)同時に実行を開始することを意味します。
  2. 独立したブランチ: 各サブエージェントは独自の実行ブランチで動作します。実行中、これらのブランチ間で会話履歴やステートが自動的に共有されることはありません
  3. 結果の収集: ParallelAgentは並列実行を管理し、通常、各サブエージェントが完了した後にその結果にアクセスする方法(例:結果やイベントのリストを通じて)を提供します。結果の順序は決定論的でない場合があります。

独立した実行と状態管理

ParallelAgent内のサブエージェントが独立して実行されることを理解することが極めて重要です。これらのエージェント間で通信やデータ共有が必要な場合は、明示的に実装する必要があります。考えられるアプローチは以下の通りです。

  • 共有InvocationContext: 各サブエージェントに共有のInvocationContextオブジェクトを渡すことができます。このオブジェクトは共有データストアとして機能します。ただし、競合状態(race condition)を避けるために、この共有コンテキストへの同時アクセスを(例:ロックを使用して)慎重に管理する必要があります。
  • 外部状態管理: 外部データベース、メッセージキュー、または他のメカニズムを使用して、共有ステートを管理し、エージェント間の通信を促進します。
  • 後処理 (Post-Processing): 各ブランチから結果を収集し、その後にデータを調整するロジックを実装します。

Parallel Agent

完全な例:並列ウェブ調査

複数のトピックを同時に調査する状況を想像してみてください。

  1. リサーチャーエージェント1: 「再生可能エネルギー源」を調査するLlmAgentです。
  2. リサーチャーエージェント2: 「電気自動車技術」を調査するLlmAgentです。
  3. リサーチャーエージェント3: 「炭素回収方法」を調査するLlmAgentです。

    ParallelAgent(sub_agents=[ResearcherAgent1, ResearcherAgent2, ResearcherAgent3])
    

これらの調査タスクは独立しています。ParallelAgentを使用すると、これらを並列実行でき、シーケンシャルに実行する場合と比較して、総調査時間を大幅に短縮できる可能性があります。各エージェントからの結果は、完了後に個別に収集されます。

全コード
 # Part of agent.py --> Follow https://google.github.io/adk-docs/get-started/quickstart/ to learn the setup
 # --- 1. Define Researcher Sub-Agents (to run in parallel) ---

 # Researcher 1: Renewable Energy
 researcher_agent_1 = LlmAgent(
     name="RenewableEnergyResearcher",
     model=GEMINI_MODEL,
     instruction="""You are an AI Research Assistant specializing in energy.
 Research the latest advancements in 'renewable energy sources'.
 Use the Google Search tool provided.
 Summarize your key findings concisely (1-2 sentences).
 Output *only* the summary.
 """,
     description="Researches renewable energy sources.",
     tools=[google_search],
     # Store result in state for the merger agent
     output_key="renewable_energy_result"
 )

 # Researcher 2: Electric Vehicles
 researcher_agent_2 = LlmAgent(
     name="EVResearcher",
     model=GEMINI_MODEL,
     instruction="""You are an AI Research Assistant specializing in transportation.
 Research the latest developments in 'electric vehicle technology'.
 Use the Google Search tool provided.
 Summarize your key findings concisely (1-2 sentences).
 Output *only* the summary.
 """,
     description="Researches electric vehicle technology.",
     tools=[google_search],
     # Store result in state for the merger agent
     output_key="ev_technology_result"
 )

 # Researcher 3: Carbon Capture
 researcher_agent_3 = LlmAgent(
     name="CarbonCaptureResearcher",
     model=GEMINI_MODEL,
     instruction="""You are an AI Research Assistant specializing in climate solutions.
 Research the current state of 'carbon capture methods'.
 Use the Google Search tool provided.
 Summarize your key findings concisely (1-2 sentences).
 Output *only* the summary.
 """,
     description="Researches carbon capture methods.",
     tools=[google_search],
     # Store result in state for the merger agent
     output_key="carbon_capture_result"
 )

 # --- 2. Create the ParallelAgent (Runs researchers concurrently) ---
 # This agent orchestrates the concurrent execution of the researchers.
 # It finishes once all researchers have completed and stored their results in state.
 parallel_research_agent = ParallelAgent(
     name="ParallelWebResearchAgent",
     sub_agents=[researcher_agent_1, researcher_agent_2, researcher_agent_3],
     description="Runs multiple research agents in parallel to gather information."
 )

 # --- 3. Define the Merger Agent (Runs *after* the parallel agents) ---
 # This agent takes the results stored in the session state by the parallel agents
 # and synthesizes them into a single, structured response with attributions.
 merger_agent = LlmAgent(
     name="SynthesisAgent",
     model=GEMINI_MODEL,  # Or potentially a more powerful model if needed for synthesis
     instruction="""You are an AI Assistant responsible for combining research findings into a structured report.

 Your primary task is to synthesize the following research summaries, clearly attributing findings to their source areas. Structure your response using headings for each topic. Ensure the report is coherent and integrates the key points smoothly.

 **Crucially: Your entire response MUST be grounded *exclusively* on the information provided in the 'Input Summaries' below. Do NOT add any external knowledge, facts, or details not present in these specific summaries.**

 **Input Summaries:**

 *   **Renewable Energy:**
     {renewable_energy_result}

 *   **Electric Vehicles:**
     {ev_technology_result}

 *   **Carbon Capture:**
     {carbon_capture_result}

 **Output Format:**

 ## Summary of Recent Sustainable Technology Advancements

 ### Renewable Energy Findings
 (Based on RenewableEnergyResearcher's findings)
 [Synthesize and elaborate *only* on the renewable energy input summary provided above.]

 ### Electric Vehicle Findings
 (Based on EVResearcher's findings)
 [Synthesize and elaborate *only* on the EV input summary provided above.]

 ### Carbon Capture Findings
 (Based on CarbonCaptureResearcher's findings)
 [Synthesize and elaborate *only* on the carbon capture input summary provided above.]

 ### Overall Conclusion
 [Provide a brief (1-2 sentence) concluding statement that connects *only* the findings presented above.]

 Output *only* the structured report following this format. Do not include introductory or concluding phrases outside this structure, and strictly adhere to using only the provided input summary content.
 """,
     description="Combines research findings from parallel agents into a structured, cited report, strictly grounded on provided inputs.",
     # No tools needed for merging
     # No output_key needed here, as its direct response is the final output of the sequence
 )


 # --- 4. Create the SequentialAgent (Orchestrates the overall flow) ---
 # This is the main agent that will be run. It first executes the ParallelAgent
 # to populate the state, and then executes the MergerAgent to produce the final output.
 sequential_pipeline_agent = SequentialAgent(
     name="ResearchAndSynthesisPipeline",
     # Run parallel research first, then merge
     sub_agents=[parallel_research_agent, merger_agent],
     description="Coordinates parallel research and synthesizes the results."
 )

 root_agent = sequential_pipeline_agent
    model, err := gemini.NewModel(ctx, modelName, &genai.ClientConfig{})
    if err != nil {
        return fmt.Errorf("failed to create model: %v", err)
    }

    // --- 1. Define Researcher Sub-Agents (to run in parallel) ---
    researcher1, err := llmagent.New(llmagent.Config{
        Name:  "RenewableEnergyResearcher",
        Model: model,
        Instruction: `You are an AI Research Assistant specializing in energy.
 Research the latest advancements in 'renewable energy sources'.
 Use the Google Search tool provided.
 Summarize your key findings concisely (1-2 sentences).
 Output *only* the summary.`,
        Description: "Researches renewable energy sources.",
        OutputKey:   "renewable_energy_result",
    })
    if err != nil {
        return err
    }
    researcher2, err := llmagent.New(llmagent.Config{
        Name:  "EVResearcher",
        Model: model,
        Instruction: `You are an AI Research Assistant specializing in transportation.
 Research the latest developments in 'electric vehicle technology'.
 Use the Google Search tool provided.
 Summarize your key findings concisely (1-2 sentences).
 Output *only* the summary.`,
        Description: "Researches electric vehicle technology.",
        OutputKey:   "ev_technology_result",
    })
    if err != nil {
        return err
    }
    researcher3, err := llmagent.New(llmagent.Config{
        Name:  "CarbonCaptureResearcher",
        Model: model,
        Instruction: `You are an AI Research Assistant specializing in climate solutions.
 Research the current state of 'carbon capture methods'.
 Use the Google Search tool provided.
 Summarize your key findings concisely (1-2 sentences).
 Output *only* the summary.`,
        Description: "Researches carbon capture methods.",
        OutputKey:   "carbon_capture_result",
    })
    if err != nil {
        return err
    }

    // --- 2. Create the ParallelAgent (Runs researchers concurrently) ---
    parallelResearchAgent, err := parallelagent.New(parallelagent.Config{
        AgentConfig: agent.Config{
            Name:        "ParallelWebResearchAgent",
            Description: "Runs multiple research agents in parallel to gather information.",
            SubAgents:   []agent.Agent{researcher1, researcher2, researcher3},
        },
    })
    if err != nil {
        return fmt.Errorf("failed to create parallel agent: %v", err)
    }

    // --- 3. Define the Merger Agent (Runs *after* the parallel agents) ---
    synthesisAgent, err := llmagent.New(llmagent.Config{
        Name:  "SynthesisAgent",
        Model: model,
        Instruction: `You are an AI Assistant responsible for combining research findings into a structured report.
 Your primary task is to synthesize the following research summaries, clearly attributing findings to their source areas. Structure your response using headings for each topic. Ensure the report is coherent and integrates the key points smoothly.
 **Crucially: Your entire response MUST be grounded *exclusively* on the information provided in the 'Input Summaries' below. Do NOT add any external knowledge, facts, or details not present in these specific summaries.**
 **Input Summaries:**

 *   **Renewable Energy:**
     {renewable_energy_result}

 *   **Electric Vehicles:**
     {ev_technology_result}

 *   **Carbon Capture:**
     {carbon_capture_result}

 **Output Format:**

 ## Summary of Recent Sustainable Technology Advancements

 ### Renewable Energy Findings
 (Based on RenewableEnergyResearcher's findings)
 [Synthesize and elaborate *only* on the renewable energy input summary provided above.]

 ### Electric Vehicle Findings
 (Based on EVResearcher's findings)
 [Synthesize and elaborate *only* on the EV input summary provided above.]

 ### Carbon Capture Findings
 (Based on CarbonCaptureResearcher's findings)
 [Synthesize and elaborate *only* on the carbon capture input summary provided above.]

 ### Overall Conclusion
 [Provide a brief (1-2 sentence) concluding statement that connects *only* the findings presented above.]

 Output *only* the structured report following this format. Do not include introductory or concluding phrases outside this structure, and strictly adhere to using only the provided input summary content.`,
        Description: "Combines research findings from parallel agents into a structured, cited report, strictly grounded on provided inputs.",
    })
    if err != nil {
        return fmt.Errorf("failed to create synthesis agent: %v", err)
    }

    // --- 4. Create the SequentialAgent (Orchestrates the overall flow) ---
    pipeline, err := sequentialagent.New(sequentialagent.Config{
        AgentConfig: agent.Config{
            Name:        "ResearchAndSynthesisPipeline",
            Description: "Coordinates parallel research and synthesizes the results.",
            SubAgents:   []agent.Agent{parallelResearchAgent, synthesisAgent},
        },
    })
    if err != nil {
        return fmt.Errorf("failed to create sequential agent pipeline: %v", err)
    }
 import com.google.adk.agents.LlmAgent;
 import com.google.adk.agents.ParallelAgent;
 import com.google.adk.agents.SequentialAgent;
 import com.google.adk.events.Event;
 import com.google.adk.runner.InMemoryRunner;
 import com.google.adk.sessions.Session;
 import com.google.adk.tools.GoogleSearchTool;
 import com.google.genai.types.Content;
 import com.google.genai.types.Part;
 import io.reactivex.rxjava3.core.Flowable;

 public class ParallelResearchPipeline {

   private static final String APP_NAME = "parallel_research_app";
   private static final String USER_ID = "research_user_01";
   private static final String GEMINI_MODEL = "gemini-2.0-flash";

   // Assume google_search is an instance of the GoogleSearchTool
   private static final GoogleSearchTool googleSearchTool = new GoogleSearchTool();

   public static void main(String[] args) {
     String query = "Summarize recent sustainable tech advancements.";
     SequentialAgent sequentialPipelineAgent = initAgent();
     runAgent(sequentialPipelineAgent, query);
   }

   public static SequentialAgent initAgent() {
     // --- 1. Define Researcher Sub-Agents (to run in parallel) ---
     // Researcher 1: Renewable Energy
     LlmAgent researcherAgent1 = LlmAgent.builder()
         .name("RenewableEnergyResearcher")
         .model(GEMINI_MODEL)
         .instruction("""
                     You are an AI Research Assistant specializing in energy.
                     Research the latest advancements in 'renewable energy sources'.
                     Use the Google Search tool provided.
                     Summarize your key findings concisely (1-2 sentences).
                     Output *only* the summary.
                     """)
         .description("Researches renewable energy sources.")
         .tools(googleSearchTool)
         .outputKey("renewable_energy_result") // Store result in state
         .build();

     // Researcher 2: Electric Vehicles
     LlmAgent researcherAgent2 = LlmAgent.builder()
         .name("EVResearcher")
         .model(GEMINI_MODEL)
         .instruction("""
                     You are an AI Research Assistant specializing in transportation.
                     Research the latest developments in 'electric vehicle technology'.
                     Use the Google Search tool provided.
                     Summarize your key findings concisely (1-2 sentences).
                     Output *only* the summary.
                     """)
         .description("Researches electric vehicle technology.")
         .tools(googleSearchTool)
         .outputKey("ev_technology_result") // Store result in state
         .build();

     // Researcher 3: Carbon Capture
     LlmAgent researcherAgent3 = LlmAgent.builder()
         .name("CarbonCaptureResearcher")
         .model(GEMINI_MODEL)
         .instruction("""
                     You are an AI Research Assistant specializing in climate solutions.
                     Research the current state of 'carbon capture methods'.
                     Use the Google Search tool provided.
                     Summarize your key findings concisely (1-2 sentences).
                     Output *only* the summary.
                     """)
         .description("Researches carbon capture methods.")
         .tools(googleSearchTool)
         .outputKey("carbon_capture_result") // Store result in state
         .build();

     // --- 2. Create the ParallelAgent (Runs researchers concurrently) ---
     // This agent orchestrates the concurrent execution of the researchers.
     // It finishes once all researchers have completed and stored their results in state.
     ParallelAgent parallelResearchAgent =
         ParallelAgent.builder()
             .name("ParallelWebResearchAgent")
             .subAgents(researcherAgent1, researcherAgent2, researcherAgent3)
             .description("Runs multiple research agents in parallel to gather information.")
             .build();

     // --- 3. Define the Merger Agent (Runs *after* the parallel agents) ---
     // This agent takes the results stored in the session state by the parallel agents
     // and synthesizes them into a single, structured response with attributions.
     LlmAgent mergerAgent =
         LlmAgent.builder()
             .name("SynthesisAgent")
             .model(GEMINI_MODEL)
             .instruction(
                 """
                       You are an AI Assistant responsible for combining research findings into a structured report.
                       Your primary task is to synthesize the following research summaries, clearly attributing findings to their source areas. Structure your response using headings for each topic. Ensure the report is coherent and integrates the key points smoothly.
                       **Crucially: Your entire response MUST be grounded *exclusively* on the information provided in the 'Input Summaries' below. Do NOT add any external knowledge, facts, or details not present in these specific summaries.**
                       **Input Summaries:**

                       *   **Renewable Energy:**
                           {renewable_energy_result}

                       *   **Electric Vehicles:**
                           {ev_technology_result}

                       *   **Carbon Capture:**
                           {carbon_capture_result}

                       **Output Format:**

                       ## Summary of Recent Sustainable Technology Advancements

                       ### Renewable Energy Findings
                       (Based on RenewableEnergyResearcher's findings)
                       [Synthesize and elaborate *only* on the renewable energy input summary provided above.]

                       ### Electric Vehicle Findings
                       (Based on EVResearcher's findings)
                       [Synthesize and elaborate *only* on the EV input summary provided above.]

                       ### Carbon Capture Findings
                       (Based on CarbonCaptureResearcher's findings)
                       [Synthesize and elaborate *only* on the carbon capture input summary provided above.]

                       ### Overall Conclusion
                       [Provide a brief (1-2 sentence) concluding statement that connects *only* the findings presented above.]

                       Output *only* the structured report following this format. Do not include introductory or concluding phrases outside this structure, and strictly adhere to using only the provided input summary content.
                       """)
             .description(
                 "Combines research findings from parallel agents into a structured, cited report, strictly grounded on provided inputs.")
             // No tools needed for merging
             // No output_key needed here, as its direct response is the final output of the sequence
             .build();

     // --- 4. Create the SequentialAgent (Orchestrates the overall flow) ---
     // This is the main agent that will be run. It first executes the ParallelAgent
     // to populate the state, and then executes the MergerAgent to produce the final output.
     SequentialAgent sequentialPipelineAgent =
         SequentialAgent.builder()
             .name("ResearchAndSynthesisPipeline")
             // Run parallel research first, then merge
             .subAgents(parallelResearchAgent, mergerAgent)
             .description("Coordinates parallel research and synthesizes the results.")
             .build();

     return sequentialPipelineAgent;
   }

   public static void runAgent(SequentialAgent sequentialPipelineAgent, String query) {
     // Create an InMemoryRunner
     InMemoryRunner runner = new InMemoryRunner(sequentialPipelineAgent, APP_NAME);
     // InMemoryRunner automatically creates a session service. Create a session using the service
     Session session = runner.sessionService().createSession(APP_NAME, USER_ID).blockingGet();
     Content userMessage = Content.fromParts(Part.fromText(query));

     // Run the agent
     Flowable<Event> eventStream = runner.runAsync(USER_ID, session.id(), userMessage);

     // Stream event response
     eventStream.blockingForEach(
         event -> {
           if (event.finalResponse()) {
             System.out.printf("Event Author: %s \n Event Response: %s \n\n\n", event.author(), event.stringifyContent());
           }
         });
   }
 }