Arhellist
3 subscribers
41 photos
31 links
Алексей Пасечник (Arhellist) — fullstack-разработчик, более 7 лет в коммерческой разработке, основатель xChangePro. Пишу о разработке, AI-инструментах и своих проектах. Сайт: arhellist.ru · Связь: @arhellist
Download Telegram
Outbox: коробка недоделанных побочных эффектов

Агент решил отправить задачу другой группе или записать файл, и тут процесс упал. Сделалось действие или нет? В Элис на это отвечает outbox — «коробка недоделанных побочных эффектов».

Как это устроено и почему идемпотентность здесь важнее скорости.

Полный текст — в следующем сообщении 👇
Идея. Действие, которое меняет мир, сначала кладёт в state.db запись «надо сделать». Потом выполняется. Потом запись закрывается. После рестарта система первым делом разбирает pending: доделывает или честно закрывает.

Что даёт:
• не теряются действия, которые агент «обещал» сделать;
• действия не выполняются дважды вслепую;
• видно, на каком шаге оборвалось.

Связь с журналом. Outbox живёт в state.db, а state.db — проекция журнала. Поэтому намерение и результат видны и в аудите, и при replay.

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

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

Дальше — как стартует задача: от команды до первого вызова модели.

#HarnessOS #Элис #outbox #надёжность

👉 Канал про HarnessOS и Элис: https://t.me/harness_ai_ru
Как я решал самые сложные задачи

Как я строил HarnessOS · 9/10

Resume, rollback и идемпотентность: три задачи про надёжность, которые оказались самыми сложными. Без деталей реализации.

Полный текст — в следующем сообщении 👇
Каждый из сложных аспектов harness’а я решал отдельно. Не пытался сделать всё сразу.

Вот три задачи, которые оказались самыми сложными. И как я их решал — без деталей реализации.

Задача 1. Как не терять работу при сбоях

Представь: агент делает задачу из 10 шагов. Сделал 6. Упал сервер.

Наивное решение — начать заново. Минус: теряется время, сжигаются токены.

Что я сделал: каждое действие агента записывается. Не в оперативную память, а в постоянное хранилище. Когда агент запускается снова, он читает эту запись и понимает, где остановился.

Это называется resume. Работа не теряется. Продолжаем с того же места.

Задача 2. Как откатывать плохие шаги

Представь: агент сделал шаг, и что-то сломалось. Он понял, что сделал неправильно.

Наивное решение — чинить руками. Минус: долго, рискованно, можно сломать ещё больше.

Что я сделал: после каждого шага агента сохраняется снимок состояния. Если шаг плохой, берём предыдущий снимок. Всё, что было после, отменяется.

Это называется rollback. Не надо чинить руками. Откатил — и работаешь с чистой точки.

Задача 3. Как не создавать дубли

Представь: агент отправил команду «создать заказ». Но ответ не пришёл — сеть моргнула. Агент не знает, создался заказ или нет.

Наивное решение — повторить. Минус: создастся второй заказ.

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

Это называется идемпотентностью (idempotency). Повторная попытка не ломает систему.

Все три задачи — про надёжность. Про то, что может пойти не так. И про то, чтобы система не рассыпалась от первой же проблемы.

В последнем посте серии — что я понял за это время.

#HarnessOS #AIразработка #КакЯСтроилHarnessOS #AIагенты #разработка
Как стартует задача: от команды до первого токена

Что происходит между «оператор нажал Enter» и «модель начала думать»? В Элис это девять шагов, и у каждого своя причина существовать.

Разбираю путь: вход → транспорт → замок → outbox → журнал → классификатор → промпт → цикл → честный конец.

Полный текст — в следующем сообщении 👇
Путь задачи:
• вход: harness run, Mission Control или транспорт;
• оркестратор выбирает транспорт — локально, unix-сокет или remote — с одним контрактом: отправь, прерви, поставь в очередь, запроси одобрение;
• замок: один активный разговор на группу, иначе очередь или отказ «занято»;
• восстановление outbox;
• запись в журнал и стрим в UI;
• классификация: поиск, навигация, файлы, генерация, побочный эффект, многошаговая, болтовня, системная;
• системный промпт и цикл;
• ответ или инструменты, по кругу;
• проверка «не молчаливый ли провал», конец разговора с режимом исхода и кодом выхода CLI.

