A2A Protocol

Guide Complet du SDK A2A JS : Guide de Démarrage Rapide

MILO
Share
Guide Complet du SDK A2A JS : Guide de Démarrage Rapide

Table des Matières

  1. Qu'est-ce que le SDK A2A JS ?
  2. Installation et Configuration d'A2A JS
  3. Concepts Fondamentaux d'A2A JS
  4. Création de Votre Premier Agent A2A JS
  5. Développement Serveur A2A JS
  6. Utilisation du Client A2A JS
  7. Fonctionnalités Avancées d'A2A JS
  8. Meilleures Pratiques A2A JS
  9. Dépannage A2A JS

Qu'est-ce que le SDK A2A JS ?

Le SDK A2A JS est une bibliothèque puissante conçue spécifiquement pour les développeurs JavaScript/TypeScript qui souhaitent créer des applications d'agents intelligents conformes au Protocole Agent2Agent (A2A). Grâce à ce framework A2A JS, les développeurs peuvent facilement créer des systèmes d'agents intelligents capables de communiquer et de collaborer entre eux.

Avantages Clés d'A2A JS

  • 🚀 Facilité d'utilisation : A2A JS fournit une API intuitive pour un démarrage rapide
  • 🔄 Communication en Temps Réel : Support du traitement en streaming et des Server-Sent Events (SSE)
  • 🛡️ Sécurité des Types : Basé sur TypeScript, offre un support complet des types
  • 🌐 Multiplateforme : A2A JS peut fonctionner dans les environnements Node.js et navigateur
  • 📡 Protocole Standard : Implémentation complète de la spécification du Protocole A2A

Installation et Configuration d'A2A JS

Installation du SDK A2A JS

Installez le SDK A2A JS en utilisant npm :

npm install @a2a-js/sdk

Ou utilisez yarn :

yarn add @a2a-js/sdk

Vérification de l'Installation d'A2A JS

Créez un fichier de test simple pour vérifier l'installation correcte d'A2A JS :

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

console.log("SDK A2A JS installé avec succès !");

Concepts Fondamentaux d'A2A JS

Avant de commencer à utiliser A2A JS, il est important de comprendre les concepts fondamentaux suivants :

1. Carte d'Agent

Chaque agent A2A JS nécessite une carte d'agent qui décrit ses capacités et son interface :

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

const agentCard: AgentCard = {
  name: 'Mon Agent A2A JS',
  description: 'Agent intelligent construit avec le SDK A2A JS',
  url: 'http://localhost:3000/',
  provider: {
    organization: 'Développeur A2A JS',
    url: 'https://example.com'
  },
  version: '1.0.0',
  capabilities: {
    streaming: true,
    pushNotifications: false,
    stateTransitionHistory: true,
  },
  skills: [{
    id: 'general_chat',
    name: 'Chat Général',
    description: 'Conversation générale utilisant A2A JS',
    tags: ['chat', 'a2a-js'],
    examples: ['Bonjour', 'Aide à répondre aux questions']
  }]
};

2. Exécuteur d'Agent

La logique d'exécution principale d'A2A JS est implémentée via l'AgentExecutor :

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

class MyA2AJSExecutor implements AgentExecutor {
  async execute(
    requestContext: RequestContext,
    eventBus: IExecutionEventBus
  ): Promise<void> {
    // Logique de l'agent A2A JS
    console.log("Traitement de la requête de l'agent A2A JS...");
  }

  async cancelTask(taskId: string, eventBus: IExecutionEventBus): Promise<void> {
    console.log(`Annulation de la tâche A2A JS : ${taskId}`);
  }
}

Création de Votre Premier Agent A2A JS

Créons un exemple complet d'agent utilisant le SDK A2A JS :

Étape 1 : Définir la Carte d'Agent A2A JS

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

const myAgentCard: AgentCard = {
  name: 'Agent Hello World A2A JS',
  description: 'Mon premier agent A2A JS pour apprendre le SDK',
  url: 'http://localhost:3000/',
  provider: {
    organization: 'Tutoriel 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: 'Compétence exemple A2A JS : répondre aux salutations',
    tags: ['hello', 'greeting', 'a2a-js'],
    examples: [
      'Bonjour',
      'Bienvenue',
      'Parle-moi d\'A2A JS'
    ],
    inputModes: ['text/plain'],
    outputModes: ['text/plain']
  }],
  supportsAuthenticatedExtendedCard: false,
};

