Избранное
a2a-symfony-bundle
Агенты A2A 1.0.0 в Symfony — маршруты, слой безопасности приложения, хранилище на Doctrine, воркеры Messenger и опциональный gRPC поверх a2a-php-sdk.
- PHP 8.4
- Symfony 7.4 / 8
- A2A 1.0.0
- Doctrine DBAL
- Symfony Messenger
- Symfony Security
- gRPC (OpenSwoole)
- Prometheus
- PostgreSQL 18
Проблема
a2a-php-sdk даёт PHP сам протокол. Приложению на Symfony вокруг него всё равно нужна обвязка: маршруты, сервисы, аутентификация через собственный слой безопасности, хранилище задач, общее для нескольких процессов, и фоновые воркеры. Собирать серверные компоненты SDK руками в каждом проекте — ровно то место, где появляются ошибки.
Что добавляет бандл
- Один импорт маршрутов открывает JSON-RPC (
/a2a/rpc), REST (/a2a), потоковую передачу через SSE и обнаружение по/.well-known/agent-card.json. - Агент — это один сервис Symfony, реализующий
Executor. Внешние агенты внедряются как именованные сервисыClient, у каждого свои TLS, дедлайны и заголовки. - Аутентификация через карту Bearer-токенов или существующий
AccessTokenHandlerInterfaceSymfony. Задачи разграничены по идентификатору вызывающего и tenant, одинаково для HTTP и gRPC. - Хранилище — файлы на общем томе или Doctrine DBAL. Таблицу явно создаёт
a2a:storage:init, схема никогда не меняется во время запроса. - Messenger: задачи с
returnImmediatelyуходят в настоящий асинхронный транспорт, синхронные транспорты для них отклоняются.a2a:workотвечает за восстановление и повторную доставку вебхуков. - Опционально — нативный gRPC через
a2a:grpc:serveна OpenSwoole, JSON-логи и сохраняемые счётчики и гистограммы задержек Prometheus.
a2a:
executor: App\Agent\MyExecutor
card_file: '%kernel.project_dir%/config/agent-card.json'
public_url: '%env(A2A_PUBLIC_URL)%'
storage:
driver: doctrine
connection: doctrine.dbal.default_connection
clients:
peer:
endpoint: '%env(A2A_PEER_ENDPOINT)%'
binding: jsonrpc
Проверен на реальной инфраструктуре
make test-postgresработает с PostgreSQL 18 во временных контейнерах: переподключение, изоляция доступа, конфликтующие обновления, откат, дубликаты ID и восстановление аренды.make test-symfonyповторяет тесты и компиляцию контейнера на Symfony 7.4 и 8.0; lock-файл покрывает 8.1.- Реальные вызовы с TLS и mTLS и потоковая передача через именованные клиенты; сертификаты генерируются внутри тестового контейнера.
- Собранный ZIP ставится в чистый проект и выполняет обнаружение и задачу по JSON-RPC без gRPC-расширений.
- PHPStan level 8 и PSR-12. CI бандла проверяет интеграцию с Symfony; совместимость с протоколом подтверждает официальный прогон TCK в SDK.
Выпуск
Опубликован на Packagist под Apache-2.0, текущая версия v1.0.2: composer require vbcherepanov/a2a-symfony-bundle. Рецепт Flex принят в официальный symfony/recipes-contrib (2026-09-16): он регистрирует бандл, подключает маршруты и кладёт закомментированный пример конфигурации. Импорт маршрутов работает и до настройки A2A, так что свежее приложение поднимается в dev и prod.
Решения
- Создание схемы — это команда, а не побочный эффект. HTTP-запрос, который молча мигрирует боевую таблицу, — это сценарий аварии, а не удобство.
- Личность берётся только из аутентификатора. Один и тот же контракт идентификатора и tenant действует для HTTP и gRPC, поэтому задача, созданная через один транспорт, не видна чужому клиенту через другой.