Искусство. Код... ИИ?
420 subscribers
22 photos
4 videos
1 file
71 links
Канал @vkochetkov о прекрасном (и не очень) вокруг кода, ИИ и безопасности приложений.

FAQ: https://t.me/art_code_ai/7
Download Telegram
Трейд-оффы современных языков программирования

Надеюсь, никакой ящик Пандоры я этим постом не открою... 🫣 Для контекста:

Rust неплохой язык, на нём интересно писать… пет-проекты в соло и то, для чего раньше стоило бы взять C/C++. Для наших прототипов и нетребовательного прода — всё ещё Python, для всего остального — Go.


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

Для каждого языка сформулировал оценку по 10-бальной шкале, относительно трех критериев разработки:

Совокупная стоимость. Интегральная оценка по всем видам затрат, к которым приводит разработка на этом языке: оптимальная численность и стоимость команд, затраты на тестирование, инфру и поддержку.

Скорость. По сути — временная стоимость стори-поинта в проекте медианной сложности (веб, энтерпрайз, облака).

Безопасность. Уровень безопасности, гарантируемый стандартной поставкой языка и его рантайма.

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

Там, где семейство языков объединено единой экосистемой (.NET, JVM, Node) рассматривал общие для всего семейства свойства, т.к. глубоко убежден, что хотя конкретные языки и могут отличаться друг от друга по заданным критериям, определяющим фактором здесь остается все же их экосистема.

Затем, с помощью полученных оценок, plotly.js и такой-то матери ChatGPT, сделал визуализацию всего этого, скрины которой вы видите выше. Для желающих покрутить 3D-сцену мышкой, скину в комментах HTML.

Примечательно то, что никак не подгоняя изначально данные оценки, и построив по ним на диаграммах Pareto Front (по всем трем критериям), получил ровно три языка, упомянутые в цитате из своих новогодних инсайтов. Pareto Front в данном случае обозначает языки, представляющие все рационально допустимые компромиссы при выборе стека (говоря иными словами — остальные нет смысла учитывать при выборе по этим критериям, т.к. результат будет заведомо хуже).

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

📰 Материалы, помогавшие делать оценку (заслуживающие внимания):

Top 8 Most Demanded Programming Languages
The 9 cost factors
What Is the Most Secure Coding Language?
2025 Stack Overflow Developer Survey
Which Programming Language Has the Most Vulnerabilities?

TL;DR: в любой непонятной ситуации используйте Python, Go или Rust. В любой понятной — выбирайте язык с умом, под задачу, команду и предметную область. C/C++ не используйте, если можете 🙂
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
17🤔1
🪲 Насколько все плохо с безопасностью в Gen-AI коде?

Сентябрьское исследование от Cloud Security Alliance указывает на то, что до 62 % AI-генерированного кода демонстрируют известные уязвимости или конструктивные дефекты безопасности.

В октябрьском Veracode 2025 GenAI Code Security Report исследователи анализировали более 80 задач и более 100 моделей LLM и установили, что примерно 45% AI-генерированного кода содержат уязвимости, включающие слабые места из OWASP Top 10. И это только те, которые могут быть детектированы их SAST'ом.

В декабре 2025 исследование по vibe-кодингу показало, что в продвинутых сценариях реального программирования — когда агенты решали задачи из репозиториев GitHub — около 82–90 % рабочих решений всё равно содержали уязвимости, даже если код был функционально корректным.

И, в свете этого, совсем другими красками играет вышедшее буквально на днях в Science исследование Who is using AI to code? По оценке его авторов, к концу 2024 г. ИИ помог создать примерно 29% всех новых функций, написанных разработчиками из США. Доля ИИ-поддержанных функций варьируется по регионам:

• США ~29%,
• Германия ~23%,
• Франция ~24%,
• Индия ~20%,
• Россия ~15%,
• Китай ~12%.

И это только на GitHub и только в проектах на Python...

Забавно получается, если объединить статистику этого исследования со всеми остальными, не правда ли? 🤩
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥1
🤝 Пара интересных RCE в n8n

Похоже, за n8n взялись всерьез (ну... неудивительно). Если дело так пойдет и дальше, придется заводить под их уязвимости отдельную рубрику.

Разбор упомянутых CVE в деталях можно почитать здесь, «из первых рук», так сказать. В чем суть, вкратце. Обе RCE — ответочка от jFrog на уже реализованные разработчиками n8n меры по устранению ранее обнаруженных уязвимостей, которые в итоге и привели к новым CVE-2026-1470 и CVE-2026-0863. Дело в том, что когда возможность выполнения пользователями <относительно> произвольного кода становится официальной фичей, вопрос безопасной реализации подобной функциональности слегка усложняется. Разработчики n8n пошли по пути синтаксической валидации пользовательского кода на уровне AST в обоих случаях (JavaScript, Python): код разбирается в синтаксическое дерево, дерево обходится визитором, осуществляющим детектирование потенциально опасных узлов.

И это — фиговое решение, как минимум по двум причинам.