Étape 2 : Implémentation de l'Exécuteur 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(`Annulation de la tâche par l'exécuteur 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(`Traitement du message par l'agent A2A JS : ${userMessage.parts[0]?.text}`);

    // Créer une nouvelle tâche
    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);
    }

    // Publier la mise à jour du statut
    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: 'L\'agent A2A JS réfléchit...' }],
          taskId: taskId,
          contextId: contextId,
        },
        timestamp: new Date().toISOString(),
      },
      final: false,
    };
    eventBus.publish(workingUpdate);

    // Simuler le temps de traitement
    await new Promise(resolve => setTimeout(resolve, 1000));

    // Vérifier l'état d'annulation
    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;
    }

    // Générer la réponse
    const userText = userMessage.parts[0]?.text || '';
    let responseText = '';
    
    if (userText.toLowerCase().includes('hello') || userText.toLowerCase().includes('hi')) {
      responseText = `Bonjour ! Bienvenue dans le SDK A2A JS ! Je suis un agent intelligent construit avec A2A JS.`;
    } else if (userText.toLowerCase().includes('a2a js')) {
      responseText = `Le SDK A2A JS est une puissante bibliothèque JavaScript pour créer des applications d'agents intelligents !`;
    } else {
      responseText = `Je suis un agent A2A JS et j'ai reçu votre message : "${userText}". Merci d'utiliser le SDK A2A JS !`;
    }

    // Publier le résultat final
    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);
  }
}

Étape 3 : Démarrer le Serveur 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(`Serveur agent A2A JS démarré sur http://localhost:${PORT}`);
  console.log(`Carte d'agent A2A JS : http://localhost:${PORT}/.well-known/agent.json`);
  console.log('Appuyez sur Ctrl+C pour arrêter le serveur A2A JS');
});

Développement Serveur A2A JS

Stockage des Tâches

A2A JS fournit un stockage de tâches en mémoire et permet également l'implémentation de stockages personnalisés :

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(`Récupération de la tâche A2A JS : ${taskId}`);
    return this.tasks.get(taskId);
  }

  async setTask(task: Task): Promise<void> {
    console.log(`Sauvegarde de la tâche A2A JS : ${task.id}`);
    this.tasks.set(task.id, task);
  }

  async deleteTask(taskId: string): Promise<void> {
    console.log(`Suppression de la tâche A2A JS : ${taskId}`);
    this.tasks.delete(taskId);
  }
}

Support des Middlewares

A2A JS est basé sur Express.js et prend en charge tous les middlewares standard :

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

const app = express();

// Configuration des middlewares du serveur A2A JS
app.use(cors());
app.use(express.json());

// Middleware de journalisation personnalisé A2A JS
app.use((req, res, next) => {
  console.log(`Requête A2A JS : ${req.method} ${req.path}`);
  next();
});

Utilisation du Client A2A JS

Opérations Client de Base

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("Test du client A2A JS...");
  
  const messageParams: MessageSendParams = {
    message: {
      messageId: uuidv4(),
      role: "user",
      parts: [{ kind: "text", text: "Bonjour, A2A JS !" }],
      kind: "message"
    },
    configuration: {
      blocking: true,
      acceptedOutputModes: ['text/plain']
    }
  };

  try {
    const response = await client.sendMessage(messageParams);
    
    if (response.error) {
      console.error("Erreur du client A2A JS :", response.error);
      return;
    }

    console.log("Réponse A2A JS :", response.result);
  } catch (error) {
    console.error("Erreur de communication A2A JS :", error);
  }
}

testA2AJSClient();

Streaming A2A JS

A2A JS prend en charge la communication en streaming en temps réel :

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

async function streamA2AJSResponse() {
  const client = new A2AClient("http://localhost:3000");
  
  console.log("Démarrage du streaming A2A JS...");
  
  const streamParams = {
    message: {
      messageId: uuidv4(),
      role: "user",
      parts: [{ kind: "text", text: "Conversation en streaming avec A2A JS" }],
      kind: "message"
    }
  };

  try {
    const stream = client.sendMessageStream(streamParams);
    
    for await (const event of stream) {
      if (event.kind === 'task') {
        console.log(`Tâche A2A JS créée : ${event.id}`);
      } else if (event.kind === 'status-update') {
        const statusEvent = event as TaskStatusUpdateEvent;
        console.log(`Mise à jour du statut A2A JS : ${statusEvent.status.state}`);
        
        if (statusEvent.status.message?.parts[0]?.text) {
          console.log(`Message A2A JS : ${statusEvent.status.message.parts[0].text}`);
        }
        
        if (statusEvent.final) {
          console.log("Streaming A2A JS terminé");
          break;
        }
      }
    }
  } catch (error) {
    console.error("Erreur de streaming A2A JS :", error);
  }
}

Fonctionnalités Avancées d'A2A JS

Traitement des Artéfacts

A2A JS prend en charge la génération et la gestion des artéfacts :

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

