A2A 又是啥?和 MCP 的關係?個人理解和定義梳理

繼 Anthropic 推出 MCP 之後,Google 終於下場了,推出了新的 AI 協議:A2A。

這東西到底是幹啥的?和 MCP 有啥區別?具體咋用?下面我們詳細道來。

A2A 能幹啥?

A2A,全程 agent2agent,顧名思義,就是 agent 和 agent 之間的交流溝通的範式,詳細地說它可以實現 agent 和 agent 之間溝通、協作、委派、信息同步的同能,並將這個工作作爲一個標準協議用於所有類型的 agent 之間。

和 MCP 有啥區別?

A2A 實際上是可以覆蓋 MCP 的功能的,他只是 MCP 概念的進一步封裝和抽象

MCP 的缺陷:

1、無安全隔離機制

2、無任何授權認證機制

A2A 協議的核心特性:

1、具備企業級的安全策略, 包含監控、追蹤、認證等等

2、具備異步的特性, 支持長時間的任務運行且允許隨時進行人工干預

3、支持多模態處理能力

4、多個代理無需共享狀態

A2A 定義了哪些規矩?

A2A 定義的核心規則,就這 agent 之間溝通的模板。

Task 任務

任務是一個對象實體,它用於 agent 和 agent 之間的任務委派,比如 A agent 需要向 B agent 發出一個請求,讓 B agent 幫它做一個任務,就用到了它,具體定義的對象內容如下

interface Task {
  id: string;         // 任務的唯一標識符
  sessionId: string;  // 客戶端生成的會話ID,用於持有該任務
  status: TaskStatus; // 任務的當前狀態
  history?: Message[]; // 消息歷史記錄
  artifacts?: Artifact[]; // 任務的最後結果,也成爲工件
  metadata?: Record<string, any>; // 擴展元數據
}
// 任務狀態及附帶消息
interface TaskStatus {
  state: TaskState;     // 任務狀態
  message?: Message;    // 給客戶端的額外狀態更新
  timestamp?: string;   // ISO 格式時間戳
}
// 服務器在 sendSubscribe 或 subscribe 請求期間發送
interface TaskStatusUpdateEvent {
  id: string;           // 任務ID
  status: TaskStatus;   // 任務狀態
  final: boolean;       // 表示事件流的結束
  metadata?: Record<string, any>; // 擴展元數據
}
// 服務器在 sendSubscribe 或 subscribe 請求期間發送
interface TaskArtifactUpdateEvent {
  id: string;           // 任務ID
  artifact: Artifact;   // 產物對象
  metadata?: Record<string, any>; // 擴展元數據
}
// 客戶端發送給代理以創建、繼續或重啓任務
interface TaskSendParams {
  id: string;
  sessionId?: string;   // 未設置時,服務器會爲新任務創建新的 sessionId
  message: Message;     // 消息內容
  historyLength?: number; // 要檢索的最近消息數量
  // 斷開連接時服務器應發送通知的目標配置
  pushNotification?: PushNotificationConfig;
  metadata?: Record<string, any>; // 擴展元數據
}
type TaskState =
  | "submitted"       // 已提交
  | "working"         // 處理中
  | "input-required"  // 需要輸入
  | "completed"       // 已完成
  | "canceled"        // 已取消
  | "failed"          // 已失敗
  | "unknown";        // 未知狀態

Message 消息

消息是 agent 之間溝通發送的對象,包括代理思維、用戶上下文、指令、錯誤、狀態或元數據

interface Message {
  role: "user" | "agent";
  parts: Part[];
  metadata?: Record<string, any>;
}

Artifact 工件

這是 agent 和 agent 之間委派任務後的最終結果,工件是不可變的,一個任務可以生成多個工件

interface Artifact {
  name?: string;  // 工件名稱
  description?: string;   // 工件描述
  parts: Part[];   // 工件組成部分
  metadata?: Record<string, any>;  // 元數據
  index: number;  // 索引
  append?: boolean;   
  lastChunk?: boolean;  
}

Part 工件塊

