Реализовать протокол A2A с discovery и capability negotiation
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Реализовать протокол A2A с discovery и capability negotiation
1. Цель задачи
Разработать и реализовать протокол взаимодействия между автономными AI-агентами (Agent-to-Agent, A2A), включающий механизмы обнаружения (discovery) и согласования возможностей (capability negotiation). В результате агенты должны уметь находить друг друга по описанию своих способностей и устанавливать канал для дальнейшего обмена сообщениями или выполнения кооперативных задач.
Ключевой результат Демонстрация, в которой два (или более) агента динамически находят друг друга в сети на основе заявленных capabilities и успешно завершают handshake с передачей согласованных параметров взаимодействия.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Описание протокола A2A (черновик) | Разработать самостоятельно в рамках задачи |
| Среда выполнения агентов | Docker / локальная сеть / minikube |
| Язык программирования для агентов | Python 3.10+ |
| Библиотека для асинхронного HTTP | aiohttp или FastAPI |
| Реестр агентов (registry) | Реализовать как микросервис на FastAPI |
| Инструмент тестирования | curl, httpx, pytest-asyncio |
Если нет реального инструмента — симулируем:
- Если нет реального реестра, создаём простой HTTP-сервер на FastAPI, который хранит список агентов с их capabilities.
- Вместо mDNS используем HTTP-запросы к реестру (централизованная модель discovery).
- Если не хватает агентов, пишем два демо-агента с разными capabilities (например:
translate,summarize,code_review).
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Реестр агентов (Registry) | FastAPI / Python + SQLite / Redis | Хранит зарегистрированные агенты и их capabilities |
| Агент A | Python, aiohttp, asyncio | Реализует протокол A2A, регистрируется в реестре |
| Агент B | Python, aiohttp, asyncio | Второй агент с отличающимися capabilities |
| Протокол A2A | JSON over HTTP (RESTful) | Определяет эндпоинты: POST /register, GET /discover, POST /negotiate |
| Сериализация | Pydantic v2 | Валидация схем messages и capabilities |
| Логирование | structlog / logging | Трассировка всех взаимодействий |
| Контейнеризация | Docker + docker-compose | Оркестрация нескольких агентов и реестра |
4. Этапы выполнения
Этап 1: Проектирование протокола A2A (1 час)
Действия
-
Определить структуру сообщений на основе JSON Schema.
- AgentManifest – описание агента:
agent_id,name, endpoint, capabilities (список строк или мапа строк). - DiscoveryRequest –
{ "required_capabilities": [...] }. - DiscoveryResponse – список подходящих агентов.
- NegotiationRequest – { "session_id": "...", "capabilities": [...], "parameters": {...} }.
- NegotiationResponse – { "session_id": "...", "accepted": true/false, "parameters": {...} }.
- AgentManifest – описание агента:
-
Спроектировать эндпоинты для протокола A2A
POST /register– регистрация агента в реестре (передаётся AgentManifest).- GET /discover?capabilities=translate,summarize – поиск агентов по списку требуемых capabilities.
POST /negotiate– начало переговоров между агентами (вызывается от agentA к agentB или через реестр).
-
Зафиксировать схему в формате OpenAPI (опционально) или Pydantic models.
Ожидаемый результат этапа Документ с описанием протокола (в README или Markdown) и файл schemas.py с Pydantic моделями.
Этап 2: Реализация реестра агентов (1.5 часа)
Действия
-
Создать FastAPI-приложение с эндпоинтами
POST /register– принимает AgentManifest, сохраняет в in-memory dict (или SQLite).GET /discover– принимает query-параметр capabilities (через запятую), фильтрует зарегистрированных агентов и возвращает тех, чьи capabilities содержат все запрошенные.DELETE /agents/{agent_id}– для отмены регистрации.GET /agents– список всех агентов (для отладки).
-
Реализовать проверку уникальности agent_id
-
Добавить время жизни (TTL) для записей агентов – использовать фоновую задачу для удаления устаревших записей (например, каждые 30 секунд).
-
Добавить базовое логирование всех запросов
# Пример модели
from pydantic import BaseModel, Field
from typing import List, Dict, Optional
class AgentManifest(BaseModel):
agent_id: str
name: str
endpoint: str # URL для прямого вызова агента
capabilities: List[str]
class DiscoveryResponse(BaseModel):
agents: List[AgentManifest]
Ожидаемый результат этапа Работающий микросервис реестра с тестовыми запросами через curl / httpx.
Этап 3: Реализация базового агента с A2A-клиентом (2 часа)
Действия
-
Разработать класс Agent с основными методами:
register(registry_url)– регистрация в реестре.discover(registry_url, required_capabilities)– поиск других агентов.- negotiate(target_agent_url, capabilities, parameters) – отправка negotiation-запроса.
handle_negotiation(request)– обработка входящего negotiation-запроса.
-
Реализовать два экземпляра агента с разными capabilities:
- Агент А – capabilities:
["translate", "summarize"]. - Агент Б – capabilities:
["translate", "code_review"]. - Оба запускаются в отдельных процессах/контейнерах с разными портами.
- Агент А – capabilities:
async def negotiate(self, target_url: str, desired_capabilities: List[str]) -> Optional[dict]:
payload = NegotiationRequest(
agent_id=self.manifest.agent_id,
session_id=str(uuid4()),
capabilities=desired_capabilities,
parameters={"language": "ru"}
)
async with aiohttp.ClientSession() as session:
async with session.post(f"{target_url}/negotiate", json=payload.dict()) as response:
if response.status == 200:
return await response.json()
return None
Ожидаемый результат этапа Два работающих агента, которые могут зарегистрироваться в реестре и обмениваться HTTP-запросами.
Этап 4: Интеграция discovery и negotiation (1.5 часа)
Действия
-
Написать скрипт, который симулирует use-case:
- Запустить реестр.
- Зарегистрировать агента А и агента Б.
- Агент А хочет найти агента с capability
code_review. - Агент А запрашивает реестр, получает информацию об агенте Б.
- Агент А отправляет negotiation-запрос агенту Б.
- Агент Б обрабатывает запрос, проверяет свои capabilities, соглашается.
- Вывести логи handshake.
-
Добавить обработку ошибок
- Если реестр недоступен – повтор с exponential backoff.
- Если агент не ответил на negotiation (timeout) – переключиться на другого кандидата.
- Если capabilities не совпадают – возвращать отказ.
-
Записать tracelog всех сообщений (пример ниже).
[REGISTRY] 10:00:00.123 Register agent_A ['translate', 'summarize'] -> OK
[AGENT_A] 10:00:01.456 Discover for ['code_review'] -> found agent_B (http://agent_B:8001)
[AGENT_A] 10:00:02.789 Sent negotiation to agent_B (session_id: abc-123)
[AGENT_B] 10:00:02.790 Received negotiation, checking capabilities: code_review -> accepted
[AGENT_B] 10:00:02.891 Sent negotiation response: accepted
[AGENT_A] 10:00:02.894 Handshake completed with agent_B
Ожидаемый результат этапа Полный цикл discovery + negotiation, зафиксированный в логах.
Этап 5: Покрытие тестами и контейнеризация (1.5 часа)
Действия
-
Написать юнит-тесты для Pydantic моделей и валидации (pytest).
-
Написать интеграционные тесты
- Тест: регистрация, поиск по существующей capability, поиск по отсутствующей.
- Тест: negotiation success и failure.
- Тест: TTL агентов (дождаться удаления и проверить, что discovery возвращает пустой список).
-
Создать
docker-compose.ymlregistry(образ FastAPI, порт 8000).agent_a(тот же образ с агентами или отдельный скрипт, порт 8001).agent_b(порт 8002).- Использовать зависимости (depends_on) для порядка запуска.
-
Добавить README с инструкцией запуска
Ожидаемый результат этапа Все тесты проходят, docker-compose up запускает систему из 3 контейнеров.
5. Критерии приемки (Definition of Done)
- Опубликовано описание протокола A2A в формате Markdown (эндпоинты, схемы данных).
- Реестр агентов реализован как отдельный микросервис, принимает регистрацию и возвращает список по capabilities.
- Агент A может зарегистрироваться в реестре.
- Агент B может зарегистрироваться в реестре с другим набором capabilities.
- Агент A успешно находит агента B через discovery-запрос с фильтром
['code_review']. - Negotation (handshake) между A и B завершается успешно с возвратом согласованных параметров.
- Тайм-ауты и отказ capabilities обрабатываются корректно (лог errors без падений).
- Написаны минимум 3 интеграционных теста (pytest) на основной сценарий.
- Docker-compose поднимает всю систему одной командой.
- В README описаны шаги запуска и пример команд curl.
6. Ожидаемый результат
-
В репозитории (папка
a2a-protocol): -
Содержимое артефакта
- Рабочая команда
docker-compose up --buildзапускает реестр и двух агентов. - При выполнении
demo.py(или аналогичного скрипта) в выводе видны логи discovery и negotiation. - Тесты
pytest tests/– зеленые.
- Рабочая команда
-
Опционально простой Web UI (на
streamlitилиfastapi-admin) для просмотра зарегистрированных агентов и их capabilities.
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Агенты не могут найти друг друга при развёртывании в Docker Compose | Использовать имена сервисов в качестве hostname (agent_a, agent_b). Реестр должен быть доступен по имени registry. |
| Зависание при timeout | Добавить asyncio.timeout() на HTTP-запросы (например, 5 секунд). |
| Синхронизация порядка запуска (агент регистрируется до старта реестра) | Использовать depends_on в композе, а также retry-логику в агенте (повтор каждые 2 секунды, до 10 попыток). |
| Необходимость поддерживать TTL регистрации | В реестре реализовать фоновую задачу (BackgroundTasks) с asyncio.sleep(30) и удалять устаревшие записи. Агенты должны перерегистрироваться каждые 20 секунд. |
| Разные версии Pydantic / FastAPI | Зафиксировать версии в requirements.txt: fastapi==0.115.0, pydantic==2.8.0. |
| Сложность отладки распределённой системы | Включить детальное логирование с request_id и trace_id. Использовать curl -v для ручной проверки эндпоинтов. |
8. Бюджет времени (оценка)
| Этап | Время (часы) |
|---|---|
| Этап 1: Проектирование протокола A2A | 1.0 |
| Этап 2: Реализация реестра агентов | 1.5 |
| Этап 3: Реализация базового агента | 2.0 |
| Этап 4: Интеграция discovery и negotiation | 1.5 |
| Этап 5: Тестирование и контейнеризация | 1.5 |
| Итого | 7.5 часов |
Примечание Для первого выполнения задачи (включая изучение протокола, отладку) закладывайте до 10 часов.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 411 | Протоколы межсервисного взаимодействия (gRPC, REST) |
| 412 | Service Discovery (DNS, Consul, etcd) |
| 413 | Capability-based negotiation в распределённых системах |
| 414 | JSON Schema и валидация сообщений |
| 415 | Асинхронное программирование в Python (asyncio) |
| 416 | FastAPI – проектирование микросервисов |
| 417 | Docker Compose для multi-container приложений |
| 418 | Pytest асинхронные тесты (pytest-asyncio) |
| 419 | OpenAPI / Swagger документирование API |
| 420 | Паттерны отказоустойчивости (retry, timeout, circuit breaker) |
10. Чек-лист самопроверки
- Я проверил, что агент A успешно регистрируется в реестре (код 200).
- Я проверил, что при поиске
['code_review']агент A получает агента B. - Я проверил, что negotiation-запрос отправляется на правильный endpoint агента B.
- Я проверил, что в логах отображаются все ключевые шаги: регистрация, discovery, handshake.
- Я проверил, что
docker-compose upзапускает всю систему без ошибок и скриптdemo.pyотрабатывает без сбоев.