Я автоматизировал поиск работы, сделал 553 отклика за три недели и сходил на собеседования

В сентябре я начал искать работу, роль COO или CTO, или DevRel и тд. И сделал то, что делаю со всеми своими задачами: отдал рутину агентам.

За три недели мои агенты нашли 10 687 вакансий в 2 204 компаниях и довели 553 отклика до кнопки «отправить». Из них мне были назначены 3 собеседования, которые я прошел.

Если честно, я в шоке как устроен найм в 2026 году: с обеих сторон стола сидят роботы

Как выглядит найм.

Раньше я представлял поиск работы так: нашёл вакансию, отправил резюме, получил ответ. Теперь между мной и живым человеком на той стороне — три слоя автоматики.

Первый слой это системы приема откликов, ATS. Почти все отклики ушли в две системы: Greenhouse и Ashby — это 96% всех отправленных откликов

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

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

Я строил автоматизацию под первый слой, но, само собой, сложности во втором и третьем

Откуда берутся вакансии и где их искать самому

Никакого волшебства в поиске вакансий, конечно же, нет: почти все компании держат вакансии в какой-то из систем найма, и у каждой из них есть открытый адрес, который отдаёт список вакансий обычным текстом. Ни логина, ни ключа, ни браузера не нужно.

Вот эти адреса, подставьте вместо скобок имя компании:

Greenhouse       https://boards-api.greenhouse.io/v1/boards/{company}/jobs
Ashby            https://api.ashbyhq.com/posting-api/job-board/{company}
Lever            https://api.lever.co/v0/postings/{company}?mode=json
Workable         https://apply.workable.com/api/v1/widget/accounts/{company}
SmartRecruiters  https://api.smartrecruiters.com/v1/companies/{company}/postings

Имя компании берётся из адреса её страницы с вакансиями. Сейчас в карте 397: Ashby 206, Greenhouse 139, Lever 42, Workable 9, SmartRecruiters 1. Список я собрал автоматически и каждую такую доску проверил живым запросом, про способ проверки — чуть ниже.

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

Himalayas   https://himalayas.app/jobs/api
Remotive    https://remotive.com/api/remote-jobs
Jobicy      https://jobicy.com/api/v2/remote-jobs
Arbeitnow   https://www.arbeitnow.com/api/job-board-api
RemoteOK    https://remoteok.com/api

Плюс два потока новостями: вакансии с Hacker News из ежемесячной ветки «Who is hiring» и русскоязычные Telegram-каналы с вакансиями.

Не получилось (пока) у меня настроить сбор информации с Reddit, он без регистрации приложения отвечает отказом, у ai-jobs.net публичного потока я не нашёл, и не получилось (опять же, надеюсь, пока) с CryptoJobsList Но все такие источники я записываю в отдельный список, чтобы к ним потом вернуться

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

Сколько чего пришло:

источник

объявлений

Greenhouse

4 265

Ashby

3 143

Himalayas

1 193

Telegram-каналы

877

Lever

471

Arbeitnow

386

Jobicy

145

Hacker News

129

Workable

67

RemoteOK

11

За три недели так набралось 10 687 объявлений от 2 204 компаний. Из них 7 946 это вакансии на настоящих платформах, страницах, куда можно подать отклик, а остальные 2 741 пришли с агрегаторов, из Telegram и с Hacker News, где формы обычно нет и её ещё надо отдельно найти на сайте компании.

Как я искал компании, в которых могли быть вакансии

У Greenhouse, Ashby и Lever есть открытые доски: список вакансий компании оттуда забирается обычным запросом, без браузера. Но чтобы такой запрос сделать, нужен адрес доски, а в нём помещено короткое имя компании.

У Lever это выглядит как api.lever.co/v0/postings/<имя>, у Greenhouse как boards-api.greenhouse.io/v1/boards/<имя>. Имя почти никогда не совпадает с названием компании: бывает без пробелов, бывает со старым названием до ребрендинга, бывает вообще внутреннее.

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

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

То есть искать надо не по названиям компаний, а по самой строке адреса. Поиск по коду GitHub умеет это прямо из командной строки.

# запрос к поиску по коду → достаёт имя компании из найденного куска
QUERIES = [
    ("lever", '"api.lever.co/v0/postings"',
     r"api.lever.co/v0/postings/([A-Za-z0-9._-]{2,40})"),
    ("greenhouse", '"boards-api.greenhouse.io/v1/boards"',
     r"boards-api.greenhouse.io/v1/boards/([A-Za-z0-9._-]{2,40})"),
    ("ashby", '"api.ashbyhq.com/posting-api/job-board"',
     r"api.ashbyhq.com/posting-api/job-board/([A-Za-z0-9._-]{2,40})"),
]

Дальше четыре шага:.

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

Второй: выкинуть весь мусор. В примерах кода вместо настоящего имени стоит test, demo, acme, your_company, и таких совпадений находится много.

Третий: сверить с тем, что я уже знаю, и не проверять это заново.

Четвертый: сделать живой запрос к каждому. Ко мне в итоге попадают только те, кто ответил непустым списком вакансий, всё остальное уходит в отдельный список (список отбракованных)