一個工件可以由多個塊組成(多模態,包含文字、圖片、視頻等等),是結果的部分呈現,包含文本塊、文件塊、數據塊

interface TextPart {
  type: "text";
  text: string;
}
interface FilePart {
  type: "file";
  file: {
    name?: string;
    mimeType?: string;
    // oneof {
    bytes?: string; //base64 encoded content
    uri?: string;
    //}
  };
}
interface DataPart {
  type: "data";
  data: Record<string, any>;
}
type Part = (TextPart | FilePart | DataPart) & {
  metadata: Record<string, any>;
};

除了上述的定義的對象,下面介紹具體如何使用上面定義的對象來構建 agent 之間溝通的方法

Agent Card  代理卡

每個 agent 都有一個代理卡,其中記錄着這個 agent 的基礎信息,類似於自己的名片,讓別人指導這個 agent 是幹嘛的,有哪些能力和使用規範

{
  "name""Google Maps Agent", // agent名稱
  "description""Plan routes, remember places, and generate directions", // agent描述
  "url""https://maps-agent.google.com", // agent 服務url 
  "provider"{   // 組織信息
    "organization""Google",
    "url""https://google.com"
  },
  "version""1.0.0",
  "authentication"{
    "schemes""OAuth2"
  },
  "defaultInputModes"["text/plain"],  // 默認輸入格式
  "defaultOutputModes"["text/plain""application/html"],  // 默認輸出格式
  "capabilities"{  // 能力,是否支持流式輸出或者通知能力
    "streaming": true,
    "pushNotifications"false
  },
  "skills"[  //agent的能力,可以有多個
    {
      "id""route-planner",
      "name""Route planning",
      "description""Helps plan routing between two locations",
      "tags"["maps""routing""navigation"],
      "examples"[
        "plan my route from Sunnyvale to Mountain View",
        "what's the commute time from Sunnyvale to San Francisco at 9AM",
        "create turn by turn directions from Sunnyvale to Mountain View"
      ],
      // can return a video of the route
      "outputModes"["application/html""video/mp4"]
    },
    {
      "id""custom-map",
      "name""My Map",
      "description""Manage a custom map with your own saved places",
      "tags"["custom-map""saved-places"],
      "examples"[
        "show me my favorite restaurants on the map",
        "create a visual of all places I've visited in the past year"
      ],
      "outputModes"["application/html"]
    }
  ]
}

Send a Task  發送任務

由一個 agent 發送消息到另一個 agent 的方法結構體,其中 params 就是上面的 TaskSendParams

//Request
{
  "jsonrpc""2.0",
  "id": 1,
  "method":"tasks/send",
  "params"{
    "id""de38c76d-d54c-436c-8b9f-4c2703648d64",
    "message"{
      "role":"user",
      "parts"[{
        "type":"text",
        "text""tell me a joke"
      }]
    },
    "metadata"{}
  }
}
//Response
{
  "jsonrpc""2.0",
  "id": 1,
  "result"{
    "id""de38c76d-d54c-436c-8b9f-4c2703648d64",
    "sessionId""c295ea44-7543-4f78-b524-7a38915ad6e4",
    "status"{
      "state""completed",
    },
    "artifacts"[{
      "name":"joke",
      "parts"[{
          "type":"text",
          "text":"Why did the chicken cross the road? To get to the other side!"
        }]
      }],
    "metadata"{}
  }
}

Get a Task  獲取任務

//Request
{
  "jsonrpc""2.0",
  "id": 1,
  "method":"tasks/get",
  "params"{
    "id""de38c76d-d54c-436c-8b9f-4c2703648d64",
    "historyLength": 10,
    "metadata"{}
  }
}
//Response
{
  "jsonrpc""2.0",
  "id": 1,
  "result"{
    "id""de38c76d-d54c-436c-8b9f-4c2703648d64",
    "sessionId""c295ea44-7543-4f78-b524-7a38915ad6e4",
    "status"{
      "state""completed"
    },
    "artifacts"[{
      "parts"[{
        "type":"text",
        "text":"Why did the chicken cross the road? To get to the other side!"
      }]
    }],
    "history":[
      {
        "role""user",
        "parts"[
          {
            "type""text",
            "text""tell me a joke"
          }
        ]
      }
    ],
    "metadata"{}
  }
}

