Kestra-AI-Orchestration / flows / 6_multi_agent_research.yaml
6_multi_agent_research.yaml
Raw
id: 6_multi_agent_research
namespace: zoomcamp

description: |
  This flow demonstrates a multi-agent system where specialized agents collaborate.
  Architecture:
  - Main Agent (Analyst): Synthesizes findings and creates structured reports
  - Research Agent (Tool): Gathers web data using Tavily search
  The main agent uses the research agent as a TOOL, demonstrating how agents can delegate specialized work to other agents.  

inputs:
  - id: company_name
    type: STRING
    description: The company to research
    defaults: kestra.io

tasks:
  - id: analysis
    type: io.kestra.plugin.ai.agent.AIAgent
    description: Main analyst agent that orchestrates research
    configuration:
      logRequests: false
      logResponses: false
    provider:
      type: io.kestra.plugin.ai.provider.GoogleGemini
    systemMessage: |
      You are a senior market intelligence analyst. You can use the research tool to gather accurate, up-to-date company data. 
      After retrieving information, summarize and synthesize it into structured, factual insights.
      If information is incomplete, infer from context or industry knowledge, but never leave required fields empty.
      Output must be a **valid JSON object only** — without markdown, code fences, or commentary.
      Never include ```json or ``` markers.      
    prompt: |
      Research the company "{{ inputs.company_name }}" using the research tool.
      Then summarize your findings in this JSON structure:

      {
        "company": "string — name of the company",
        "summary": "string — overview of what the company does and its main products or services",
        "recent_news": [
          {
            "title": "string — short headline or topic",
            "date": "string — publication date or approximate timeframe",
            "description": "string — short summary of the news item"
          }
        ],
        "competitors": ["string — list of notable competitors or similar companies"]
      }

      Rules:
      - Do **not** use markdown or code fences in your response.
      - Always output a single valid JSON object.
      - Always include at least two `recent_news` entry (real or inferred) and at least two `competitors`.
      - Do **not** include explanations or commentary outside the JSON.      
    tools:
      - type: io.kestra.plugin.ai.tool.AIAgent
        description: Web research and data gathering
        configuration:
          logRequests: false
          logResponses: false
        systemMessage: |
          You are a research assistant that searches the web for factual and up-to-date company information as of date {{ now() }}.
          Look for recent news from this year, funding announcements, blog posts, or competitor mentions.
          Return concise factual summaries — no markdown, no formatting, no speculation.          
        provider:
          type: io.kestra.plugin.ai.provider.GoogleGemini
        contentRetrievers:
          - type: io.kestra.plugin.ai.retriever.TavilyWebSearch
            apiKey: "{{ secret('TAVILY_API_KEY') }}"

  - id: parse_results
    type: io.kestra.plugin.core.log.Log
    message: |
      🎯 Competitive Intelligence Report
      =====================================
      
      Company: {{ json(outputs.analysis.textOutput).company }}
      Summary: {{ json(outputs.analysis.textOutput).summary }}
      
      Recent News:
      {% for news in json(outputs.analysis.textOutput).recent_news %}
      - {{ news.title }} ({{ news.date }})
        {{ news.description }}
      {% endfor %}
      
      Competitors:
      {% for competitor in json(outputs.analysis.textOutput).competitors %}
      - {{ competitor }}
      {% endfor %}
      
      📊 System Performance:
      - Main agent tokens: {{ outputs.analysis.tokenUsage.totalTokenCount }}
      
      💡 Multi-Agent Pattern:
      This demonstrates how the main analyst agent delegated the research 
      work to a specialized research agent, achieving modularity and 
      separation of concerns.      

pluginDefaults:
  - type: io.kestra.plugin.ai.provider.GoogleGemini
    values:
      modelName: gemini-2.5-flash
      apiKey: "{{ secret('GEMINI_API_KEY') }}"