Театр одного агента: режиссура мультиагентной системы. llm.. llm. Анализ и проектирование систем.. llm. Анализ и проектирование систем. Блог компании Сбер.. llm. Анализ и проектирование систем. Блог компании Сбер. ИИ.. llm. Анализ и проектирование систем. Блог компании Сбер. ИИ. ии-агенты.. llm. Анализ и проектирование систем. Блог компании Сбер. ИИ. ии-агенты. Информационная безопасность.. llm. Анализ и проектирование систем. Блог компании Сбер. ИИ. ии-агенты. Информационная безопасность. искусственный интеллект.
Театр одного агента: режиссура мультиагентной системы - 1

Меня зовут Михаил Афанасьев, я главный специалист в команде кибербезопасности Platform V в СберТехе, занимаюсь подготовкой продуктов к прохождению сертификации ФСТЭК России. Хочу рассказать о режиссуре LLM-агентов и о том, как выбор ролей и написание промптов превращают хаотичный поток запросов к нейросети в надёжную инженерную систему.

История одной постановки на тему поиска секретов в коде

Всё началось с простой реплики в темноте зала: «Было бы круто, если бы кто‑то за меня бродил по репозиторию и вылавливал там секреты».

Поначалу это выглядело как монодрама. Один актёр (LLM), один микрофон (чат), одна задача: «Нужно найти в файлах что-то опасное». Но любой режиссёр скажет вам: хороший спектакль не строится на одном монологе. Если заставить одного актёра бегать по сцене, искать реквизит, анализировать улики и писать рецензию самому себе, он устанет, собьётся и начнёт импровизировать там, где нужно следовать сценарию.

Так родилась идея творческой команды, а вместо одинокого актера появилась труппа.

Почему аналогия с театром? Разработка сложной системы напоминает постановку спектакля: есть сценарий (промты), актёры (агенты), режиссёр (оркестратор), а пользовательский интерфейс или CI/CD-журнал — это зрительный зал. Я давно увлекаюсь театром, и мне показалось, что эта метафора лучше всего объясняет хаос, который возникает, когда один агент пытается сыграть всю труппу сразу. Поэтому далее я буду использовать термины из мира сцены, чтобы показать, как превратить импровизацию в отлаженную систему.

Акт I. От артиста до труппы

Эволюция нашего проекта прошла две классические стадии, знакомые любому, кто ставит эксперименты с нейросетями.

Монодрама («Один большой агент»)

Замысел: одна модель, один промпт: «Вот код, найди секреты»

Проблема: актёр пытается играть всё сразу. Он ищет, анализирует и пишет отчёт на одном дыхании. Результат непредсказуем: где-то гениально, где-то галлюцинации, а формат ответа меняется каждый раз. Встроить это в CI/CD невозможно — это как строить график спектакля по настроению ведущего актера.

Режиссёрская правка («Мне нужен порядок»)

Появляется желание разделить сцены. Отдельно поиск, отдельно анализ, отдельно финал.

Зачем нам эта труппа? Зачем вообще усложнять постановку и звать нейросеть, если есть сканеры? Проблема в шуме. Специальные инструменты, такие как GitLeaks, выдают тонну срабатываний. Человек не способен реально всё посмотреть и вынести вердикт вручную. Поэтому мы внедряем LLM-агент не вместо инструмента, а как умный фильтр. Как и в современных SAST-решениях, это нужно для уменьшения времени на разбор полётов и увеличения полноты анализа.

Требования к постановке. Система обретает форму труппы. Каждый агент — это характер со своей биографией (промптом) и задачей.

Система должна иметь свойства:

  • Воспроизводимость: одна и та же пьеса должна звучать одинаково.

  • Проверяемость: логика не должна растворяться в импровизации.

  • Масштабируемость: завтра можно ввести нового персонажа (например, проверку лицензий), не переписывая всю пьесу.

Для достижения такой системы должны присутствовать роли:

  • Режиссёр (оркестратор): принимает заявку от зрителя и распределяет роли.

  • Сыщик (сканер): ходит по файлам, ищет улики.

  • Эксперт (аналитик): проверяет, настоящая ли это улика или ложный след.

  • Летописец (репортёр): пишет итоговый протокол для истории.

Акт II. Кастинг и роли

Если в классической UML-диаграмме классы — это просто сухие прямоугольники с методами и полями, то в мультиагентной системе каждый «прямоугольник» оживает. К структуре добавляется «психология»: системный промпт, стиль общения, приоритеты и жёсткие ограничения, которые определяют, как именно агент будет реагировать на данные.