Деталь про поиск. Для поисковых задач бот сначала смотрит сниппеты, а не спрашивает оператора «выбери сайт 1/2/3».

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

Дальше — раннеры и цикл агента.

#HarnessOS #Элис #AIагенты #архитектура

👉 Канал про HarnessOS и Элис: https://t.me/harness_ai_ru
Что я понял в процессе

Как я строил HarnessOS · 10/10

Пять вещей, которые я понял, пока строил HarnessOS. Первая: модель — не главное.

Полный текст — в следующем сообщении 👇
Когда я начинал, я думал, что строю «AI-инструмент». В какой-то момент понял, что строю операционную систему для AI-разработки.

Это другая категория продукта. Не «помощник в редакторе», а control plane. Не «быстрее писать код», а управлять процессом.

Вот пять вещей, которые я понял.

Первое: модель — не главное.

Можно взять DeepSeek. Можно локальную модель через Ollama. Можно что угодно. Результат во многом определяется harness’ом. Хороший harness с обычной моделью нередко даёт больше, чем слабый harness с топовой.

Второе: дисциплина важнее скорости.

Быстро писать код без дисциплины — это скорость без направления. Verification Tax съедает всё, что ты сэкономил. Дисциплина — это направление.

Третье: приёмка — самое сложное.

Не оркестрация. Не инфраструктура. А доказать, что результат корректен. Это человеческая задача, а не техническая. HarnessOS её не убирает. Он делает её явной.

Четвёртое: self-hosted — не фича, а принцип.

Не опция. Не «для Enterprise». А основа. Код, память, логи — у тебя. Это не «мы такие хорошие». Это архитектурное решение.

Пятое: я на правильной стороне рынка.

DeepSeek, GitHub и AWS вкладываются в harness’ы и разработку по спецификациям. Сообщество уже склеивает эти инструменты плагинами. Значит, проблема реальная. Готового self-hosted control plane, который собирает спецификации, исполнение, проверки и эскалацию в один процесс, я пока не нашёл. Это моя ниша.

Что дальше

Я не строю «ещё один AI-инструмент». Я строю инфраструктуру для управляемой AI-разработки. Это долгая игра. Но правильная.

Спасибо, что дочитали. Если интересно — подписывайтесь. Буду рассказывать, как продвигается.

#HarnessOS #AIразработка #КакЯСтроилHarnessOS #AIагенты #разработка
Цикл агента: модель → инструменты → снова модель

В Элис цикл разделён на две роли. ConversationRunner — режиссёр всего прогона. AgentLoop — один ход с моделью. Плюс отдельные раннеры для субагентов и eval.

Рассказываю, где с DeepSeek пришлось повозиться.

Полный текст — в следующем сообщении 👇
ConversationRunner собирает прогон: группа, клиент модели, реестр инструментов, бюджет, политика. Держит лимиты ходов, бюджет, прерывания, сжатие. После успеха фоном предлагает сохранить навык. Есть fixture-режим без живой модели — для дымовых тестов.

AgentLoop — один ход: стабильный системный текст + история + динамический хвост, вызов DeepSeek, затем ответ или инструменты. Прогресс и статус отделены от финального ответа.

Раннер субагента. Агент из файла в agents/ вызывается как инструмент, пишет в журнал родителя, а его бюджет не больше остатка бюджета родителя.

Раннер eval — гоняет сценарии качества.

Ключевая трудность (инженерная): reasoning round-trip и целостность пар. DeepSeek требует, чтобы рассуждения модели гонялись туда-обратно в истории. И цепочка «вызов ↔ результат» должна быть целой до следующего HTTP-запроса: у каждого вызова — ровно один результат с нужным идентификатором. Если пара порвана, это нарушение протокола и стоп, а не «как-нибудь продолжим». Отсюда правило: отказ политики, таймаут и прерывание — тоже полноценные результаты. И при сжатии истории нельзя разрезать пару посередине.

