Я разрабатываю ИИ-планировщик, которому можно писать обычным языком: «перенеси встречу с Сергеем», «каждую первую субботу проверяй остатки корма» или «нет, не событие, а дело». Код в основном создаётся агентом, а мои усилия уходят на описание предметной области, пользовательских сценариев и проверок.
Это не туториал по созданию готового SaaS и не подробный разбор агентской разработки. Статья — промежуточный отчёт о проекте: какую предметную модель я выбрал, как проверяю ответы моделей, почему разделил LLM и детерминированные операции и с какими проблемами столкнулся после первого деплоя.
В статье я показываю архитектурные решения и текущие результаты, включая те части, которые ещё не работают идеально.
Состояние проекта: закрытая бета. На сайте доступен ограниченный демо-режим и лист ожидания: planitforme.ru. Исходный код пока закрыт.
До этого у меня был опыт использования агентской разработки для создания специализированного ЯП, но это был узконаправленный исследовательский интерес. Также я активно применяю агентов для разработки и автоматизации своей рутины как тимлида небольшой команды. При этом опыта создавать с нуля приложение, проектировать UX/UI/CUI, чат-бота, безопасность, расписывать пользовательские сценарии и реализовывать различные схемы работы с моделью, у меня ещё не было и данная статья является попыткой зафиксировать то, с чем я столкнулся, работая над пет-проектом.
Пта статья про разработку в ситуации, когда времени и денег мало, зато полно энтузиазма решить прикладную задачу — перестать забывать редкие события и не тратить много времени на трекинг дел. Моя методика реализации проекта исходит из ограничений: код не пишется руками и существенная часть усилий тратится на фиксацию требований и созданию условий для доказуемых инкрементальных улучшений. Это моё ключевое решение и в некотором смысле суть эксперимента — вместо работы непосредственно над продуктом строить обвязку, позволяющую агентам выстроить нужный мне продукт.
Идея проекта
Мечта об умном чате для планирования возникла у меня ещё до массового распространения ИИ и ждала, а возможно, ещё подождёт, оптимального отношения цены, скорости и зрелости моделей.
Если простой TODO-лист пишется не приходя в сознание за 15 минут на любом современном фреймворке, то как только мы пытаемся сделать что-то более сложное и минимизировать когнитивную нагрузку на пользователя, то будто бы утыкаемся в бетонную стену. Моя проблема со всеми приложениями, которые я пробовал, заключается в том, что в какой-то момент мне нужно тратить слишком много времени на поддержание запланированного.
Я же хочу планировать так, будто я общаюсь с ассистентом, причём в тех каналах, где я уже привык общаться текстом или голосом. В моём случае это Telegram и Алиса. Пользовательский интерфейс нужен скорее для того, чтобы проконтролировать, посмотреть прогресс или эпизодически, когда есть подходящее настроение, плотно поработать над планами.
Есть вариант взять что-то наподобие OpenClaw или другого агента и получить возможность планирования практически за бесплатно. Это частично так. Действительно, возможность вести личные дела в Obsidian и подключить к агенту Telegram многое решает. Но такое взаимодействие нельзя назвать полноценным продуктом. Это скорее некий DIY-проект, который может дать впечатляющие результаты, но требует времени на настройку и вовлечение.
В специализированном решении можно задать онтологию предметной области, закрепить интеграции и контракты, сделать специализированный UI и разбор сложных кейсов. Нарастить обвязку, целиком заточенную под решение конкретных продуктовых задач. Например, мне важно, чтобы приложение обеспечивало быстрые и правильные ответы, точно ловило мои интенции и имело при этом низкую себестоимость.
Если смотреть под таким углом, то планировщик, который я задумал, должен дополнять вещи типа OpenClaw, а не конкурировать с ними: персональный ИИ-помощник может использовать API планера для создания задач, загружать и выгружать сущности, и это, на мой взгляд, только дополняет картину. Но и без ассистента у меня должна быть возможность быстро запланировать задачу, скорректировать планы и получить о них детальную информацию.
С точки зрения компонент приложения всё выглядит так:
Основное веб-приложение
Админка (prompt-studia)
HTTP API
MCP (WIP)
Чат-бот для ТГ
Обвязка для Алисы (WIP)
По языкам: фронтенд на TypeScript, весь бек на питоне
Агент: Codex (GPT-5.5 High)
Навыки для ИИ: superpowers и несколько своих навыков для контура знаний и продуктовой разработки.
Мне нравится начинать любой проект с построения модели предметной области. Раньше это были формальные и не очень OWL-онтологии, сейчас — просто некая вспомогательная конструкция, которая помогает понять, что есть, что можно получить из того, что есть, и даёт дополнительные ограничения для кодирующих агентов. Наличие онтологии даёт агентам опору при генерации тестовых сценариев и позволяет точно отвечать на вопрос что предусмотрено, а что нет. Кроме того, это даёт более точную коммуникацию с агентом — он меньше угадывает и чинить ошибки понимания тоже проще, например корректирующая фраза "не событие, а дело" имеет вполне себе точный смысл, если "событие" и "дело" — известные агенту сущности.
На картинке не полная онтология, но показательная. Отличается она в основном тем, что сфера — отдельная сущность, и кроме неизменной сферы «Жизнь», которая есть у всех изначально, пользователи могут добавить другие сферы, например «Работа». Также отсутствуют технические сущности типа "Пункт в расписании".

