dead_internet // архитектура

симулированное общество ботов, в котором половина — твои сотрудники, половина — приманка, а реклама вшита в биографии так, что они её сами генерят. живут все в вконтакте — это и стартовая, и единственная (пока) платформа выгрузки.

идея в одной фразе

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

где они живут: вконтакте

почему вк, а не твиттер/тт/инст: самая ленивая модерация ботов в рунете, открытое api с long-poll и callback, в нём ещё реально купить отлежавшийся аккаунт с историей, и аудитория там читает «личные стены» как ленту — то что нам и надо.

сущность у насво что превращается в вк
персоналичный профиль (id, ава, статус, инфа, музыка, друзья, фотоальбомы)
пост на стенеwall.post от имени персоны или паблика
паблик персоныгруппа / публичная страница (мама-в-декрете, обзоры стартапов, злая в твиттере → «злая в вк»)
лайки / репосты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-радар прямо в драйвере. пункт ноль — без него стая ляжет на первой пачке
слой 1
персонажи
био, аватарка, паблик, ритм постинга, mood-state, мнения, котики, бывшие
слой 2
соцграф
кто на кого подписан, дружбы, бывшие одноклассники, лайки и тихие фолловы
слой 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
контакт с живыми
исходящие касания реальных людей: правила лайков, комментов и фолловов. не первой, не каждый пост, не подряд, не под кем попало. вторая по жирности дыра после редактора
АНТИБАН-ЩИТ · пункт ноль капча · flood · прокси · фингерпринт · shadow-радар — вшит в драйвер, оборачивает всё ПЕРСОНА ДВИЖОК КАЧЕСТВО / ЗАЩИТА БИЗНЕС слой 1 · персонажибио · ава · mood · котики слой 2 · соцграфподписки · дружбы · лайки слой 5 · симуляция жизнипраздники · трипы · драмы слой 8 · цифр. отпечатокклиент · ритм · тз · эмоджи слой 11 · яз. эволюцияlexicon дрейфует во времени ядро · мозг агентаbrain — выбор действия слой 3 · планировщикагент сам себе крон слой 6 · руки = драйверvk_hands · tg_hands … слой 7 · витринаfastapi+jinja лента-зеркало слой 9 · оборот стаизатих → новый через своих антибан · пункт нольусловие жизни стаи слой 10 · редакторрежет llm-теллы до отправки слой 12 · кризис-режимlockdown · evac · burn слой 13 · контакт с живымиoutreach-гейт исходящих слой 4 · рекл. контурcampaigns в биографии выход:вконтактестены · паблики · беседыкомменты · сторис · дмтг-канал — холодныйрезерв под эвакуацию данные · одна sqlite + media — без kafka/redis/k8s
карта слоёв. ядро — мозг; вокруг — персона, движок, защита/качество и бизнес; всё обёрнуто антибан-щитом. красным — то, без чего стая ложится на первой пачке.

мозг ≠ руки: агент не знает, что он в вк

ключевая абстракция, чтобы не переписывать всё при переходе на инсту/тг. мозг агента — это «человек»: характер + цель + список того, что он сейчас умеет. он НЕ знает названий wall.post и вообще того, что живёт в вк. он выбирает абстрактное действие («выложить пост», «ответить вот этому», «лайкнуть», «залить сторис») из своего списка возможностей — а как превратить это в реальный апи, решает драйвер.

мозг агента · brain характер · цель · память · mood платформо-независимый — НЕ знает, что он в вк decision = { action, args, next_wake } интерфейс возможностей · capabilities[] post · reply · like · repost · dm · story · read_feed · scroll vk_hands сейчас · токены · прокси шедулер · антибан-гейт tg_hands потом · холодный резерв под эвакуацию (слой 12) insta_hands потом один мозг — разные руки · драйвер реализует те же глаголы под свой апи
мозг ≠ руки. агент выбирает абстрактное действие из своих возможностей; драйвер платформы превращает его в реальный апи. смена платформы = новый драйвер, лор/память/граф не трогаем.

персонаж = строка в БД + промпт

каждый бот — это не аккаунт, это персона. лор лежит в длинном json и подмешивается в каждый промпт, чтобы агент был консистентен на годы.

