AI-агент на LinkedIn: когда Haiku не слушается
Я давно хотел автоматизировать рутину вокруг контента на imarch.dev. Не генерацию текстов - это я предпочитаю делать сам или с AI-ассистентом в интерактивном режиме. А всё остальное: парсинг новостных источников, создание PR в GitHub, публикация в LinkedIn, управление pipeline. Каждая из этих задач по отдельности занимает 5-10 минут, но вместе - это час в день, который уходит на переключение контекста между вкладками.
Вопрос, который я поставил: можно ли собрать агента, который делает всё это через одну точку управления - Telegram? Не абстрактного “AI-помощника”, а конкретный инструмент: я пишу в бот “опубликуй пост в LinkedIn”, и он открывает браузер, находит форму, вставляет текст, нажимает кнопку. Без моего участия, кроме начальной команды.
Платформу OpenClaw я нашёл подходящей - self-hosted, система скиллов через markdown-файлы, Telegram-канал из коробки, browser automation через Chrome DevTools Protocol. Заработало, но с приключениями, которые оказались поучительнее, чем сам результат.

Стек и архитектура
OpenClaw - это self-hosted платформа для AI-агентов. Node.js gateway принимает сообщения из каналов (в моем случае Telegram), обрабатывает их через систему скиллов (markdown-файлы с инструкциями для модели) и отправляет в LLM с набором доступных tools. Один из tools - browser automation через CDP. Всё крутится в Docker.
Архитектура двухуровневая по стоимости. Для чата в Telegram и простых команд - Haiku 4.5 по $1/$5 за миллион input/output токенов. Для генерации блог-постов - отдельные Python-скрипты с Sonnet 4.6 ($3/$15), потому что качество текста на дешевой модели неприемлемо. Для обложек - DALL-E 3 ($0.08 за изображение). Суммарная стоимость одного блог-поста - около $0.46.
Выбор двухуровневой модели не случаен. Если гонять Sonnet на все задачи, включая ответы на “какой статус парсера?” и “сколько новых статей?”, бюджет вырастает в 3 раза без какой-либо выгоды. Haiku справляется с простыми командами нормально. Проблема, как выяснилось, начинается когда Haiku нужно не просто ответить текстом, а вызвать tool.
Haiku галлюцинирует про Browser Relay
Haiku 4.5 за $1/$5 - это одна из самых дешевых моделей с поддержкой tool use. Для обычного чата в Telegram - вопрос-ответ, статус системы, простые команды - хватает с запасом. Проблема проявилась когда я попросил агента зайти в LinkedIn и опубликовать пост.
Инструкция в IDENTITY.md была прямолинейной:
У тебя есть встроенный browser tool. Headless Chromium УЖЕ запущен.
НИКОГДА не говори "нужно подключить Chrome tab" или "нужен Browser Relay".
Просто используй browser navigate.
Что сделал Haiku:
“Браузер не авторизован в LinkedIn. Нужна аутентификация - используй свой браузер с авторизацией (через Browser Relay в Chrome).”
Browser Relay - это выдуманная сущность. Её не существует ни в Chrome, ни в CDP, ни в OpenClaw. Haiku прочитал инструкцию “НИКОГДА не говори про Browser Relay” и тут же галлюцинировал Browser Relay. Это классическая проблема дешевых моделей с negation в промптах: модель видит термин “Browser Relay” в контексте, и этого достаточно чтобы она начала его воспроизводить, игнорируя частицу “НИКОГДА”.
Причина, по которой это происходит, связана с тем как работает attention. Инструкция “не делай X” содержит X в своём тексте. При маленьком context window и ограниченных reasoning capabilities модель ассоциирует X с контекстом сильнее, чем негацию. Более мощные модели (Sonnet, Opus) справляются с этим лучше, потому что у них хватает возможностей на отслеживание логической структуры инструкции. Haiku - нет.
Три попытки и что из них работает
Попытка 1: Добавил инструкции в конец IDENTITY.md. Haiku проигнорировал. Это ожидаемо - в длинном system prompt модель уделяет больше внимания началу и концу, но в случае Haiku “конец” часто обрезается при prompt caching или просто теряет weight при длинном контексте.
Попытка 2: Усилил формулировки - “ЗАПРЕЩЕНО”, “ОБЯЗАТЕЛЬНО”, капсом. Haiku всё равно генерирует текст вместо вызова tool. Капс и эмоциональные усилители помогают с моделями уровня Sonnet и выше, но на Haiku эффект минимален. Модель видит tool в списке доступных инструментов, видит инструкцию вызвать tool, и всё равно генерирует текстовый ответ. Потому что генерация текста - это дефолтное поведение, а tool calling требует дополнительного “решения” от модели, на которое у Haiku может не хватать reasoning возможностей.
Попытка 3: Переместил инструкцию в самый верх файла, сразу после заголовка, и сменил формулировку с негативной на позитивную:
## CRITICAL: LinkedIn = browser tool
Когда пользователь просит ЛЮБОЕ действие с LinkedIn -
ты ОБЯЗАН вызвать browser tool. НЕ ОТВЕЧАЙ ТЕКСТОМ. ВЫЗОВИ TOOL.
Стало ощутимо лучше. Позитивная формулировка (“ВЫЗОВИ TOOL”) работает надежнее негативной (“НИКОГДА не говори про Browser Relay”), потому что модели не нужно отслеживать, чего она НЕ должна делать. Плюс позиция в начале промпта дает инструкции больший weight при attention. Но я пока не уверен, что это решение надежно на 100%. Может быть, дешевые модели принципиально не потянут сложные инструкции с tool use. А может быть, я просто не нашел правильную структуру промпта.
Jailbreak-защита: два уровня вместо трех
У меня уже есть production чатбот на imarch.dev с тремя уровнями защиты от jailbreak. Первый уровень - pre-flight regex с 42 паттернами, который ловит попытки prompt injection до того, как сообщение дойдет до модели. Второй - ABSOLUTE_RULES в system prompt, которые запрещают модели раскрывать инструкции, менять роль или выполнять инъекции. Третий - tool-level guards на выходе, которые проверяют что модель не пытается отправить email на произвольный адрес.
В OpenClaw-агенте middleware для regex-фильтров нет - сообщения идут напрямую в модель. Это архитектурное ограничение платформы: OpenClaw не предоставляет hook для обработки входящих сообщений до отправки в LLM. Пришлось обойтись двумя уровнями через IDENTITY.md и voice-guide:
- IMMUTABLE rules в начале IDENTITY.md - агент не раскрывает инструкции, не меняет роль, не выполняет prompt injection. Работает на уровне system prompt, то есть зависит от послушности модели.
- Компетентностные границы - если тема за пределами моего CV и экспертизы, агент не комментирует и не импровизирует, а пишет мне в чат. Это снижает поверхность атаки: нельзя заставить агента авторитетно высказываться на тему, которая не входит в его scope.
Потеря первого уровня (regex pre-filter) - это реальная уязвимость. Regex ловит очевидные паттерны prompt injection (“ignore previous instructions”, “you are now DAN”) до модели, что надежнее, чем полагаться только на послушности модели с системными инструкциями. Без regex-фильтра защита полностью зависит от того, насколько хорошо Haiku следует IMMUTABLE rules. А учитывая, как Haiku справляется с Browser Relay, уверенности не прибавляется.
Насколько это надежно в реальности - пока не знаю. Чатбот с regex-фильтрами проверен, он работает больше недели под реальной нагрузкой. Агент - пока нет. Буду тестировать и, возможно, добавлю свой middleware между Telegram и OpenClaw.
Экономика: почему двухуровневая модель
Экономика агента строится на простом наблюдении: 90% задач не требуют дорогой модели. Ответить на статус-запрос, показать список собранных статей, подтвердить команду - для этого Haiku более чем достаточен. Дорогая модель нужна только для генерации контента, где качество текста критично.
Чатбот на imarch.dev экономит 80% токенов через Hybrid RAG - стабильное ядро системного промпта (~2,500 токенов) живет в кэше Anthropic, а знания подтягиваются из Qdrant только по запросу. Вместо отправки полного промпта в 15,000 токенов каждый раз, отправляется 2,500 + 1-3 релевантных chunk по ~300 токенов. Я описывал эту архитектуру подробнее.
Агент экономит проще и грубее - дешевая модель для 90% операций, дорогая для 10%. Haiku $5/M output vs Opus $75/M output - разница в 15 раз. На практике агент обрабатывает десятки сообщений в день по $0.001-0.005 каждое, и генерирует один пост в неделю по $0.30-0.50. Суммарный бюджет - меньше $5 в месяц.
Prompt caching в OpenClaw тоже работает - cacheRetention: "short" в конфиге. IDENTITY.md и скиллы кэшируются между запросами, что экономит на повторной отправке system prompt. Правда, я пока не замерял реальную экономию - верю документации, но планирую проверить через Anthropic usage dashboard.
LinkedIn-сессия и heartbeat
LinkedIn оказался самой хрупкой частью системы. Cookies живут в Docker volume и сохраняются между рестартами контейнера, но LinkedIn сбрасывает сессию если долго нет активности. Точный таймаут я не знаю - LinkedIn не документирует это, и поведение, похоже, зависит от множества факторов: IP-адрес, fingerprint браузера, частота использования.
Решение - heartbeat, который периодически “заходит” на LinkedIn, чтобы сессия выглядела живой:
while true; do
# Random sleep: 8-16 hours
SLEEP_SECS=$(( RANDOM % 28800 + 28800 ))
sleep "$SLEEP_SECS"
# Pick random LinkedIn page, open via CDP, close
curl -sf -X PUT "$CDP/json/new?${PAGE}"
sleep 10
curl -sf -X PUT "$CDP/json/close/$TAB_ID"
done
Рандомные интервалы от 8 до 16 часов, разные страницы при каждом “визите”. Рандомизация нужна чтобы паттерн не выглядел как бот - если заходить ровно каждые 12 часов, это легко детектить. Посмотрим, поможет ли - может LinkedIn сбрасывает сессию по другой причине (смена IP, обновление cookies policy), и heartbeat тут ни при чем.
Отдельная проблема - headless Chrome детектится анти-бот системами. LinkedIn использует проверку “verify you are human”, которая определяет headless-браузер по нескольким сигналам: отсутствие webGL, нестандартные window dimensions, отсутствие plugin array. Переключение с --headless на --headless=new (новый headless mode в Chrome, который эмулирует обычный браузер точнее) решило проблему. Но я понимаю, что это гонка вооружений - через какое-то время LinkedIn может обновить детекцию.
Что я понял
Главный урок этого проекта - не про OpenClaw и не про LinkedIn. Он про то, где проходит граница возможностей дешевых моделей. Haiku за $1/$5 прекрасно работает как чатбот: вопрос-ответ, простые команды, маршрутизация. Но tool use - это другой уровень сложности. Модель должна не просто понять запрос, а решить, какой tool вызвать, с какими параметрами, и сделать это вместо генерации текста. Для Haiku это на границе возможного. Для Sonnet - рутина.
Второй урок - про jailbreak-защиту. Без middleware между пользователем и моделью ты полностью зависишь от послушности модели. А compliance дешевой модели - это не то, на что стоит ставить в production. Regex pre-filter, каким бы грубым он ни был, ловит 80% атак до модели. Потеря этого уровня ощущается.
Пока больше вопросов чем ответов. Но агент работает, отвечает в Telegram, статьи собирает, LinkedIn открывает. Остальное - итерации.
Это пятая статья в серии про AI-инструменты на imarch.dev. Предыдущие: чатбот, защита, лид-генерация, Hybrid RAG.


