A2A Protocol

A2A JS SDK完全ガイド:クイックスタートガイド

MILO
Share
A2A JS SDK完全ガイド:クイックスタートガイド

目次

  1. A2A JS SDKとは?
  2. A2A JSのインストールと設定
  3. A2A JSの基本概念
  4. 最初のA2A JSエージェントを作成する
  5. A2A JSサーバー開発
  6. A2A JSクライアントの使用
  7. A2A JSの高度な機能
  8. A2A JSのベストプラクティス
  9. A2A JSのトラブルシューティング

A2A JS SDKとは?

A2A JS SDKは、Agent2Agent (A2A) プロトコルに準拠したインテリジェントエージェントアプリケーションを構築するために、JavaScript/TypeScript開発者向けに特別に設計された強力なライブラリです。このA2A JSフレームワークにより、開発者は相互に通信し協調できるインテリジェントエージェントシステムを簡単に作成できます。

A2A JSの主な利点

  • 🚀 使いやすさ: A2A JSは開発者が素早く始められる直感的なAPIを提供します
  • 🔄 リアルタイム通信: ストリーミング処理とServer-Sent Events (SSE)をサポート
  • 🛡️ 型安全性: TypeScriptベースで構築され、完全な型サポートを提供
  • 🌐 クロスプラットフォーム: A2A JSはNode.jsとブラウザ環境の両方で動作可能
  • 📡 標準プロトコル: A2Aプロトコル仕様を完全に実装

A2A JSのインストールと設定

A2A JS SDKのインストール

npmを使用してA2A JS SDKをインストールします:

npm install @a2a-js/sdk

またはyarnを使用します:

yarn add @a2a-js/sdk

A2A JSのインストール確認

A2A JSが正しくインストールされたことを確認するための簡単なテストファイルを作成します:

import { A2AClient, AgentCard } from "@a2a-js/sdk";

console.log("A2A JS SDKが正常にインストールされました!");

A2A JSの基本概念

A2A JSを使用する前に、以下の基本概念を理解することが重要です:

1. エージェントカード

A2A JSの各エージェントは、エージェントの機能とインターフェースを説明するエージェントカードが必要です:

import { AgentCard } from "@a2a-js/sdk";

const agentCard: AgentCard = {
  name: '私のA2A JSエージェント',
  description: 'A2A JS SDKで構築されたインテリジェントエージェント',
  url: 'http://localhost:3000/',
  provider: {
    organization: 'A2A JS開発者',
    url: 'https://example.com'
  },
  version: '1.0.0',
  capabilities: {
    streaming: true,
    pushNotifications: false,
    stateTransitionHistory: true,
  },
  skills: [{
    id: 'general_chat',
    name: '一般チャット',
    description: 'A2A JSを使用した一般的な会話',
    tags: ['chat', 'a2a-js'],
    examples: ['こんにちは', '質問に答えるお手伝いをします']
  }]
};

2. エージェントエグゼキューター

A2A JSのコア実行ロジックはAgentExecutorを通じて実装されます:

import { AgentExecutor, RequestContext, IExecutionEventBus } from "@a2a-js/sdk";

class MyA2AJSExecutor implements AgentExecutor {
  async execute(
    requestContext: RequestContext,
    eventBus: IExecutionEventBus
  ): Promise<void> {
    // A2A JSエージェントロジック
    console.log("A2A JSエージェントがリクエストを処理中...");
  }

  async cancelTask(taskId: string, eventBus: IExecutionEventBus): Promise<void> {
    console.log(`A2A JSタスクをキャンセル中: ${taskId}`);
  }
}

最初のA2A JSエージェントを作成する

A2A JS SDKを使用して完全なエージェントの例を作成してみましょう:

ステップ1: A2A JSエージェントカードの定義

import { AgentCard } from "@a2a-js/sdk";

const myAgentCard: AgentCard = {
  name: 'Hello World A2A JSエージェント',
  description: 'A2A JS SDKを学ぶための最初のA2A JSエージェント',
  url: 'http://localhost:3000/',
  provider: {
    organization: 'A2A JSチュートリアル',
    url: 'https://example.com'
  },
  version: '1.0.0',
  capabilities: {
    streaming: true,
    pushNotifications: false,
    stateTransitionHistory: true,
  },
  defaultInputModes: ['text/plain'],
  defaultOutputModes: ['text/plain'],
  skills: [{
    id: 'hello_world',
    name: 'Hello World',
    description: 'A2A JSサンプルスキル:挨拶への応答',
    tags: ['hello', 'greeting', 'a2a-js'],
    examples: [
      'こんにちは',
      'はじめまして',
      'A2A JSについて教えてください'
    ],
    inputModes: ['text/plain'],
    outputModes: ['text/plain']
  }],
  supportsAuthenticatedExtendedCard: false,
};

