A2A Protocol

Tutorial Completo do A2A JS SDK: Guia de Início Rápido

MILO
Share
Tutorial Completo do A2A JS SDK: Guia de Início Rápido

Índice

  1. O que é o A2A JS SDK?
  2. Instalação e Configuração do A2A JS
  3. Conceitos Básicos do A2A JS
  4. Criando Seu Primeiro Agente A2A JS
  5. Desenvolvimento do Servidor A2A JS
  6. Uso do Cliente A2A JS
  7. Recursos Avançados do A2A JS
  8. Melhores Práticas do A2A JS
  9. Solução de Problemas do A2A JS

O que é o A2A JS SDK?

A2A JS SDK é uma biblioteca poderosa projetada especificamente para desenvolvedores JavaScript/TypeScript construírem aplicações de agentes inteligentes que estejam em conformidade com o Protocolo Agent2Agent (A2A). Este framework A2A JS permite que os desenvolvedores criem facilmente sistemas de agentes inteligentes que podem se comunicar e colaborar entre si.

Vantagens Principais do A2A JS

  • 🚀 Fácil de Usar: A2A JS fornece APIs intuitivas que permitem que os desenvolvedores comecem rapidamente
  • 🔄 Comunicação em Tempo Real: Suporta processamento de streaming e Server-Sent Events (SSE)
  • 🛡️ Segurança de Tipos: Construído em TypeScript, fornecendo suporte completo a tipos
  • 🌐 Multiplataforma: A2A JS pode ser executado tanto em ambientes Node.js quanto em navegadores
  • 📡 Protocolo Padrão: Implementa completamente as especificações do protocolo A2A

Instalação e Configuração do A2A JS

Instalando o A2A JS SDK

Instale o A2A JS SDK usando npm:

npm install @a2a-js/sdk

Ou usando yarn:

yarn add @a2a-js/sdk

Verificando a Instalação do A2A JS

Crie um arquivo de teste simples para verificar se o A2A JS está instalado corretamente:

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

console.log("A2A JS SDK instalado com sucesso!");

Conceitos Básicos do A2A JS

Antes de começar a usar o A2A JS, é importante entender os seguintes conceitos básicos:

1. Cartão do Agente

Cada agente no A2A JS requer um Cartão do Agente que descreve as capacidades e interfaces do agente:

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

const agentCard: AgentCard = {
  name: 'Meu Agente A2A JS',
  description: 'Agente inteligente construído com A2A JS SDK',
  url: 'http://localhost:3000/',
  provider: {
    organization: 'Desenvolvedores A2A JS',
    url: 'https://example.com'
  },
  version: '1.0.0',
  capabilities: {
    streaming: true,
    pushNotifications: false,
    stateTransitionHistory: true,
  },
  skills: [{
    id: 'general_chat',
    name: 'Chat Geral',
    description: 'Conversa geral usando A2A JS',
    tags: ['chat', 'a2a-js'],
    examples: ['Olá', 'Me ajude a responder perguntas']
  }]
};

2. Executor do Agente

A lógica principal de execução do A2A JS é implementada através do AgentExecutor:

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

class MyA2AJSExecutor implements AgentExecutor {
  async execute(
    requestContext: RequestContext,
    eventBus: IExecutionEventBus
  ): Promise<void> {
    // Sua lógica do agente A2A JS
    console.log("Agente A2A JS está processando a requisição...");
  }

  async cancelTask(taskId: string, eventBus: IExecutionEventBus): Promise<void> {
    console.log(`A2A JS cancelando tarefa: ${taskId}`);
  }
}

Criando Seu Primeiro Agente A2A JS

Vamos criar um exemplo completo de agente usando o A2A JS SDK:

Passo 1: Definindo o Cartão do Agente A2A JS

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

const myAgentCard: AgentCard = {
  name: 'Agente Hello World A2A JS',
  description: 'Meu primeiro agente A2A JS para aprender o A2A JS SDK',
  url: 'http://localhost:3000/',
  provider: {
    organization: 'Tutorial 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: 'Exemplo de habilidade A2A JS: responder a saudações',
    tags: ['hello', 'greeting', 'a2a-js'],
    examples: [
      'Olá',
      'Oi',
      'Me fale sobre A2A JS'
    ],
    inputModes: ['text/plain'],
    outputModes: ['text/plain']
  }],
  supportsAuthenticatedExtendedCard: false,
};

