Blog

Criando uma sala de imprensa para agentes LLM com protocolo A2A e MCP no Elasticsearch: Parte II

Descubra como construir uma redação especializada para agentes LLM em um ambiente híbrido, utilizando o protocolo A2A para colaboração entre agentes e o MCP para acesso a ferramentas no Elasticsearch.

A2A e MCP: o código em ação

Este artigo é um complemento ao artigo "Criando uma sala de imprensa com o agente LLM usando os protocolos A2A e MCP no Elasticsearch!", que explicou os benefícios de implementar as arquiteturas A2A e MCP no mesmo agente para aproveitar ao máximo as vantagens exclusivas de ambas as estruturas. Um repositório está disponível caso você queira executar a demonstração por conta própria.

Fluxo de trabalho do agente de protocolo A2A e MCP

Vamos analisar como nossos agentes de redação colaboram usando tanto o A2A quanto o MCP para produzir um artigo jornalístico. O repositório que acompanha o projeto, onde é possível ver os agentes em ação, pode ser encontrado aqui.

Etapa 1: Atribuição da história

O chefe de jornalismo (atuando como cliente) designa uma pauta:

{
  "message_type": "task_request",
  "sender": "news_chief",
  "receiver": "reporter_agent",
  "payload": {
    "task_id": "story_renewable_energy_2024",
    "assignment": {
      "topic": "Renewable Energy Adoption in Europe",
      "angle": "Policy changes driving solar and wind expansion",
      "target_length": 1200,
      "deadline": "2025-09-30T18:00:00Z"
    }
  }
}

Etapa 2: O repórter solicita pesquisa.

O Agente Repórter reconhece que precisa de informações básicas e delega essa tarefa ao Agente Pesquisador por meio do método A2A:

{
  "message_type": "task_request",
  "sender": "reporter_agent",
  "receiver": "researcher_agent",
  "payload": {
    "task_id": "research_eu_renewable_2024",
    "parent_task_id": "story_renewable_energy_2024",
    "capability": "fact_gathering",
    "parameters": {
      "queries": [
        "EU renewable energy capacity 2024",
        "Solar installations growth Europe",
        "Wind energy policy changes 2024"
      ],
      "depth": "comprehensive"
    }
  }
}

Etapa 3: O repórter solicita contexto histórico ao Agente de Arquivo.

O agente repórter reconhece que o contexto histórico fortaleceria a matéria. Ele delega ao Agente de Arquivo (com tecnologia A2A do Elastic) via A2A a busca no arquivo de artigos da sala de notícias, que utiliza o Elasticsearch:

{
  "message_type": "task_request",
  "sender": "reporter_agent",
  "receiver": "archive_agent",
  "payload": {
    "task_id": "archive_search_renewable_2024",
    "parent_task_id": "story_renewable_energy_2024",
    "capability": "search_archive",
    "parameters": {
      "query": "European renewable energy policy changes and adoption trends over past 5 years",
      "focus_areas": ["solar", "wind", "policy", "Germany", "France"],
      "time_range": "2019-2024",
      "result_count": 10
    }
  }
}

Etapa 4: O Agente de Arquivamento usa o Agente A2A Elástico com MCP

O Agente de Arquivamento utiliza o Agente A2A da Elastic, que por sua vez usa o MCP para acessar as ferramentas do Elasticsearch. Isso demonstra a arquitetura híbrida onde o A2A permite a colaboração entre agentes enquanto o MCP fornece acesso às ferramentas:

# Archive Agent using Elastic A2A Agent
async def search_historical_articles(self, query_params):
    # The Archive Agent sends a request to Elastic's A2A Agent
    elastic_response = await self.a2a_client.send_request(
        agent="elastic_agent",
        capability="search_and_analyze",
        parameters={
            "natural_language_query": query_params["query"],
            "index_pattern": "newsroom-articles-*",
            "filters": {
                "topics": query_params["focus_areas"],
                "date_range": query_params["time_range"]
            },
            "analysis_type": "trend_analysis"
        }
    )
    
    # Elastic's A2A Agent internally uses MCP tools:
    # - platform.core.search (to find relevant articles)
    # - platform.core.generate_esql (to analyze trends)
    # - platform.core.index_explorer (to identify relevant indices)
    
    return elastic_response

