Подключить LLM к API сегодня относительно несложно. Гораздо сложнее решить, что должно произойти после фразы: «Создай мне рекламную кампанию и запусти её».

Если у агента есть OAuth-доступ к Яндекс Директу, технически он может изучить существующие кампании, посмотреть Метрику, собрать семантику, написать объявления, создать объекты через API и включить показы.

Но рекламный кабинет — не тестовый проект. Ошибка здесь может означать реальные расходы.

Когда я начал делать плагины для работы Codex и Claude Code с Яндекс Метрикой и Яндекс Директом, довольно быстро выяснилось, что главная инженерная задача вообще не в генерации объявлений и даже не в API-клиенте. Гораздо важнее построить вокруг API модель доверия: дать агенту достаточно возможностей для полезной работы, но не позволять ему превращать догадки в изменения реального аккаунта.

Немного контекста

Я разработчик и занимаюсь продуктами, но не являюсь директологом. Последний раз сам достаточно плотно настраивал рекламу руками примерно в 2012 году. Представление о процессе у меня есть, но современным специалистом по Яндекс Директу я себя не считаю.

Отчасти поэтому мне и стал интересен такой инструмент: насколько далеко сможет зайти человек, который хорошо знает свой продукт и клиентов, но не занимается профессионально рекламными кабинетами.

Сейчас я тестирую плагины в том числе на собственном проекте с небольшим реальным бюджетом. Поэтому графиков «CPA снизился в два раза» здесь не будет — данных для таких выводов пока мало.

Зато качество исследовательской работы уже интересно. Агент анализирует продукт и посадочные страницы, работает с семантикой, связывает рекламу с Метрикой, строит структуру кампаний, пишет объявления и объясняет свои решения. Но прежде чем позволить ему создавать всё это в реальном кабинете, пришлось поставить довольно много ограничителей.

OAuth не означает «разрешено всё»

Одна из первых вещей, которые пришлось разделить, — технический доступ и разрешение на конкретную операцию.

OAuth отвечает на вопрос: может ли приложение обратиться к API в рамках полученных scopes. Но наличие write-доступа ещё не означает, что агент имеет право менять конкретную цель, кампанию или бюджет.

Для себя я сформулировал это так:

Scope определяет предел технических возможностей приложения. Подтверждённый план определяет право выполнить конкретное действие.

В Метрике это особенно хорошо видно на разделении read- и write-контуров. Агент может свободно исследовать счётчики, цели и отчёты, но изменение проходит отдельный workflow с проверкой текущего состояния, планом и подтверждением.

В Директе границы ещё строже. Создать кампанию, отправить её на модерацию и начать показы — три разных действия. Одного запроса «сделай мне рекламу» недостаточно, чтобы начать тратить деньги.

Ограничения лучше закладывать в код, а не в промпт

Для первой версии плагина Метрики я специально начинал с GET-only транспорта.

Можно было дать агенту универсальный HTTP-клиент и написать в инструкции:

Never modify the user's Yandex Metrica configuration.

Но тогда read-only существует только до тех пор, пока модель следует инструкции.

Гораздо надёжнее, когда запрещённая операция физически не может пройти через транспорт.

Сейчас плагин умеет не только читать данные, но и выполнять ограниченные операции с целями. Однако write-контур отделён от обычного анализа: свободный текст пользователя не превращается напрямую в POST.

Общая логика получилась такой:

read → evidence → recommendation

и для изменений:

read → plan → confirmation → write → readback

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

Мультиаккаунтность — это задача изоляции контекста

Пока у пользователя один сайт, один счётчик и один рекламный кабинет, всё просто. Проблемы начинаются, когда появляются несколько продуктов, профилей, счётчиков и клиентов.

LLM вполне способна взять кампанию продукта A, цель из Метрики продукта B и статистику продукта C, после чего построить очень убедительное объяснение происходящего.

Поэтому агент не должен самостоятельно выбирать «наиболее вероятный» контекст.

В Метрике перед работой фиксируются профиль, логин и конкретный счётчик. Если выбор неоднозначен, он остаётся неоднозначным до подтверждения пользователя.

Даже название цели ничего не гарантирует. Цель Заявка может означать открытие формы, нажатие на кнопку или действительно отправленную заявку. Поэтому бизнес-роль цели не выводится автоматически из её названия.

В Директе похожая изоляция применяется к продуктам, кампаниям, аудиториям, семантике, экономике и статистике. Для агентских кабинетов отдельно контролируется Client-Login.

Статус UNKNOWN здесь оказался очень полезным. Для агента честное «не знаю» лучше, чем убедительная догадка в неправильном аккаунте.

Токен не должен попадать в чат

OAuth-токены и другие credentials не передаются в промпт и не принимаются обычными аргументами CLI.

Пользователь самостоятельно проходит login, 2FA и consent, после чего токен вводится локально и сохраняется в защищённом хранилище операционной системы: DPAPI в Windows, Keychain в macOS или Secret Service в Linux.