ステップ2: A2A JSエグゼキューターの実装

import {
  AgentExecutor,
  RequestContext,
  IExecutionEventBus,
  Task,
  TaskState,
  TaskStatusUpdateEvent
} from "@a2a-js/sdk";
import { v4 as uuidv4 } from "uuid";

class HelloWorldA2AJSExecutor implements AgentExecutor {
  private cancelledTasks = new Set<string>();

  async cancelTask(taskId: string, eventBus: IExecutionEventBus): Promise<void> {
    this.cancelledTasks.add(taskId);
    console.log(`A2A JSエグゼキューターがタスクをキャンセル中: ${taskId}`);
  }

  async execute(
    requestContext: RequestContext,
    eventBus: IExecutionEventBus
  ): Promise<void> {
    const userMessage = requestContext.userMessage;
    const existingTask = requestContext.task;
    
    const taskId = existingTask?.id || uuidv4();
    const contextId = userMessage.contextId || existingTask?.contextId || uuidv4();

    console.log(`A2A JSエージェントがメッセージを処理中: ${userMessage.parts[0]?.text}`);

    // 新しいタスクの作成
    if (!existingTask) {
      const initialTask: Task = {
        kind: 'task',
        id: taskId,
        contextId: contextId,
        status: {
          state: TaskState.Submitted,
          timestamp: new Date().toISOString(),
        },
        history: [userMessage],
        metadata: userMessage.metadata,
        artifacts: [],
      };
      eventBus.publish(initialTask);
    }

    // タスクステータスの発行
    const workingUpdate: TaskStatusUpdateEvent = {
      kind: 'status-update',
      taskId: taskId,
      contextId: contextId,
      status: {
        state: TaskState.Working,
        message: {
          kind: 'message',
          role: 'agent',
          messageId: uuidv4(),
          parts: [{ kind: 'text', text: 'A2A JSエージェントが考え中...' }],
          taskId: taskId,
          contextId: contextId,
        },
        timestamp: new Date().toISOString(),
      },
      final: false,
    };
    eventBus.publish(workingUpdate);

    // 処理時間のシミュレーション
    await new Promise(resolve => setTimeout(resolve, 1000));

    // キャンセル状態の確認
    if (this.cancelledTasks.has(taskId)) {
      const cancelledUpdate: TaskStatusUpdateEvent = {
        kind: 'status-update',
        taskId: taskId,
        contextId: contextId,
        status: {
          state: TaskState.Canceled,
          timestamp: new Date().toISOString(),
        },
        final: true,
      };
      eventBus.publish(cancelledUpdate);
      return;
    }

    // レスポンスの生成
    const userText = userMessage.parts[0]?.text || '';
    let responseText = '';
    
    if (userText.toLowerCase().includes('hello') || userText.toLowerCase().includes('hi')) {
      responseText = `こんにちは!A2A JS SDKへようこそ!私はA2A JSで構築されたインテリジェントエージェントです。`;
    } else if (userText.toLowerCase().includes('a2a js')) {
      responseText = `A2A JS SDKはインテリジェントエージェントアプリケーションを構築するための強力なJavaScriptライブラリです!`;
    } else {
      responseText = `私はA2A JSエージェントで、あなたのメッセージを受け取りました:「${userText}」。A2A JS SDKをご利用いただきありがとうございます!`;
    }

    // 最終結果の発行
    const finalUpdate: TaskStatusUpdateEvent = {
      kind: 'status-update',
      taskId: taskId,
      contextId: contextId,
      status: {
        state: TaskState.Completed,
        message: {
          kind: 'message',
          role: 'agent',
          messageId: uuidv4(),
          parts: [{ kind: 'text', text: responseText }],
          taskId: taskId,
          contextId: contextId,
        },
        timestamp: new Date().toISOString(),
      },
      final: true,
    };
    eventBus.publish(finalUpdate);
  }
}

ステップ3: A2A JSサーバーの起動

import express from 'express';
import {
  A2AExpressApp,
  DefaultRequestHandler,
  InMemoryTaskStore
} from "@a2a-js/sdk";

const taskStore = new InMemoryTaskStore();
const agentExecutor = new HelloWorldA2AJSExecutor();

const requestHandler = new DefaultRequestHandler(
  myAgentCard,
  taskStore,
  agentExecutor
);

const appBuilder = new A2AExpressApp(requestHandler);
const expressApp = appBuilder.setupRoutes(express(), '');

const PORT = process.env.PORT || 3000;
expressApp.listen(PORT, () => {
  console.log(`A2A JSエージェントサーバーが http://localhost:${PORT} で起動しました`);
  console.log(`A2A JSエージェントカード: http://localhost:${PORT}/.well-known/agent.json`);
  console.log('A2A JSサーバーを停止するにはCtrl+Cを押してください');
});

A2A JSサーバー開発

タスクストア