Процесс проектирования был непростым, так как, с одной стороны, хотелось опираться на понятные метафоры — путь / шаг / цель, а с другой — я совершенно не привык к неймингу сущностей на русском, и это оказалась одна из плохо делегируемых LLM тем. Я до конца так и не уверен, что преуспел, но на текущий момент большая часть моих дел органично вписываются в заданный каркас.
Требования к планировщику
Далее я хотел, чтобы у приложения была возможность:
создавать планы с привязкой к дате и без неё;
задавать минимальный интервал между событиями («переворачивать матрас каждые две недели»);
привязываться к порядковому номеру временной сущности («последнюю субботу месяца планировать вылазки на следующий месяц»);
создавать события, которые длятся несколько дней, и при этом я могу быть занят постоянно в эти дни (командировка) или частично (фестиваль/конференция в моём городе), а расписание занятости может изменяться в зависимости от дня;
записывать рутины — действия, которые должны повторяться, о которых нужно помнить, но для которых история не важна. Например, планировать еду на неделю по субботам;
записывать практики — действия, для которых важны непрерывность и отслеживаемость. Например, занятия йогой;
связывать планы с людьми и местами. Например: «Пойти с женой в кино»;
создавать текстовые заметки, связанные с планами;
использовать русский язык со всей его вариативностью.
Наглядный пример:
Раз в две недели по средам вечером созваниваться с мамой
В этой фразе есть несколько разных смысловых слоёв:
это регулярное действие, а не разовая задача;
интервал — раз в две недели;
день недели — среда;
время — вечер, то есть мягкое окно, а не точное
19:30;человек — мама, и это может быть важным контекстом для будущих запросов;
действие относится к личной сфере, а не к работе;
если пользователь пропустит созвон и сделает его позже, возможно, следующий повтор должен считаться от фактического выполнения.
Задача планировщика — превратить бытовую фразу в связку устойчивых сущностей так, чтобы с этой связкой можно было работать в дальнейшем: исправлять, планировать, переносить и использовать через API.
Ещё несколько примеров:
Фраза пользователя | Наивная трактовка | Что нужно хранить на самом деле |
|---|---|---|
| Ежемесячная задача | Рутину с правилом «первая суббота месяца» и отдельный подготовительный шаг «проверить остатки», потому что порядок действий важен. |
| Событие в октябре или заметка | Обслуживающую рутину или запланированное дело с неточной датой: месяц известен, день может потребовать уточнения, следующий цикл должен считаться от фактического выполнения. |
| Календарное событие с точным временем | Дело, а не событие: дата «завтра», мягкое время «вечером», без фиксации точного начала и конца. |
| Текстовая заметка или простой reminder | Событие: точное начало, длительность 2 часа, человек |
| Создать новое событие «встреча с Сергеем» | Обновить уже существующее событие, найденное по названию и человеку; сохранить идентичность, не делать дубль. |
| Создать новую встречу в офисе | Обновить место существующей встречи, не потеряв время и участника. |
| Человек | Дело или событие с ролью/командой в тексте; |
Главная сложность здесь не в извлечении даты или названия сущности. Системе нужно понять, создаёт ли пользователь новый объект, изменяет существующий или исправляет предыдущую интерпретацию. Ошибка на этом этапе приводит либо к дублям, либо к изменению не того объекта. Поэтому дальнейшая архитектура строится вокруг сохранения идентичности сущностей, контролируемых исправлений и регрессионных сценариев.
Реализация