Распределение ролей

Роль

Характер

Задача на сцене

Оркестратор

Спокойный управленец

Принимает запрос, разбивает на сцены, следит за таймингом.

Сканер

Внимательный, дотошный

Сканирует текст и отчёты инструментов (например, GitLeaks), не упускает детали. На вход ему поступает не только код, но и результаты работы специализированных инструментов.

Аналитик

Критичный, скептичный

Не верит Сканеру на слово. Перепроверяет каждую находку.

Репортёр

Педантичный писарь

Превращает хаос данных от Аналитика в строгий JSON или Markdown.

Протокол общения (реплики)

Чтобы актёры не перебивали друг друга, им нужна последовательность реплик. В нашем случае это структурированные сообщения (JSON) — что-то вроде текста роли.

Пример реплики от Режиссёра к Сыщику:

Чёткий контракт позволяет заменять актёров. Если завтра Сыщик устанет (например, модель станет дорогой), то вы сможете заменить его на другого, не меняя сценарий для Режиссёра.

{
   "role": "code_scanner",
   "task": "scan_files",
   "payload": {
     "root_path": "/repo",
     "files": [
      { "path": "src/app.py", "content": "..."}
    ]
"tool_results": [
       { "source": "gitleaks", "findings": [...] }
     ]
  },
   "meta": {
     "request_id": "123e4567",
     "status": "pending"
   }
}

Акт III. Сценарий как закон

Промпт в мультиагентной системе —  как полноценный сценарий. В нём прописано не только «что сказать», но и «как играть», «какова мотивация» и «что делать в экстренной ситуации».

Структура идеального сценария. Хороший промпт — это баланс между свободой актёра и дисциплиной режиссёра.

Шаблон промпта для агента-Сыщика:

Роль: Ты — LLM‑агент, специализирующийся на обнаружении секретов в исходном коде. Твой характер — внимательный, дотошный и осторожный.

Цель (мотивация):
— Найти потенциальные секреты (пароли, токены).
— Минимизировать ложные срабатывания (не поднимать шум напрасно).
— Дать чёткое обоснование каждой находке.
Контекст (декорации):
— Секреты живут в строках, переменных окружения, конфигурациях.
— На вход поступают файлы и результаты работы специализированных инструментов.
— Строки типа “TODO”, “FIXME” — это не секреты, игнорируй их.
— Краткие числа (1, 0, 123) не являются секретами.

Формат выхода (регламент):
Отвечай строго в формате JSON. Никакого текста вне JSON.
json > { >   "secrets": [ >     { >       "file": "путь/к/файлу", >       "line": номер_строки, >       "snippet": "подозрительная строка", >       "reason": "краткое объяснение" >     } >   ] > } >

Ограничения (запреты):
— Не придумывай файлы. Используй только предоставленные данные.
— Если секретов нет, то верни { "secrets": []}.

Режиссура через цепочки (Prompt Chaining)

Важно не сваливать всё в одну кучу. Спектакль идёт по актам:

  1. Акт 1 (Оркестратор): получает задачу «проанализировать репозиторий»; решает, какие сцены (файлы) играть.

  2. Акт 2 (Сканер): получает файлы, ищет кандидатов.

  3. Акт 3 (Аналитик): подтверждает или отбрасывает кандидатов.

  4. Финал (Репортёр): собирает всё в читаемый вид.

Каждому акту — свой промпт, чтобы можно было отлаживать каждую мизансцену по отдельности.

Акт IV. Механика театрального действия (код)

Как это выглядит за кулисами? Принцип «одна театральная роль — один программный класс» упрощает разработку. Каждый класс инкапсулирует свой системный промпт, знает, какие данные принимать на вход, и строго регламентирует формат ответа.

Мы оборачиваем LLM-клиент в класс, который хранит свой системный промпт и знает, как взаимодействовать с залом.

class AnalyzerAgent:
    def __init__(self, llm_client, system_prompt: str):
        self.llm = llm_client
        self.system_prompt = system_prompt # Сценарий роли

    def analyze(self, text: str) -> dict:
        # Формируем контекст диалога
        messages = [
            { "role": "system", "content": self.system_prompt},
            { "role": "user", "content": f"Проанализируй этот текст:nn{text}"}
        ]
        # Вызов модели (Игра актёра)
        response = self.llm.chat(messages)
        
        # Валидация ответа (Контроль режиссёра)
        try:
            return json.loads(response["content"])
        except json.JSONDecodeError:
            return {"error": "Actor broke character", "raw": response["content"]}