A2A JSはメモリ内タスクストアを提供し、カスタムストアも実装できます:

import { TaskStore, Task } from "@a2a-js/sdk";

class CustomA2AJSTaskStore implements TaskStore {
  private tasks = new Map<string, Task>();

  async getTask(taskId: string): Promise<Task | undefined> {
    console.log(`A2A JSタスクを取得中: ${taskId}`);
    return this.tasks.get(taskId);
  }

  async setTask(task: Task): Promise<void> {
    console.log(`A2A JSタスクを保存中: ${task.id}`);
    this.tasks.set(task.id, task);
  }

  async deleteTask(taskId: string): Promise<void> {
    console.log(`A2A JSタスクを削除中: ${taskId}`);
    this.tasks.delete(taskId);
  }
}

ミドルウェアサポート

A2A JSはExpress.jsベースで、すべての標準ミドルウェアをサポートします:

import cors from 'cors';
import express from 'express';

const app = express();

// A2A JSサーバーミドルウェアの設定
app.use(cors());
app.use(express.json());

// カスタムA2A JSロギングミドルウェア
app.use((req, res, next) => {
  console.log(`A2A JSリクエスト: ${req.method} ${req.path}`);
  next();
});

A2A JSクライアントの使用

基本的なクライアント操作

import { A2AClient, MessageSendParams } from "@a2a-js/sdk";
import { v4 as uuidv4 } from "uuid";

const client = new A2AClient("http://localhost:3000");

async function testA2AJSClient() {
  console.log("A2A JSクライアントをテスト中...");
  
  const messageParams: MessageSendParams = {
    message: {
      messageId: uuidv4(),
      role: "user",
      parts: [{ kind: "text", text: "こんにちは、A2A JS!" }],
      kind: "message"
    },
    configuration: {
      blocking: true,
      acceptedOutputModes: ['text/plain']
    }
  };

  try {
    const response = await client.sendMessage(messageParams);
    
    if (response.error) {
      console.error("A2A JSクライアントエラー:", response.error);
      return;
    }

    console.log("A2A JSレスポンス:", response.result);
  } catch (error) {
    console.error("A2A JS通信エラー:", error);
  }
}

testA2AJSClient();

A2A JSストリーミング

A2A JSはリアルタイムストリーミング通信をサポートします:

import { A2AClient, TaskStatusUpdateEvent } from "@a2a-js/sdk";

async function streamA2AJSResponse() {
  const client = new A2AClient("http://localhost:3000");
  
  console.log("A2A JSストリーミングを開始...");
  
  const streamParams = {
    message: {
      messageId: uuidv4(),
      role: "user",
      parts: [{ kind: "text", text: "A2A JSを使用したストリーミング会話" }],
      kind: "message"
    }
  };

  try {
    const stream = client.sendMessageStream(streamParams);
    
    for await (const event of stream) {
      if (event.kind === 'task') {
        console.log(`A2A JSタスクが作成されました: ${event.id}`);
      } else if (event.kind === 'status-update') {
        const statusEvent = event as TaskStatusUpdateEvent;
        console.log(`A2A JSステータス更新: ${statusEvent.status.state}`);
        
        if (statusEvent.status.message?.parts[0]?.text) {
          console.log(`A2A JSメッセージ: ${statusEvent.status.message.parts[0].text}`);
        }
        
        if (statusEvent.final) {
          console.log("A2A JSストリーミングが完了しました");
          break;
        }
      }
    }
  } catch (error) {
    console.error("A2A JSストリーミングエラー:", error);
  }
}

A2A JSの高度な機能

アーティファクト処理

A2A JSはアーティファクトの生成と管理をサポートします:

import { TaskArtifactUpdateEvent } from "@a2a-js/sdk";

// AgentExecutorからアーティファクトを発行
const artifactUpdate: TaskArtifactUpdateEvent = {
  kind: 'artifact-update',
  taskId: taskId,
  contextId: contextId,
  artifact: {
    artifactId: "a2a-js-example",
    name: "A2A JSサンプルファイル",
    parts: [{ 
      text: `# A2A JSで生成されたコンテンツ\n\nこれはA2A JS SDKを使用して生成されたサンプルファイルです。`
    }],
  },
  append: false,
  lastChunk: true,
};
eventBus.publish(artifactUpdate);

セキュリティ設定

A2A JSエージェントのセキュリティオプションを設定:

const secureAgentCard: AgentCard = {
  name: 'セキュアA2A JSエージェント',
  description: 'セキュアA2A JSエージェント',
  // ... その他の設定
  securitySchemes: {
    apiKey: {
      type: 'apiKey',
      name: 'X-API-Key',
      in: 'header'
    }
  },
  security: [{
    apiKey: []
  }]
};

A2A JSのベストプラクティス

1. エラー処理

A2A JSアプリケーションで包括的なエラー処理を実装:

