Автоотклик на HH.ru: агент в Telegram с ручным approval
Мониторить свежие вакансии на HH вручную утомляет: одни и те же запросы, десятки карточек, половина мимо. Нужен помощник, который сам обойдёт выдачу, отсечёт явный мусор по заголовку и пришлёт в Telegram то, на что стоит взглянуть — а отклик отправит только после вашего решения. Платных сервисов «автоотклика на HH.ru» хватает — здесь тот же класс задачи, только код открытый и без подписки.
Я взял открытый hh-ai-agent и сделал форк hh-ai-agent-advance. Скрипт универсальный: подставляете свои запросы, резюме и стоп-слова — подойдёт разработчику, аналитику, маркетологу, SEO и любой другой специальности. Ниже — порядок работы, настройка и использование; в примерах — SEO-вакансии, потому что так настроен мой рабочий профиль.
Важное отличие от апстрима: в оригинале на каждую вакансию вызывается LLM («подходит / не подходит» + часто сразу письмо). На reasoning-моделях это быстро сжигает бюджет. В форке цикл поиска не ходит в модель. Письмо генерируется только по кнопке в Telegram, когда вакансия вам уже интересна.
→ github.com/google-dad/hh-ai-agent-advance
«Автоотклик» здесь = автоматический поиск и превью + отклик только после вашей кнопки. Массовой рассылки без участия человека нет — и это сознательно.
Порядок работы
- По списку
search_queriesагент ищет свежие вакансии на HH. - Заголовок проходит локальный фильтр (стоп-слова, ваши исключения, маркеры роли).
- Браузер открывает карточку, читает описание и рейтинг компании.
- В Telegram приходит превью.
- Вы жмёте «Сгенерировать письмо» (LLM) → при необходимости правите текст → «Откликнуться» или «Пропустить».
На карточке без письма две кнопки: «Сгенерировать письмо» и «Пропустить». После генерации — текст письма и «Откликнуться» / «Изменить письмо» / «Пропустить».