Passo 2: Implementando o Executor 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(`Executor A2A JS cancelando tarefa: ${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(`Agente A2A JS processando mensagem: ${userMessage.parts[0]?.text}`);

    // Criando nova tarefa
    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);
    }

    // Publicando status de trabalho
    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: 'Agente A2A JS está pensando...' }],
          taskId: taskId,
          contextId: contextId,
        },
        timestamp: new Date().toISOString(),
      },
      final: false,
    };
    eventBus.publish(workingUpdate);

    // Simulando tempo de processamento
    await new Promise(resolve => setTimeout(resolve, 1000));

    // Verificando status de cancelamento
    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;
    }

    // Gerando resposta
    const userText = userMessage.parts[0]?.text || '';
    let responseText = '';
    
    if (userText.toLowerCase().includes('hello') || userText.toLowerCase().includes('hi')) {
      responseText = `Olá! Bem-vindo ao A2A JS SDK! Sou um agente inteligente construído com A2A JS.`;
    } else if (userText.toLowerCase().includes('a2a js')) {
      responseText = `A2A JS SDK é uma poderosa biblioteca JavaScript para construir aplicações de agentes inteligentes!`;
    } else {
      responseText = `Sou um agente A2A JS e recebi sua mensagem: "${userText}". Obrigado por usar o A2A JS SDK!`;
    }

    // Publicando resultado 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);
  }
}

Passo 3: Iniciando o Servidor 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(`Servidor do agente A2A JS iniciado em http://localhost:${PORT}`);
  console.log(`Cartão do agente A2A JS: http://localhost:${PORT}/.well-known/agent.json`);
  console.log('Pressione Ctrl+C para parar o servidor A2A JS');
});

Desenvolvimento do Servidor A2A JS

Armazenamento de Tarefas

A2A JS fornece armazenamento de tarefas em memória, e você também pode implementar armazenamento personalizado:

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 obtendo tarefa: ${taskId}`);
    return this.tasks.get(taskId);
  }

  async setTask(task: Task): Promise<void> {
    console.log(`A2A JS salvando tarefa: ${task.id}`);
    this.tasks.set(task.id, task);
  }

  async deleteTask(taskId: string): Promise<void> {
    console.log(`A2A JS deletando tarefa: ${taskId}`);
    this.tasks.delete(taskId);
  }
}

Suporte a Middleware

A2A JS é baseado em Express.js e suporta todos os middlewares padrão:

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

const app = express();

// Configuração de middleware do servidor A2A JS
app.use(cors());
app.use(express.json());

// Middleware de logging personalizado A2A JS
app.use((req, res, next) => {
  console.log(`Requisição A2A JS: ${req.method} ${req.path}`);
  next();
});

Uso do Cliente A2A JS

Operações Básicas do Cliente

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

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

    console.log("Resposta A2A JS:", response.result);
  } catch (error) {
    console.error("Erro de comunicação A2A JS:", error);
  }
}

testA2AJSClient();

Streaming A2A JS

A2A JS suporta comunicação em tempo real via streaming:

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

async function streamA2AJSResponse() {
  const client = new A2AClient("http://localhost:3000");
  
  console.log("Iniciando streaming A2A JS...");
  
  const streamParams = {
    message: {
      messageId: uuidv4(),
      role: "user",
      parts: [{ kind: "text", text: "Conversa em streaming usando A2A JS" }],
      kind: "message"
    }
  };

  try {
    const stream = client.sendMessageStream(streamParams);
    
    for await (const event of stream) {
      if (event.kind === 'task') {
        console.log(`Tarefa A2A JS criada: ${event.id}`);
      } else if (event.kind === 'status-update') {
        const statusEvent = event as TaskStatusUpdateEvent;
        console.log(`Atualização de status A2A JS: ${statusEvent.status.state}`);
        
        if (statusEvent.status.message?.parts[0]?.text) {
          console.log(`Mensagem A2A JS: ${statusEvent.status.message.parts[0].text}`);
        }
        
        if (statusEvent.final) {
          console.log("Streaming A2A JS concluído");
          break;
        }
      }
    }
  } catch (error) {
    console.error("Erro de streaming A2A JS:", error);
  }
}

Recursos Avançados do A2A JS

Manipulação de Artefatos

A2A JS suporta criação e gerenciamento de artefatos:

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

// Publicando artefatos no AgentExecutor
const artifactUpdate: TaskArtifactUpdateEvent = {
  kind: 'artifact-update',
  taskId: taskId,
  contextId: contextId,
  artifact: {
    artifactId: "a2a-js-example",
    name: "Arquivo de Exemplo A2A JS",
    parts: [{ 
      text: `# Conteúdo Gerado pelo A2A JS\n\nEste é um arquivo de exemplo gerado usando A2A JS SDK.`
    }],
  },
  append: false,
  lastChunk: true,
};
eventBus.publish(artifactUpdate);

