Я хотел оживить голема, но получил галлюцинирующего идиота
- пятница, 24 апреля 2026 г. в 00:00:43

В игре Warcraft есть такая тварь — железный голем. Здоровенная кукла, слепленная из глины и металла, которую оживляют магическим словом. Тупой, но мощный исполнитель. Сказали бить — бьёт. Сказали охранять — стоит насмерть.
Я захотел такого же, но в коде.
Телом пусть будет Telegram-бот. А мозгом — нейросеть. Не просто очередной «чат с ИИ», а настоящий кодинг-агент. Чтобы кидаешь ему проект, а он: «Тут у тебя SQL-инъекция, тут гонка данных, тут ты импорт забыл, и вообще у тебя в зависимостях дыра». Идея казалась простой: берём aiogram, прикручиваем DeepSeek, пишем промпт «ты senior-разработчик, разбери этот код» — и готово.
Первая версия была готова за вечер.
Я кинул Голему свой проект. Он задумался на пару секунд и выдал:
«Твой код обрывается. Похоже, ты прислал неполный файл. Я не могу его проанализировать».
Я перепроверил. Файл был полный.
Кинул другой проект. Ответ:
«Интересный фрагмент, но он заканчивается на середине функции. Пришли весь код».
Чёрт подери!!!!
Я сидел и смотрел на этот ответ минут пять. Нейросеть буквально говорила мне, что я идиот, который не умеет копировать файлы. Хотя проблема была в ней самой.
LLM не умеют читать большие объёмы кода. У них есть контекстное окно — как короткая память у рыбки. Они дочитывают до какого-то момента, теряют нить, и им кажется, что текст оборвался. А на самом деле они просто не дошли до конца.
И вот тут я понял: просто «мозг» в «теле» — это не голем. Это говорящая голова на палке. Она не видит проект целиком, не понимает его структуру, не знает, где реальные проблемы, а где просто странный нейминг.
Чтобы оживить голема по-настоящему, ему нужны были глаза.
Тогда и родилась идея «гибрида».
Сначала я попробовал запускать линтеры последовательно:
# Первая версия гибрида — тупая и медленная bandit_result = await run_bandit(project_dir) # безопасность ruff_result = await run_ruff(project_dir) # стиль и баги pip_audit_result = await run_pip_audit(project_dir) # уязвимости в зависимостях # Собираем всё в одну кучу и шлём в LLM context = f""" Bandit нашёл: {bandit_result} Ruff нашёл: {ruff_result} pip-audit нашёл: {pip_audit_result} """ response = llm.ask(context)
Работало. Но медленно. Каждый линтер ждал предыдущего, а проект мог быть большим. Я сидел и смотрел на экран как дебил, пока Bandit копался в коде.
Переписал:
# Параллельный запуск — глаза открываются одновременно bandit_result, ruff_result, pip_audit_result = await asyncio.gather( run_bandit(project_dir), run_ruff(project_dir), run_pip_audit(project_dir) )
Все три тулзы отрабатывают одновременно. Но и это было не идеально. Линтеры выдают портянку — сотни строк в своём формате. Если скормить всё это LLM, она снова начинает тупить. Тогда я добавил фильтр:
# Оставляем только проблемные строки с контекстом def extract_issues(bandit_result, ruff_result, pip_audit_result): issues = [] for issue in bandit_result.get("results", []): issues.append({ "file": issue["filename"], "line": issue["line_number"], "severity": issue["issue_severity"], "problem": issue["issue_text"], "code": issue.get("code", "") }) for issue in ruff_result.get("results", []): issues.append({ "file": issue["filename"], "line": issue["line"], "severity": "medium", "problem": issue["message"], "code": issue.get("rule", "") }) return issues[:30] # Не больше 30 проблем — остальное мусор
И только эти выжимки летят в LLM:
main.py:42 — Bandit HIGH — Possible SQL injection auth/login.py:15 — Ruff medium — Unused import 'os' requirements.txt — pip-audit CRITICAL — CVE-2024-1234 in package xyz==1.2.3
Нейросеть получает сжатый набор фактов, а не гору кода. И выдаёт читаемый отчёт: где проблема, почему критично, как исправить.