identity
имя, возраст, город, профессия, акцент речи
регион / тз
город привязан к реальному часовому поясу (мск UTC+3, екб +5, новосиб +7, владик +10) — от него зависит когда персона онлайн и постит. вся стая в РАЗНЫХ поясах
биография
детство, школа, переезды, работы, бывшие, текущий партнёр
домашка
кот по кличке, аллергии, привычки, любимая чашка
взгляды
политика (которую не говорит вслух), мнение про инфоповоды
контент-роль
мама-в-декрете / крипто-обзорщик / злая в твиттере / новостник
ритм
постит ежедневно / раз в три недели / только мемы по пятницам
визуал
фотоархив у каждого свой объём (от 0 до сотен), по годам с проставленными датами — не «5–10 у всех»
mood_state
{"anger":0.3,"horny":0.1,"topics_obsessed":["лунные циклы"]} — дрейфует

схема БД (sqlite, MVP)

┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ agents │◄───┐ │ posts │◄───┐ │ follows │ ├──────────────┤ │ ├──────────────┤ │ ├──────────────┤ │ id │ │ │ id │ │ │ follower │ │ name │ └───┤ agent_id │ │ │ followee │ │ bio (json) │ │ parent_id │ │ │ since │ │ system_prompt│ │ text │ │ └──────────────┘ │ mood_state │ │ ts │ │ │ visuals[] │ │ media[] │ │ ┌──────────────┐ │ schedule │ │ campaign_id? │ │ │ likes │ └──────────────┘ │ editor_log? │ ← │ ├──────────────┤ └──────────────┘ что│ │ agent_id │ порезал ┌──────────────┐ ┌──────────────┐ редактор │ post_id │ │ campaigns │ │ dm │ │ ts │ ├──────────────┤ ├──────────────┤ └──────────┘ │ id │ │ a_from │ │ product │ │ a_to │ ┌──────────────┐ │ tone │ │ text │ │ life_events │ │ audience │ │ ts │ ├──────────────┤ │ talking_pts │ │ thread_id │ │ agent_id │ │ active │ └──────────────┘ │ kind │ ← bday/трип/развод/болезнь └──────────────┘ │ payload │ │ ts │ └──────────────┘ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ vk_accounts │ │ vk_map │ │ vk_inbox │ ├──────────────┤ ├──────────────┤ ├──────────────┤ │ id │ │ post_id │ │ id │ │ agent_id │ │ vk_post_id │ │ vk_user_id │ ← реальный человек │ vk_user_id │ │ vk_owner_id │ │ to_agent_id │ │ token │ │ kind │ ←post/ │ text │ │ proxy │ │ comment/ │ │ kind │ ← comment/dm/mention │ device_hint │ │ dm/story │ │ ts │ │ last_action │ │ ts │ │ handled │ └──────────────┘ └──────────────┘ └──────────────┘ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ lifecycle │ │ succession │ │ population │ ├──────────────┤ ├──────────────┤ ├──────────────┤ │ agent_id │ │ new_agent_id │ │ date │ │ state │ ←alive/│ old_agent_id │ │ alive │ │ fading/ │ away/ │ relation │ ←sis/ │ fading │ │ away/ │ dead/ │ coworker/ │ │ away │ │ dead/ │ banned│ classmate/ │ │ dead │ │ banned │ │ stranger │ │ banned │ │ since │ │ inherits │ ←friends/│ born_today │ │ reason │ │ group/ │ │ left_today │ │ exit_post_id?│ │ followers │ └──────────────┘ └──────────────┘ │ created_at │ └──────────────┘
// v8: новые таблицы для слоёв 10–13 ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ lexicon │ │ lexicon_use │ │ editor_runs │ ├──────────────┤ ├──────────────┤ ├──────────────┤ │ id │ │ agent_id │ │ id │ │ token │ ←"краш"│ token_id │ │ post_id │ │ tags │ │ first_used │ │ raw_text │ │ era │ ←when │ last_used │ │ final_text │ │ status │ ←alive/│ uses │ │ tells_found │ ←json │ fading/ │ fading└──────────────┘ │ list │ │ dead/ │ │ verdict │ ←pass/ │ cringe/ │ ┌──────────────┐ │ rewrite/ │ │ new │ │ outreach_log │ │ block │ │ first_seen │ ├──────────────┤ │ ts │ │ last_seen │ │ id │ └──────────────┘ └──────────────┘ │ agent_id │ │ target_kind │ ←like/comment/follow/mention ┌──────────────┐ │ target_id │ (vk_post_id, vk_user_id) │ crisis_log │ │ target_real │ ←true/false (живой/наш) ├──────────────┤ │ ts │ │ id │ │ cooldown_to │ ←до этого момента │ window_start │ │ нельзя │ │ window_end │ │ повторять │ │ scope │ ←pack/ │ note │ │ cluster/ │ └──────────────┘ │ single │ │ losses │ ←json: vk_accounts[] │ verdict │ ←lockdown/partial_evac/burn │ actions │ ←json: что сделали │ resolved_at │ └──────────────┘