O Agente de Arquivamento recebe dados históricos abrangentes do Agente A2A da Elastic e os retorna ao Reporter:

{
  "message_type": "task_response",
  "sender": "archive_agent",
  "receiver": "reporter_agent",
  "payload": {
    "task_id": "archive_search_renewable_2024",
    "status": "completed",
    "archive_data": {
      "historical_articles": [
        {
          "title": "Germany's Energiewende: Five Years of Solar Growth",
          "published": "2022-06-15",
          "key_points": [
            "Germany added 7 GW annually 2020-2022",
            "Policy subsidies drove 60% of growth"
          ],
          "relevance_score": 0.94
        },
        {
          "title": "France Balances Nuclear and Renewables",
          "published": "2023-03-20",
          "key_points": [
            "France increased renewable target to 40% by 2030",
            "Solar capacity doubled 2021-2023"
          ],
          "relevance_score": 0.89
        }
      ],
      "trend_analysis": {
        "coverage_frequency": "EU renewable stories increased 150% since 2019",
        "emerging_themes": ["policy incentives", "grid modernization", "battery storage"],
        "coverage_gaps": ["Small member states", "offshore wind permitting"]
      },
      "total_articles_found": 47,
      "search_confidence": 0.91
    }
  }
}

Esta etapa demonstra como o agente A2A da Elastic se integra ao fluxo de trabalho da redação. O Agente de Arquivo (um agente específico para redações) trabalha em conjunto com o Agente A2A da Elastic (um especialista terceirizado) para aproveitar os poderosos recursos de busca e análise do Elasticsearch. O agente da Elastic usa o MCP internamente para acessar as ferramentas do Elasticsearch, demonstrando a clara separação entre a coordenação do agente (A2A) e o acesso às ferramentas (MCP).

Etapa 5: O pesquisador utiliza servidores MCP

O Agente Pesquisador acessa vários servidores MCP para coletar informações:

# Researcher Agent using MCP to access tools
async def gather_facts(self, queries):
    results = []
    
    # Use News API MCP Server
    news_data = await self.mcp_client.invoke_tool(
        server="news_api_mcp",
        tool="search_articles",
        parameters={
            "query": queries[0],
            "date_range": "2024-01-01 to 2024-09-30",
            "sources": ["reuters", "bloomberg", "euractiv"]
        }
    )
    
    # Use Statistics MCP Server
    stats_data = await self.mcp_client.invoke_tool(
        server="eurostat_mcp",
        tool="get_energy_statistics",
        parameters={
            "metrics": ["solar_capacity_mw", "wind_capacity_mw"],
            "countries": ["EU27"],
            "year": 2024
        }
    )
    
    # Use Fact-Checking MCP Server
    verified_facts = await self.mcp_client.invoke_tool(
        server="factcheck_mcp",
        tool="verify_claims",
        parameters={
            "claims": [
                "EU solar capacity increased 40% in 2024",
                "Germany leads in wind installations"
            ]
        }
    )
    
    return self._synthesize_research(news_data, stats_data, verified_facts)

Etapa 6: O pesquisador devolve os dados ao repórter.

O Agente de Pesquisa envia uma pesquisa completa de volta via A2A:

{
  "message_type": "task_response",
  "sender": "researcher_agent",
  "receiver": "reporter_agent",
  "payload": {
    "task_id": "research_eu_renewable_2024",
    "status": "completed",
    "research_data": {
      "key_facts": [
        {
          "claim": "EU solar capacity reached 260 GW in 2024",
          "source": "Eurostat Q3 2024 Report",
          "confidence": 0.95,
          "verified": true
        },
        {
          "claim": "Germany installed 12 GW of wind capacity in 2024",
          "source": "German Federal Network Agency",
          "confidence": 0.92,
          "verified": true
        }
      ],
      "statistics": {
        "solar_growth_rate": "35%",
        "wind_growth_rate": "28%"
      },
      "sources_count": 15
    }
  }
}

Etapa 7: O repórter escreve o artigo

O Repórter Agente utiliza os dados da pesquisa e suas próprias capacidades de mestrado em Direito (LLM) para redigir o artigo. Durante a escrita, o Repórter utiliza os servidores MCP para estilo e modelos:

