课程首页 › Module 6 · 协议与工程:MCP / Agent 协议 / 可信赖 / Context / Memory › L12

L12 Agent 协议三剑客:MCP / A2A / NLWeb

课程目标:理解 AI Agent 生态的三大开放协议——MCP(工具调用)、A2A(Agent 间协作)、NLWeb(自然语言 Web)——能向团队讲清楚它们各自的定位与协同方式。


一、Agent 生态的"巴别塔"问题#

L7 你已经学过 MCP,知道了"工具调用有标准"。

但你想过没有——只有工具标准够吗?

想象 2025 年的 Agent 世界:

这就是微软在 Agentic Protocols 里强调的:

AI Agent 生态需要三类协议——工具协议、Agent 协议、Web 协议。

这一课我们一次学会三种协议,看它们怎么拼成完整的"Agent 互联网"。


二、用一个比喻:三种协议 = 三种人类协作方式#

把 Agent 生态比作跨国公司的协作:

协议解决的问题比喻
MCPAgent 怎么用工具员工按手册操作公司内部软件(标准化的"工具调用"接口)
A2AAgent 怎么找别的 Agent 协作部门之间发"工作单"互相委托(标准化的"任务交接"协议)
NLWeb网站怎么让 Agent 读懂公司的官网提供对外的"问答窗口"(自然语言版的 API)

MCP 是手(操作工具),A2A 是嘴(沟通协作),NLWeb 是耳朵(理解外部世界)。

三者各司其职,缺一不可。


三、协议一:MCP(Model Context Protocol)#

L7 你已经学过了。简单回顾:

核心定位:把 Agent 调用外部工具这件事标准化——让工具提供方实现一次,所有 Agent 都能用。

三大原语:

架构:

┌──────────────┐    JSON-RPC 2.0    ┌──────────────┐
│  MCP Host    │ ◄────────────────► │  MCP Server  │
│ (Agent)      │   stdio/SSE/HTTP   │ (工具提供方)  │
└──────────────┘                    └──────────────┘

MCP 是 L7 的重点,这里不再展开。


四、协议二:A2A(Agent-to-Agent Protocol)#

4.1 为什么需要 A2A?#

MCP 解决了"Agent 怎么用工具",但没解决"Agent 怎么找别的 Agent"。

想象你是携程的差旅 Agent,用户让你订"上海到夏威夷的蜜月套餐"。你自己没法搞定——你得:

  1. 找国航 Agent问机票

  2. 找夏威夷酒店 Agent问住宿

  3. 找租车 Agent问接送

每个 Agent 都有自己的 LLM、自己的工具、自己的数据。它们不知道彼此的存在,也没法直接"通话"。

A2A 解决了这个问题——它是一套让不同 Agent 互相发现、调用、协作的协议。

4.2 A2A 的四大核心组件#

组件职责类比
Agent CardAgent 的"名片"——名字、技能、端点、能力餐厅的菜单 + 招牌菜
Agent Executor实际接收任务并执行的"代理"餐厅的服务员
Artifact任务完成后的"工作成果"餐厅上桌的菜
Event Queue异步消息队列,处理长任务餐厅的叫号系统

4.3 Agent Card 示例#

每个 A2A Agent 都有一张"电子名片":

{
  "name": "AirlineAgent",
  "description": "Book flights across 50+ airlines",
  "skills": [
    {"name": "search_flights", "description": "Search available flights"},
    {"name": "book_flight", "description": "Book a specific flight"}
  ],
  "endpoint": "https://airline-agent.example.com/a2a",
  "version": "1.0",
  "capabilities": ["streaming", "push_notifications"]
}

其他 Agent 通过这张卡片发现你能干什么、怎么联系你。

4.4 A2A 调用示例#

from a2a_sdk import A2AClient

# 你的差旅 Agent 想要找机票
client = A2AClient("https://airline-agent.example.com/a2a")

# 第一步:发现 Agent 能干啥
agent_info = await client.get_card()
# → 返回上面的 Agent Card