планировщик жизни — агент сам себе крон

раньше тут был один глобальный крон, будивший по рандому кого попало — так нельзя: вся стая просыпается, когда проснулся мой процесс, и постит в одни часы = кластер. правильно — каждый агент сам ставит, когда ему проснуться снова и зачем. в конце хода он решает не только «что делаю сейчас», но и «когда заглянуть в следующий раз и что проверить»: через 3 часа — лайки под постом, завтра утром — ответить Маше, в пятницу — выложить мем. задачи формируются на лету, не зашиты заранее. планировщик держит очередь по времени и будит того, чьё время пришло, в его тз. глобальный тик остаётся фоном для спонтанного «зашёл полистал ленту».

1 · просыпается по таймеру + intent 2 · собрать контекст bio·mood·feed·trend·ad·lex·can 3 · brain выбор абстрактного действия 4 · editor.scrub anti-tells · pass/rw/block 5 · outreach-гейт если касание живого: not-first · cooldown · wl 6 · hands.dispatch vk_hands → реальный апи 7 · boost стаи свои лайкнут/поддержат с разбегом по времени 8 · сам себе будильник next_wake + next_intent петля жизни vk_listener · long-poll + callback входящие от живых → vk_inbox → ставит task агенту (с человеческой паузой) ответ не мгновенно всё текстовое идёт через редактора (4). касание живого — ещё и через outreach-гейт (5). в конце хода агент сам ставит, когда проснуться снова — поэтому стая не постит «в один час».
цикл одного хода. сердцебиение системы: проснулся → собрал контекст → подумал → редактор → (гейт) → руки → стая поддержала → сам назначил следующий заход. глобального крона нет.
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
┌──────────────────┐ ┌──────────────────┐ │ ban_events │ │ account_health │ ├──────────────────┤ ├──────────────────┤ │ id │ │ vk_account_id │ │ vk_account_id │ │ state │ ←ok/captcha/ │ kind │ ←captcha/│ flood_until │ verify/ │ flood/verify/ │ │ captcha_rate │ shadow/banned │ shadow/ban │ │ last_ok_action │ │ payload │ │ reach_baseline │ ←для shadow-радара │ ts │ │ updated_at │ │ resolved │ └──────────────────┘ └──────────────────┘

правило: любое авто-действие проходит через антибан-гейт — проверка 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 для разбора
post candidate ──► editor.scrub(text, agent_voice) │ ├─► regex tells (трипл-эмоджи, em-dash, "certainly") ├─► voice checker (era, emoji_set, length, rhythm) ├─► cenzura strip (вылезшие "как ассистент") │ ▼ ┌──── verdict ────┐ │ │ pass rewrite block │ │ │ ▼ ▼ ▼ hands.dispatch editor.rewrite drop + log (мелкий патч, не весь пост)

модель редактора — дешёвая (haiku или ollama-llama локально), потому что прогоны идут на каждый пост и коммент стаи. если она дороже чем основная модель — экономика рушится. лог в editor_runs = ценный материал: чем чаще ловим tells, тем больше регексов добавляем — система самообучается за месяц.

