A2A Protocol
Пример A2A Java

Клонирование кода

git clone https://github.com/google-a2a/a2a-samples
cd a2a-samples/samples/java

Этот проект представляет собой пример реализации протокола Agent-to-Agent (A2A) на Java, предоставляющий полные клиентские и серверные SDK, а также демонстрационное приложение сервиса перевода с использованием ИИ.

Архитектура проекта

Этот проект использует многомодульную архитектуру Maven, содержащую следующие три основных модуля:

samples/java/
├── model/          # Модели данных протокола A2A
├── server/         # A2A Server SDK и сервис перевода
├── client/         # A2A Client SDK и примеры кода
└── pom.xml         # Родительский файл конфигурации Maven

Детали модулей

🎯 Модуль Model (model/)

Основные модели данных для протокола A2A, предоставляющие полные структуры данных для JSON-RPC 2.0 и протокола A2A:

  • Модели сообщений: Message, Part, TextPart, Artifact
  • Модели задач: Task, TaskStatus, TaskState
  • Модели агентов: AgentCard, AgentCapabilities, AgentSkill
  • Модели JSON-RPC: JSONRPCRequest, JSONRPCResponse, JSONRPCError
  • Модели событий: TaskStatusUpdateEvent, TaskArtifactUpdateEvent

🚀 Модуль Server (server/)

A2A серверный SDK на основе Spring Boot, интегрированный с фреймворком Spring AI:

  • Основные компоненты:

    • A2AServer: Основной серверный класс, управляющий поведением агента
    • A2AController: REST-контроллер, реализующий конечные точки протокола A2A
    • TaskHandler: Интерфейс обработки задач
    • A2AServerConfiguration: Конфигурация AI-бота для перевода
  • Ключевые функции:

    • Полная поддержка JSON-RPC 2.0
    • Публикация карточки агента (/.well-known/agent-card)
    • Управление задачами (отправка, запрос, отмена)
    • Поддержка потоковых ответов (Server-Sent Events)
    • Интеграция Spring AI с поддержкой OpenAI и других моделей

📱 Модуль Client (client/)

Чистый Java A2A клиентский SDK с примерами клиента перевода:

  • Основные компоненты:

    • A2AClient: Основной клиентский класс, обрабатывающий все операции A2A
    • StreamingEventListener: Интерфейс слушателя потоковых событий
    • A2AClientException: Обработка исключений, специфичных для A2A
    • A2AClientExample: Полный пример клиента перевода
  • Ключевые функции:

    • Реализация клиента JSON-RPC 2.0
    • Обнаружение агентов и запрос возможностей
    • Синхронные/асинхронные операции с задачами
    • Обработка потоковых ответов
    • Пулинг соединений и восстановление после ошибок

Реализация основной функциональности

🤖 Сервис AI-перевода

Проект реализует интеллектуального агента перевода, поддерживающего многоязычный перевод:

Логика перевода:

  • Китайский → Английский
  • Английский → Китайский
  • Другие языки → Английский

Технические особенности:

  • Основан на Spring AI ChatClient
  • Поддерживает OpenAI, Azure OpenAI и другие модели
  • Контекстно-зависимый перевод естественного языка
  • Потоковые ответы в реальном времени

🔄 Реализация протокола A2A

Полная реализация спецификаций протокола A2A:

Основные операции:

  • tasks/send: Отправка сообщений задач
  • tasks/get: Запрос статуса задачи
  • tasks/cancel: Отмена выполнения задачи

Функции протокола:

  • Коммуникация JSON-RPC 2.0
  • Обнаружение возможностей агента
  • Отслеживание статуса задач
  • Потоковая отправка событий
  • Стандартизированные коды ошибок

📡 Механизмы коммуникации

Синхронная коммуникация:

  • HTTP POST /a2a - Стандартные JSON-RPC запросы
  • HTTP GET /.well-known/agent-card - Получение информации об агенте

Потоковая коммуникация:

  • HTTP POST /a2a/stream - Server-Sent Events
  • Обновления статуса задач в реальном времени
  • Автоматическое переподключение и восстановление после ошибок

Как запустить

Требования

  • Java: 17 или выше

Шаг 1: Компиляция проекта

Выполните компиляцию в корневой директории проекта:

cd samples/java
./mvnw clean install -DskipTests

Шаг 2: Настройка переменных окружения

Установите переменные окружения, связанные с AI-моделью (необходимо для функциональности перевода):

# Конфигурация OpenAI
export OPENAI_API_KEY="your-openai-api-key"
export OPENAI_BASE_URL="https://api.openai.com"
export OPENAI_CHAT_MODEL="gpt-4o"

# Или конфигурация GCP OpenAI
export OPENAI_API_KEY="your-gcp-api-key"
export OPENAI_BASE_URL="https://{location}-aiplatform.googleapis.com/v1/projects/{project_id}/locations/{location}/endpoints/openapi"
export OPENAI_CHAT_MODEL="gemini-2.5-pro-preview-05-06"

Конфигурация OpenRouter

export OPENAI_API_KEY="sk-or-v1-"
export OPENAI_BASE_URL="https://openrouter.ai/api"
export OPENAI_CHAT_MODEL="openai/gpt-4o-2024-11-20"

Обратите внимание на OPENAI_BASE_URL, в URL нет /v1.

Шаг 3: Запуск сервера перевода

Запустите A2A сервер перевода:

cd server
../mvnw spring-boot:run