# Reporter Agent writing with MCP assistance
async def write_article(self, research_data, assignment):
    # Get style guidelines via MCP
    style_guide = await self.mcp_client.get_resource(
        server="newsroom_mcp",
        resource="style://editorial/ap_style_guide"
    )
    
    # Get article template via MCP
    template = await self.mcp_client.get_resource(
        server="newsroom_mcp",
        resource="template://articles/news_story"
    )
    
    # Generate article using LLM + research + style
    draft = await self.llm.generate(
        prompt=f"""
        Write a news article following these guidelines:
        {style_guide}
        
        Using this template:
        {template}
        
        Based on this research:
        {research_data}
        
        Assignment: {assignment}
        """
    )
    
    # Self-evaluate confidence in claims
    confidence_check = await self._evaluate_confidence(draft)
    
    return draft, confidence_check

Etapa 8: baixa confiança desencadeia nova pesquisa

O agente repórter avalia sua versão preliminar e constata que uma das afirmações apresenta baixo nível de confiança. Envia outra solicitação ao Agente Pesquisador:

{
  "message_type": "collaboration_request",
  "sender": "reporter_agent",
  "receiver": "researcher_agent",
  "payload": {
    "request_type": "fact_verification",
    "claims": [
      {
        "text": "France's nuclear phase-down contributed to 15% increase in renewable capacity",
        "context": "Discussing policy drivers for renewable growth",
        "current_confidence": 0.45,
        "required_confidence": 0.80
      }
    ],
    "urgency": "high"
  }
}

O pesquisador verifica a alegação usando servidores de checagem de fatos do MCP e retorna informações atualizadas:

{
  "message_type": "collaboration_response",
  "sender": "researcher_agent",
  "receiver": "reporter_agent",
  "payload": {
    "verified_claims": [
      {
        "original_claim": "France's nuclear phase-down contributed to 15% increase...",
        "verified_claim": "France's renewable capacity increased 18% in 2024, partially offsetting reduced nuclear output",
        "confidence": 0.88,
        "corrections": "Percentage was 18%, not 15%; nuclear phase-down is gradual, not primary driver",
        "sources": ["RTE France", "French Energy Ministry Report 2024"]
      }
    ]
  }
}

Etapa 9: O repórter revisa e envia ao editor.

O repórter incorpora os fatos verificados e envia a versão finalizada ao editor por meio do sistema A2A:

{
  "message_type": "task_request",
  "sender": "reporter_agent",
  "receiver": "editor_agent",
  "payload": {
    "task_id": "edit_renewable_story",
    "parent_task_id": "story_renewable_energy_2024",
    "content": {
      "headline": "Europe's Renewable Revolution: Solar and Wind Surge 30% in 2024",
      "body": "[Full article text...]",
      "word_count": 1185,
      "sources": [/* array of sources */]
    },
    "editing_requirements": {
      "check_style": true,
      "check_facts": true,
      "check_seo": true
    }
  }
}

Etapa 10: Revisão do editor usando as ferramentas MCP

O Agente de Edição utiliza vários servidores MCP para revisar o artigo:

# Editor Agent using MCP for quality checks
async def review_article(self, content):
    # Grammar and style check
    grammar_issues = await self.mcp_client.invoke_tool(
        server="grammarly_mcp",
        tool="check_document",
        parameters={"text": content["body"]}
    )
    
    # SEO optimization check
    seo_analysis = await self.mcp_client.invoke_tool(
        server="seo_mcp",
        tool="analyze_content",
        parameters={
            "headline": content["headline"],
            "body": content["body"],
            "target_keywords": ["renewable energy", "Europe", "solar", "wind"]
        }
    )
    
    # Plagiarism check
    originality = await self.mcp_client.invoke_tool(
        server="plagiarism_mcp",
        tool="check_originality",
        parameters={"text": content["body"]}
    )
    
    # Generate editorial feedback
    feedback = await self._generate_feedback(
        grammar_issues, 
        seo_analysis, 
        originality
    )
    
    return feedback

O editor aprova o artigo e o encaminha:

{
  "message_type": "task_response",
  "sender": "editor_agent",
  "receiver": "reporter_agent",
  "payload": {
    "status": "approved",
    "quality_score": 9.2,
    "minor_edits": [
      "Changed 'surge' to 'increased' in paragraph 3 for AP style consistency",
      "Added Oxford comma in list of countries"
    ],
    "approved_content": "[Final edited article]"
  }
}

