使用 A2A 协议和 MCP 在 Elasticsearch 中创建一个 LLM agent 新闻室:第二部分

A2A与MCP融合构建LLM新闻代理

作者:来自 Elastic Justin Castilla

Agent Builder 现在作为技术预览版提供。使用 Elastic Cloud 试用即可开始,并在这里查看 Agent Builder 文档。


A2A 和 MCP:代码实战

这是文章 “在 Elasticsearch 中使用 A2A 协议和 MCP 创建一个 LLM agent 新闻室” 的配套内容,该文章解释了在同一个 agent 中同时实现 A2A 和 MCP 架构以真正获得两个框架独特优势的好处。我们也提供了一个代码仓库,方便你自己运行这个演示。

让我们来看看新闻室的 agent 如何同时使用 A2A 和 MCP 协作完成一篇新闻文章。你可以在这里找到配套的代码仓库,查看这些 agent 的实际运作。

步骤 1:选题分配

新闻主管(作为 client)分配一个选题:

{
  "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"
    }
  }
}

步骤 2:记者请求调研

Reporter agent 发现它需要背景信息,并通过 A2A 将任务委派给 Researcher agent:

{
  "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"
    }
  }
}

步骤 3:记者向 Archive agent 请求历史背景

Reporter agent 意识到历史背景会强化报道。它通过 A2A 将任务委派给由 Elastic 的 A2A agent 驱动的 Archive agent,在新闻室的 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
    }
  }
}

步骤 4:Archive agent 使用带 MCP 的 Elastic A2A agent

Archive agent 使用 Elastic 的 A2A agent,而这个 A2A agent 又使用 MCP 来访问 Elasticsearch 工具。这个过程展示了混合架构:A2A 负责 agent 协作,而 MCP 提供工具访问:

# 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

Archive agent 从 Elastic 的 A2A agent 收到全面的历史数据,并将其返回给 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
    }
  }
}

这一步展示了 Elastic 的 A2A agent 是如何融入新闻室工作流的。Archive agent(新闻室的专用 agent)与 Elastic 的 A2A agent(第三方专家)协作,从而利用 Elasticsearch 强大的搜索和分析能力。Elastic 的 agent 在内部使用 MCP 来访问 Elasticsearch 工具,体现了 agent 协作(A2A)与工具访问(MCP)之间清晰的分离。

步骤 5:Researcher 使用 MCP 服务器

Researcher agent 访问多个 MCP 服务器来收集信息:

# 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)

步骤 6:Researcher 将数据返回给 Reporter

Researcher agent 通过 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
    }
  }
}

步骤 7:Reporter 撰写文章

Reporter agent 使用调研数据和自身的 LLM 能力来撰写文章。在写作过程中,Reporter 使用 MCP 服务器来获取风格和模板:

# 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

步骤 8:低置信度触发重新调研

Reporter agent 评估其草稿后发现有一个观点置信度较低。它向 Researcher agent 发送另一个请求:

{
  "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"
  }
}

Researcher 使用 fact-checking MCP 服务器验证该观点,并返回更新的信息:

{
  "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"]
      }
    ]
  }
}

步骤 9:Reporter 修改并提交给 Editor

Reporter 将已验证的事实纳入文章,并通过 A2A 将完成的草稿发送给 Editor agent:

{
  "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
    }
  }
}

步骤 10:Editor 使用 MCP 工具进行审核

Editor agent 使用多个 MCP 服务器来审核文章:

# 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

Editor 批准文章并将其发送出去:

{
  "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]"
  }
}

步骤 11:Publisher 通过 CI/CD 发布

最后,Printer agent 使用 MCP 服务器操作 CMS 和 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"]
    }

Publisher 通过 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
    }
  }
}

这是配套代码仓库中使用上述相同 agent 的完整 A2A 工作流序列。

#FromToActionProtocolDescription
1UserNews ChiefAssign StoryHTTP POSTUser submits story topic and angle
2News ChiefInternalCreate Story-Creates story record with unique ID
3News ChiefReporterDelegate AssignmentA2ASends story assignment via A2A protocol
4ReporterInternalAccept Assignment-Stores assignment internally
5ReporterMCP ServerGenerate OutlineMCP/HTTPCreates article outline and research questions
6aReporterResearcherRequest ResearchA2ASends questions (parallel with 6b)
6bReporterArchivistSearch ArchiveA2A JSONRPCSearches historical articles (parallel with 6a)
7ResearcherMCP ServerResearch QuestionsMCP/HTTPUses Anthropic via MCP to answer questions
8ResearcherReporterReturn ResearchA2AReturns research answers
9ArchivistElasticsearchSearch IndexES REST APIQueries news_archive index
10ArchivistReporterReturn ArchiveA2A JSONRPCReturns historical search results
11ReporterMCP ServerGenerate ArticleMCP/HTTPCreates article with research/archive context
12ReporterInternalStore Draft-Saves draft internally
13ReporterNews ChiefSubmit DraftA2ASubmits completed draft
14News ChiefInternalUpdate Story-Stores draft, updates status to "draft_submitted"
15News ChiefEditorReview DraftA2AAuto-routes to Editor for review
16EditorMCP ServerReview ArticleMCP/HTTPAnalyzes content using Anthropic via MCP
17EditorNews ChiefReturn ReviewA2ASends editorial feedback and suggestions
18News ChiefInternalStore Review-Stores editor feedback
19News ChiefReporterApply EditsA2ARoutes review feedback to Reporter
20ReporterMCP ServerApply EditsMCP/HTTPRevises article based on feedback
21ReporterInternalUpdate Draft-Updates draft with revisions
22ReporterNews ChiefReturn RevisedA2AReturns revised article
23News ChiefInternalUpdate Story-Stores revised draft, status to "revised"
24News ChiefPublisherPublish ArticleA2AAuto-routes to Publisher
25PublisherMCP ServerGenerate TagsMCP/HTTPCreates tags and categories
26PublisherElasticsearchIndex ArticleES REST APIIndexes article to news_archive index
27PublisherFilesystemSave MarkdownFile I/OSaves article as .md file in /articles
28PublisherNews ChiefConfirm PublicationA2AReturns success status
29News ChiefInternalUpdate Story-Updates story status to "published"

结论

在现代增强型 LLM 基础设施范式中,A2A 和 MCP 都扮演着重要角色。A2A 为复杂的多 agent 系统提供灵活性,但可能可移植性较低且运维复杂度更高。MCP 提供了标准化的工具集成方法,更易于实现和维护,但并非设计用于多 agent 协同。

选择并非二选一。如我们新闻室示例所示,最复杂且高效的 LLM 支持系统通常结合两种方法:agent 通过 A2A 协议进行协调和专业化,同时通过 MCP 服务器访问其工具和资源。这种混合架构在提供多 agent 系统组织效益的同时,也带来了 MCP 的标准化和生态优势。这表明,可能根本不需要选择:直接将两者作为标准方法即可。

作为开发者或架构师,你需要测试并确定两种解决方案的最佳组合,以针对你的具体用例产生最佳结果。理解每种方法的优势、局限性及适用场景,将帮助你构建更高效、可维护且可扩展的 AI 系统。

无论你是在构建数字新闻室、客户服务平台、研究助理还是其他 LLM 驱动的应用,仔细考虑你的协调需求(A2A)和工具访问需求(MCP)都将为成功奠定基础。

附加资源

原文:https://www.elastic.co/search-labs/blog/a2a-protocol-mcp-llm-agent-workflow-elasticsearch

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值