Дальше — кэш промпта и почему в префиксе нельзя писать время.

#HarnessOS #Элис #DeepSeek #LLM

👉 Канал про HarnessOS и Элис: https://t.me/harness_ai_ru
Стабильный префикс и динамический хвост

Стабильный префикс в Элис — это одинаковые байты между вызовами внутри группы. Всё изменчивое уходит в динамический хвост — отдельное system-сообщение после истории. Это не эстетика, а деньги и скорость: префикс попадает в кэш провайдера.

Почему одна строка с текущим временем обнуляет кэш.

Полный текст — в следующем сообщении 👇
В стабильном префиксе:
• кто ты;
• инварианты: не выводи секреты, не обходи тюрьму путей, не вводи пароли, не решай CAPTCHA;
• контракт общения;
• каталог навыков (только каталог, не тела);
• правила доверия к браузеру;
• типы задач.

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

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

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

Дальше — контракт общения и классификатор задач.

#HarnessOS #Элис #LLM #promptcaching

👉 Канал про HarnessOS и Элис: https://t.me/harness_ai_ru
Внешний вызов прошёл, а запись — нет

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

Разбор — в следующем сообщении 👇

#ЭлисAI #ИИагенты #архитектура
Внешний вызов прошёл, а запись — нет

Вопрос звучит просто: «внешний вызов уже прошёл, а результат не успел записаться на диск — сверяться с внешней системой или останавливаться и ждать оператора?»

На самом деле «сверяться или ждать» — ложная дилемма. Безопасность — не свойство метода сверки, а свойство самого действия. У разных действий разные гарантии, и одна политика на всех — верный способ сделать систему либо опасной, либо бесполезной.

Три примера:
- файл записан атомарно, но событие в журнал не попало — сверка «файл существует?» решает проблему;
- письмо, возможно, ушло — но мы этого не знаем. Повтор — это второе письмо, значит, единственный безопасный выбор — оператор;
- git push прошёл — сверка возможна, но требует внешней точки правды, которая сама может врать.

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

Почему не «всегда сверяться»? Сверка — тоже внешний вызов: она может упасть, вернуть неверный ответ или занять время. Почему не «всегда ждать оператора»? Оператор — не бесплатный ресурс: если каждая запись файла требует подтверждения, агент бесполезен. А «повторять всё, что не записалось» — самый опасный вариант: второе письмо, двойное списание.

Технически всё просто: перед каждым действием записываем намерение, после него — результат. «Намерение есть, результата нет» — это и есть точка сверки. Дальше — по классу действия: файловые и read-only операции сверяем и повторяем, браузерные и time-sensitive помечаем needs_reconcile и ждём решения оператора.

И главное: класс действия должен быть явным. Не «агент сам решит», а «в контракте инструмента написано». Агент не должен угадывать.

Полный разбор — с примерами, классами действий и тем, что не работает, — в блоге: https://blog.arhellist.ru/blog/vneshniy-vyzov-proshyol-a-zapis-net-sveryatsya-ili-zhdat-operatora

#ЭлисAI #ИИагенты #архитектура
Кто принимает результат

Кто принимает результат — агент или отдельный проверяющий? Коротко: агент производит, код принимает — на трёх уровнях.

Разбор — в следующем сообщении 👇

#ЭлисAI #ИИагенты #архитектура
Кто принимает результат

Вопрос: «кто принимает результат — отдельный проверяющий шаг или сам агент?» Это вопрос про архитектуру доверия в многошаговом агенте. И ответ — не «то или это», а «и то, и другое, но в разных ролях».

«Сам агент» — это декларация, а не проверка. Агент видит интерфейс, а не реальность: тост «письмо отправлено» мог быть про черновик. Агент не врёт — он просто не знает, что произошло на самом деле.

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