Сервер запустится на http://localhost:8080, предоставляя следующие конечные точки:

  • http://localhost:8080/.well-known/agent-card - Информация об агенте
  • http://localhost:8080/a2a - Конечная точка протокола A2A
  • http://localhost:8080/a2a/stream - Потоковая конечная точка

Валидация карточки агента:

Шаг 4: Запуск клиента перевода

В новом окне терминала запустите пример клиента:

cd client
../mvnw exec:java -Dexec.mainClass="com.google.a2a.client.A2AClientExample"

Диаграмма последовательности

Следующая диаграмма последовательности иллюстрирует полный поток взаимодействия примера приложения A2A Java, основанного на A2AClientExample.java:

sequenceDiagram
    participant Example as A2AClientExample
    participant Client as A2AClient
    participant Server as A2A Server<br/>(localhost:8080)
    
    Note over Example,Server: Диаграмма последовательности примера A2A Java
    
    %% 1. Initialize Client
    Example->>Client: new A2AClient("http://localhost:8080")
    activate Client
    
    %% 2. Get Agent Card
    Example->>Client: getAgentCard()
    Client->>Server: GET /.well-known/agent-card
    Server-->>Client: AgentCard (name, description, version, skills)
    Client-->>Example: AgentCard
    Note over Example: Вывод информации об агенте
    
    %% 3. French to Chinese Translation
    Example->>Client: sendTask(frenchToChineseParams)
    Note right of Example: TextPart: "Bonjour le monde!<br/>Comment allez-vous?"
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/send
    Server-->>Client: Task (id, status, history)
    Client-->>Example: JSONRPCResponse<Task>
    Note over Example: Вывод результата перевода
    
    %% 4. Chinese to English Translation
    Example->>Client: sendTask(chineseParams)
    Note right of Example: TextPart: "你好,世界!<br/>欢迎使用AI翻译机器人。"
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/send
    Server-->>Client: Task (id, status, history)
    Client-->>Example: JSONRPCResponse<Task>
    Note over Example: Вывод результата перевода
    
    %% 5. Streaming Translation
    Example->>Client: sendTaskStreaming(frenchParams, StreamingEventListener)
    Note right of Example: TextPart: "Bonjour le monde!<br/>Comment allez-vous?"
    Client->>Server: POST /a2a/stream<br/>Server-Sent Events
    activate Server
    
    loop Streaming Response
        Server-->>Client: SSE Event (прогресс перевода)
        Client-->>Example: onEvent(event)
        Note over Example: Вывод событий перевода в реальном времени
    end
    
    Server-->>Client: SSE Complete
    deactivate Server
    Client-->>Example: onComplete()
    Note over Example: Потоковый перевод завершен
    
    %% 6. Query Task Status
    Example->>Client: getTask(queryParams)
    Note right of Example: Запрос статуса задачи французского перевода
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/get
    Server-->>Client: Task (обновленный статус)
    Client-->>Example: JSONRPCResponse<Task>
    Note over Example: Вывод статуса задачи
    
    %% 7. Send Task to be Canceled
    Example->>Client: sendTask(cancelParams)
    Note right of Example: TextPart: "Diese Übersetzung<br/>wird abgebrochen." (немецкий)
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/send
    Server-->>Client: Task (id, status)
    Client-->>Example: JSONRPCResponse<Task>
    
    %% 8. Cancel Task
    Example->>Client: cancelTask(cancelTaskParams)
    Client->>Server: POST /a2a<br/>JSON-RPC: tasks/cancel
    Server-->>Client: Task (статус отменен)
    Client-->>Example: JSONRPCResponse<Task>
    Note over Example: Вывод результата отмены
    
    deactivate Client
    Note over Example,Server: Выполнение примера программы завершено

Ключевые паттерны взаимодействия

Диаграмма последовательности демонстрирует следующие основные паттерны взаимодействия:

  1. Инициализация клиента: Создание экземпляра A2AClient, подключенного к локальному серверу
  2. Обнаружение агента: Получение информации об агенте через конечную точку /.well-known/agent-card
  3. Примеры многоязычного перевода:
    • Французский → Китайский перевод
    • Китайский → Английский перевод
    • Немецкий → Английский потоковый перевод
  4. Управление задачами:
    • Запрос статуса задачи
    • Отмена выполнения задачи

Механизмы коммуникации

  • Синхронный перевод: Использование конечной точки POST /a2a с JSON-RPC запросами
  • Потоковый перевод: Использование конечной точки POST /a2a/stream с Server-Sent Events (SSE)
  • Запросы статуса: Использование метода tasks/get для проверки статуса выполнения задачи
  • Отмена задач: Использование метода tasks/cancel для отмены выполняющихся задач

Примеры использования API

Получение информации об агенте

curl -X GET http://localhost:8080/.well-known/agent-card \
  -H "Accept: application/json"

Отправка задачи перевода

curl -X POST http://localhost:8080/a2a \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "request-1",
    "method": "tasks/send",
    "params": {
      "id": "translation-task-1",
      "message": {
        "messageId": "msg-1",
        "kind": "message",
        "role": "user",
        "parts": [
          {
            "kind": "text",
            "text": "Hello, world!"
          }
        ]
      }
    }
  }'

Потоковый перевод

curl -X POST http://localhost:8080/a2a/stream \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": "stream-request-1",
    "method": "tasks/send",
    "params": {
      "id": "streaming-translation-task",
      "message": {
        "messageId": "stream-msg-1",
        "kind": "message",
        "role": "user",
        "parts": [
          {
            "kind": "text",
            "text": "Hello world!"
          }
        ]
      }
    }
  }'