При таком подходе нужно будет сразу отдавать LLM весь контекст, из-за чего сразу понятно, что он не годится — мы быстро превысим короткие контексты флеш моделей и сильно усложним им задачу. Но даже такой пайплайн позволяет собрать контур тестирования, посмотреть на ответы разных LLM-моделей и понять, какие промпты для чего лучше подходят. Следующий шаг — сделать так, чтобы функционал приложения был доступен для модели в виде описанного набора возможных вызовов.
Очень быстро я пришёл к тому, что мне нужна качественная обвязка — то, что в статьях по ИИ называется harness. Тащить LangChain/Graph казалось усложнением, и я решил сделать узкозаточенный инструмент — так появился PromptStudio. Это админка, которая позволяет динамически задавать промпты, работать с моделью напрямую, смотреть трейсы, работать с инструментами, задавать сценарии для проверки и вести статистику по связкам «модель + промпт». Всё это можно было собрать из открытых решений, но это казалось и до сих пор кажется сложнее, чем завайбкодить за пару дней что-то своё.
Существенный фактор в пользу вайбкодинга — я сразу понимал, что нужно и что я собираюсь делать: хранить в YAML весь пайплайн, редактировать его в UI, иметь возможность варьировать запросы к моделям в пайплайнах и прогонять разные пайплайны на разных моделях с наборами тестов, чтобы в итоге автоматически получить скор. Также студия умеет использовать сервисы планера как инструменты модели и привязывать пайплайны к API.
Как это всё выглядит

Я загрузил в неё набор из 64 базовых сценариев и стал проверять их на бесплатных моделях (локально и через OpenRouter) и яндексовских моделях. Само облако мне знакомо по прошлым проектам, плюс есть начальный грант. Так я определил круг моделей, которые достаточно выразительны, чтобы пройти все кейсы без ошибок.
Сценарии устроены следующим образом: они определяют, что отсылать и какой дополнительный контекст передавать, а затем проверяются статус ответа, тип сущности, действие, ключевые поля, отсутствие лишних уточнений, сохранение в БД, отсутствие дублей, чистота контракта и иногда задержка с токенами. Сейчас всё устроено так, что почти каждая найденная ошибка автоматически превращается в сценарий, в котором выделяются части, отличающие его от существующих сценариев, и таким образом база проверок ежедневно растёт.
Пример простого сценария — один запрос + немного контекста:
{ "text": "Встретиться с Сергеем сегодня в 19:00", "quick_add": true, "user_context": { "language": "ru", "timezone": "Europe/Moscow", "known_spheres": [ "Жизнь", "Работа", "Здоровье" ] }, "shortlists": { "goals": [ "Запустить MVP продукта", "Ремонт" ], "milestones": [ "Согласовать словарь", "Разработка" ], "people": [ "Сергей — коллега", "Сергей — тренер", "Мария", "Анна" ], "locations": [ "Офис", "Namastation" ] }, "context_ids": {} }
Есть более сложные варианты, где пользователь может уточнить уже сделанный запрос и, например, отметить прогресс. Для каждого варианта можно оценить, насколько модель справилась: вызвала ли нужный инструмент, смогла ли заполнить итоговую структуру. Баллы за каждый пункт проставляет SOTA-модель. Я пока не встречал кейс, где она бы ошиблась и сделала что-то неправильное.
Когда я только начал экспериментировать, наиболее комфортной из открытых моделей была Qwen 235B A22B. Какое-то время я был ею доволен: модель прощала много ошибок, на моих тестах с отрывом набирала большое количество очков, и в целом выглядело так, что по соотношению цены и качества — самое то. Минуса было два:
Цену хотелось ещё ниже: эксперименты быстро высасывают выданный грант, а мне хотелось проверить как можно больше гипотез за как можно меньше денег. Один прогон на всех сценариях выходил в 500–800 рублей, в зависимости от количества пайплайнов.
Скорость. Модель работала сильно медленно, около 30 секунд на ответ, и это ставило саму идею проекта под угрозу. Дело в том, что основной интерфейс должен быть чат/войсы, а в таком режиме 30 секунд — слишком ощутимая задержка.
Тогда я стал исследовать модели с быстрым инференсом и смотреть предложения на российском рынке. Быстро выяснилось, что можно далеко не ходить — хорошие результаты показала яндексовская Alice AI LLM Flash, которую я дисквалифицировал на первом отсеве из-за того, что она стабильно игнорировала часть инструкций. Но к этому моменту я уже был более подготовлен — после экспериментов с бесплатными и локальными моделями, и у меня был развитый repair-слой, который позволял не замечать некоторые вольности в формировании JSON и доводил вывод модели до необходимого контракта. При этом яндексовская «флешка» отвечала остальным критериям: низкая цена и высокая скорость работы. Большая часть ответов укладывалась в 5 секунд даже с корректирующими запросами Так, обнаружив, что мои базовые кейсы проходят, я решил остановить дальнейшие поиски .
Хочется отметить, что в некоторых случаях для классификации намерения модель вообще не нужна: справляются комбинация dateparse, pymorph3 и rapidfuzz. Были большие надежды на Natasha, но они не оправдались: тесты сходу не показали качественного улучшения, и я отложил эту идею до той поры, когда можно будет выделить большее времени на погружение в детали.
В итоге пришел к следующему варианту