Configuração de Segurança

Configure opções de segurança para agentes A2A JS:

const secureAgentCard: AgentCard = {
  name: 'Agente Seguro A2A JS',
  description: 'Agente seguro A2A JS',
  // ... outras configurações
  securitySchemes: {
    apiKey: {
      type: 'apiKey',
      name: 'X-API-Key',
      in: 'header'
    }
  },
  security: [{
    apiKey: []
  }]
};

Melhores Práticas do A2A JS

1. Tratamento de Erros

Implemente tratamento de erros abrangente em aplicações A2A JS:

class RobustA2AJSExecutor implements AgentExecutor {
  async execute(requestContext: RequestContext, eventBus: IExecutionEventBus) {
    try {
      // Lógica de execução A2A JS
      await this.processRequest(requestContext, eventBus);
    } catch (error) {
      console.error("Erro de execução A2A JS:", error);
      
      // Publicando status de erro
      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: 'Ocorreu um erro durante o processamento A2A JS, por favor tente novamente mais tarde.' }],
          },
          timestamp: new Date().toISOString(),
        },
        final: true,
      };
      eventBus.publish(errorUpdate);
    }
  }
}

2. Otimização de Performance

Otimize a performance da sua aplicação A2A JS:

// Otimizando cliente A2A JS com pool de conexões
const client = new A2AClient("http://localhost:3000", {
  keepAlive: true,
  timeout: 30000
});

// Cache de respostas do agente 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}`;
    
    // Verificando cache A2A JS
    if (this.cache.has(cacheKey)) {
      console.log("A2A JS usando resposta em cache");
      // Retornando resposta em cache
    }
    
    // Processando nova requisição e cacheando resultado
  }
}

3. Logging

Adicione logging detalhado às aplicações 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' })
  ]
});

// Usando no código A2A JS
a2aJSLogger.info('Agente A2A JS iniciado com sucesso');
a2aJSLogger.error('Erro de processamento A2A JS', { error: errorDetails });

Solução de Problemas do A2A JS

Resolução de Problemas Comuns

1. Problemas de Conexão A2A JS

// Verificando conexão com servidor 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("Conexão com servidor A2A JS normal");
    } else {
      console.error("Resposta anormal do servidor A2A JS:", response.status);
    }
  } catch (error) {
    console.error("Falha na conexão A2A JS:", error);
  }
}

Você também pode tentar os seguintes métodos:

2. Erros de Tipo A2A JS

Certifique-se de importar corretamente os tipos A2A JS:

// Importações corretas de tipos A2A JS
import {
  AgentCard,
  AgentExecutor,
  A2AClient,
  Task,
  TaskState,
  Message,
  MessageSendParams
} from "@a2a-js/sdk";

3. Depuração de Performance A2A JS

// Monitoramento de performance A2A JS
class PerformanceA2AJSExecutor implements AgentExecutor {
  async execute(requestContext: RequestContext, eventBus: IExecutionEventBus) {
    const startTime = Date.now();
    console.log(`A2A JS iniciando processamento: ${startTime}`);
    
    try {
      // Sua lógica A2A JS
      await this.processRequest(requestContext, eventBus);
    } finally {
      const endTime = Date.now();
      console.log(`Processamento A2A JS concluído, duração: ${endTime - startTime}ms`);
    }
  }
}

Resumo

A2A JS SDK é uma ferramenta poderosa para construir aplicações de agentes inteligentes. Através deste tutorial, você aprendeu:

  • Conceitos básicos e arquitetura do A2A JS
  • Como criar e configurar agentes A2A JS
  • Desenvolvimento de servidor e cliente A2A JS
  • Recursos avançados e melhores práticas do A2A JS
  • Métodos de solução de problemas para aplicações A2A JS

Agora você pode começar a construir suas próprias aplicações A2A JS! Lembre-se, o A2A JS SDK fornece funcionalidades ricas para ajudar você a criar sistemas de agentes inteligentes poderosos e escaláveis.

Para mais recursos e exemplos do A2A JS, visite:

Comece sua jornada de desenvolvimento com A2A JS! 🚀