Cancel a Task  取消任務

//Request
{
  "jsonrpc""2.0",
  "id": 1,
  "method":"tasks/cancel",
  "params"{
    "id""de38c76d-d54c-436c-8b9f-4c2703648d64",
    "metadata"{}
  }
}
//Response
{
  "jsonrpc""2.0",
  "id": 1,
  "result"{
    "id""de38c76d-d54c-436c-8b9f-4c2703648d64",
    "sessionId""c295ea44-7543-4f78-b524-7a38915ad6e4",
    "status"{
      "state""canceled"
    },
    "metadata"{}
  }
}

以上就是 A2A 定義的核心的內容,當然還有一些別的方法和對象的定義,這裏只列舉了最核心的,有助於對 A2A 的內容有一個全覽概況

google 代碼示例結構粗講

google 這次提供的示例代碼質量一般,相當的 "示例",整體代碼結構如下

demo 

是前端交互相關的代碼,它構建了一個聊天界面和 agent 配置相關交互和邏輯

sample:

1、有兩個庫,js 和 python,主要看 python,導入 python 就可以了。

2、common 是 A2A 的核心代碼,講述了 client 如何構建,server 如何構建,數據結構如何構建(type.py)。

3、最重要的 host,講了如何進行服務發現、服務註冊,由前端 UI 來進行調用。

4、agents 中講述 A2A 多 agent server 的搭建。

總結和個人理解

整體理解下來,A2A 的核心就是上面講到的 agent 和 agent 之間傳遞的對象結構和方法結構(這個是一定要遵守的),其他都是根據自己的應用自由開發。

主要流程:

發現:客戶端從 /.well-known/agent.json 獲取 Agent Card,瞭解智能體的能力。

啓動:客戶端發送

    使用 tasks/send 處理即時任務,返回最終 Task 對象。

    使用 tasks/sendSubscribe 處理長期任務,服務器通過 SSE 事件發送更新。

處理:服務器處理任務,可能涉及流式更新或直接返回結果。

交互(可選):若任務狀態爲 input-required,客戶端可發送更多消息,使用相同 Task ID 提供輸入。

完成:任務達到終端狀態(如 completed、failed 或 canceled)。

核心理解:

核心對象 / 方法 + web server + 服務發現 / 註冊。

如果要構建一個 A2A 框架:

step1:建立多個 agent,然後分別對每個 agent 封裝一套 web server,比如 fastapi,接下來,每個 agent 創建一個任務管理器,用於這個 agent 的啓動、取消、獲取

step2:構建一個服務註冊,可以通過前端或 cli 將 step1 創建的每個 agent 服務註冊到內存中

step3:構建一個服務發現邏輯,這裏需要創建一個父 LLM 或父 agent,通過 LLM 的能力判斷是否需要調用其他的 agent 完成任務

可能的 A2A 的架構設計:

第一種架構:

構建一個 agent(可以通過 Agent 框架實現,也可以通過 LLM 本身構建 prompt 實現),這個 agent 作爲父 agent,它裏面實現服務發現和服務註冊的邏輯,獲取子 agent 的 agent card 信息,然後拼接在自己的 agent 的 prompt 中,由父 agent 的 AI 自主的編排和任務規劃,1 對多結構,這個和 MCP 類似,可以覆蓋 MCP 的功能

第二種架構:

沒有父子 agent 的概念,每一個 agent 都有服務發現的功能,比如:一共 3 個 agent,三個 agent 可以通過協作完成一個目標任務,每一個 agent 都可以鏈式或委派方式調用別的 agent,最終有一個總體的狀態管理和消息彙總的 LLM(總管)

第三種架構:

父 agent 或 LLM,結合 MCP 中的(工具、prompt、資源等),再結合 A2A agent 實現一個通過自定義編程或 agent 框架,實現一個複雜的多 agent 應用

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Gu9NQZrSghbF95Prm93YUw