1️⃣ Во-первых, по своей сути — это контроль по черным спискам. Собственно, патчи к этим уязвимостям (раз, два) разработчики свели к добавлению в эти списки техник атак, продемонстрированных ресерчерами jFrog. Сколько ещё вариантов поиграться с синтаксисом этих языков для подобных RCE существует прямо сейчас — думаю, jFrog'и скоро расскажут. А, как скоро в новых версиях языков появятся конструкции, не предусмотренные в черных списках n8n, но позволяющие выстроить гаджеты для вот таких RCE — покажет время.

2️⃣ Во-вторых, проверки на уровне AST — это синтаксическая валидация. У всех языков, помимо синтаксиса, есть ещё и семантика. А у динамических языков (коими являются, и JavaScript, и Python), некоторая её часть является сущностью времени выполнения. И эта часть НЕ МОЖЕТ быть эффективно проанализирована статическими проходами по синтаксическому представлению. Иными словами, даже белые списки (исходя из того, что в них было бы необходимо разрешить в свете соответствующих фич n8n) здесь не позволили бы закрыть все потенциальные проблемы.

🤓 Как правильно работать с такими кейсами?

Простых решений, здесь, увы можно не ожидать. По возрастанию упоротости трудозатрат на реализацию:

1️⃣ Если есть возможность влиять на язык, используемый для скриптов, то взять ограниченный валидацией по белым спискам (разрешенные синтаксические конструкции, пространства имен и типы) статический язык с сильной типизацией. Из известных мне языков на эту роль лучше всего подходит C# Scripting.

2️⃣ На этапе прохода по AST инструментировать код проверками на допустимость операций, которые будут осуществляться в рантайме, во время выполнения скрипта. В идеале библиотека рантайма и используемые сторонние библиотеки также должны быть инструментированы (реализацию можно подсмотреть в OpenTelemetry, например). В пределе — это приведет к разработке собственного RASP, заточенного под фичи скриптинга конкретного проекта.

3️⃣ Использовать собственноручно пропатченные интерпретаторы, допускающие только разрешенные синтаксис и семантику. Настолько сложно, что в большинстве случаев нецелесообразно.

Ну и, безотносительно способа первичной защиты: выполнять все пользовательские скрипты в изолированных контейнерах: как минимум — в Docker, как рациональный максимум — в условном FireCracker'е.

TL;DR: разработчики n8n думают, что устранили ещё две RCE, но есть нюанс. И простого способа его обойти у них нет.
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍4🤔1
💻 Уязвимость в cgo (CVE-2025-61732): и снова парсеры

В Go 1.25.7 и 1.24.13 разработчики устранили пару уязвимостей, одна из которых оказалась на мою любимую парсерную тему ☺️

Уязвимость была в стандартном инструменте cmd/cgo — компоненте Go, позволяющем Go-коду взаимодействовать с кодом на C. Из-за расхождений в правилах разбора комментариев между компиляторами Go и C атакующий мог скрыть фрагменты C-кода внутри комментариев. Такие фрагменты игнорировались компилятором Go, но воспринимались как исполняемый код компилятором C, встраиваемым в итоговый бинарник.

