🏒

A2A 各コンポーネント探求

はじめに

昨日、A2Aの記事を投稿しました。
https://zenn.dev/acntechjp/articles/a9feca96759f7e
自分の学習のためも含めて、各コンポーネントについてさらに探求していきます。
参考にした資料は下記。
https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
https://github.com/google/A2A
https://google.github.io/A2A/#/documentation

Agent2Agentプロトコルとは

Agent2Agent(A2A)プロトコルは、異なるフレームワークやベンダーで構築されたAIエージェント間の相互運用性を実現するためのオープンプロトコルです。このプロトコルにより、エージェントはメモリ、思考プロセス、ツールを共有することなく、コンテキスト、ステータス、指示、データを交換できるようになります。

A2Aプロトコルは以下の5つの主要な設計原則に基づいています:

  1. エージェント機能の活用: エージェントが自然な非構造化モダリティで連携できるようにし、エージェントを単なる「ツール」に制限しません。
  2. 既存標準の活用: HTTP、SSE、JSON-RPCなどの既存の一般的な標準の上に構築されており、企業の既存ITスタックとの統合が容易です。
  3. セキュリティ優先: エンタープライズグレードの認証と認可をサポートするように設計されています。
  4. 長時間タスクのサポート: 短時間のタスクから数時間または数日かかる深い調査まで、さまざまなシナリオをサポートします。
  5. モダリティ非依存: テキストだけでなく、音声やビデオストリーミングなどさまざまなモダリティをサポートします。

A2Aプロトコルのアクター

A2Aプロトコルには3つの主要なアクターが存在します:

  1. ユーザー: エージェントシステムを使用してタスクを達成する最終ユーザー(人間またはサービス)。
  2. クライアント: ユーザーに代わってリモートエージェントにアクションを要求するエンティティ(サービス、エージェント、アプリケーション)。
  3. リモートエージェント(サーバー): A2Aサーバーとして機能する不透明な(「ブラックボックス」)エージェント。

これらのアクター間の通信は、クライアントとリモートエージェントがエンドユーザーのリクエストを協力して満たすタスク完了指向です。

A2Aプロトコルのコアコンポーネント

A2Aプロトコルは、以下の主要なコンポーネントで構成されています:

1. タスク(Task)

タスクは、クライアントとリモートエージェントが特定の成果を達成し、結果を生成するための状態を持つエンティティです。クライアントとリモートエージェントはタスク内でメッセージを交換し、リモートエージェントは結果をアーティファクトとして生成します。

タスクは常にクライアントによって作成され、ステータスは常にリモートエージェントによって決定されます。複数のタスクは、クライアントが必要とする場合、共通のセッション(オプションのsessionIdで示される)の一部となることがあります。

リモートエージェントは以下のようなアクションを取ることができます:

  • リクエストをすぐに実行する
  • 後で作業をスケジュールする
  • リクエストを拒否する
  • 異なるモダリティを交渉する
  • クライアントに追加情報を求める
  • 他のエージェントやシステムに委任する

タスクのインターフェース定義は以下の通りです:

interface Task {
  id: string; // unique identifier for the task
  sessionId: string; // client-generated id for the session holding the task.
  status: TaskStatus; // current status of the task
  history?: Message[];
  artifacts?: Artifact[]; // collection of artifacts created by the agent.
  metadata?: Record<string, any>; // extension metadata
}

タスクのステータスは以下の状態を持ちます:

type TaskState =
  | "submitted"
  | "working"
  | "input-required"
  | "completed"
  | "canceled"
  | "failed"
  | "unknown";

2. アーティファクト(Artifact)

エージェントはタスクの最終結果としてアーティファクトを生成します。アーティファクトは不変で、名前を付けることができ、複数のパートを持つことができます。ストリーミングレスポンスは既存のアーティファクトにパートを追加できます。

1つのタスクで多くのアーティファクトを生成できます。例えば、「ウェブページを作成する」というタスクでは、別々のHTMLと画像のアーティファクトを作成する可能性があります。

interface Artifact {
  name?: string;
  description?: string;
  parts: Part[];
  metadata?: Record<string, any>;
  index: number;
  append?: boolean;
  lastChunk?: boolean;
}

3. メッセージ(Message)

メッセージはアーティファクトではないすべてのコンテンツを含みます。これには、エージェントの思考、ユーザーコンテキスト、指示、エラー、ステータス、メタデータなどが含まれます。

クライアントからのすべてのコンテンツはメッセージの形式で来ます。エージェントはステータスを伝えたり指示を提供したりするためにメッセージを送信します(生成された結果はアーティファクトとして送信されます)。

メッセージは異なるコンテンツの部分を示すために複数のパートを持つことができます。例えば、ユーザーリクエストには、ユーザーからのテキスト記述と、クライアントからのコンテキストとして使用される複数のファイルが含まれる可能性があります。

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

4. パート(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>;
};

A2Aの通信フロー