Вот так Голем обрёл зрение. А потом я захотел, чтобы он ещё и действовал.
Когда Голем начал выдавать вменяемые отчёты, я выдохнул. Но радость была недолгой. Потому что я смотрел на эти отчёты и думал: «Ок, он нашёл 15 проблем. А исправлять кто будет? Я?»
Ну уж нет.
Ruff — он не только находит проблемы, но и умеет их автоматически исправлять. Правда, не все. Но то, что умеет — делает молча и быстро. Осталось только научить Голема запускать эту магию по команде.
Так появился /fix.
# /fix — запуск автоисправления через Ruff async def fix_project(project_dir: str): proc = await asyncio.create_subprocess_exec( "ruff", "check", project_dir, "--fix", stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE ) stdout, stderr = await proc.communicate() if proc.returncode == 0: # Показываем, что изменилось diff = await get_diff(project_dir) return diff else: return f"Ошибка: {stderr.decode()}"
Юзер жмёт /fix — Ruff проходится по проекту и молча правит что может: неиспользуемые импорты, кривой синтаксис, нарушение стиля. А Голем показывает дифф:

Минус одна проблема. Минус одна строчка в отчёте. Красота.
Но не всё так радужно. Ruff чинит только свои замечания. Уязвимости безопасности от Bandit он не трогает. Дыры в зависимостях от pip-audit — тоже. Поэтому /fix — это не панацея, а первый шаг. Дальше — руками или головой.
И вот когда база для Python устаканилась, я подумал: «А почему только Python?»
В моём канале как раз прошло голосование. Народ хотел Go.
Для Go свой набор инструментов:
# Go-линтеры: gosec (безопасность) и staticcheck (стиль и баги) gosec_result, staticcheck_result = await asyncio.gather( run_gosec(project_dir), run_staticcheck(project_dir) )
gosec ищет хардкод ключей, небезопасные криптографические вызовы, уязвимости. staticcheck — неиспользуемые переменные, необработанные ошибки, устаревший синтаксис.
Архитектура та же: параллельный запуск → сбор проблемных строк → фильтр → LLM → читаемый отчёт.
И когда я первый раз прогнал через Голема urfave/cli — библиотеку с 22 тысячами звёзд на GitHub — он нашёл 14 проблем безопасности и 2 косяка в стиле за пару минут.

Но знаете что? Это всё ещё не «крутой кодинг-агент», о котором я думал в начале. Это полезный инструмент, да. Но до настоящего голема — автономного, помнящего, самообучающегося — ещё далеко.
То, что работает сейчас — это набор разрозненных инструментов, собранных в одного бота:
/analyze — гибридный разбор Python и Go
/fix — автоисправление части проблем через Ruff
/github_push — заливка на GitHub
Общение — ответы на вопросы про код
Выглядит неплохо. Но технически это просто разные функции и голем сам не видит картину в целом.
Текущая версия — это инструмент. Полезный, но с ограниченной памятью. Он реагирует на команды, но не запоминает ни свой опыт, ни пользователей, ни результаты своей работы. Для v2 я перепроектирую ядро так, чтобы у Голема появилась настоящая архитектура агента.
Память и самосознание. Появятся две таблицы в SQLite — agent_memory (что Голем знает о себе и своих возможностях) и agent_actions (журнал всех действий и решений). Это даст ему контекст. Он будет помнить, что делал минуту, час или неделю назад, и сможет использовать этот опыт.
Восприятие. Через Telegram API Голем начнёт собирать объективные данные о своей работе: какие возможности востребованы, как часто к нему обращаются и с какими задачами, какие его ответы вызывают реакцию, а какие — нет.
Мотив. Вся эта информация будет собираться не ради отчётов, а чтобы дать Голему возможность действовать осознанно. Его главная внутренняя цель — становиться полезнее и совершеннее. Имея данные, он сможет сам определять: «Вот здесь я справляюсь плохо, надо усилить это направление», или «Этой фичей пользуются чаще всего, значит, её нужно развивать в первую очередь». Или в чат ему юзеры пишут типо " А вот круто было если бы ты умел деплоить проекты сразу на сервер.." И Голем задумается над этим и возможно перепишет свой код)))
Замкнутый цикл. Так мы приходим к замкнутому циклу эволюции. Голем видит результат своих действий, анализирует его и предлагает конкретные технические улучшения в своей архитектуре и коде. Он уже сейчас анализирует Python и Go. v2 будет способен анализировать и улучшать самого себя.
Вот так задумывался настоящий Голем. Не просто ещё один бот с командами, а автономная единица, способная к саморазвитию.
Бот @Golem666bot работает прямо сейчас. Кидайте ссылки на репозитории, тестируйте анализ.