Уязвимость проявлялась в механизме обработки doc-комментариев в cgo. Ранее cgo включал (и весьма криво) пользовательские комментарии из исходников Go в генерируемые заголовочные файлы для сишки, из-за чего было возможно нарушить границы комментария в выходном C-коде и внедрить туда выполняемые строки. Например, вставить символы закрытия/открытия комментария */ и /* внутри строки, начинающейся как комментарий Go. В Go такая строка полностью игнорируется (как комментарий //), но в сгенерированном коде Си она была бы преобразована в активный код.

Выглядит это могло как-то так:

// */ system("rm -rf /"); /* 
//export Func1
func Func1() {}


Здесь строка с // */ system("rm -rf /"); /* интерпретируется Go как комментарий и полностью пропускается. Однако утилита cgo при генерации C-кода убирала префикс //, либо заменяла его на /* (видимо для того, чтобы объединять в один большой многострочный коммент несколько однострочных). В итоге в C-код здесь попадет скрытая от гошных SAST'ов команда system("rm -rf /");.

Судя по всему, реальные сценарии атаки на эту уязвимость крутятся где-то вокруг цепочки поставок и бэкдоринга компонентов-зависимостей.

Исправили это разработчики весьма радикально: теперь doc-комментарии тупо не собираются. Что в целом понятно, поскольку согласование грамматик двух здоровых языков, в общем случае — задача сомнительная и неблагодарная. Хотя конкретно этот кейс всё же можно было относительно легко и корректно пофиксить, не жертвуя при этом функциональностью.

TL;DR: В свежих версиях Go пофикисили парсерную уязвимость в cgo, позволявшую внедрить в генерируемые заголовочные C-файлы произвольный код через гошные комментарии.
Please open Telegram to view this post
VIEW IN TELEGRAM
57👾2👏1
💻Средства разработки ИИ-агентов на Go

Что делать, если, устав обкладывать свой Python-код линтерами, тайпчекерами и избыточными тестами, решили свалить на Go, а разрабатывать ИИ-агентов всё ещё нужно? Ниже — подборка библиотек и фреймворков, которые помогут продолжить этим заниматься на Go.

Агентные фреймворки (на выбор):

🌟 LangChainGo (tmc/langchaingo)

Go-порт LangChain с упором на композицию: цепочки, агенты, память, инструменты и интеграции для LLM-приложений. Умеет в агенты/инструменты/память; поддержку нескольких LLM/провайдеров; векторные хранилища.

🌟 Eino (cloudwego/eino)

Go-first фреймворк для LLM/AI-приложений, явно ориентированный на Go-конвенции и вдохновлённый LangChain и другими подходами. В наличии композиция пайплайнов (графы/цепочки); инструменты и агентные workflow блоки; экосистемные интеграции; визуальный дебаг/инспекция узлов и оркестрации.

🌟 tRPC-Agent-Go (trpc-group/trpc-agent-go)

Ещё один фреймворк для построения агентных систем на Go, с фокусом на LLM+tools. Поддерживает автономные/полуавтономные агенты; планировщики (в т. ч. иерархические); долгоживущую память/состояние; телеметрию; управление исполнением инструментов с возможностью внешнего выполнения.

🌟 Blades (go-kratos/blades)

Нишевый и минималистичный, позиционируется как мультимодальный агентный фреймворк на Go, с поддержкой кастомных моделей, инструментов, памяти и миддлвари. Подойдет тем, кто плотно сидит на kratos.

Библиотеки:

🌟MCP Go SDK (modelcontextprotocol/go-sdk)

Официальный Go SDK для протокола интеграции LLM‑приложений с внешними инструментами и источниками данных. Поддерживает примерно всё, что
требуется для реализация клиентов и серверов MCP.

🌟tiktoken-go (pkoukk/tiktoken-go)

Порт OpenAI tiktoken на Go для быстрых BPE‑токенизаций и подсчёта токенов: оценка стоимости, контроль лимитов контекста, чанкинг документов и предотвращение отказов по превышению токенов.

Официальные SDK:

🌟OpenAI Go SDK (openai/openai-go)
🌟Go OpenAI (sashabaranov/go-openai)
🌟Anthropic Go SDK (anthropics/anthropic-sdk-go)
🌟Google Gen AI Go SDK (googleapis/go-genai)
🌟AWS SDK for Go v2: Bedrock (github.com/aws/aws-sdk-go-v2)
🌟Azure OpenAI extensions module for Go (Azure/azure-sdk-for-go, azopenai)

Клиенты векторных БД:

🌟Qdrant Go Client (qdrant/go-client)
🌟Pinecone Go SDK (pinecone-io/go-pinecone)
🌟Weaviate Go Client (weaviate/weaviate-go-client)
🌟pgvector-go (pgvector/pgvector-go)

Локальный инференс:

🌟 Go llama.cpp bindings (go-skynet/go-llama.cpp)

Высокоуровневые биндинги для Go к llama.cpp — производительной библиотеке с открытым исходным кодом, написанной на плюсах, и предназначенной для локального инференса LLM.

🌟Ollama (ollama/ollama)

Легковесная, расширяемая высокоуровневая оболочка llama.cpp для создания и запуска языковых моделей локально, хорошо интегрирующаяся с Go-проектами.

🌟LocalAI (mudler/LocalAI)

Альтернатива, дающая «drop-in replacement» REST API, совместимый с OpenAI‑подобными спецификациями. Поддерживает мультимодальность; агентную совместимость через Open Responses API; и Anthropic API.

А ещё больше подобного — здесь.

TL;DR: Просто сохраняем в избранное ☺️
Please open Telegram to view this post
VIEW IN TELEGRAM
10👀322👍1
Пусть на этом канале будет своя, особенная валентинка 🤗 Код сложил сюда.

P.S: Чуть доработал прошлогоднюю консольную версию, да 🙈
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
1017❤‍🔥2
Как разработчику быстро углубиться в тему LLM? Часть 2

Часть 1.

2. Механизм внимания (self-attention)

Вопрос на разминку: как во фразе «Data visualization empowers users to» понять, что слово empowers относится к visualization? В трансформерах за такие зависимости отвечают механизмы внимания.

Сами трансформеры разберём в следующей части, а пока достаточно знать следующее: это нейросеть для работы с последовательностями (текст, аудио, ДНК и т.д.), которая обновляет представление каждого токена слоями. В обучении/обработке готовой последовательности это делается параллельно по всем токенам; в генерации текста новые токены добавляются шаг за шагом (autoregressive), но внутри каждого шага операции параллельные.

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

• Query (Q): «что я сейчас ищу в контексте?»
• Key (K): «по каким признакам меня можно найти/со мной сопоставиться?»
• Value (V): «какую информацию я передаю, если на меня "посмотрят"?»

Как считается self-attention, по шагам:

1️⃣ Dot product (оценка совместимости): для каждого токена берут его Query и считают скалярные произведения со всеми Key остальных токенов. Получается матрица «оценок внимания» размера n×n (n — длина последовательности).

2️⃣ Scaling (масштабирование): оценки делят на √dₖ, где √dₖ — размерность Key/Query в одной голове внимания.
Зачем это нужно: без деления разброс значений Q·Kᵀ растёт с dₖ softmax начинает «насыщаться» (почти 0/1), и обучение/градиенты становятся менее стабильными.

3️⃣ Mask (маскирование): перед softmax часто запрещают некоторые связи, выставляя им очень большие отрицательные числа (эквивалент −∞), чтобы после него они получили почти нулевой вес. Два самых частых случая:
• padding mask: игнорировать токены-паддинги;
causal mask: в генерации текста запретить смотреть в будущее (токен i видит только позиции ≤ i).

4️⃣ Softmax (и иногда dropout): превращает оценки в нормированные веса (распределение внимания), которые суммируются в 1 по строке — для каждого «смотрящего» токена.

5️⃣ Взвешенная сумма Values: веса умножают на V и суммируют — получается контекстный вектор для каждого токена: он содержит информацию о других токенах пропорционально их важности.

Формально:
Attention(Q,K,V) = softmax(Q·Kᵀ / √dₖ) · V,
где T — транспонирование (чтобы Q·Kᵀ дало матрицу n×n).

Зачем вниманию несколько голов (multi-head)?

Одна голова — это один «взгляд» на последовательность: свои матрицы проекций для Q/K/V и свои веса внимания. Multi-head attention делает такие «взгляды» параллельно: каждая голова считает attention независимо, затем выходы голов конкатенируются и проходят через выходную линейную проекцию (W^O). Практический смысл: разные головы могут подхватывать разные типы зависимостей (локальные, дальние, синтаксические/семантические шаблоны), и итоговый контекст получается богаче.

Наивная реализация self-attention опирается на матрицу n×n, поэтому вычислительная природа операции квадратичная по длине контекста. По памяти квадрат возникает, когда мы явно материализуем/храним attention-матрицу (веса). В продакшене часто используют оптимизированные подходы (например, FlashAttention), которые уменьшают пиковую память за счёт того, что не пишут всю матрицу внимания n×n в глобальную память. В autoregressive inference LLM обычно кэшируют K и V для уже сгенерированных токенов (KV-cache), чтобы не пересчитывать их на каждом шаге. Этот кэш растёт линейно с длиной контекста и на больших окнах часто становится главным потребителем памяти на инференсе. Как прикинуть потребление памяти KV-cache для заданной модели и длины контекста хорошо описано здесь.

✍️ На правах домашнего задания стоит изучить следующие материалы:

The Annotated Transformer
Attention? Attention!
FlashAttention
Краткая история механизма внимания в NLP

... и обязательно поиграться с левой частью интерактивной визуализации 🦄
Please open Telegram to view this post
VIEW IN TELEGRAM
106👍1💯1
Agentity: самомодифицирующийся ИИ-агент

В эфире рубрика «потому что могу» 🦄

Набросал игрушечного (~350 строк кода) ИИ-агента для решения примерно всех задач. Ну... в теории 😬 Из коробки эта кроха умеет только читать собственный код, модифицировать его (преимущественно — добавляя себе реализации новых инструментов, необходимых для достижения цели), и рестартовать с сохранением контекста, чтобы подтягивались сделанные изменения.

В наличии также принудительные проверки всех патчей линтером и тайпчекером, а также режим самопочинки, если крохе удастся досамокодиться до исключений в рантайме.

Задачи «на смекалочку» хорошо решает только с большими моделями, типа gpt-5.2, deepseek и т.п. Увы, но их младшие локальные братья зачастую просто не вдупляют, как им могут помочь доступные на старте три инструмента, несмотря на всё, написанное в системном промпте. Тут и сам промпт оптимизировать надо, и структурированный вывод прикручивать (SGR здесь прям напрашивался, но сразу сделать было лень), и нормальный планировщик запиливать. Ну, или дотошно расписывать в формулировке задачи, как связана модификация кода агента с достижением поставленной цели.

Никаких песочниц или ограничений прав — все сурово и по-взрослому (на всякий случай предупреждаю, если вдруг кто решит запустить).

Ну и пока нормально работает только с задачами, чье решение влезает в одно контекстное окно — ни сжатия/суммаризации контекста, ни суб-агентов, здесь не предусмотрено.

Но, блин, оно работает 🎉 А лежит — здесь.

В комменты скину логи с примерами работы.
Please open Telegram to view this post
VIEW IN TELEGRAM
50🔥91👍1
🎲 Вайб... ресёрчинг?

Вдохновленный OpenSpec'овским opsx-explore (скилл для исследований перед разработкой спеки), сделал его вайбовую версию для ненапряжных ресёрчей по вечерам, когда совсем нехрен делать хочется прекрасного, а думать лень. Воркфлоу предельно простой:

1️⃣ Обозначаете общую тему ресёрча.
2️⃣ ИИ собирает релевантную инфу в сети, обогащает ею контекст, предлагает варианты, и задает уточняющие вопросы.
3️⃣ Отвечаете на вопросы, корректируете текущий вектор мыси на древе, если нужно.
4️⃣ Всё повторяется с шага 2, пока не надоест.

Работает, как часы ☺️ Воткнул его в QoderWork (на скрине, рекомендую — реально хороший агент для повседневных задач, с песочницей и тулами).

В комменты скину SKILL.md, в нём стоит поправить имена тулов для поиска в сети и скачивания контента, если захочется использовать в другом агенте. В теории, ничего не мешает и просто воткнуть текст оттуда в промпт условного ChatGPT, если что.
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥6👍32
🧩 Мой набор кастомных агентских скиллов

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

• vibe-research — скилл из предыдущего поста;
• scamper — трансформация идей по методике SCAMPER;
• explore — обобщенная под произвольные темы ресёрчей версия /opsx-explore из OpenSpec;
• triz-solver — ресёрч через ТРИЗ.

Позднее буду туда докидывать также и скиллы для разработки и прочих смежных задач R&D (сейчас они гвоздями прибиты к моим воркфлоу в Qoder'е, как дойдут руки отвязать — так сразу).
Please open Telegram to view this post
VIEW IN TELEGRAM
14👍103😱1
This media is not supported in your browser
VIEW IN TELEGRAM
Всех подписчиц — с чудесным весенним праздником! 🫶🌷

P.S: код того, что на видео, сложил здесь, если что.
Please open Telegram to view this post
VIEW IN TELEGRAM
512🔥4👍3🥰2
This media is not supported in your browser
VIEW IN TELEGRAM
Вы как, слушаете подкасты? Мне нравится и послушать, и поговорить. Недавно вот, был в гостях у подкаста «В SREду на кухне», который ведут инженеры Avito. Обсуждали, как безопасность влияет на надёжность, где чья зона ответственности и в какой момент разработки уже пора думать о безопасности.

Посмотреть и послушать можно на YouTube, VK Video, RuTube или на странице подкаста.
10👍87🔥5💯3
Тут нечаянно (но зато с душой и в лучших чувствах) родилась вот такая незатейливая утилитка, позволяющая мониторить качество соединения к заданному хосту и фиксировать все отклонения на дашборд и в логи.

Возможно, кому-то окажется полезной 🙈
Please open Telegram to view this post
VIEW IN TELEGRAM
5🔥14😁1
🤏 Как рассуждают кодинг-агенты?

Почему (например) Cline, OpenCode и Claude Code дают настолько разные по полноте и качеству результаты на одной и той же LLM? И почему нетривиальный код, написанный тупо в чате с ChatGPT, почти всегда не заводится с нескольких попыток? Дело здесь не только и не столько в промптах, сколько в модели рассуждений (ризонинге), реализованной в конкретном агенте или чат-боте. Ну и ещё в механизмах управления контекстом, которые, тем не менее, напрямую зависят от ризонинга.

В основе большинства современных агентов лежит композиция нескольких паттернов ризонинга: ReAct задаёт базовый цикл рассуждения и действия, Chain-of-Thought структурирует внутренние рассуждения, Plan-and-Execute разделяет стратегическое планирование и тактическое исполнение, а Reflexion обеспечивает самокоррекцию через вербальную рефлексию.

1️⃣ ReAct: фундаментальный цикл рассуждения и действия

Паттерн ReAct (Reasoning + Acting) является основой практически каждого кодинг-агента. Ключевая идея состоит в том, что на каждом шаге агент генерирует либо «мысль» — свободный рассуждательный трейс, не влияющий на среду, — либо «действие» — вызов инструмента или команду, которая порождает наблюдение из среды.

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

В контексте кодинг-агентов цикл ReAct отображается естественно: мысль — «нужно найти функцию, обрабатывающую аутентификацию», действие — grep -r "def authenticate" src/, наблюдение — список найденных файлов. Далее: мысль — «файл auth.py содержит релевантный код, нужно его прочитать», действие — open auth.py, наблюдение — содержимое файла. И так далее до решения задачи.

Сильные стороны ReAct — интерпретируемость, приземление, гибкость. Ограничения — давление на контекстное окно, чувствительность к качеству примеров в промпте и риск зацикливания без явных механизмов завершения.

2️⃣ Chain-of-Thought: структурирование внутреннего ризонинга

Chain-of-Thought (CoT) заставляет модель генерировать промежуточные шаги рассуждения перед финальным ответом. Для генерации кода это означает, что модель сначала рассуждает об алгоритме, структурах данных и граничных случаях, а затем пишет код.

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

Structured CoT (SCoT) ограничивает рассуждения программными конструкциями — последовательностью, ветвлением и циклом, зеркально отражая структуру исходного кода. Semantic CoT (SeCoT) направляет модель рассуждать о потоке данных и потоке управления перед генерацией кода, что особенно полезно для задач с нетривиальной логикой. Intention CoT (ICoT) фиксирует алгоритмическую суть и временную сложность до написания кода.

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

Продолжение — в следующем посте.
Please open Telegram to view this post
VIEW IN TELEGRAM
47👍3💯1
Продолжение...

3️⃣ Agent-Computer Interface: циклы использования инструментов

Если ReAct задаёт абстрактную схему, то циклы использования инструментов (tool-use loops) наполняют её конкретикой. Кодинг-агент взаимодействует с файловой системой, терминалом, LSP (Language Server Protocol), браузером и интерпретатором кода в итеративных циклах: наблюдение текущего состояния → ризонинг → выбор инструмента и аргументов → исполнение → получение результата → обновление контекста.

Ключевое открытие, определившее направление всего поля, было сделано в SWE-agent: интерфейс между агентом и его инструментами столь же важен, как и базовая модель. Авторы ввели понятие Agent-Computer Interface (ACI) — набора специально спроектированных команд (open, edit, search_dir, find_file), оптимизированных для восприятия LLM. Например, команда edit автоматически проверяет синтаксис и отклоняет некорректные правки, показывая агенту, что пошло не так.

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

Ещё один интересный результат был получен в Live-SWE-agent: агент стартует с минимальным набором инструментов (только bash) и автономно эволюционирует собственный скаффолдинг в процессе работы, адекватно поставленной цели. Собственно, agentity был сделан под влиянием именно этой работы, хотя ризонинг там и ограничивается пусть и специализированным, но весьма примитивным ReAct'ом.

4️⃣ Plan-and-Execute: разделение стратегии и тактики

Паттерн Plan-and-Execute (P-t-E) разделяет процесс на две фазы: сначала модель формирует план (последовательность шагов), затем последовательно исполняет каждый шаг. В кодинг-агентах это часто выглядит как: понять задачу, локализовать релевантный код, спланировать изменения, реализовать изменения, проверить тестами, итерировать при необходимости.

Ключевые варианты: статический P-t-E (план фиксирован), динамический реплэнинг (план пересматривается после каждого шага на основе результатов), иерархическое планирование (цели → подзадачи → конкретные действия) и DAG-based execution, где независимые шаги исполняются параллельно.

5️⃣ Reflexion: вербальное обучение с подкреплением

Reflexion вводит самокоррекцию через вербальную рефлексию — агент анализирует неудачную попытку, формулирует на естественном языке, почему она не удалась, и сохраняет этот анализ в эпизодическую память. При следующей попытке рефлексия включается в контекст, направляя улучшенное поведение.

Архитектура включает три компонента: Актор (генерирует действия в ReAct-стиле), Оценщик (сигнал о качестве траектории — тесты прошли/не прошли, ошибки компиляции), Рефлектор (анализирует неудачу и генерирует вербальную рефлексию).

Reflection-Driven Control идёт ещё дальше, встраивая рефлексию непосредственно в процесс генерации: агент непрерывно запускает внутренний цикл рефлексии, который мониторит и оценивает его собственный путь принятия решений, извлекая релевантные примеры ремонта и руководства по безопасному коду из эволюционирующей рефлективной памяти.

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

Как паттерны композируются в реальных системах

Кодинг-агенты используют композицию этих паттернов. Общая тенденция: Plan-and-Execute на макроуровне для декомпозиции задач, ReAct на микроуровне для каждого шага исполнения, CoT внутри отдельных шагов рассуждения, tool-use loops для приземления в реальность, и Reflexion для самокоррекции при неудачах.

Но дьявол здесь, как водится, в деталях, которые в итоге и определяют качество «выхлопа» агента: как именно реализован ReAct, чем ограничен CoT и каков он, развит ли Reflexion до re-plan, реализован ли DAG в P-t-E и каким образом и т.п.

Если пост вызовет достаточный интерес, попробую подготовить разбор подходов к ризонингу и контекст-менеджменту, реализованных в конкретных кодинг-агентах.
Please open Telegram to view this post
VIEW IN TELEGRAM
211👍8💯2
🥸 Как рассуждает Claude Code?

Как и обещал, рассмотрим подходы, применяемые в реальных решениях. Было бы странно начать не с Claude Code, чей внезапный и незапланированный врыв в мир опенсорса, вчера анонсировали все релевантные каналы.

Архитектура CC основана на 3 типах агентов и 3 механизмах их работы.

Агенты:

• Встроенные (tools/AgentTool/built-in/): generalPurposeAgent — универсальный, Explore — только для чтения кода, и Plan — планировщик.

• Пользовательские — загружаются из .claude/agents/*.md.

• Плагинные — регистрируются через систему плагинов.

Механизмы:

coordinator/coordinatorMode.ts реализует режим, при котором агент-координатор делегирует работу агентам-воркерам.

tools/AgentTool/forkSubagent.ts реализует механизм FORK_SUBAGENT. Субагент наследует полный родительский контекст. Режимы fork и координатор взаимно исключают друг друга.

utils/swarm/spawnInProcess.ts и utils/swarm/inProcessRunner.ts реализуют поддержку механизма, позволяющего запускать рой агентов (по сути — ролевую команду исполнителей).

На всем этом строятся используемые CC подходы к ризонингу.

ReAct: центральный цикл рассуждения, реализован в query.ts:L241-1728, и состоит из обычного «наблюдение→мышление→действие». Действия при этом могут выполняться параллельно, распределяясь по батчам.

Plan & Execute: активируется командой /plan в commands/plan/plan.tsx. В этом режиме модель записывает план в plan.md, пользователь проверяет и одобряет его перед выполнением.

В commands/ultraplan.tsx предусмотрен также более мощный режим Ultraplan, использующий облачные сессии для работы по схеме: «удалённая сессия→мультиагентное исследование→декомпозиция→одобрение→выполнение».

В skills/bundled/batch.ts реализован скилл пакетного выполнения: фаза 1 — исследование и планирование, фаза 2 — декомпозиция на независимые единицы для параллельного выполнения.

Явная реализация CoT отсутствует, CC полагается на возможности своих моделей и имеет три режима: автоматический выбор между следующими двумя, явное включение мышления с лимитом токенов и явное отключение. По аналогии с UltraPlan агент также умеет в UltraThink, увеличивающим бюджет токенов при явном включении, а также — в уровни усилий мышления моделей (utils/effort.ts).

RAG'и, графовые модели кода и т.п. в агенте также отсутствуют. Для быстрой навигации по коду используется tools/AgentTool/built-in/exploreAgent.ts полагающийся на ripgrep (tools/GrepTool/GrepTool.ts) и тулу для чтения файлов (tools/FileReadTool/FileReadTool.ts).

В memdir/memdir.ts также реализована семантическая память: файлы хранятся в ~/.claude/projects/<slug>/memory/, точкой входа служит MEMORY.md. За отбор воспоминаний отвечает memdir/findRelevantMemories.ts: модель выбирает топ-5 наиболее релевантных записей для текущего запроса. Сессионная память реализована в services/SessionMemory/sessionMemory.ts, хранится в ~/.claude/projects/<slug>/session_memory/<sessionId>.md и работаает аналогично семантической, но в рамках конкретной сессии.

А native-ts/file-index/index.ts реализует индексацию кода с нечётким поиском на основе алгоритма Nucleo, применяющим бонусы за совпадение по границам слов, camelCase-совпадения, последовательные совпадения символов, и штрафующим тестовые файлы.

В CC также есть забавный механизм «снов» autoDream (services/autoDream/ для регулярного обогащения семантической памяти новыми знаниями о проекте.

Оффтопиком стоит упомянуть распиаренную команду commands/security-review.ts, по факту представляющую собой промпт в ~200 строк, полагающийся на работу с кодом, как с текстом. И вот к этому есть вопросики, поскольку в больших проектах, протянуть контекст по той же тейнт-модели от сорса к синку, оперируя кодом, как текстом, весьма непросто. Даже примитивная формальная модель кода в виде графа вызовов — уже могла бы улучшить качество ревью в разы (про PDG/CPG скромно промолчу).

TL;DR: архитектура с реализацией достаточно стандартные и незамысловатые (но в этом и их прелесть). Из оригинальных решений стоит выделить роевой запуск агентов, движок сна, и подход к индексации кода и поиску с Nucleo.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍101💔1
Разбор CVE-2025-15031

В понедельник мы публиковали таск про реальную уязыимость в MLflow. Сегодня разбираем, что там произошло, почему это опасно и как это починили (три месяца чинили, кстати).

Вот уязвимый код ещё раз:


def extract_archive_to_dir(archive_path, dest_dir):
os.makedirs(dest_dir, exist_ok=True)
with tarfile.open(archive_path, "r") as tar:
tar.extractall(path=dest_dir)


А вот ссылка на репорт: https://huntr.com/bounties/09856f77-f968-446f-a930-657d126efe4e

Проблема кроется в последней строке: tarfile.extractall() распаковывает архив, доверяя путям файлов внутри него. А эти пути — просто строки, которые записал тот, кто создавал архив, т.е. потенциальный злоумышленник.

Ничто не мешает ему положить в архив файл с именем ../../config/settings.py или /etc/cron.d/backdoor. Python при распаковке честно создаст его именно там, где сказано.

Это атака Tar Slip — та же механика, что и Zip Slip, только для .tar.gz. И она в целом классическая: сама документация Python помечает extractall() как небезопасный метод начиная с 3.12. Но код был написан раньше, и никто не обратил внимания. OpenSource, hah?

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

1. Абсолютный путь


/etc/cron.d/mlflow-backdoor


Файл с абсолютным путём записывается именно туда, игнорируя dest_dir полностью.

2. Path traversal через `..`


../../.env
../../app/config.py


Классика — выход за пределы целевой директории через .. в имени файла.

3. Traversal через симлинк

Это самый хитрый вектор. В архив кладётся симлинк escape -> .., а потом файл escape/pwned.txt. При наивной проверке путь выглядит безобидно — никаких .. в имени. Но физически файл окажется за пределами директории назначения, потому что симлинк выводит наружу.

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

И вот как выглядит исправление


def check_tarfile_security(archive_path):
with tarfile.open(archive_path, "r") as tar:
symlink_set = set()

# Первый проход: собираем все симлинки
for m in tar.getmembers():
path = posixpath.normpath(m.name)
if m.issym():
symlink_set.add(path)
else:
# Блокируем абсолютные пути
if path.startswith("/"):
raise MlflowException(f"Absolute path is not allowed: {path}")
# Блокируем path traversal
if path.split("/")[0] == "..":
raise MlflowException(f"Escaped path is not allowed: {path}")

# Второй проход: проверяем пути через симлинки
for m in tar.getmembers():
if not m.issym():
path_parts = posixpath.normpath(m.name).split("/")
for prefix_len in range(1, len(path_parts) + 1):
prefix = "/".join(path_parts[:prefix_len])
if prefix in symlink_set:
raise MlflowException(
f"Path goes through a symlink, not allowed: {m.name}"
)


И одна строка в extract_archive_to_dir:


def extract_archive_to_dir(archive_path, dest_dir):
check_tarfile_security(archive_path) # <- вот и весь фикс снаружи
os.makedirs(dest_dir, exist_ok=True)
with tarfile.open(archive_path, "r") as tar:
tar.extractall(path=dest_dir)


В контексте MLflow жертва часто даже не знает, что запускает чужой артефакт — модели регулярно обновляются и загружаются автоматически. А сам MLflow нередко работает с широкими правами, потому что ему нужен доступ к S3, базам и GPU-инфраструктуре.

Встречали ли Вы когда-нибудь похожие места в своём коде, где архивы распаковываются без проверки путей? А может, даже писали что-то подобное?🫣
🔥3👍1
🤭 Да или нет вайб-кодингу?

На днях участвовал в дебатах на сабжевую тему, в рамках конференции Data Fusion. И остался под впечатлением, скажем так.

Меня пугают некоторые CTO (благо хоть — из других компаний), которые уже сейчас готовы пересадить всех своих разработчиков на кодинг исключительно с помощью агентов, а всех несогласных — уволить, и заменить ИИ.

Я не луддит. Последние 7-8 месяцев, число строк кода, которые мне пишет ИИ, исчисляется тысячами, иногда — десятками тысяч в месяц. Я перепробовал туеву хучу решений, от Claude Code до весьма недооцененного Oh-My-Pi, плотно поработав с каждым на реальных проектах минимум неделю-две, чтобы решить для себя вопросы его применимости.

ИИ-кодинг прекрасно работает для PoC и MVP, внутренних утилит, быстрой проверки гипотез — везде, где стоимость ошибки низкая. Неплохо справляется и с boilerplate-кодом: ИИ сейчас вполне способен запилить по mockup'ам добротный фронт и грамотного подвязать его к запиленному им же бэку, на уровне чуть выше тривиального CRUD, спрятанного за REST API. Ок. Искренне рад за тех, у кого работа сводится только к этому.

Но даже в этом случае, до того, чтобы стать прод-стандартом, ИИ-кодингу ещё — как до Луны. Стандарт предполагает зрелые процессы вокруг ИИ-разработки, а у большинства компаний их всё ещё нет. Да и пока толком нет понимания, как их выстраивать.

Качество ИИ-кода у более сложных задач, чем обычный веб, ещё и с непростой логикой и алгоритмами, контролем доступа и параллельными вычислениями — вообще отдельная (и весьма печальная) тема. Говорю это, как тот, кто именно такими задачами и занимается 😢

Иллюзия готового продукта

Главный риск ИИ-кода — не в том, что он плохой, содержит баги, уязвимости и т.п. В том-то и беда, что он выглядит убедительно хорошим. Агент выдаёт что-то, что компилируется, проходит тесты, рендерит красивый UI. И возникает непреодолимый соблазн пустить это в прод, не заглядывая внутрь. Тем временем, с точки зрения, как функциональности, так и стабильности с безопасностью, там всё... «альтернативно».

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

Cost-to-deliver vs cost-of-ownership

Все говорят: ИИ снижает стоимость разработки. И это правда — cost-to-deliver падает. Но вот cost-of-ownership — нет. Эксплуатация, поддержка, инциденты, комплаенс. Если ИИ-код не проходит через тот же девсекопс-пайплайн... исследования по-прежнему показывают, что он содержит уязвимости чаще, чем написанный опытными разработчиками. Так это точно дешевле? Или просто кто-то внутрь не заглядывал?

Инженер ≠ оператор промптов

Человек, который виртуозно промптит, но слаб без AI — это инженер? Я считаю — нет. Инженер — тот, кто понимает, почему код работает, а не только что он делает. Кто может объяснить, почему в промпте или ризонинге были приняты те или иные решения, по всем аспектам. ИИ снижает порог входа в написание кода — это прекрасно. Но не в предметную область. И теперь нужно не просто писать код, а уметь промптить чуть выше уровня «сделай мне збс», писать спеки, и обеспечивать качество кода, который ты не писал сам.

За любой инцидент отвечать потом придется всё же человеку, а не ИИ.

Возможно, через 2-3 года инженерам вообще не нужно будет смотреть в ИИ-код и разбираться в нём. Мне бы очень хотелось, чтобы однажды это стало возможным. Но сейчас «попромптил и задеплоил» звучит так же дико, как «я не пишу тесты — и так работает».

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

TL;DR: ИИ-кодинг сейчас — ок, но без зрелых процессов, построенных вокруг него, с учетом всей его специфики и сопутствующих рисков — чистое безумие. Или непрофессионализм, тут уж кому как.
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥17👍9💯6