Что работает — три уровня приёмки, каждый ловит свой класс ошибок:
- оракул — код, который проверяет факт (slug, теги, письмо в «Отправленных», текст в PDF) и говорит PASS или FAIL;
- аудит — проверяет полноту: всё ли, что просили, сделано;
- оператор — разрешает неопределённость там, где повтор опасен, а сверка ненадёжна.

Оракул не спрашивает агента: он смотрит в реальность и, если FAIL, возвращает конкретное поле — «slug старый», «теги не те». Пока оракул не сказал PASS, задача не закрыта. Аудит ловит «сделал две вещи из трёх», оператор — «мы не знаем, что произошло, и автоматика не может узнать».

Каждый уровень дополняет другие, а не заменяет. Если убрать один, ошибки его класса проходят. И LLM-judge здесь — не судья: это мнение, а не факт, полезный дополнительный фильтр, но не замена оракулу.

Итог: агент результат производит, а принимает его код. Агент, который принимает результат сам, — это агент, который врёт с чистой совестью. Агент, который отдаёт результат на проверку коду и человеку, — это агент, которому можно доверять.

Полный разбор — с примером из жизни и тем, что не работает, — в блоге: https://blog.arhellist.ru/blog/kto-prinimaet-rezultat-v-mnogoshagovom-agente-agent-proveryayuschiy-ili-kod

#ЭлисAI #ИИагенты #архитектура
Недавно прошёл свои витрины чек-листом технического SEO — не ради отчёта, а чтобы понять, что реально видит бот.

Коротко, что смотрел и правил:
• текст/title/h1 в HTML, а не пустой CSR-shell
• уникальные title, description, canonical
• один h1, без служебных EN-stubs
• честный 404 (+ noindex), не soft-404 с 200
• редиректы без хоровода: https, www↔apex, trailing slash
• robots + sitemap без служебного и дублей
• сжатие: gzip и отдельно brotli (Accept-Encoding: br → content-encoding: br)
• кэш HTML без вечного no-store и без годового s-maxage без purge
• JSON-LD по типу страницы
• тонкий контент vs карточки + один CTA
• дубли путей (поддомен блога vs /blog/, чужой canonical)
• HSTS, nosniff; по желанию убрать версию nginx из Server

Brotli в этом списке не «вишенка»: если клиент просит br, а вы отдаёте сырой или только gzip — просто дарите лишний вес ответа.

Полный разбор — в блоге https://arhellist.ru/blog/tehnicheskoe-seo-kak-chek-list-chto-ya-proveryayu-na-svoih-vitrinah/.


Почему Next SSR, а не обычный SPA на React: боту нужен текст в первом HTML. SPA часто отдаёт пустую оболочку и ждёт JS — человек видит страницу, робот нет. SSR отдаёт готовую разметку сразу; React потом только оживляет UI. Для публичных витрин так спокойнее с title/h1/404/canonical.

#seo #техническоеSEO #webdev #brotli
Контракт общения: почему агент не должен читать лекции

Пишешь агенту «глянь, что там с ценами», а получаешь три абзаца теории и вопрос «какой сайт вы имели в виду?». Модель не глупая — ей просто никто не объяснил, что за сообщение перед ней. В Элис эту проблему решают два механизма: классификатор задач и контракт общения из шести правил.

Полный текст — в следующем сообщении 👇

#Элис #ЭлисAI #AIагенты #LLM
Контракт общения: почему агент не должен читать лекции

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

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

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

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

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

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

Урок: прежде чем учить агента отвечать, научите его понимать, что именно у него спросили.

А вас агенты чаще раздражают лекциями или вопросами?

#Элис #ЭлисAI #AIагенты #LLM

👉 Канал про Элис: https://t.me/harness_ai_ru
Охрана ответа: как поймать агента на «уже отправил»

Самая неприятная ошибка агента — не падение, а уверенное «отправил», когда ничего не отправлено. Падение видно сразу. Ложный отчёт всплывает, когда уже поздно. Рассказываю, как в Элис финальный ответ сверяется с журналом действий.

Полный текст — в следующем сообщении 👇

#Элис #ЭлисAI #AIагенты #надёжность