class RobustA2AJSExecutor implements AgentExecutor {
  async execute(requestContext: RequestContext, eventBus: IExecutionEventBus) {
    try {
      // A2A JS実行ロジック
      await this.processRequest(requestContext, eventBus);
    } catch (error) {
      console.error("A2A JS実行エラー:", error);
      
      // エラー状態の発行
      const errorUpdate: TaskStatusUpdateEvent = {
        kind: 'status-update',
        taskId: requestContext.task?.id || uuidv4(),
        contextId: requestContext.userMessage.contextId || uuidv4(),
        status: {
          state: TaskState.Failed,
          message: {
            kind: 'message',
            role: 'agent',
            messageId: uuidv4(),
            parts: [{ kind: 'text', text: 'A2A JS処理中にエラーが発生しました。後でもう一度お試しください。' }],
          },
          timestamp: new Date().toISOString(),
        },
        final: true,
      };
      eventBus.publish(errorUpdate);
    }
  }
}

2. パフォーマンス最適化

A2A JSアプリケーションのパフォーマンスを最適化:

// コネクションプーリングでA2A JSクライアントを最適化
const client = new A2AClient("http://localhost:3000", {
  keepAlive: true,
  timeout: 30000
});

// A2A JSエージェントレスポンスのキャッシュ
class CachedA2AJSExecutor implements AgentExecutor {
  private cache = new Map<string, string>();
  
  async execute(requestContext: RequestContext, eventBus: IExecutionEventBus) {
    const userText = requestContext.userMessage.parts[0]?.text || '';
    const cacheKey = `a2a-js-${userText}`;
    
    // A2A JSキャッシュの確認
    if (this.cache.has(cacheKey)) {
      console.log("A2A JSキャッシュされたレスポンスを使用中");
      // キャッシュされたレスポンスを返す
    }
    
    // 新しいリクエストの処理と結果のキャッシュ
  }
}

3. ロギング

A2A JSアプリケーションに詳細なロギングを追加:

import { createLogger, format, transports } from 'winston';

const a2aJSLogger = createLogger({
  level: 'info',
  format: format.combine(
    format.timestamp(),
    format.printf(({ timestamp, level, message }) => {
      return `[A2A JS] ${timestamp} ${level}: ${message}`;
    })
  ),
  transports: [
    new transports.Console(),
    new transports.File({ filename: 'a2a-js.log' })
  ]
});

// A2A JSコードで使用
a2aJSLogger.info('A2A JSエージェントが正常に起動しました');
a2aJSLogger.error('A2A JS処理エラー', { error: errorDetails });

A2A JSのトラブルシューティング

一般的な問題の解決

1. A2A JS接続の問題

// A2A JSサーバー接続の確認
async function checkA2AJSConnection() {
  try {
    const client = new A2AClient("http://localhost:3000");
    const response = await fetch("http://localhost:3000/.well-known/agent.json");
    
    if (response.ok) {
      console.log("A2A JSサーバー接続正常");
    } else {
      console.error("A2A JSサーバーレスポンス異常:", response.status);
    }
  } catch (error) {
    console.error("A2A JS接続失敗:", error);
  }
}

以下の方法も試してみてください:

2. A2A JS型エラー

A2A JSの型を正しくインポートしているか確認:

// 正しいA2A JS型のインポート
import {
  AgentCard,
  AgentExecutor,
  A2AClient,
  Task,
  TaskState,
  Message,
  MessageSendParams
} from "@a2a-js/sdk";

3. A2A JSパフォーマンスのデバッグ

// A2A JSパフォーマンスのモニタリング
class PerformanceA2AJSExecutor implements AgentExecutor {
  async execute(requestContext: RequestContext, eventBus: IExecutionEventBus) {
    const startTime = Date.now();
    console.log(`A2A JS処理開始: ${startTime}`);
    
    try {
      // A2A JSロジック
      await this.processRequest(requestContext, eventBus);
    } finally {
      const endTime = Date.now();
      console.log(`A2A JS処理完了、所要時間: ${endTime - startTime}ms`);
    }
  }
}

まとめ

A2A JS SDKはインテリジェントエージェントアプリケーションを構築するための強力なツールです。このチュートリアルを通じて以下のことを学びました:

  • A2A JSの基本概念とアーキテクチャ
  • A2A JSエージェントの作成と設定方法
  • A2A JSサーバーとクライアントの開発
  • A2A JSの高度な機能とベストプラクティス
  • A2A JSアプリケーションのトラブルシューティング方法

これで独自のA2A JSアプリケーションを構築できます!A2A JS SDKは、強力で拡張可能なインテリジェントエージェントシステムを構築するのに役立つ豊富な機能を提供します。

より多くのA2A JSリソースとサンプルは以下をご覧ください:

A2A JS開発の旅を始めましょう!🚀