Etapa 11: A editora publica via CI/CD

Por fim, o Agente de Impressão publica o artigo aprovado usando os servidores MCP para o pipeline CMS e CI/CD:

# Publisher Agent publishing via MCP
async def publish_article(self, content, metadata):
    # Upload to CMS via MCP
    cms_result = await self.mcp_client.invoke_tool(
        server="wordpress_mcp",
        tool="create_post",
        parameters={
            "title": content["headline"],
            "body": content["body"],
            "status": "draft",
            "categories": metadata["categories"],
            "tags": metadata["tags"],
            "featured_image_url": metadata["image_url"]
        }
    )
    
    post_id = cms_result["post_id"]
    
    # Trigger CI/CD deployment via MCP
    deploy_result = await self.mcp_client.invoke_tool(
        server="cicd_mcp",
        tool="trigger_deployment",
        parameters={
            "pipeline": "publish_article",
            "environment": "production",
            "post_id": post_id,
            "schedule": "immediate"
        }
    )
    
    # Track analytics
    await self.mcp_client.invoke_tool(
        server="analytics_mcp",
        tool="register_publication",
        parameters={
            "post_id": post_id,
            "publish_time": datetime.now().isoformat(),
            "story_id": metadata["story_id"]
        }
    )
    
    return {
        "status": "published",
        "post_id": post_id,
        "url": f"https://newsroom.example.com/articles/{post_id}",
        "deployment_id": deploy_result["deployment_id"]
    }

A editora confirma a publicação via A2A:

{
  "message_type": "task_complete",
  "sender": "printer_agent",
  "receiver": "news_chief",
  "payload": {
    "task_id": "story_renewable_energy_2024",
    "status": "published",
    "publication": {
      "url": "https://newsroom.example.com/articles/renewable-europe-2024",
      "published_at": "2025-09-30T17:45:00Z",
      "post_id": "12345"
    },
    "workflow_metrics": {
      "total_time_minutes": 45,
      "agents_involved": ["reporter", "researcher", "archive", "editor", "printer"],
      "iterations": 2,
      "mcp_calls": 12
    }
  }
}

Segue abaixo a sequência completa do fluxo de trabalho A2A no repositório anexo, utilizando os mesmos agentes descritos acima.

#

De

Para

Ação

Protocolo

Descrição

1

Usuário

Chefe de Notícias

Atribuir história

HTTP POST

O usuário envia o tema e o enfoque da matéria.

2

Chefe de Notícias

Interno

Criar história

-

Cria um registro de história com um ID exclusivo.

3

Chefe de Notícias

Repórter

Atribuição de Delegado

A2A

Envia a atribuição da matéria através do protocolo A2A

4

Repórter

Interno

Aceitar tarefa

-

Atribuição de estoques internamente

5

Repórter

Servidor MCP

Gerar esboço

MCP/HTTP

Cria o esboço do artigo e as perguntas de pesquisa.

6a

Repórter

Pesquisador

Solicitar pesquisa

A2A

Envia perguntas (paralelo com 6b)

6b

Repórter

Arquivista

Pesquisar no arquivo

A2A JSONRPC

Pesquisa artigos históricos (paralelo com 6a)

7

Pesquisador

Servidor MCP

Questões de pesquisa

MCP/HTTP

Utiliza a abordagem antropogênica via MCP para responder a perguntas.

8

Pesquisador

Repórter

Retornar à pesquisa

A2A

Devolve respostas de pesquisa

9

Arquivista

Elasticsearch

Índice de pesquisa

API REST do ES

Consultas ao índice news_archive

10

Arquivista

Repórter

Retornar ao arquivo

A2A JSONRPC

Retorna resultados de pesquisa históricos

11

Repórter

Servidor MCP

Gerar artigo

MCP/HTTP

Cria artigo com contexto de pesquisa/arquivo

12

Repórter

Interno

Rascunho da loja

-

Salva o rascunho internamente

13

Repórter

Chefe de Notícias

Enviar rascunho

A2A

Entrega a versão finalizada

14

Chefe de Notícias

Interno

Atualização da história

-

Armazena o rascunho e atualiza o status para "rascunho_enviado".

15

Chefe de Notícias

Editor

Revisão do rascunho

A2A

Encaminha automaticamente para o Editor para revisão.

