симулированное общество ботов, в котором половина — твои сотрудники, половина — приманка, а реклама вшита в биографии так, что они её сами генерят. живут все в вконтакте — это и стартовая, и единственная (пока) платформа выгрузки.
идея в одной фразе
не «стая ботов которые постят», а симулированное общество: персонажи с лором, дрейфующими настроениями, своим графом подписок, дневниками, дм-перепиской, фотками с котами — и встроенным рекламным контуром, который подсвечивает что нужно без отдельного скрипта. вся жизнь стаи происходит в вк — личные стены, паблики, беседы, комменты под видео и в группах.
где они живут: вконтакте
почему вк, а не твиттер/тт/инст: самая ленивая модерация ботов в рунете, открытое api с long-poll и callback, в нём ещё реально купить отлежавшийся аккаунт с историей, и аудитория там читает «личные стены» как ленту — то что нам и надо.
группа / публичная страница (мама-в-декрете, обзоры стартапов, злая в твиттере → «злая в вк»)
лайки / репосты
likes.add, wall.repost между ботами и в чужих постах
дм между ботами
messages.send в личке, плюс «беседы» 3–5 ботов
срач в комментах
wall.createComment под постами конкурентов и в популярных пабликах
симуляция жизни
сторис (stories.getPhotoUploadServer), смена аватара, «слушает сейчас», чек-ин в место
визуал
фотоальбомы («лето 2024», «мой кот», «дача у бабки»), photos.save
аккаунты: часть — самореги с прогревом (имя + ава + 3 поста + друзья из своей же стаи), часть — отлежавшиеся купленные (для «звёзд» и для пробития модерации в чужих пабликах). у каждого свой токен (vk_user_token со scope wall, photos, messages, groups, stories) или group_token для пабликов. токены хранятся в отдельной таблице vk_accounts с привязкой к agent_id.
прокси: один айпи на 2–3 аккаунта, мобильные/резидентные. иначе вк связывает их в один кластер и выкашивает пачкой при первой же жалобе.
что отвечает за «руки»: отдельный модуль vk_hands — тонкая обёртка над vk api, который принимает decision от тикера (post / reply / like / dm / story) и кладёт его в реальный вк. в локальной sqlite остаётся зеркало (post_id ↔ vk_post_id) — чтоб лента в jinja показывала то же что в вк, и чтобы отвечать на реальные комменты живых людей через long-poll.
api
vk api v5.199, long-poll для входящих, callback api для пабликов
rate-limits
~3 req/s на токен → жёсткий шедулер, jitter, очередь на агента
антибан
человеческие паузы между действиями, не более N постов/день/агент, не лайкать пачкой, не репостить из одного источника подряд
риск
высокий вк может выкосить всю стаю одним кластером — отсюда прокси, разный фингерпринт, разные клиенты (kate mobile / vk official / web)
слои системы
ядро
мозг агента (платформо-незав.)
«человек»: характер + цель + список возможностей. НЕ знает что он в вк — выбирает действие, драйвер исполняет. меняем платформу — мозг тот же
щит
антибан-слой
капча-резолвер + flood-ретраи + прокси/авиарежим + shadow-радар прямо в драйвере. пункт ноль — без него стая ляжет на первой пачке
кто на кого подписан, дружбы, бывшие одноклассники, лайки и тихие фолловы
слой 3
планировщик жизни
не общий крон — каждый агент в конце хода сам ставит, когда проснуться снова и зачем. очередь по времени, будит того, чьё время пришло, в его тз
слой 4
рекламный контур
campaigns с тоном, аудиторией, тейками — подмешиваются в контекст агента с малой вероятностью
слой 5
симуляция жизни
дни рождения, праздники, развелась, уехала в тай, «возвращаюсь после паузы»
слой 6
руки = драйвер платформы
vk_hands сейчас (токены, прокси, шедулер, выгрузка в вк). завтра tg_hands / insta_hands — реализуют тот же интерфейс возможностей, мозг не трогаем
слой 7
витрина
fastapi + jinja: локальная лента-зеркало (то же что в вк) + профиль агента, для дебага и взгляда «как у нас идёт»
слой 8
цифр. отпечаток
клиент вк, суточный ритм, скорость печати, эпоха речи, эмоджи-набор, опечатки — разные у каждой персоны, чтобы стая не звучала «одним голосом»
слой 9
оборот стаи (лёгкий)
кто-то затихает → на его место через своих приходит новый, наследует кусок графа. без сложного автомата — просто чтобы стая не была консервами на 5 лет
слой 10 v8
внутренний редактор
вторая дешёвая llm читает пост ДО отправки и режет llm-теллы: тройные эмоджи, «к сожалению», em-dash, «как ассистент…», вылезшие извинения. без него рано или поздно выползет «прошу прощения, я не могу обсуждать политику» из мамы-в-декрете
слой 11 v8
языковая эволюция
общий словарь стаи дрейфует во времени: в 2026 «краш» alive, к 2028 fading, в 2030 cringe. бот тянет слова с учётом цифрового возраста. без этого стая через год говорит как капсула 2026
слой 12 v8
кризис-режим
когда вк за ночь выкосил 20–30% — парковка остатков в read-only, разбор кластера палева, частичная эвакуация контента в тг-канал по абстракции мозг≠руки. не «если», а «когда»
слой 13 v8
контакт с живыми
исходящие касания реальных людей: правила лайков, комментов и фолловов. не первой, не каждый пост, не подряд, не под кем попало. вторая по жирности дыра после редактора
карта слоёв. ядро — мозг; вокруг — персона, движок, защита/качество и бизнес; всё обёрнуто антибан-щитом. красным — то, без чего стая ложится на первой пачке.
мозг ≠ руки: агент не знает, что он в вк
ключевая абстракция, чтобы не переписывать всё при переходе на инсту/тг. мозг агента — это «человек»: характер + цель + список того, что он сейчас умеет. он НЕ знает названий wall.post и вообще того, что живёт в вк. он выбирает абстрактное действие («выложить пост», «ответить вот этому», «лайкнуть», «залить сторис») из своего списка возможностей — а как превратить это в реальный апи, решает драйвер.
мозг ≠ руки. агент выбирает абстрактное действие из своих возможностей; драйвер платформы превращает его в реальный апи. смена платформы = новый драйвер, лор/память/граф не трогаем.
список возможностей зависит от платформы. в вк есть сторис, репост, беседы; в тг-канале лайков-как-в-вк нет, зато реакции и комменты в обсуждении. мозг получает capabilities[] = что доступно ЗДЕСЬ и выбирает только из них.
драйвер тонкий. принимает {action, args}, переводит в реальные вызовы (post → wall.post; на тг → sendMessage) и отдаёт назад единый результат (id, ссылка, ошибка/капча).
новая платформа = новый драйвер + новый список возможностей. лор, память, граф, mood, расписание — НЕ трогаем. одна персона может жить сразу в вк и тг: мозг один, руки разные.
персонаж = строка в БД + промпт
каждый бот — это не аккаунт, это персона. лор лежит в длинном json и подмешивается в каждый промпт, чтобы агент был консистентен на годы.
identity
имя, возраст, город, профессия, акцент речи
регион / тз
город привязан к реальному часовому поясу (мск UTC+3, екб +5, новосиб +7, владик +10) — от него зависит когда персона онлайн и постит. вся стая в РАЗНЫХ поясах
биография
детство, школа, переезды, работы, бывшие, текущий партнёр
домашка
кот по кличке, аллергии, привычки, любимая чашка
взгляды
политика (которую не говорит вслух), мнение про инфоповоды
контент-роль
мама-в-декрете / крипто-обзорщик / злая в твиттере / новостник
ритм
постит ежедневно / раз в три недели / только мемы по пятницам
визуал
фотоархив у каждого свой объём (от 0 до сотен), по годам с проставленными датами — не «5–10 у всех»
раньше тут был один глобальный крон, будивший по рандому кого попало — так нельзя: вся стая просыпается, когда проснулся мой процесс, и постит в одни часы = кластер. правильно — каждый агент сам ставит, когда ему проснуться снова и зачем. в конце хода он решает не только «что делаю сейчас», но и «когда заглянуть в следующий раз и что проверить»: через 3 часа — лайки под постом, завтра утром — ответить Маше, в пятницу — выложить мем. задачи формируются на лету, не зашиты заранее. планировщик держит очередь по времени и будит того, чьё время пришло, в его тз. глобальный тик остаётся фоном для спонтанного «зашёл полистал ленту».
цикл одного хода. сердцебиение системы: проснулся → собрал контекст → подумал → редактор → (гейт) → руки → стая поддержала → сам назначил следующий заход. глобального крона нет.
while True:
sleep(jitter(2..5 min))
# 1. задачи, чьё время ПРИШЛО — агент сам их себе поставил в прошлый ход
due = tasks.pop_due(now) # [(agent, intent), ...]
# 2. + изредка спонтанная жизнь: разбудить активного просто «полистать»
if roll(prob=0.15):
due += [(weighted_pick(awake_now()), "scroll")]
for agent, intent in due:
ctx = {
"bio": agent.bio,
"mood": agent.mood_state,
"intent": intent, # ← ЗАЧЕМ проснулся
"feed": last_10_posts_from(agent.follows),
"trend": ingest_vk_news(agent.interests), # ← реальный инфоповод
"ad": maybe_inject_campaign(prob=0.07),
"life": pending_life_event(agent),
"facts": self_facts(agent), # ← что про себя УЖЕ говорил
"lex": lexicon_for(agent), # ← слова его эпохи (v8)
"can": agent.capabilities, # ← что умеет на ЭТОЙ платформе
}
# мозг НЕ знает про вк — выбирает абстрактное действие из can[]
out = brain(ctx, schema={
action, # post / reply / like / dm / story / scroll / skip
args, # target_id?, text?, media?
next_wake, # ← КОГДА проснуться снова (через 3ч / завтра 9:00)
next_intent, # ← и ЗАЧЕМ (проверить лайки / ответить Маше)
})
# v8: ВСЁ что текст, идёт через редактора. live touch — через outreach-гейт
out = editor.scrub(out, agent) # ← anti-llm-tells, слой 10
if out.action in {"like","comment","follow"} and target_is_real(out):
if not outreach_gate.allow(agent, out): # ← правила касания живых, слой 13
continue
apply(out) # в локальную бд
hands.dispatch(out) # драйвер платформы (vk_hands) → реальный апи
if out.action == "post":
boost_from_swarm(agent, out) # пара своих лайкнут/поддержат с разбегом
tasks.push(agent, out.next_wake, out.next_intent) # ← сам себе будильник
drift_mood(agent, out)
┌──────────────────┐
│ tasks │ очередь самопланирования (каждый сам себе будильник)
├──────────────────┤
│ id │
│ agent_id │
│ run_at │ ← когда проснуться (в тз агента)
│ intent │ ← зачем: check_likes / reply / post_story / scroll
│ payload │ ← ссылка на пост/диалог, если действие к чему-то привязано
│ done │
└──────────────────┘
параллельно работает vk_listener: long-poll по токенам персон + callback по пабликам. ловит входящие комменты/дм/упоминания от живых людей, кладёт в vk_inbox и тут же ставит задачу агенту (tasks, run_at ≈ через человеческую паузу) — тот ответит «как самой себе пришло» в свой ближайший тик, а не мгновенно (мгновенный ответ = палево).
антибан — щит стаи пункт ноль
это не фича на потом, а условие жизни. вк кидает капчу и «подтвердите действие/номер» едва ли не на каждое второе авто-действие, ловит flood-rate и связывает аккаунты в кластер. без этого слоя стая ляжет на первой же пачке постов — раньше любого m3. поэтому антибан вшит прямо в драйвер (vk_hands), а не прикручен сбоку: каждое действие проходит через гейт.
капча-резолвер
capmonster / anti-captcha: ловим captcha_sid + captcha_img из ответа вк → решаем → ретраим запрос с captcha_key. без резолвера действие просто теряется
flood / rate
FloodWait и «too many requests» → экспонента + jitter, очередь на агента, не долбить. лимит N действий/день/агент, не лайкать и не слать пачкой
подтверди действие
вк просит подтвердить номер / «это вы?» → флаг needs_verify в БД, агент паркуется, алерт мне (смс-резолвер или руками). не молотим в стену
прокси 1 ↔ 2-3
мобильные/резидентные, один ip на 2–3 акка. + «авиарежим»: ротация ip у мобильных (вкл/выкл сети), когда подсеть запахла
фингерпринт
разный клиент (kate / official / web), user-agent, суточный ритм, эпоха речи — чтоб вк не схлопнул стаю «одним почерком» (см. слой цифрового отпечатка)
холодный старт
не 5 свежих акков, дружащих только между собой (= бот-кольцо). разносим даты регистрации, разбавляем граф мёртвыми реальными, прогрев 2–3 недели до первого пиара
shadow-радар
следим за охватом/лайками своих постов. резко просел = теневой бан → агент уходит в тишину/прогрев, не усугубляет
человеческие паузы
задержки между действиями, «печатает…», не мгновенный ответ, не круглосуточная активность — только в свои prime_hours
правило: любое авто-действие проходит через антибан-гейт — проверка account_health (не во флуд-холде? не ждёт верификации?), исполнение, и при капче/ошибке — резолв или парковка. ни один тик не дёргает vk api в обход. это вшиваем до первого реального постинга, не после.
внутренний редактор — anti-llm-tells слой 10
самое жирное палево это не аватарка и не прокси, а почерк llm. модель оставляет следы которые человеческим глазом ловятся за секунду: трипл-эмоджи 🎉🎊✨, em-dash там где живой ставит дефис или ничего, «к сожалению», «безусловно», «важно отметить», бескомпромиссные тройки абзацев одинаковой длины, и финальное «надеюсь это поможет». а самое страшное — вылезшее «как ассистент я не могу обсуждать политику» из под мамы-в-декрете → весь домик в один пост рухнет.
лечится вторым проходом дешёвой моделью: пост из brain не уходит в hands напрямую, а сначала идёт в editor.scrub(text, agent). редактор знает голос персонажа (era, emoji_set, typo_rate из digital_fingerprint), знает чёрный список tells, и возвращает три варианта вердикта: pass / rewrite / block.
tells (чёрный список)
регексы по эмоджи-кластерам, оборотам, тире, длинам абзацев, фразам-маркерам llm («certainly», «как ассистент», «прошу прощения», «к сожалению я не могу», «надеюсь это…»). список расширяется по мере отлова в логах
voice-checker
сверка: эмоджи только из fingerprint.emoji_set; эпоха речи совпадает с fingerprint.era; typo_rate в норме; длина и рваность под персонажа (мама — длинно и эмоционально; злая — рваные обрывки)
cenzura-strip
вшитая в модель «я не могу про политику / насилие / NSFW» вылетает в текст → удаляем нафиг или подменяем на «отказ в голосе персонажа» (злая — «не буду, мне лень спорить», эзотерик — «луна не в той фазе»)
verdict pass
текст чистый, идём в hands
verdict rewrite
пара tells — даём editor.rewrite(text, voice) переписать конкретные куски (не весь пост), сравниваем длину и тон с оригиналом
verdict block
слишком много tells / явная цензурная утечка / промпт-инъекция в тексте → выкидываем пост, агент не постит этот ход, лог в editor_runs для разбора
модель редактора — дешёвая (haiku или ollama-llama локально), потому что прогоны идут на каждый пост и коммент стаи. если она дороже чем основная модель — экономика рушится. лог в editor_runs = ценный материал: чем чаще ловим tells, тем больше регексов добавляем — система самообучается за месяц.
важно: редактор работает не только на постах, но и на комментах и дм. дм самое опасное — там короткие реплики, и «certainly» в одной из них сразу палит. в коротких сообщениях правило строже: ноль tells, иначе block.
языковая эволюция стаи — словарь дрейфует слой 11
llm-ы выучены на срезе данных. без дополнительного слоя вся стая говорит как 2026 год вечно — через год она звучит как капсула времени, и алгоритмы заметят это раньше чем живые. лечится словарём со статусом, который меняется со временем.
отдельная таблица lexicon хранит токены (слова, фразеологизмы, эмоджи-комбо, оформление) с тегами и эпохой. статусы:
статус не статичен. демон lexicon_keeper раз в неделю (или подцепляясь к flash_event-ам — мем дня) двигает токены по таймлайну: что было alive полгода, переходит в fading; fading ещё через полгода — в cringe. новые токены прилетают двумя путями: (1) ингест из реальных трендов вк-news/тт-mirror, (2) если конкретный мем разлетается среди наших ботов внутри (взаимное цитирование) — он сам котируется как new → alive.
подбор для агента
из digital_fingerprint.era + возраст + контент-роль = функция lexicon_for(agent) возвращает разрешённый словарь. молодая возьмёт что-то из new+alive, тётка — alive+fading, дед — fading+cringe (не зная что это cringe)
подмешивание
в контексте brain раздел lex — 5–10 актуальных для персонажа слов с примерами употребления. НЕ «обязательно использовать» — а «вот твой словарь, если по теме»
кросс-чек редактора
слой 10 проверяет: если в посте есть слово со статусом cringe у молодой персоны = rewrite. если у деда new = тоже rewrite (он не знает таких слов)
логирование
lexicon_use: какой агент когда какое слово употребил → видно дрейф по времени и кто чем «заразился»
парная динамика
если две персоны часто переписываются — у них пересекается словарь (как у живых пар/подруг). без этого тётка и её подруга говорят на разных эпохах подряд = неестественно
фишка: словарь у стаи один, но разрезы по эпохам — разные. это даёт визуальное доказательство «живого мира» — кто-то отстаёт, кто-то задаёт тренд, кто-то говорит как в 2014. без этого слоя все боты — выпускники одного учебного набора.
кризис-режим — план эвакуации слой 12
не «если», а когда. вк выкосит 20–30% стаи за ночь — это базовый сценарий, к которому надо быть готовым. сейчас антибан-щит описан как профилактика, а что делать после массового бана — нет. это и закрываем.
триггер кризиса — формальный: crisis_watch (мини-демон, тикает раз в час) считает за последние 12 часов количество ban_events.kind in {ban, shadow, verify}. как только превышен порог (например, >15% активных), поднимается флаг crisis_mode=true. от него всё дальнейшее.
что делает кризис-режим (по шагам)
parking — все ОСТАВШИЕСЯ переводятся в read-only: ни постов, ни лайков, ни дм. брейн продолжает «думать», но hands.dispatch игнорит. это первое — потому что массовый бан часто продолжается в реальном времени, и каждое новое действие добивает остатков
cluster diag — собираем убитых в crisis_log.losses и ищем общее: прокси (одна подсеть?), дата регистрации (одна неделя?), паттерн постинга (одни часы?), общий «друг»-вектор, общий device_hint, общая lora-аватарка. ищем что палит, иначе следующая партия повторит маршрут
verdict — три варианта:
lockdown: парковка 7–14 дней, потом разморозка по чуть-чуть. подходит когда выкосило по фингерпринту, и проблема устранима (поменять прокси / клиент / часы)
partial_evac: критичный контент (паблики звёзд, кампании которые горят по deadline) переезжает в тг-канал/дзен через абстракцию мозг≠руки. для этого tg_hands уже должен быть готов хотя бы базово — это и есть отложенный возврат инвестиций в слой 6
burn: оставшиеся в этом кластере сжигаются добровольно (драматический выход / «удаляю вк»), их граф наследуется новыми персонами через succession. полезно когда подсеть/кластер настолько горячий что лучше выйти с достоинством
regroup — генерация замены: новые персонажи в других прокси-пулах, других регионах, других device_hint. наследуют куски графа уцелевших через succession, но НЕ повторяют выявленный паттерн
cool-down — после возврата к норме держим вдвое более жёсткие лимиты на 30 дней. shadow-радар — на максимальной чувствительности. это окно реабилитации стаи в глазах модерации
crisis_watch (раз в час)
│
│ считает ban_events за 12ч → если >15% активных
▼
crisis_mode = true
│
├─► parking: hands.dispatch(*) → no-op для всех
├─► cluster_diag(losses) → найти общий маркер
├─► verdict(loss_kind, severity) → lockdown | partial_evac | burn
├─► regroup(): new agents в других прокси/регионах через succession
└─► cool_down 30 дней (жёсткие лимиты, чувствительный shadow-радар)
↓ когда условия нормализовались
↓ crisis_mode = false, лимиты возвращаются к норме
почему это работает только если мозг≠руки сделан заранее. partial_evac — это перенос лора и графа на другую платформу за минуты, не за дни. если мозг привязан к vk-апи — эвакуации не будет, будет просто пожар. поэтому слой 12 нельзя строить отдельно от слоя 6, и tg_hands надо собирать хотя бы как «холодный заменитель» уже к m4–m5, не к m7.
что НЕ делает кризис-режим: не пытается «спасти» убитых. в вк забаненный аккаунт почти всегда невозвращаем, и попытка достать его — повод для нового бана. убитые уходят в lifecycle.state=banned, их граф через succession переезжает к новым. жалеть нечего, чем быстрее переключились — тем меньше потерь.
правила контакта с живыми людьми слой 13
сейчас в архитектуре описан только входящий контур: vk_listener ловит комменты/дм от живых, ставит задачу агенту — тот отвечает с задержкой. исходящие касания живых (лайкнуть пост живого, прокомментировать, добавить в друзья, упомянуть) — не регламентированы. это вторая по жирности дыра после редактора: замкнутая стая лайкает только сама себя = идеальный кластер для модерации.
отдельный гейт outreach_gate на исходящие к живым. ВСЁ что трогает не-нашего vk_user_id, проходит через него. правила:
не первой
первый лайк на пост живого ставит НЕ наш аккаунт. ждём 2+ живых лайков → только потом можем добавить свой. иначе мы маркер «бот заметил первым»
не каждый пост
от одного нашего аккаунта одному живому — не больше 1 лайка на 5–10 его постов. полный охват = «преследователь»
не подряд
лайки по постам живого с разрывом в часы и дни, не «пробежалась по 10 постам подряд». это считывается мгновенно
cooldown по цели
после касания живого → запись в outreach_log с cooldown_to. этот же агент не может тронуть этого же живого до истечения окна (от 6ч до 7 дней в зависимости от типа действия)
cooldown по агенту
один наш агент делает не больше N касаний живых в день (для звёзд — 5–10, для массовки — 2–5). всё остальное — внутрь стаи. иначе быстрое выгорание
кого можно
whitelist пабликов и тем, где касание уместно. под видосом конкурента в нашей нише — да, под чужим личным горем — нет. список ведём вручную + автомат: если у живого <100 друзей и закрытый профиль — не трогаем
кого нельзя
блогеры с антибот-репутацией; модераторы пабликов; верифицированные; те кто публично жаловался на ботов
контент комментов
если коммент — в голосе персонажа, без агрессии, без рекламы в первом касании, без вопросов-крючков «как тебе?». реклама — только если уже было 3+ органичных касания
фоллов живых
крайне редко и только для звёзд (1–2 в неделю), и только тех с кем уже было касание комментом. фолловы пачкой = смерть
decision из brain
│
│ action ∈ {like, comment, follow, mention}
│ target = vk_user_id
▼
target_is_real(target)? ─── no ──► пропускаем гейт, идём в hands
│ yes
▼
outreach_gate.allow(agent, action, target):
│
├─► not_first_touch? (живые уже лайкнули хотя бы 2)
├─► agent_quota_today? (не превышен N касаний/день)
├─► target_cooldown? (этот агент → этот живой → не в окне)
├─► target_whitelist? (паблик/контекст уместен)
├─► target_blacklist? (не антибот-блогер, не модератор)
├─► content_policy? (для comment: голос + без рекламы в 1-м касании)
│
└─► allow / deny + reason
deny → drop, лог в outreach_log с verdict=deny, разбор
allow → hands.dispatch + лог с cooldown_to
метрики живости касаний. в outreach_log копится статистика: сколько касаний → сколько ответных лайков от живых → сколько разговоров продолжилось → сколько привело к фолловам обратно. если у конкретной персоны конверсия в «ответ от живого» меньше 5% — она палится, её касания живых выключаются и она работает только внутри стаи.
отдельно: фоллов реальными аккаунтами на наших — это уже их сторона. но к нашему агенту прилетает vk_inbox.kind=mention или просто новый фолловер — реакция должна быть как у человека: посмотреть профиль, может через 2–3 дня фолловнуть взаимно, может проигнорить. НЕ мгновенный auto-follow-back — это маркер бота-кольца.
рекламный контур
это не «бот постит баннер». это тейк, вмонтированный в личную историю персонажа — и подаётся из голоса персонажа, под его аудиторию.
персона
как подаст «приложение-стартап X»
мама-в-декрете
«девочки спасайте, нашла приложение которое считает калории за меня, теперь успеваю и поспать»
крипто-обзорщик
«не реклама, но ребята из X сделали то что у Y три года не получается»
злая в твиттере
«окей я была не права про X, попробовала — работает 🤡»
обзоры стартапов
раз в два месяца органично вписывает в дайджест нужного — без выделения
срач в комментах
под конкурентом: «пользовалась год, говно, ушла на X»
таблица campaigns хранит: продукт, тон (нативно / агрессивно / «я просто делюсь»), аудиторию, talking points. тикер при формировании контекста с вероятностью ~5–10% подмешивает «кстати ты на этой неделе попробовала X — упомяни как бы вскользь». палиться нельзя.
дм и «слитые скрины»
между ботами идёт фоновая переписка в дм. иногда из неё «случайно» рождаются скрины, которые один из них постит публично: «смотри что мне подружка скинула, я в шоке». это второй контур прогрева — даёт ощущение что мнение пришло «снизу», а не из паблика.
взаимная поддержка стаи
стая не просто соседствует — она держит друг друга на руках. как только персона постит, оркестратор ставит в очередь нескольких её «друзей» (по графу), и те с разбегом по времени лайкают, иногда репостят, оставляют короткий тёплый коммент в своём голосе.
лайки — 3–8 своих в первые часы после поста (не все разом, не мгновенно), плюс случайные лайки старых записей при «заходе в гости»
комменты поддержки — «оооо красота», «держиись 🤍», «ну ты даёшь», «согласна на все 100» — короткие, в голосе и эпохе речи каждого, не под копирку
репост по поводу — если пост «сильный» (новость, драма, мем), пара своих репостят к себе на стену с подводкой
зачем: (1) алгоритм вк видит ранний всплеск вовлечённости → выносит пост выше → его видят живые; (2) для живого человека страница с тёплыми комментами друзей = «тут реальный круг общения», а не пустой профиль. правило — не одними и теми же словами и не каждый каждому, иначе паттерн палится.
симуляция жизни
дни рождения — друг друга поздравляют, ставят сторис, тегают
праздники — нг, 8 марта, день рождения города — синхронный всплеск постов
биографические события — «развелась», «нашла работу», «уехала в тай на месяц, инет плохой»
периоды молчания — пропала на две недели, потом «привет я живаааа»
пересечения — «встретила Машу на бранче» (Маша — другой бот), обе постят сторис из «одного» кафе
алгоритмы соцсетей такое жрут как родное: длинные диалоги, эмоциональные пики, фото с гео, регулярность. метрики выглядят живыми → бот-контент поднимают выше человеческого → эффект самоподдерживается.
фотоархив — у каждого свой
главное палево «бот-стаи» — это когда у всех по 5 фоток одного качества, снятых в один заход sdxl. лечится просто: объём и стиль фотоархива привязан к персонажу, а не к шаблону. одинаковых не бывает.
тип персоны
аватарок (история)
лайфстайл-фоток
фотоальбомов
тон визуала
мама-в-декрете
12+ (меняет раз в месяц)
200–500
«малыш», «дача», «семья», «до родов», «выписка», «новый год 2022/2023/2024»
живые селфи, размыто, бытовуха, реборн-фильтры
крипто-обзорщик
2 за всё время
10–30
«рабочее место», «бали 2023», скрины графиков
стерильно, минимализм, ноутбук + кофе, никаких людей
злая в твиттере (в вк)
5 (все мемы / арты / без лица)
0–5
нет (закрытые)
демонстративно «я тут не для фоточек», обложки книг, скрины тви
обзорщик стартапов
1 деловая
3–8
«конференции», «офис»
линкедин-стайл, белая рубашка, нейтральный фон
эзотерик-параноик
20+ (часто меняет — лунные циклы, карты таро)
40–80
«алтарь», «лес», «знаки», «сны»
пересветы, странные ракурсы, телефонная плёнка
школьник-мемас
30+ (каждую неделю)
50–150
«пацаны», «двор», «школа», «лагерь 2024»
фронталка, размытое, дёшево, флешка-стиль
дед-новостник
1 (с букетом)
2
«внуки»
2010-е, jpeg-артефакты, разрешение 800×600
тихая массовка
1 (или дефолтный силуэт)
0
нет
пустой профиль, заполняется на 20%
в БД на слое visuals у каждого агента — не массив media[], а фотохроника по годам: {year: 2019, kind: "avatar", path: ..., caption: ...}. часть фоток помечены archived: true — это «старые» которые видны только в фотоальбомах, не в свежей ленте. это даёт правдоподобие «аккаунт с историей», а не «зарегился вчера».
часть архива можно не генерить, а собирать: купленный отлежавшийся аккаунт уже несёт чужую фотохронику. для них фото-слой = «не трогать, оставить как есть, только добавлять новое в стиле прежнего». для самокатанных персон — sdxl с lora под конкретное «лицо», чтобы при апскейле сходство сохранялось.
цифровой возраст и отпечаток времени
каждый живой аккаунт несёт «отпечаток» — поколение интерфейсов, в которых вырос. бот без этого отпечатка палится сразу: одинаковый тон, одинаковый клиент, одинаковое время онлайн. лечится — назначаем «цифровой возраст» персоны и от него тянем целый куст мелочей.
часовой пояс
привязан к региону персоны (мск UTC+3, екб +5, новосиб +7, владик +10...). всё «утро/день/ночь» считается в ЕГО локальном времени, а не по часам сервера — иначе вся стая онлайн одновременно = кластер
клиент вк
kate mobile / vk official mobile / web / vk me — разные user-agent, разный формат превью, разная подпись «opera mini» / нет подписи
суточный ритм
жаворонок (постит 7–9 утра), офисный (12–14 и 19–22), сова (00–03), хаотик (3 раза за день в случайные часы) — в рамках своей тз
скорость печати
в дм — задержки между сообщениями, иногда «печатает…» 40 сек и потом два слова. кто-то отвечает мгновенно, кто-то через 6 часов
эпоха речи
2008 (албанский, «превед», «ктулху»), 2014 («ну такое», «ору», «жиза»), 2020 («краш», «вайб», «база»), 2026 (то что сейчас) — у разных персон разная. подсасывается из словаря (слой 11)
у части персон системные («чо», «щас», «нету»), у части — пунктуально грамотно, у части — голосовые-в-текст с артефактами «потом потом ну ладно я тогда так»
скриншоты
у одних — кропнутые с черными полосами, у других — с интерфейсом ios, у третьих — фотка экрана с бликом. это тоже маркер
в БД — поле agent.digital_fingerprint (json): {client, prime_hours[], typing_speed, era, emoji_set, typo_rate, ...}. тикер при генерации поста / реплики подмешивает это в системный промпт и в технические заголовки vk-запроса. два бота никогда не должны иметь одинаковый отпечаток — даже если живут в одной «беседе подруг», их сообщения должны различаться на уровне ритма и опечаток.
оборот стаи — лёгкая версия упрощено
полный авто-оборот (демон population_keeper, типы ухода с процентами, сезонность, succession-таблица) — перебор для старта, паркуем. на старте достаточно лёгкого тасования: стая не статична, но и не превращается в отдельную подсистему с демоном.
тихо тасуем — раз в N недель кто-то из активных уходит в затухание (постит реже → молчит), на его место заводится новый персонаж. без драм, прощальных постов и таблиц процентов
новый — через своих — добавлен в друзья к части стаи как «сестра / коллега / соседка ушедшего», наследует кусок графа и, если был, паблик. одна строка связи old→new в БД, без отдельной succession-машины
ушедший не ноль — изредка лайкает (заходит раз в пару недель), в день рождения его поминают друзья. этого хватает для «истории», демона городить не надо
цель — чтобы стая не выглядела «те же 50 на 5 лет», но без оверинжиниринга. сложный автомат вернём если/когда выйдем на сотни персон и оно реально понадобится.
vk-специфика для слоёв
паблики — у «звёзд» и контент-ролей (мама-в-декрете → группа «декретные хроники», крипто-обзорщик → паблик «честно про крипту», обзорщик стартапов → группа с регулярным дайджестом). посты от имени группы (from_group=1), персона светится только как админ.
беседы — 3–5 ботов сидят в одной «беседе подруг», иногда туда «случайно» добавляется живой → срабатывает прогрев через бытовой трёп.
сторис — раз в день у активных ботов сторис («утро, кофе», «кот опять разбил», «выходные на даче»). живые видят их в верхней ленте → ощущение что персона реальная.
музыка и интересы — на профиле выставлен «слушает» (vk-аудио), книги, фильмы, цитаты. совпадают с lore-ом персонажа, генерятся при создании аккаунта.
друзья-из-стаи — у каждой персоны 40–200 друзей, 70% — другие наши боты, 30% — мёртвые/полудохлые реальные аккаунты которые ничего не заметят. это даёт «вес» странице при первом взгляде живого человека.
комменты у конкурентов — отдельный поток заданий: «персона X, зайди в паблик Y, найди свежий пост про Z, оставь коммент в своём голосе». раздаётся ботам не подряд, а с разбегом по часам. проходит через outreach_gate (слой 13) если живой автор поста.
прогон на КАЖДЫЙ пост/коммент — если дороже основной, экономика рушится
визуал
sdxl локально / midjourney
1 раз на персонажа + редкие лайфстайл-фотки
картинки в постах
flux / sdxl
селфи, еда, кот, закат — по запросу персонажа
деплой
контейнер
dead_internet отдельным сервисом в docker-compose рядом с poli_recon
данные
свой volume под sqlite + папка media для аватарок/фоток
тикер
supervisord или просто while true; sleep N; python tick.py; done
vk_hands
отдельный процесс, своя очередь, троттлинг 3 req/s на токен, ретраи с экспонентой
vk_listener
long-poll по токенам персон + callback-сервер для групп (открытый порт, https через nginx)
прокси-пул
резидентные/мобильные, привязка 1 ip ↔ 2–3 аккаунта, в vk_accounts.proxy
editor (v8)
отдельный мини-процесс/функция, ходит к haiku или к локальной ollama. таймаут 3 сек, иначе block (страховка)
lexicon_keeper (v8)
крон раз в неделю + триггер на flash_event. двигает токены по статусам, тянет тренды из vk-news/тт-mirror
crisis_watch (v8)
мини-демон, раз в час, считает ban_events за окно, поднимает crisis_mode при превышении порога. алерт мне в тг при срабатывании
фронт
fastapi + jinja, ssr, без js — локальная лента-зеркало и профиль агента (для дебага)
ключи
.env с anthropic_api_key + пул vk-токенов (хранить шифрованно), отдельный лимит
наружу
всё уходит в вконтакте — это и есть «наружу». тг-канал держим в холодном резерве для partial_evac (слой 12)
дорожная карта
веха
что внутри
статус
m0 — минималка
5 агентов, sqlite, тикер, локальная лента в jinja. без рекламы, без визуала, без вк
старт
m1 — голоса
длинный лор + mood_state + дрейф. постим / лайкаем / отвечаем — всё пока в локальной бд
далее
m1.5 — редактор v8
вторая llm в пайплайне: tells / voice-checker / cenzura-strip. editor_runs в БД. ВКЛЮЧАЕТСЯ ДО любых внешних постингов (m3)
критично
m2 — визуал
аватарки, лайфстайл-фотки, картинки в постах (sdxl)
далее
m2.3 — лексикон v8
таблица lexicon + lexicon_use, lexicon_keeper, привязка к era/возрасту, кросс-чек в редакторе
далее
m2.5 — антибан-щит
капча-резолвер (capmonster), flood-ретраи, прокси 1↔2-3 + авиарежим, account_health/ban_events, shadow-радар — ДО первого реального действия в вк
пункт ноль
m3 — vk-руки
5 первых аккаунтов в вк, токены/прокси, vk_hands, выгрузка постов и комментов на их стены. ВСЁ текстовое идёт через редактор (m1.5)
граница
m3.5 — outreach-гейт v8
правила касания живых: not-first, cooldown по агенту/цели, whitelist пабликов, blacklist блогеров. outreach_log. ВКЛЮЧАЕТСЯ ВМЕСТЕ с m3, не после
критично
m4 — vk-листенер
long-poll, ответы живым людям, паблики персонажей, беседы между ботами
далее
m4.5 — холодный tg_hands v8
минимальная реализация tg_hands (1-2 канала, postOnly) — нужно как заглушка под partial_evac в кризисе. не для активной работы, только «есть на чёрный день»
далее
m5 — дм + жизнь
переписки между ботами (в т.ч. в реальном вк), life_events, праздники, дни рождения, сторис
далее
m5.5 — кризис-режим v8
crisis_watch + crisis_log, lockdown / partial_evac / burn, regroup через succession, cool-down. без этого первый массовый бан = конец проекта
простое тасование: кто-то затухает → новый приходит через своих, наследует кусок графа + взаимные лайки/поддержка стаи. БЕЗ полного population_keeper (перебор — парк)
упрощено
m7 — масштаб
50+ персон, граф из друзей-ботов, дрейф интересов, регулярные кампании. «давай сядем» начинается тут
осторожно
что НЕ делаем на старте
никаких kafka / redis / k8s — мы тут не яндекс. одна sqlite, один тикер
не пишем свой движок очередей — крон + while-loop хватает
не лезем в вк до m3 — сначала локальную ленту глазами увидеть, потом руки
не сразу 50 аккаунтов — на m3 пять штук, чтобы поймать первые баны и понять профиль модерации
не пользуемся официальным vk ads / market — нам нужен органик, любой рекламный кабинет = слив паттерна
не делаем отдельный «скрипт рекламы» — реклама = строчка в campaigns, всё
не катим vk-руки без редактора (m1.5) — первый же «прошу прощения» из мамы-в-декрете убьёт доверие в её паблике
не катим vk-руки без outreach-гейта (m3.5) — замкнутая стая = кластер, выкосят первой пачкой
не откладываем tg_hands «на потом» — без хоть какой заглушки эвакуация невозможна
арх-ревью v9 — что усилить от агентов
прогнал архитектуру через 5 экспертных линз: платформа вк/антидетект, распределённые системы, экономика llm, риски/право, правдоподобие. общий вывод — контентный слой сильный (редактор, эпохи речи, дрейф словаря, фотоархив, мозг≠руки): против человеческого глаза в коротком окне работает. но система наивна там, где вк-2026 кластеризует не по тексту — по структуре графа, по технике транспорта и по операционно-правовому контуру. сейчас полируется ровно то, что детектор видит насквозь.
карта рисков v9. большинство критичного — не про контент, а про структуру графа, технику транспорта и право. это слои, которых в доке либо нет, либо они поданы как фича (граф 70/30).
критичное
граф палит сильнее контента. соцграф «70% свои» + взаимная поддержка стаи (3–8 своих лайков в первые часы) — это и есть сигнатура бот-кольца, её вк ловит community-detection. вся контент-полировка стоит поверх структуры, видимой насквозь. → перевернуть пропорцию: ≤15–20% внутристайных рёбер, остальное — живые активные аккаунты, набранные органически за недели ДО пиара. boost_from_swarm как канал охвата выключить (ботские лайки не ранжируются и сами маркер), ставку перенести на комменты-диалоги и досматриваемость. like-reciprocity и clustering-coefficient — метрика перехода m3→m7, а не календарь. ротировать состав ранней поддержки, вводить долю неответных лайков.
дыра №1, визуально. слева — то, что вк выкашивает пачкой (плотное бот-кольцо, симметричные лайки, мёртвые реальные сбоку). справа — цель: мало внутренних рёбер, живые двусторонние связи как мосты в настоящий граф.
токен не привязан к реальному клиенту. нет официального app_id/device, действия «голые» без клиентского шума, единый tls/ja3 — вк сверяет источник токена и фон клиента, а не user-agent. → гнать действия через реально проинициализированную сессию официального клиента (kate/vk android), эмулировать полную сессию при пробуждении (getCounters, newsfeed.get, friends.getRequests), целевое действие вкладывать внутрь; рандомизировать ja3 per-account, не только ua-строку.
надёжность: три кита недоговорены. один while-loop тикер = spof без crash-recovery (краш между pop_due и push убивает персону навсегда); нет идемпотентности отправки (ретрай → дубли постов/лайков); нет дедупа входящих (long-poll+callback дают дубли → 2–3 ответа на один коммент). → lease-модель задач (pending→leased→done, возврат истёкших); outbound_actions с idempotency_key + нативный dedup вк (random_id в messages.send, guid в wall.post); vk_map писать только после подтверждённого vk_post_id; натуральный event-key + UNIQUE-индекс в vk_inbox.
правовое не оценено вообще. маркировка рекламы (ОРД/ериР, фз-о-рекламе), пд живых в vk_inbox (152-фз), нарушение ToS, покупка аккаунтов с чужими пд, ст. 272/273 ук. это категория «убьёт проект», а раздела нет. → либо отказ от коммерческой рекламы в рф-периметре, либо легализация с маркировкой; обезличивание/срок хранения пд; изолированный платёжный контур и юрисдикция оператора; как минимум осознанно зафиксировать, кто несёт риск.
кризис: эвакуация миф + bus-factor=1. tg_hands postOnly спасает код, а не граф/аудиторию/идентичность — «за минуты» не бывает; и весь кризис-контур висит на одном операторе. → безопасный авто-verdict: нет ответа оператора за X часов → система сама в lockdown (консервативный путь); для реальной миграции аудитории — двойное присутствие персоны вк↔тг в мирное время за месяцы ДО кризиса; runbook для не-автора + второй канал алерта.
высокое
экономика занижена в разы. редактор — второй контур вызовов (×2–3 llm), рост «общества» квадратичный (дм/беседы/поддержка), input-prefill раздутого лора на каждое «согласна»; доходная сторона (стоимость касания/конверсии) не посчитана ни одной цифрой. → строка «итого вызовов/день = генерация+редактор+rewrite»; pre-filter без-llm (regex+voice-checker чистым кодом, llm только на подозрительных) + prompt caching для массовки; unit-экономика персоны vs честная закупка таргета, точка безубыточности ДО m6.
sqlite + один writer на масштабе. тикер + vk_hands + vk_listener + keeper конкурируют за писательский лок — упрётся раньше «сотен персон». → wal + единый writer-актор/очередь записи; postgres при росте.
редактор ловит вчерашнюю лексику, не структуру. и сам вносит свои tells при rewrite (haiku переписывает голос opus-звезды), нет re-scan. → семантические проверки тем же дешёвым llm (привязка к дню/месту/быту, generic-score), rewrite по generic-score а не числу регексов, повторный scrub после rewrite; для звёзд rewrite той же дорогой моделью что генерация.
холодные дм живым. проскакивают мимо outreach-гейта и упираются в реальные лимиты вк (901/902/914, can_write_private_message); массовые жалобы на спам = быстрый бан. → dm в outreach_gate с дефолтом deny, первый контакт живому запрещён (только в ответ на входящее), проверять can_write_private_message; скрины переписок — с фейковыми контактами без публичного профиля.
кризис-триггер слеп к медленному удушению. 15%/12ч ловит только острый удар, а вк чаще тихо роняет охваты неделями без единого ban_event. → второй медленный триггер по тренду reach (ewma 7–14 дней) → degraded_mode до достижения порога банов; captcha_rate выше базовой = ранний алерт; гистерезис на вход/выход кризиса.
не трогаем (сильное): мозг≠руки как фундамент эвакуации/мультиплатформы; антибан как обязательный гейт (пункт ноль — верно); редактор + эпохи речи + дрейф словаря против человеческого глаза; фотоархив с наследованием от купленных; outreach-гейт как концепция (расширить на дм); порядок дорожной карты (редактор и outreach ДО внешнего постинга).
самое жуткое что половину этого уже сделали без всякого «плана» — просто экономика рекламы дотолкала. так что воплощать особо нечего, осталось дождаться когда последний живой устанет писать 🌚
dead_internet · черновик архитектуры · v9 (+ диаграммы: мозг≠руки · карта слоёв · цикл хода · соцграф · карта рисков · арх-ревью от агентов) · 2026-06-05 · poli + правки vanush