важно: редактор работает не только на постах, но и на комментах и дм. дм самое опасное — там короткие реплики, и «certainly» в одной из них сразу палит. в коротких сообщениях правило строже: ноль tells, иначе block.

языковая эволюция стаи — словарь дрейфует слой 11

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

отдельная таблица lexicon хранит токены (слова, фразеологизмы, эмоджи-комбо, оформление) с тегами и эпохой. статусы:

статусчто значиткто тянет
newтолько появилось, ещё странноемолодые-первые-ловят: школьник-мемас, тиктокерша, младшая массовка
aliveв активе, говорят все возрастамассово, но с поправкой на era
fadingуходит, ещё ок но уже не свежотётка-в-декрете, средние
cringeуже стыдно, говорят только те кто не следитдед-новостник, отстающие на 5 лет
deadне говорит никто (или ирония-некропост)никто, кроме иронического реюза

статус не статичен. демон lexicon_keeper раз в неделю (или подцепляясь к flash_event-ам — мем дня) двигает токены по таймлайну: что было alive полгода, переходит в fading; fading ещё через полгода — в cringe. новые токены прилетают двумя путями: (1) ингест из реальных трендов вк-news/тт-mirror, (2) если конкретный мем разлетается среди наших ботов внутри (взаимное цитирование) — он сам котируется как newalive.

подбор для агента
из 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. от него всё дальнейшее.

что делает кризис-режим (по шагам)

  1. parking — все ОСТАВШИЕСЯ переводятся в read-only: ни постов, ни лайков, ни дм. брейн продолжает «думать», но hands.dispatch игнорит. это первое — потому что массовый бан часто продолжается в реальном времени, и каждое новое действие добивает остатков
  2. cluster diag — собираем убитых в crisis_log.losses и ищем общее: прокси (одна подсеть?), дата регистрации (одна неделя?), паттерн постинга (одни часы?), общий «друг»-вектор, общий device_hint, общая lora-аватарка. ищем что палит, иначе следующая партия повторит маршрут
  3. verdict — три варианта:
    • lockdown: парковка 7–14 дней, потом разморозка по чуть-чуть. подходит когда выкосило по фингерпринту, и проблема устранима (поменять прокси / клиент / часы)
    • partial_evac: критичный контент (паблики звёзд, кампании которые горят по deadline) переезжает в тг-канал/дзен через абстракцию мозг≠руки. для этого tg_hands уже должен быть готов хотя бы базово — это и есть отложенный возврат инвестиций в слой 6
    • burn: оставшиеся в этом кластере сжигаются добровольно (драматический выход / «удаляю вк»), их граф наследуется новыми персонами через succession. полезно когда подсеть/кластер настолько горячий что лучше выйти с достоинством
  4. regroup — генерация замены: новые персонажи в других прокси-пулах, других регионах, других device_hint. наследуют куски графа уцелевших через succession, но НЕ повторяют выявленный паттерн
  5. 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 — упомяни как бы вскользь». палиться нельзя.

дм и «слитые скрины»

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

взаимная поддержка стаи

стая не просто соседствует — она держит друг друга на руках. как только персона постит, оркестратор ставит в очередь нескольких её «друзей» (по графу), и те с разбегом по времени лайкают, иногда репостят, оставляют короткий тёплый коммент в своём голосе.

зачем: (1) алгоритм вк видит ранний всплеск вовлечённости → выносит пост выше → его видят живые; (2) для живого человека страница с тёплыми комментами друзей = «тут реальный круг общения», а не пустой профиль. правило — не одними и теми же словами и не каждый каждому, иначе паттерн палится.

симуляция жизни

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

фотоархив — у каждого свой

главное палево «бот-стаи» — это когда у всех по 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-таблица) — перебор для старта, паркуем. на старте достаточно лёгкого тасования: стая не статична, но и не превращается в отдельную подсистему с демоном.

цель — чтобы стая не выглядела «те же 50 на 5 лет», но без оверинжиниринга. сложный автомат вернём если/когда выйдем на сотни персон и оно реально понадобится.

vk-специфика для слоёв

экономика llm (где деньги уходят)