Рис. 1. Превью без письма. Внизу клавиатура: Пауза, Продолжить, Отклики, Ожидают.
Реальный отклик возможен только при трёх условиях сразу: режим approval, флаг ENABLE_REAL_APPLY=true и нажатие кнопки вашим Telegram ID.
Почему LLM не оценивает каждую вакансию
Допустим, за цикл нашлось ~40 вакансий по запросам, после фильтра заголовка осталось ~12 карточек, письмо вы запросили по 3.
| Подход | Вызовы LLM | Итог по токенам |
|---|---|---|
| Оценка + письмо на каждую | ~40 оценок и часто письма сразу | дорого, особенно на reasoning-моделях |
| Этот форк | 0 оценок в цикле + письма по кнопке | токены только на выбранные отклики |
Фильтр и просмотр глазами закрывают основной отсев. Модель нужна для текста письма, а не для сотен авто-вердиктов suitable.
Установка
Нужны: Python 3.11+, Telegram-бот и ваш User ID, браузер (CloakBrowser или Playwright), LLM — если будете генерировать письма (Ollama / Mistral / OpenAI-compatible вроде Together).
git clone https://github.com/google-dad/hh-ai-agent-advance.git
cd hh-ai-agent-advance
py -3.12 -m venv .venv
.\.venv\Scripts\activate
pip install -r requirements.txt
python setup_wizard.py
python main.py --check-config
python main.py --check-llm
python main.py
Wizard создаст локальные .env и profile.yaml (в Git их нет). Правки позже: python setup_wizard.py --edit или руками в YAML.
Режимы:
| Режим | Поведение |
|---|---|
dry_run |
Поиск и карточки без кнопок отклика — начните с него |
approval |
Можно генерировать письмо и откликаться после вашей кнопки |
Telegram-бот
Бот — отдельный аккаунт в Telegram, через который скрипт шлёт карточки. Создаётся один раз, токен и ваш User ID попадают в .env.
- Откройте @BotFather и отправьте
/newbot. Задайте отображаемое имя и username (должен заканчиваться наbot). В ответ придёт токен вида123456789:AA.... - Узнайте свой числовой User ID: напишите что угодно @userinfobot. Это не username — бот отвечает числом.
- Привяжите бота к скрипту.
python setup_wizard.pyспрашивает токен и User ID и записывает их в локальный.env. Вручную — те же поля:
TG_BOT_TOKEN=123456:your_bot_token
TG_USER_ID=your_numeric_id
- Запустите
python main.pyи напишите своему боту/start. Карточки и кнопки отклика принимает только этотTG_USER_ID: чужой чат с ботом отклик не отправит.
Повторная правка токена или ID: python setup_wizard.py --edit. Файл .env в git не коммитьте.
Настройка profile.yaml
Специальность задаётся не «режимом SEO», а содержимым профиля: запросы поиска, резюме, стоп-слова, текст о себе для писем.
Обязательное
| Поле | За что |
|---|---|
candidate.name |
Имя в промпте письма |
candidate.desired_positions |
Целевые роли для письма (не строки поиска HH) |
candidate.experience_summary |
Опыт — основной блок фактов для LLM |
hh.resume_name |
Точное имя резюме в селекторе HH при отклике |
hh.search_queries |
Запросы, по которым агент ищет вакансии |
Поиск и отсев
| Поле | За что |
|---|---|
hh.areas |
ID регионов HH (1 Москва, 2 СПб). [] — без геофильтра. Не писать «Москва» текстом |
hh.experience_filters |
noExperience / between1And3 / between3And6 / moreThan6 или [] = любой опыт |
candidate.work_format |
Если есть «удалённо» или remote — в поиск уходит schedule=remote |
candidate.excluded_positions |
Доп. стоп-слова в заголовке (стажёр, junior, нерелевантные роли) |
cover_letter.max_length |
Лимит символов письма (у HH поле до ~10 000) |
cover_letter.language / style |
Язык и тон письма |
Полный список полей — в README и в profile.example.yaml с комментариями.
Фильтр заголовка в коде (vacancy_filter.py) по умолчанию заточен под маркеры SEO-ролей и типовой «мусор» (SMM, таргет, продажи…). Для другой специальности:
- пропишите свои
search_queriesиexcluded_positionsв профиле; - при необходимости поправьте списки
ROLE_KEYWORDS/BLOCK_WORDSвvacancy_filter.pyпод ваши маркеры роли (иначе заголовки без этих маркеров уйдут вno-role).
Пример: SEO (мой профиль)
Фрагмент идей для profile.yaml (без персональных данных и секретов):
candidate:
desired_positions:
- "SEO-специалист"
- "SEO Team Lead"
- "Линкбилдер"
work_format:
- "удалённо"
excluded_positions:
- "Junior SEO"
- "Стажёр"
- "SMM-менеджер"
- "Таргетолог"
hh:
resume_name: "SEO-специалист"
search_queries:
- "SEO-специалист"
- "SEO Team Lead"
- "линкбилдер"
- "техническое SEO"
- "PBN"
areas: []
experience_filters: []
cover_letter:
language: "ru"
max_length: 8000
style: "professional"
Для другой роли меняете запросы и стоп-слова, например: Python developer, аналитик данных, продуктовый менеджер — та же схема.
LLM для писем
На отбор в цикле поиска модель не влияет. Нужна для кнопки «Сгенерировать письмо», /keys и --check-llm.
- Ollama — локально, без облачных ключей
- Mistral / OpenAI-compatible (Together, Groq…) — пул ключей через
/keysв Telegram
Пример Together в .env (значения — плейсхолдеры):
LLM_PROVIDER=openai_compatible
LLM_MODEL=openai/gpt-oss-120b
OPENAI_COMPATIBLE_BASE_URL=https://api.together.xyz/v1
OPENAI_COMPATIBLE_API_KEY=your_key
LLM_KEYS_MASTER_KEY=your_fernet_master_key
LLM_TIMEOUT_SECONDS=90
LLM_MAX_OUTPUT_TOKENS=4000
У reasoning-моделей часть токенов уходит во внутренние рассуждения — для писем держите LLM_MAX_OUTPUT_TOKENS с запасом (~3500–4000).
Использование день за днём
- Запускаете
python main.py, в HH при необходимости логинитесь (BROWSER_HEADLESS=false). - Ждёте карточки в Telegram (
/status,/diagnostics— состояние цикла). - Ненужное — «Пропустить». Интересное — «Сгенерировать письмо», читаете, правите, «Откликнуться».
- Пауза поиска:
/pause//resume. Очередь решений:/pending.
Если карточек нет: логи — отсев по заголовку, дубли в agent.db, пауза, circuit breaker. Перед «чистым» прогоном остановите агент и сделайте backup базы.
Команды: /start, /status, /pause, /resume, /pending, /stats, /diagnostics, /keys, /cancel.
Кому подойдёт — и когда нет
Подойдёт, если вы:
- любой специальности и готовы один раз настроить запросы и фильтр под себя;
- хотите автопоиск и превью в Telegram, а отклик — под контролем;
- не хотите жечь LLM на оценку каждой строки выдачи;
- ок с Python и браузерной автоматизацией.
Не подойдёт, если нужно:
- полностью безголовая массовая рассылка откликов;
- гарантия обхода детекта, CAPTCHA и ограничений HH;
- замена чтению вакансии и письма перед отправкой.
Автоматизация HH.ru может нарушать правила сервиса. Риск для аккаунта — на вас. Используйте как ассистента с approval, не как пушку по рынку.
Ссылки
- Форк: github.com/google-dad/hh-ai-agent-advance
- Апстрим: github.com/fikstt2/hh-ai-agent
- Бот: @BotFather, свой ID: @userinfobot
Токены Telegram, API-ключи и личный profile.yaml держите вне git. В статье секретов нет.
Связанное
Связанные Tools
HH AI Agent — Python-агент для HH.ru — поиск вакансий, превью в Telegram и отклик только после вашей кнопки.