Чек-лист перед выходом на «сцену»

Перед написанием кода я задал себе вопросы, как и при подготовке пьесы:

  1. Что актёр (агент) должен делать в одиночку?

  2. Какой реквизит (данные) ему доступен?

  3. Какие решения он принимает сам, а какие выносит на суд зрителя?

Так и записали в спецификации: Описание → Вход → Выход → Ограничения. Это спасёт от хаоса в промптах.

Примеры реплик

Чтобы теория не оставалась абстракцией, посмотрим, как агенты обмениваются «репликами» на конкретном примере. Допустим, мы сканируем файл config.py.

1. Сканер (поиск улик)

Входные данные: фрагмент кода API_KEY = "sk-1234567890".

Ответ агента (JSON):

{
  "secrets": [
    {
      "file": "config.py",
      "line": 15,
      "snippet": "API_KEY = "sk-1234567890"",
      "reason": "Похоже на ключ доступа API, высокая энтропия строки"
    }
  ]
}

2. Аналитик (проверка улик)

Входные данные: результат от Сканера.

Задача: подтвердить, не является ли это тестовым значением.

Ответ агента (JSON):

{
  "verified": true,
  "confidence": 0.95,
  "comment": "Ключ имеет префикс sk-, характерный для продакшен-среды. Не похоже на заглушку."
}

3. Репортёр (финальный протокол)

Входные данные: подтверждённая находка от Аналитика.

Ответ агента (Markdown):

## Отчёт о безопасности
| Файл | Строка | Статус |
| --- | --- | --- |
| config.py | 15 | 🔴 Критично (Secret Found) |

Такой подход позволяет видеть журнал на каждом этапе и быстро находить, где «актёр» сбился с роли.

Акт V. Репетиции и типичные ошибки

Почти каждая премьера проходит через стадию «что-то пошло не так». Вот типичные проблемы нашей труппы и способы их решения.

Ошибка

Почему спектакль рушится

Как исправить режиссуру

«Играй всё»

«Найди, исправь, объясни». Актёр теряется, смешивает жанры.

Дробите роли. Поиск, анализ, отчёт — это разные агенты.

Импровизация

Нет формата ответа. Невозможно понять конец сцены.

Требуйте JSON. Закрепляйте формат: «Если тишина — верни пустой список».

Галлюцинации

Актёр выдумывает файлы, которых нет в декорациях.

Жёсткие ограничения. «Используй только входные данные».

Смешение амплуа

Актёры есть, но они нарушают границы ответственности. Например, Оркестратор начинает сам сканировать код, а Репортёр — принимать решения о безопасности. Это нарушение субординации.

Разделяйте сценарии. Оркестратор знает план, Репортёр — контекст задачи. Чёткие контракты на входе и выходе.

Нам помогло проведение генеральных репетиций и тестирование промптов интерактивно (через playground), добейтесь стабильной игры, и только потом выпускайте на суд зрителей (в эксплуатацию).

Финал — агент как зафиксированная договорённость

Если снять весь технический грим, то LLM‑агент — это договорённость между разработчиком и моделью. Договорённость базируется на трёх принципах, которые мы последовательно утверждали в предыдущих актах нашей постановки:

  • Характер персонажа (акт II): о роли, которую играет агент.

  • Язык реплик (акт II): о формате, в рамках которого агент общается с «труппой».

  • Право на импровизацию (Акт III): о том, какие решения модель принимает самостоятельно.

Промпт-инженерия в этой картине — это не магия заклинаний, а драматургия. То же самое проектирование интерфейсов, только в текстовом виде и с участием полноценного (пусть и искусственного) актёра.

Когда мы начали проектировать систему через призму театра, хаос импровизации уступил место чёткой драматургии. Роли разделились, контракты стали жёсткими, а отладка каждой «сцены» — предсказуемой.

Сегодня эта «труппа» уже работает в production и регулярно проверztn репозитории на утечку секретов. Театральная метафора оказалась не просто красивой обёрткой: она помогла нам бесшовно встроить агенты в действующие CI/CD-процессы, упростить коммуникацию внутри команды и легко масштабировать систему — новых «актёров» мы подключаем, не переписывая оркестратора. Теперь это не эксперимент, а рабочий инженерный инструмент, чья логика и характер зафиксированы в коде и сценариях.

Автор: Skaslik

Источник