Метаданные существуют отдельно от секрета. Агент может видеть, что профиль настроен и соединение работает, но не получает значение токена.

Оба плагина работают локально на компьютере пользователя и обращаются к API Яндекса напрямую. Данные рекламного аккаунта и OAuth-токены не проходят через мой сервер.

Между фразой пользователя и POST должен быть план

Предположим, пользователь пишет:

Создай цель на успешную отправку формы.

Превращать эту строку непосредственно в HTTP payload рискованно. Поэтому write-контур выглядит примерно так:

Запрос пользователя
        ↓
live snapshot
        ↓
typed specification
        ↓
validation
        ↓
immutable plan
        ↓
SHA-256 + TTL
        ↓
подтверждение
        ↓
повторный preflight
        ↓
mutation
        ↓
GET-readback
        ↓
VERIFIED / UNRESOLVED

Здесь для меня особенно важен immutable plan.

Допустим, агент предложил создать JavaScript-цель с определённым именем и событием. Пользователь её подтвердил, но перед выполнением модель решила немного «улучшить» название.

Для LLM изменение выглядит разумным. Для системы это уже другой payload, которого человек не подтверждал.

Поэтому подтверждается конкретный план. От него считается SHA-256. Изменился payload — изменился hash — старое подтверждение больше не действует.

Mutation нельзя бездумно повторять после timeout

Это одна из наиболее важных особенностей транспорта Direct.

Для чтения retry обычно безопасен. Для записи — далеко не всегда.

Представим, что запрос ушёл в API, объект был создан, но соединение оборвалось до получения ответа. Локально мы видим timeout, хотя операция уже могла выполниться.

Автоматический retry в такой ситуации способен создать дубль.

Поэтому mutation-запрос получает одну попытку. Если результат невозможно доказать, операция переходит в UNKNOWN или UNRESOLVED.

После этого разрешено только reconciliation: прочитать фактическое состояние, понять, произошло ли изменение, и при необходимости сформировать новый план.

То же относится к частично успешным операциям. PARTIAL, UNKNOWN и UNRESOLVED останавливают сценарий, а не интерпретируются как «в целом всё получилось».

HTTP 200 — это ещё не доказательство результата

Даже успешный ответ API не говорит, что система в итоге находится именно в ожидаемом состоянии.

Direct-транспорт сохраняет RequestId, API units, статусы и ошибки отдельных объектов. После изменяющей операции выполняется отдельный readback нужных Campaign, Ads или Keywords.

Получается два уровня проверки:

«Сервер принял запрос» — транспортный факт.

«Объект находится в ожидаемом состоянии» — факт о бизнес-системе.

Для агента второй значительно важнее.

Создание, модерация и запуск — разные операции

Самая очевидная причина не давать агенту команду launch_campaign() — разная цена ошибок на каждом этапе.

Создание поисковой кампании происходит последовательно:

Campaigns.add
    ↓
readback
    ↓
AdGroups.add
    ↓
readback
    ↓
assets / extensions
    ↓
Ads.add
    ↓
Keywords.add
    ↓
readback

Следующий этап не должен продолжаться, если предыдущий не подтверждён как VERIFIED.

При этом созданная кампания не начинает показываться. Сеть остаётся в SERVING_OFF. Создание само по себе не запускает ни модерацию, ни расход бюджета.

Модерация имеет собственный check и подтверждение. Статусы MODERATION и PREACCEPTED не выдаются за финальное одобрение.

Запуск — ещё один отдельный workflow. Перед ним заново проверяются состояние объектов, бюджет, стратегия, цели, регионы, расписание, URL и другие критичные параметры. После подтверждения выполняется Campaigns.resume, а затем состояние снова перечитывается.

Главный вывод здесь довольно простой:

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

Агент должен уметь говорить «данных недостаточно»

LLM хорошо строят завершённые объяснения. В аналитике это иногда становится недостатком.

Отсутствие revenue не означает revenue = 0. Пустой ответ одного API не всегда означает отсутствие кампании. Некоторые объекты могут быть доступны только через отчётный контур и помечаться как REPORT_ONLY, а часть параметров публичный API вообще может не раскрывать.

То же самое с Метрикой: наличие цели и даже зарегистрированные достижения ещё не доказывают, что эта цель действительно измеряет нужный бизнес-результат.

Поэтому факты, ограничения платформы, гипотезы и рекомендации лучше хранить раздельно.

Есть и временная проблема. Если сегодня кампания уже потратила деньги, но ещё не получила конверсий, это не обязательно основание срочно её менять. День не завершён, а conversion lag может быть неизвестен.

Поэтому health-анализ работает с завершёнными периодами. Иногда его правильный ответ — не очередные десять рекомендаций, а предложение подождать накопления данных.

Почему нет автоматической оптимизации