// Publier un artéfact depuis l'AgentExecutor
const artifactUpdate: TaskArtifactUpdateEvent = {
  kind: 'artifact-update',
  taskId: taskId,
  contextId: contextId,
  artifact: {
    artifactId: "a2a-js-example",
    name: "Fichier exemple A2A JS",
    parts: [{ 
      text: `# Contenu généré par A2A JS\n\nCeci est un fichier exemple généré en utilisant le SDK A2A JS.`
    }],
  },
  append: false,
  lastChunk: true,
};
eventBus.publish(artifactUpdate);

Configuration de la Sécurité

Configuration des options de sécurité pour l'agent A2A JS :

const secureAgentCard: AgentCard = {
  name: 'Agent A2A JS Sécurisé',
  description: 'Agent A2A JS avec sécurité',
  // ... autres configurations
  securitySchemes: {
    apiKey: {
      type: 'apiKey',
      name: 'X-API-Key',
      in: 'header'
    }
  },
  security: [{
    apiKey: []
  }]
};

Meilleures Pratiques A2A JS

1. Gestion des Erreurs

Implémentation d'une gestion complète des erreurs dans les applications A2A JS :

class RobustA2AJSExecutor implements AgentExecutor {
  async execute(requestContext: RequestContext, eventBus: IExecutionEventBus) {
    try {
      // Logique d'exécution A2A JS
      await this.processRequest(requestContext, eventBus);
    } catch (error) {
      console.error("Erreur d'exécution A2A JS :", error);
      
      // Publier l'état d'erreur
      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: 'Une erreur s\'est produite lors du traitement A2A JS. Veuillez réessayer plus tard.' }],
          },
          timestamp: new Date().toISOString(),
        },
        final: true,
      };
      eventBus.publish(errorUpdate);
    }
  }
}

2. Optimisation des Performances

Optimisation des performances des applications A2A JS :

// Optimisation du client A2A JS avec mise en pool des connexions
const client = new A2AClient("http://localhost:3000", {
  keepAlive: true,
  timeout: 30000
});

// Mise en cache des réponses de l'agent 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}`;
    
    // Vérifier le cache A2A JS
    if (this.cache.has(cacheKey)) {
      console.log("Utilisation de la réponse mise en cache A2A JS");
      // Retourner la réponse mise en cache
    }
    
    // Traiter la nouvelle requête et mettre en cache le résultat
  }
}

3. Journalisation

Ajout d'une journalisation détaillée dans les applications 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' })
  ]
});

// Utilisation dans le code A2A JS
a2aJSLogger.info('Agent A2A JS démarré avec succès');
a2aJSLogger.error('Erreur de traitement A2A JS', { error: errorDetails });

Dépannage A2A JS

Résolution des Problèmes Courants

1. Problèmes de Connexion A2A JS

// Vérifier la connexion au serveur 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("Connexion au serveur A2A JS normale");
    } else {
      console.error("Réponse anormale du serveur A2A JS :", response.status);
    }
  } catch (error) {
    console.error("Échec de la connexion A2A JS :", error);
  }
}

Essayez également ces méthodes :

2. Erreurs de Type A2A JS

Assurez-vous d'importer correctement les types A2A JS :

// Importer correctement les types A2A JS
import {
  AgentCard,
  AgentExecutor,
  A2AClient,
  Task,
  TaskState,
  Message,
  MessageSendParams
} from "@a2a-js/sdk";

3. Débogage des Performances A2A JS

// Surveillance des performances A2A JS
class PerformanceA2AJSExecutor implements AgentExecutor {
  async execute(requestContext: RequestContext, eventBus: IExecutionEventBus) {
    const startTime = Date.now();
    console.log(`Début du traitement A2A JS : ${startTime}`);
    
    try {
      // Logique A2A JS
      await this.processRequest(requestContext, eventBus);
    } finally {
      const endTime = Date.now();
      console.log(`Traitement A2A JS terminé, temps écoulé : ${endTime - startTime}ms`);
    }
  }
}

Résumé

Le SDK A2A JS est un outil puissant pour créer des applications d'agents intelligents. À travers ce tutoriel, nous avons appris :

  • Les concepts fondamentaux et l'architecture d'A2A JS
  • Comment créer et configurer des agents A2A JS
  • Le développement serveur et client A2A JS
  • Les fonctionnalités avancées et les meilleures pratiques d'A2A JS
  • Comment résoudre les problèmes courants des applications A2A JS

Vous pouvez maintenant créer votre propre application A2A JS ! Le SDK A2A JS fournit des fonctionnalités riches pour vous aider à créer des systèmes d'agents intelligents puissants et extensibles.

Pour plus de ressources et d'exemples A2A JS, visitez :

Commencez votre voyage de développement A2A JS ! 🚀