Про третий шаг. Сначала я сверял то, что нашел, только со списком досок, которые и так мониторил, но этого недостаточно В один из моих таких прогонов из 189 найденных живых досок 121 оказалась теми, которые я неделю назад уже проверял, и они — пустые… Поэтому теперь у меня идет сверка с двумя списками: и с тем, что я мониторю, и с тем, что уже было отбраковано.

Сейчас в карте 397 живых досок и 196 отбракованных.

Сколько откликов я сделал в результате за это время

Первое, на чём я ошибся, это масштаб. В базе было 9 447 открытых вакансий в 2 133 компаниях, и я посчитал, что это и есть весь мой список

Но у крупных компаний одна доска это сотни позиций. У одной компании было 423 открытые вакансии, у другой 247. Подаваться в одну компанию сорок раз это спам, а не поиск работы.

Поэтому у меня стоит потолок: не больше двух откликов в одну компанию. После него реальная очередь сжалась с 9 447 до 2 707, то есть в 3,5 раза.

-- очередь откликов: не больше двух на компанию, лучшие по оценке
SELECT url, company, title, score
FROM (
    SELECT *,
          ROW_NUMBER() OVER (
               PARTITION BY company
               ORDER BY score DESC
           ) AS rank_in_company
    FROM ats_jobs
    WHERE status = 'new'
)
WHERE rank_in_company <= 2
ORDER BY tier = 'vip' DESC, score DESC;

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

16 резюме вместо одного

Одним резюме на все вакансии не откликнешься. Роль в продукте, в работе с клиентами и в развитии экосистемы — это разные оттенки опыта, и рекрутер в каждом резюме ищет только то, что релевантно его компании

Я разделил вакансии на 16 типов и под каждый тип у меня есть отдельная версия резюме. Все версии собираются из одного моего файла с фактами биографии: я поправляю какую-то информацию в нем один раз, а дальше скрипт пересобирает все резюме и лендинг.

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

Как агент заполняет форму

Сама подача моих резюме устроена следующим образом: браузер под управлением скрипта открывает форму, заполняет поля и нажимает «отправить».

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

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

Где всё останавливается

Робот открыл 1 127 форм. 553 из них дошли до кнопки «отправить», 575 остановились на полпути (остальные вакансии из базы просто еще ждут своей очереди)

причина остановки

форм

вопрос без канонического ответа

383

капча на отправке

132

форма вернула ошибку

29

нажал «отправить», подтверждения нет

23

прочее (дубль, аккаунт, код из письма)

8

⅔ таких стопов — это вопросы, которые требовали моего внимание. Часто такие:

  • годовая зарплата в конкретной валюте, числом, без диапазона;

  • тестовое задание, ссылку на которое надо вставить прямо в форму;

  • есть ли у вас или ваших близких родственников интерес в компании-конкуренте или связь с кем-то из её сотрудников;

  • даты окончания каждого места работы, отдельными полями.

Выводы я тут делаю о том, что формы — это те еще двери. В них надо уметь проходить.

Экран «Спасибо за отклик»

Еще один вывод был о том, что влияло на мою статистику

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

Я сейчас у каждого отклика ставлю отметку, чем он доказан:

чем доказан отклик

откликов

письмо-подтверждение от ATS

188

только экран успеха формы

144

пока ничем (старые записи, сверка идёт)

221

Сверку у меня делает отдельный скрипт без обращений к LLM. Он идёт по отметкам в базе и ищет для каждой письмо в почте:

def verdict(job, emails):
    """Чем доказан отклик: письмом ATS, а не экраном формы."""
    mine = [e for e in emails
            if job.company.lower() in (e.subject + e.sender).lower()
            and e.date >= job.applied_at]
    if any(is_confirmation(e) for e in mine):
        return "PROVEN"            # письмо «Thank you for applying» пришло
    if any(is_security_code(e) for e in mine):
        return "STALLED"           # система прислала код, форма его не получила
    return "NO_PROOF"              # подавать заново

Отдельно надо принимать в расчет мелочи. Например, название компании иногда стоит не в теме письма, а только в поле отправителя. А письма «новый вход в аккаунт» похожи на подтверждения, но ими, конечно, не являются.

Какие у меня результаты

За три недели картина такая:

что

сколько

доля от откликов

откликов дошло до отправки

553

100%

отказов

79

14%

собеседований (компаний)

3

0,5%

пока без ответа

470

85%

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

Все три собеседования дали вакансии так назовем «массового» уровня: компании среднего размера. В «VIP»-уровень, крупные лаборатории, я отправил 63 отклика и получил 10 отказов и пока ни одного собеседования.

И все эти три собеседования на вакансии инженера, который работает прямо у клиента (forward deployed engineer), и на работу с сообществом разработчиков (DevRel). По продуктовым ролям, куда отправилось больше всего откликов, собеседований пока ноль.

Для меня это полезный вывод. Автоматизация показала, в какую дверь рынок меня пускает, а в какую нет.

Во что превратился найм

Теперь я смотрю на найм конечно иначе, чем месяц назад.

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

Отбор сдвинут с резюме в форму. Вопросы про зарплату, родственников и тестовое задание — это первый отсев, отбор еще до того, как на кандидата обратит внимание живой человек из компании

Экран «спасибо» не гарантирует получение резюме.

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

Сейчас я жду вторых этапов собеседований и продолжаю свой поиск работы.

Автор: Antondz

Источник

Оставить комментарий