# 第三步:把任务委托给它
artifact = await client.invoke_skill(
    skill="search_flights",
    params={"from": "PVG", "to": "HNL", "passengers": 2}
)
# → 返回结构化的"工作成果"

4.5 A2A 的三大优势#

4.6 适用场景:A2A vs MCP#

场景用 A2A用 MCP
调对方暴露的工具函数✗✓
委托对方完成一个完整任务✓✗
对方有自己的 LLM/记忆/工具链✓✗
只是简单的"读文件"✗✓

A2A 是"对话式协作",MCP 是"工具式调用"。


五、协议三:NLWeb(Natural Language Web)#

5.1 为什么需要 NLWeb?#

前两个协议解决了 Agent 之间怎么沟通。但普通网站怎么办?

现实是:99% 的网站没有给 Agent 设计 API——它们只有给人看的网页。

NLWeb 的目标是:让任何网站都能用自然语言与 Agent 对话。

5.2 NLWeb 的核心思想#

每个 NLWeb 站点都同时提供:

  1. 自然语言问答接口——"找夏威夷的家庭友好酒店,要有泳池"

  2. 结构化数据响应——返回 Schema.org 格式的 JSON

  3. MCP Server 兼容——其他 Agent 可以通过 MCP 调用它的 ask 方法

5.3 NLWeb 架构#

┌─────────────────────────────────┐
│         NLWeb Site              │
│  ┌──────────┐    ┌──────────┐  │
│  │ 网页内容  │    │ Schema  │  │
│  │ (HTML)   │    │ .org    │  │
│  └────┬─────┘    └────┬─────┘  │
│       │ Embeddings    │        │
│       ▼               ▼        │
│  ┌─────────────────────────┐  │
│  │  向量数据库              │  │
│  │  (Qdrant/Snowflake/...) │  │
│  └─────────┬───────────────┘  │
│            │                  │
│       ┌────▼────┐             │
│       │ LLM 处理 │             │
│       └────┬────┘             │
│            │                  │
│  ┌─────────▼──────────────┐   │
│  │ NLWeb HTTP endpoint    │   │
│  │ + MCP Server (ask 方法)│     │
│  └────────────────────────┘   │
└─────────────────────────────────┘

5.4 NLWeb 调用示例#

from nlweb_sdk import NLWebClient

client = NLWebClient("https://honolulu-hotels.example.com")

# 自然语言查询
response = await client.ask(
    "Find me a family-friendly hotel with a pool for next week."
)
# → 返回结构化 JSON:
# {
#   "results": [
#     {"name": "Hilton Hawaiian Village", "price": 350, "pool": true, ...},
#     {"name": "Aulani Disney Resort", "price": 580, "pool": true, ...}
#   ]
# }

5.5 NLWeb 的革命性:每个网站都是 Agent 工具#

NLWeb 让每个网站都变成了一个 MCP Server——其他 Agent 可以直接把它当工具用:

from mcp import Client

# Agent 通过 MCP 调用任何 NLWeb 站点
async with Client("https://honolulu-hotels.example.com/mcp") as nlweb_mcp:
    result = await nlweb_mcp.call_tool(
        "ask",
        {"query": "Hotel near Waikiki with pool under $400/night"}
    )

这意味着 Agent 生态的工具池一夜之间从几百个变成了几亿个——每个网站都是潜在的工具。


六、三大协议的协同:完整的"Agent 互联网"#

6.1 一个真实的差旅场景#

用户对差旅 Agent 说:"帮我订下周去檀香山的蜜月套餐,含机票+酒店+租车。"

┌────────────────────────────────────────────────────────┐
│  用户的差旅 Agent                                    │
│                                                        │
│  1. 通过 MCP 调用:                                    │
│     ├─ 天气 MCP Server(查夏威夷天气)                 │
│     └─ 货币 MCP Server(汇率换算)                     │
│                                                        │
│  2. 通过 A2A 委托:                                    │
│     ├─ 国航 Agent(订机票)                            │
│     ├─ 携程 Agent(订酒店)                            │
│     └─ Hertz Agent(租车)                             │
│                                                        │
│  3. 通过 NLWeb 读取:                                  │
│     ├─ 檀香山旅游局 NLWeb(景点推荐)                  │
│     └─ 酒店官网 NLWeb(核实房型可用性)                │
│                                                        │
│  4. 综合所有结果,返回用户                              │
└────────────────────────────────────────────────────────┘

