ИИ-оркестрация с LarAgent в мультиагентных системах
Современные AI-приложения редко ограничиваются одним вызовом LLM.
Реальные пользовательские сценарии требуют координации нескольких моделей, специализированных агентов, инструментов и источников данных.
Например, пользователь пишет:
«Создай 10 SEO-статей для моего блога».
На первый взгляд — простая задача.
На практике она включает:
-
анализ намерения пользователя;
-
выбор подходящего агента;
-
генерацию идей;
-
построение структуры статьи;
-
написание текста;
-
SEO-оптимизацию;
-
форматирование ответа.
В нашем продакшн-приложении на Laravel мы решили эту задачу через мультиагентную архитектуру на базе фреймворка LarAgent (maestroerror/laragent).
Эта статья показывает реальную архитектуру системы и ключевые паттерны, которые позволили построить масштабируемую AI-платформу.
Зачем нужна ИИ-оркестрация
Один вызов LLM — это просто.
Но когда система должна:
-
использовать разные агенты,
-
выполнять цепочки действий,
-
вызывать инструменты,
-
работать с пользователями и чатами,
-
поддерживать разные LLM-провайдеры,
— появляется необходимость оркестрации.
ИИ-оркестрация — это слой управления, который:
-
принимает пользовательский запрос,
-
определяет намерение пользователя,
-
выбирает подходящего агента,
-
координирует выполнение задачи.
В нашем приложении оркестратор не выполняет задачи самостоятельно — он только маршрутизирует запросы между агентами.
Архитектура: Orchestrator → Specialist Agents
Основной паттерн системы:
User Message
↓
AgentConversationManager
↓
OrchestratorAgent
↓
DetectUserIntentTool
↓
MatchIntentToAgentTool
↓
DelegateToAgentTool
↓
Specialist Agent
↓
FormatResponseForUserTool
Оркестратор работает как маршрутизатор задач.
В системе используется несколько специализированных агентов:
-
ArticleGeneratorAgent
-
MarketingAgent
-
SEOAgent
-
ConsultantAgent
-
DetectUserIntentAgent
Каждый агент отвечает только за свою область.
Это соответствует архитектурному принципу:
Single Responsibility for AI Agents
Пример OrchestratorAgent
class OrchestratorAgent extends AbstractAgent
implements AgentChatAwareInterface, UserAwareInterface, AgentInterface
{
use InteractsWithUser, InteractsWithAgentChat;
protected $provider = 'default';
protected $history = 'cache';
public function registerTools(): array
{
return [
new GetAvailableAgentsTool(),
new MatchIntentToAgentTool(),
(new DetectUserIntentTool())
->addProperty('provider', 'string', 'Название провайдера', [$this->provider])
->setRequired('provider')
->setMetaData(['history' => $this->chatHistory()]),
(new DelegateToAgentTool())
->addProperty('chat_uuid', 'string', 'UUID чата', [$this->getChatUuid()])
->setRequired('chat_uuid')
->addProperty('provider', 'string', 'Провайдер', [$this->getProviderName()])
->setRequired('provider')
->addProperty('user_id', 'integer', 'ID пользователя', [$this->user?->id])
->setRequired('user_id'),
(new FormatResponseForUserTool())
->addProperty('provider', 'string', 'Провайдер', [$this->getProviderName()])
->setRequired('provider'),
];
}
}
Оркестратор использует инструменты (tools), чтобы управлять агентами.
Intent Detection — понимание намерения пользователя
Первый шаг любой AI-системы — понять, что хочет пользователь.
В нашем случае используется structured output.
LLM возвращает не текст, а типизированный объект.
class Intent extends DataModel
{
#[Desc('Намерение пользователя')]
public string $intent = "unknown";
}
Агент определения намерения:
class DetectUserIntentAgent extends AbstractAgent
{
protected $responseSchema = Intent::class;
public function registerTools(): array
{
return [new GetUserIntentsTool()];
}
}
Теперь LLM возвращает, например:
intent = "article.create_detailed"
Маппинг Intent → Agent
После определения intent система выбирает нужного агента.
private function searchAgentByTools(array $requiredTools): ?Agent
{
$agents = $this->agentRepository->getAllWithTools();
foreach ($agents as $agent) {
if ($this->agentHasAllTools($agent, $requiredTools)) {
return $agent;
}
}
return null;
}
Таким образом:
Intent → Required Tools → Agent
LLM определяет intent, но не выбирает агента напрямую.
Это важная архитектурная защита.
Делегирование задач между агентами
Оркестратор не вызывает агента напрямую.
Он использует DelegateToAgentTool.
private function executeAgent(
string $agentClass,
string $chatUuid,
string $payload,
int $userId
): string
{
$agent = $agentClass::setConfiguration($chatUuid, $agentClass)
->addSystemMessages();
if ($agent instanceof UserAwareInterface) {
$user = $this->userRepository->findById($userId);
if ($user) {
$agent->setUser($user);
}
}
if ($agent instanceof AgentChatAwareInterface) {
$agent->setChatUuid($chatUuid);
}
$raw = $agent->respond($payload);
return is_string($raw) ? $raw : (string) $raw;
}
Это позволяет:
-
передавать контекст пользователя
-
передавать чат
-
управлять историей сообщений
Контракт оркестрируемых агентов
Чтобы агент мог быть вызван оркестратором, он должен реализовать интерфейс:
interface OrchestratableAgentInterface extends AgentInterface {}
Пример:
class ArticleGeneratorAgent extends AbstractAgent
implements OrchestratableAgentInterface,
UserAwareInterface,
AgentChatAwareInterface
{
}
Таким образом система контролирует доступ агентов.
Expert Chain — мультишаговая генерация статей
Некоторые задачи слишком сложны для одного LLM-запроса.
Например, генерация экспертной статьи.
Мы используем Expert Chain.
Цепочка из 5 шагов:
-
Генерация идей
-
Выбор лучшей идеи
-
План статьи
-
Написание секций
-
Финальное ревью
public function generate(string $topic, ?array $plan = null)
{
$selectedIdea = $topic;
$plan = $plan ?? $this->generateArticlePlan($topic);
$sections = $this->writeSections($plan);
$content = $this->reviewArticle($sections);
return new ArticleGeneratedContent(
$topic,
$content,
$selectedIdea,
$plan
);
}
Каждый шаг вызывает LLM отдельно.
Это даёт:
-
лучшее качество текста
-
более стабильный результат
-
контроль над процессом генерации
Мульти-провайдерность LLM
Система может работать с разными LLM.
Поддерживаются:
-
OpenAI
-
Claude
-
Gemini
-
YandexGPT
-
Groq
-
Ollama
-
OpenRouter
Конфигурация:
'providers' => [
'default' => [
'driver' => ChatGPTDriver::class,
'model' => 'gpt-5-mini',
],
'gemini' => [
'driver' => GeminiDriver::class,
'model' => 'gemini-2.0-flash-latest',
],
'claude' => [
'driver' => ClaudeDriver::class,
'model' => 'claude-3-7-sonnet-latest',
],
'yandexgpt' => [
'driver' => YandexDriver::class,
'model' => 'gpt://folder_id/yandexgpt-lite',
],
]
Переключение происходит динамически:
$instance->changeProvider($provider);
$instance->withModel($model);
Это позволяет:
-
менять LLM без изменения бизнес-логики
-
тестировать разные модели
-
использовать разные модели для разных задач
Фоновая обработка через Laravel Queues
Массовая генерация контента требует фоновой обработки.
Например:
«Создай 10 статей»
Каждая статья — отдельная очередь.
class CreateArticleJob implements ShouldQueue
{
public function handle(): void
{
$agent = $this->buildAgent();
$payload = $this->getCreateArticlePayload();
$agent->respond($payload);
}
}
Преимущества:
-
система не блокирует пользователя
-
задачи масштабируются горизонтально
-
можно генерировать тысячи статей
Управление контекстом
Большая проблема LLM-систем — рост контекста.
Для решения используется Truncation Strategy.
Оркестратор хранит историю:
return new SimpleTruncationStrategy([
'keep_messages' => 25,
'preserve_system' => true,
]);
Специализированные агенты — только 1 сообщение.
return new SimpleTruncationStrategy([
'keep_messages' => 1,
'preserve_system' => true,
]);
Это резко уменьшает стоимость запросов.
Защита от зацикливания
В мультиагентных системах может возникнуть бесконечный цикл:
Agent → Tool → Agent → Tool
Поэтому используется Loop Detection Service, который ограничивает число вызовов инструментов.
Точка входа системы
Все начинается с AgentConversationManager.
private function callOrchestratorAgent(
AgentChat $chat,
string $payload
): string
{
$agent = OrchestratorAgent::setConfiguration(
$chat->uuid,
OrchestratorAgent::class
)
->setChatUuid($chat->uuid)
->setUser($this->getUser());
$raw = $agent->respond($payload);
return is_string($raw) ? $raw : (string) $raw;
}
Поток работы:
HTTP Request
↓
Controller
↓
AgentConversationManager
↓
OrchestratorAgent
↓
Specialist Agent
↓
Response
Итоги
Мультиагентные системы становятся стандартом для AI-приложений.
Основные архитектурные выводы:
1. Используйте Orchestrator + Specialists
Оркестратор должен только маршрутизировать задачи.
2. Используйте Intent-based routing
LLM определяет intent, а система выбирает агента.
3. Используйте интерфейсы
Контракты вроде:
OrchestratableAgentInterface
UserAwareInterface
AgentChatAwareInterface
дают архитектурный контроль.
4. Разбивайте сложные задачи на цепочки
Expert Chain даёт намного более стабильные результаты.
5. Делайте мульти-LLM архитектуру
Модели быстро меняются — архитектура должна это учитывать.
6. Используйте очереди
LLM-задачи должны выполняться в фоне.
Заключение
Мультиагентная архитектура позволяет превратить LLM из простого генератора текста в полноценную AI-платформу.
Используя:
-
orchestrator pattern
-
intent detection
-
tool-based delegation
-
expert chains
-
multi-provider LLM
мы смогли построить систему, которая масштабируется от одного запроса до массовой генерации контента.
И это только начало развития AI-архитектур.