A2Aプロトコルでは、クライアントエージェントとリモートエージェント間の通信がタスク完了に向けて行われます。この通信フローには以下の主要な機能が含まれます:

  1. 機能発見: エージェントはJSON形式の「エージェントカード」を使用して自身の機能を広告し、クライアントエージェントがタスクを実行できる最適なエージェントを特定し、A2Aを活用してリモートエージェントと通信できるようにします。

  2. タスク管理: クライアントとリモートエージェント間の通信はタスク完了に向けて行われ、エージェントはエンドユーザーのリクエストを満たすために協力します。このタスクオブジェクトはプロトコルによって定義され、ライフサイクルを持ちます。タスクはすぐに完了することも、長時間実行タスクの場合は各エージェントがタスク完了の最新ステータスを同期するために通信することもできます。タスクの出力は「アーティファクト」として知られています。

  3. コラボレーション: エージェントはコンテキスト、返信、アーティファクト、またはユーザー指示を伝えるためにメッセージを送り合うことができます。

  4. ユーザーエクスペリエンスの交渉: 各メッセージには「パート」が含まれ、これは生成された画像のような完全に形成されたコンテンツの一部です。各パートには指定されたコンテンツタイプがあり、クライアントとリモートエージェントが必要な正しいフォーマットを交渉し、ユーザーのUI機能(iframes、ビデオ、ウェブフォームなど)を明示的に交渉できるようにします。

エージェントカード(Agent Card)

A2Aをサポートするリモートエージェントは、エージェントの機能/スキルと認証メカニズムを説明するJSON形式のエージェントカードを公開する必要があります。クライアントはエージェントカード情報を使用して、タスクを実行できる最適なエージェントを特定し、A2Aを活用してそのリモートエージェントと通信します。

エージェントカードの推奨ホスティング場所は https://base url/.well-known/agent.json です。これはクライアントがDNSを介してサーバーIPを見つけ、HTTPリクエストを送信してエージェントカードを取得するDNSアプローチと互換性があります。また、システムがプライベートレジストリ(「エージェントカタログ」やプライベートマーケットプレイスなど)を維持することも予想されています。

エージェントカードのインターフェース定義は以下の通りです:

// An AgentCard conveys key information:
// - Overall details (version, name, description, uses)
// - Skills: A set of capabilities the agent can perform
// - Default modalities/content types supported by the agent.
// - Authentication requirements
interface AgentCard {
  // Human readable name of the agent.
  // (e.g. "Recipe Agent")
  name: string;
  // A human-readable description of the agent. Used to assist users and
  // other agents in understanding what the agent can do.
  // (e.g. "Agent that helps users with recipes and cooking.")
  description: string;
  // A URL to the address the agent is hosted at.
  url: string;
  // The service provider of the agent
  provider?: {
    organization: string;
    url: string;
  };
  // The version of the agent - format is up to the provider. (e.g. "1.0.0")
  version: string;
  // A URL to documentation for the agent.
  documentationUrl?: string;
  // Optional capabilities supported by the agent.
  capabilities: {
    streaming?: boolean; // true if the agent supports SSE
    pushNotifications?: boolean; // true if the agent can notify updates to client
    stateTransitionHistory?: boolean; //true if the agent exposes status change history for tasks
  };
  // Authentication requirements for the agent.
  // Intended to match OpenAPI authentication structure.
  authentication: {
    schemes: string[]; // e.g. Basic, Bearer
    credentials?: string; //credentials a client should use for private cards
  };
  // The set of interaction modes that the agent
  // supports across all skills. This can be overridden per-skill.
  defaultInputModes: string[]; // supported mime types for input
  defaultOutputModes: string[]; // supported mime types for output
  // Skills are a unit of capability that an agent can perform.
  skills: {
    id: string; // unique identifier for the agent's skill
    name: string; //human readable name of the skill
    // description of the skill - will be used by the client or a human
    // as a hint to understand what the skill does.
    description: string;
    // Set of tagwords describing classes of capabilities for this specific
    // skill (e.g. "cooking", "customer support", "billing")
    tags: string[];
    // The set of example scenarios that the skill can perform.
    // Will be used by the client as a hint to understand how the skill can be
    // used. (e.g. "I need a recipe for bread")
    examples?: string[]; // example prompts for tasks
    // The set of interaction modes that the skill supports
    // (if different than the default)
    inputModes?: string[]; // supported mime types for input
    outputModes?: string[]; // supported mime types for output
  }[];
}

エージェントカードの例:

{
  "name": "Google Maps Agent",
  "description": "Plan routes, remember places, and generate directions",
  "url": "https://maps-agent.google.com",
  "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": [
    {
      "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"]
    }
  ]
}

プッシュ通知(Push Notifications)

A2Aは、エージェントが接続されたセッション外でPushNotificationServiceを介してクライアントに更新を通知できる安全な通知メカニズムをサポートしています。企業内および企業間では、エージェントが通知サービスのIDを検証し、サービスで自身を認証し、通知を実行中のタスクに結びつける識別子を提示することが重要です。

PushNotificationServiceのターゲットサーバーは別のサービスと見なされるべきであり、クライアントに直接接続されることは保証(または期待)されていません。このPushNotificationServiceは、エージェントの認証と承認、および検証済み通知の適切なエンドポイント(パブ/サブキュー、電子メールインボックス、その他のサービスなど)へのプロキシを担当します。

interface PushNotificationConfig {
  url: string;
  token?: string; // token unique to this task/session
  authentication?: {
    schemes: string[];
    credentials?: string;
  };
}
interface TaskPushNotificationConfig {
  id: string; //task id
  pushNotificationConfig: PushNotificationConfig;
}
Accenture Japan (有志)

Discussion