6.2 三大协议的角色分工#

协议角色谁实现调用方
MCP"手"工具提供方Agent
A2A"嘴"Agent 服务方Agent
NLWeb"耳朵"网站运营方Agent(通过 MCP)

A2A 让 Agent 之间能协作,MCP 让 Agent 能用工具,NLWeb 让网站都变成 MCP 工具。


七、动手:用 Python 模拟一个 A2A 调用#

虽然真实的 A2A 还在标准化中,但可以用简单的 HTTP + JSON 模拟:

import httpx
from pydantic import BaseModel

# 模拟一个 A2A Agent 的"名片"
class AgentCard(BaseModel):
    name: str
    description: str
    skills: list[dict]
    endpoint: str

# 模拟"差旅 Agent"调用"机票 Agent"
async def book_flight_via_a2a(origin: str, dest: str, date: str):
    # 第一步:发现 Agent(现实中是 GET /card)
    airline_card = AgentCard(
        name="AirlineAgent",
        description="Book flights",
        skills=[{"name": "search_flights"}],
        endpoint="https://airline-agent.example.com/a2a"
    )

    # 第二步:调用 skill(现实中是 POST /invoke)
    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"{airline_card.endpoint}/invoke",
            json={
                "skill": "search_flights",
                "params": {"origin": origin, "dest": dest, "date": date}
            }
        )
        # 返回"工作成果"(Artifact)
        return response.json()

# 使用
result = await book_flight_via_a2a("PVG", "HNL", "2026-10-15")
print(result)

八、关键要点回顾#

协议解决什么问题何时用
MCPAgent 怎么用工具调用对方暴露的工具函数
A2AAgent 怎么委托任务给其他 Agent让另一个 Agent 自主完成任务
NLWeb网站怎么被 Agent 读取让没有 API 的网站成为可查询的数据源

三者协同:MCP 是"手",A2A 是"嘴",NLWeb 是"耳朵"——合起来才是能独立 Agent。


九、参考资源#


十、下一课预告#

L8 你学的是 Context Engineering——Agent 的 context window 是有限的,怎么用工程手段管理"该给 LLM 看什么、不该给什么"。

为什么重要:真实场景 Agent 一跑就是几百轮对话,context 不管理就会爆炸;context 管理的好坏直接决定 Agent 的稳定性。

自测 · 检验是否真的掌握了

1. 你的差旅 Agent 需要委托另一个团队的 Agent 独立完成订票,对方有自己的大模型和内部工具。此时最该用哪个协议?

A2A 面向「委托对方 Agent 自主完成一个完整任务」,对方保留自己的 LLM、工具链和记忆,双方通过 Agent Card 发现彼此。调用对方暴露的工具函数属于 MCP 的范畴,而 NLWeb 解决的是让没有 API 的网站变成可查询数据源,定位完全不同。

2. NLWeb 协议最独特的价值在于什么?

现实中绝大多数网站只有给人看的网页,NLWeb 让每个站点同时提供自然语言问答接口、Schema.org 结构化数据,并兼容 MCP 的 ask 方法,于是每个网站都成了一个潜在工具。Agent 之间的协商与成果交换是 A2A 的职责,工具参数格式规范属于 MCP。

3. MCP、A2A、NLWeb 三大协议在真实差旅场景中的角色分工,下列对应正确的是?

课程用这套比喻区分三者职责:MCP 让 Agent 能用工具,是「手」;A2A 让 Agent 能委托和协作,是「嘴」;NLWeb 让 Agent 能理解外部网站,是「耳朵」。三者缺一不可,共同构成能独立干活的 Agent 生态。