16

Editor

Servidor MCP

Artigo de revisão

MCP/HTTP

Analisa conteúdo usando Anthropic via MCP.

17

Editor

Chefe de Notícias

Revisão de retorno

A2A

Envia comentários e sugestões editoriais.

18

Chefe de Notícias

Interno

Avaliação da loja

-

Feedback do editor de lojas

19

Chefe de Notícias

Repórter

Aplicar edições

A2A

Feedback da revisão de rotas para o repórter

20

Repórter

Servidor MCP

Aplicar edições

MCP/HTTP

Revisa o artigo com base no feedback.

21

Repórter

Interno

Rascunho atualizado

-

Atualiza a versão preliminar com revisões.

22

Repórter

Chefe de Notícias

Devolução revisada

A2A

Devolve artigo revisado

23

Chefe de Notícias

Interno

Atualização da história

-

Lojas revisaram a versão preliminar, status para "revisado"

24

Chefe de Notícias

Editor

Publicar artigo

A2A

Rotas automáticas para o editor

25

Editor

Servidor MCP

Gerar etiquetas

MCP/HTTP

Cria etiquetas e categorias

26

Editor

Elasticsearch

Artigo de índice

API REST do ES

Indexa o artigo ao índice news_archive

27

Editor

Sistema de arquivos

Salvar Markdown

Entrada/Saída de Arquivos

Salva o artigo como .md arquivo em /artigos

28

Editor

Chefe de Notícias

Confirmar publicação

A2A

Retorna o status de sucesso

29

Chefe de Notícias

Interno

Atualização da história

-

Atualiza o status da matéria para "publicada".

Conclusão

Tanto o A2A quanto o MCP desempenham papéis importantes no paradigma moderno de infraestrutura de LLM aumentada. A tecnologia A2A oferece flexibilidade para sistemas multiagentes complexos, mas potencialmente menor portabilidade e maior complexidade operacional. O MCP oferece uma abordagem padronizada para integração de ferramentas que é mais simples de implementar e manter, embora não seja projetado para lidar com orquestração multiagente.

A escolha não é binária. Conforme demonstrado em nosso exemplo de redação, os sistemas mais sofisticados e eficazes baseados em LLM geralmente combinam ambas as abordagens: os agentes se coordenam e se especializam por meio de protocolos A2A, enquanto acessam suas ferramentas e recursos por meio de servidores MCP. Essa arquitetura híbrida proporciona os benefícios organizacionais dos sistemas multiagentes, juntamente com a padronização e as vantagens do ecossistema do MCP. Isso sugere que talvez não seja necessário escolher: basta usar ambos como abordagem padrão.

Cabe a você, como desenvolvedor ou arquiteto, testar e determinar a melhor combinação de ambas as soluções para obter o resultado adequado ao seu caso de uso específico. Compreender os pontos fortes, as limitações e as aplicações adequadas de cada abordagem permitirá que você construa sistemas de IA mais eficazes, fáceis de manter e escaláveis.

Seja para criar uma redação digital, uma plataforma de atendimento ao cliente, um assistente de pesquisa ou qualquer outro aplicativo baseado em LLM, considerar cuidadosamente suas necessidades de coordenação (A2A) e requisitos de acesso às ferramentas (MCP) o colocará no caminho do sucesso.

Recursos adicionais

Conteúdo relacionado

Construtor de agentes além da caixa de bate-papo: apresentando a infraestrutura ampliada

Alexander Wert

Gerenciando a memória agentiva com o Elasticsearch

Someshwaran Mohankumar

Usando a API de Inferência Elasticsearch junto com modelos de Hugging Face

Jeffrey Rengifo

Criando um agente de IA para RH com Elastic Agent Builder e GPT-OSS

Tomás Murúa

Criando um servidor MCP do Elasticsearch com TypeScript

Jeffrey Rengifo

Pronto para criar buscas de última geração?

Uma pesquisa suficientemente avançada não se consegue apenas com o esforço de uma só pessoa. O Elasticsearch é impulsionado por cientistas de dados, especialistas em operações de aprendizado de máquina, engenheiros e muitos outros que são tão apaixonados por buscas quanto você. Vamos nos conectar e trabalhar juntos para construir a experiência de busca mágica que lhe trará os resultados desejados.

Experimente você mesmo(a)