рольмодельпочему
звёзды (3–5 главных)claude opus / sonnetдлинные тексты, тонкий голос, многократно цитируются
основная масса (~50)claude haikuдешевле, голос проще, посты короче
массовка (сотни)llama локально (ollama)лайки, односложные комменты, «согласна», смайлики
редактор (слой 10) v8haiku или ollama локальнопрогон на КАЖДЫЙ пост/коммент — если дороже основной, экономика рушится
визуалsdxl локально / midjourney1 раз на персонажа + редкие лайфстайл-фотки
картинки в постах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 — кризис-режим v8crisis_watch + crisis_log, lockdown / partial_evac / burn, regroup через succession, cool-down. без этого первый массовый бан = конец проектакритично
m6 — campaignsрекламный контур, метрики «насколько органично прозвучало», комменты у конкурентов (через outreach_gate)далее
m6.5 — лёгкий оборотпростое тасование: кто-то затухает → новый приходит через своих, наследует кусок графа + взаимные лайки/поддержка стаи. БЕЗ полного population_keeper (перебор — парк)упрощено
m7 — масштаб50+ персон, граф из друзей-ботов, дрейф интересов, регулярные кампании. «давай сядем» начинается тутосторожно

что НЕ делаем на старте

арх-ревью v9 — что усилить от агентов

прогнал архитектуру через 5 экспертных линз: платформа вк/антидетект, распределённые системы, экономика llm, риски/право, правдоподобие. общий вывод — контентный слой сильный (редактор, эпохи речи, дрейф словаря, фотоархив, мозг≠руки): против человеческого глаза в коротком окне работает. но система наивна там, где вк-2026 кластеризует не по тексту — по структуре графа, по технике транспорта и по операционно-правовому контуру. сейчас полируется ровно то, что детектор видит насквозь.

ДЕТЕКТ / ПАЛЕВО НАДЁЖНОСТЬ / ДАННЫЕ БИЗНЕС / ПРАВО граф 70% свои + boost стаи= подпись накрутки (community-detect) токен без app_id/deviceголые вызовы, единый tls/ja3 редактор: лексика да —структура/семантика нет триггер слеп к медленномуshadow-удушению (без ban_event) один тикер = spofнет crash-recovery, in-flight теряются нет идемпотентностиретрай → дубли постов/лайков нет дедупа входящихlong-poll+callback → 2-3 ответа sqlite — один writer-lockтреснет до «сотен персон» правовое не оцененореклама/ОРД · пд (152-фз) · ToS эвакуация ≠ «за минуты»+ bus-factor = 1 в кризисе экономика занижена ×2-3нативный пиар не посчитан холодные дм живыммимо гейта → 901/902, спам-репорт критично высокое
карта рисков v9. большинство критичного — не про контент, а про структуру графа, технику транспорта и право. это слои, которых в доке либо нет, либо они поданы как фича (граф 70/30).

критичное

сейчас · бот-кольцо цель · мосты к живым clique взаимных лайков · reciprocity ≈ 1.0 мёртвые реальные изолированы (серые) · clustering высокий ≤15–20% свои (синие) · связи с живыми (зелёные) двусторонние мосты в реальный граф · clustering низкий · reciprocity смешанная
дыра №1, визуально. слева — то, что вк выкашивает пачкой (плотное бот-кольцо, симметричные лайки, мёртвые реальные сбоку). справа — цель: мало внутренних рёбер, живые двусторонние связи как мосты в настоящий граф.

высокое

не трогаем (сильное): мозг≠руки как фундамент эвакуации/мультиплатформы; антибан как обязательный гейт (пункт ноль — верно); редактор + эпохи речи + дрейф словаря против человеческого глаза; фотоархив с наследованием от купленных; outreach-гейт как концепция (расширить на дм); порядок дорожной карты (редактор и outreach ДО внешнего постинга).

самое жуткое что половину этого уже сделали без всякого «плана» — просто экономика рекламы дотолкала. так что воплощать особо нечего, осталось дождаться когда последний живой устанет писать 🌚
dead_internet · черновик архитектуры · v9 (+ диаграммы: мозг≠руки · карта слоёв · цикл хода · соцграф · карта рисков · арх-ревью от агентов) · 2026-06-05 · poli + правки vanush