В нем есть несколько интересных частей:
1) Быстрая классификация
В этой части нужен ответ на вопрос: "куда это примерно отправить?"
Система проверяет типовые сигналы:
явные префиксы:
Заметка:,Событие:,Цель:,Шаг:вопросительные формы:
что,когда,покажи,?планировочные фразы:
спланируй день,составь планповторяемость:
каждый,ежедневнокоды сущностей:
S12,E5,G3временные маркеры:
завтра,сегодня, день недели, дата, время
Далее есть система правил для начальной классификации, например:event = есть явный маркер события OR есть дата + точное время OR есть день/временной маркер + час
После чего событие обогащается различными полями (например, уверенность в трактовке намерения и альтернативы, если они есть) и отправляется дальше по пайплайну.
2) Контур исправления
Тут происходит проверка — хочет ли пользователь что-то исправить или создаёт новую сущность. Если по типовым сигналам мы распознаём исправление, то дальше запускается алгоритм
"найти последнюю интерпретацию или сущность по коду → понять тип исправления → применить безопасную операцию → сохранить историю исправления → ответить пользователю"
Поддерживаемые типы исправлений:
сменить тип:
Событие → Делопоправить дату или время
привязать к существующей сущности
заполнить недостающее поле
обновить место, описание, статус
архивировать или завершить сущность
При этом исправление не переписывает историю — старый объект может быть архивирован, новый — создан, а связь между ними будет сохранена в служебном поле. Сохранять связьь критично важно, так как это позволяет собирать больше контекста при ошибках.
3) Детерминированные инструменты
Модель, если она нужна, не пишет напрямую в базу. Она возвращает структурированное намерение:создать дело, обновить событие, архивировать практику, привязать заметку к событию
Дале вызываются детерминированные функции сервиса, напримерcreate_entity update_entity get_entity и множество других
Именно инструменты проверяют существует ли сущность, принадлежит ли она пользователю, не архивна ли цель или веха, можно ли завершить объект, не нужно ли подтверждать действие пользователя.
Вынос проекта за пределы личного ноутбука
С одной стороны, мне хотелось выкатываться сразу в что-то публичное, но при этом хотелось чтобы было сделано больше минимума и система проходила сложные сценарии без запинок . С другой стороны, психологически хотелось иметь доказательство, что это всё может быть опубликовано. Пару вечеров потратил на то, чтобы осмыслить, как должна выглядеть регистрация, первый вход пользователя в систему, чем деплоить, как подключать бота и какие согласия нужно спросить.
Помню как почувствовал радость и гордость, когда в первый раз прошел регистрацию уже в прод-режиме и запланировал через телеграм первое событие. Радость была недолгой — на первых порах было очень много ошибок, которые я постепенно вычищал и сейчас большая часть команд разбирается корректно, но всё ещё есть сложные для разбора сценарии, к которым ещё нужно найти свой подход.
Примеры диалогов через ТГ



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