После того как агент научился читать кампании и Метрику, логичным следующим шагом кажется автоматическая оптимизация.

Я пока сознательно её не сделал.

Health monitoring может предложить действие типа CHECK, WAIT или CHANGE, объяснить причину, риск и confidence. Но даже принятая рекомендация CHANGE не отправляется сразу в API.

Она запускает обычный защищённый edit workflow:

live state
    ↓
edit check
    ↓
plan
    ↓
confirmation
    ↓
mutation
    ↓
readback

Автоматического изменения ставок, бюджета или таргетинга по собственной инициативе агента нет.

Пока мне кажется намного полезнее автоматизировать сбор доказательств и подготовку решений, чем автоматизировать расход денег.

Где LLM оказалась особенно полезной

Несмотря на все ограничения, большая часть работы вполне подходит агенту.

При подготовке кампании он может одновременно учитывать продукт, посадочную страницу, цели Метрики, существующий рекламный аккаунт, поисковые намерения, семантику, минус-слова и тексты объявлений.

Больше всего мне нравится даже не генерация объявлений, а способность держать в одном контексте цепочку:

поисковое намерение
        ↓
ключевая фраза
        ↓
группа объявлений
        ↓
объявление
        ↓
посадочная страница
        ↓
цель

и замечать, когда эта цепочка перестаёт быть логичной.

Я не считаю это заменой хорошему директологу. Мне интереснее другой сценарий: владелец небольшого продукта или разработчик хорошо понимает свой бизнес, но не хочет становиться специалистом по рекламному интерфейсу.

На моих текущих тестах качество подготовленных материалов уже достаточно хорошее, чтобы продолжать эксперимент. А вот статистики, позволяющей сравнивать экономическую эффективность с профессиональным ведением рекламы, пока недостаточно.

Что получилось в итоге

Метрика и Директ хорошо показывают, почему нельзя считать все API-операции одинаковыми.

Операция

Основной риск

Получить отчёт

ошибочный вывод

Изменить цель

испортить аналитику

Создать рекламу

создать неверные объекты

Запустить рекламу

потратить реальные деньги

Поэтому чем выше последствия операции, тем меньше свободы остаётся у модели.

В сильно упрощённом виде весь подход сводится к одной цепочке:

CONTEXT
   ↓
READ
   ↓
EVIDENCE
   ↓
PLAN
   ↓
CONFIRM
   ↓
APPLY
   ↓
READBACK

Для меня это оказалось более интересным результатом разработки, чем сам факт интеграции с Яндекс Директом.

Этот принцип вполне переносится на CRM, облачную инфраструктуру, task trackers и другие системы, в которых AI-агент перестаёт быть только собеседником и начинает менять реальные данные.

Исходники Метрики

Чтобы статья не оставалась только описанием архитектуры, плагин для Яндекс Метрики я выложил в открытый репозиторий:

github.com/anilau-agent-plugins/yandex-metrika

Он бесплатный и open source. Можно использовать его с Codex и Claude Code или просто посмотреть реализацию.

Это независимый проект, не официальный продукт Яндекса, OpenAI или Anthropic.

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

Поэтому пока не хочу превращать этот материал в рассказ про очередного «AI-маркетолога». Мне интереснее проверить более практическую гипотезу: может ли человек без современной профессиональной экспертизы в Директе с помощью агента выполнить значительную часть работы достаточно качественно, сохранив контроль над стратегией, деньгами и последствиями изменений.

Вместо заключения

AI-агентам уже дали терминал, Git, базы данных, браузер и облачную инфраструктуру. Поэтому доступ к реальным бизнес-системам выглядит естественным следующим шагом.

Главный вопрос здесь уже не в том, умеет ли LLM вызвать API.

Интереснее, что она сделает, если данных недостаточно, выбран не тот аккаунт, сеть оборвалась после записи или пользователь подтвердил одно действие, а перед выполнением модель решила его немного «улучшить».

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

В итоге большая часть инженерной работы у меня ушла не на генерацию рекламы, а на контекст, credentials, состояния UNKNOWN, immutable plans, подтверждения и readback.

Чем выше цена ошибки агента, тем меньше у него должно быть возможностей самостоятельно догадаться и продолжить.

Ищу несколько неприятных тест-кейсов

Плагин Директа я продолжаю тестировать, и собственных сценариев уже становится недостаточно. Поэтому трём авторам содержательных комментариев, у которых есть реальный рекламный аккаунт и желание проверить этот подход, готов дать плагин бесплатно.

Особенно интересны сложные случаи: несколько клиентов или счётчиков, старые кампании, неоднозначные цели, неполная аналитика и ситуации, где агенту приходится выбирать между действием и честным UNKNOWN.

Главное, что хотелось бы получить взамен, — технический фидбек: где проверки мешают нормальной работе и где, наоборот, агент попытался сделать то, чего ему делать не следовало.