Забудьте про фреймворки. Пора строить как инженер
Откройте любой гайд по созданию AI-агентов в 2026 году. Что вы увидите? Стек из пяти фреймворков, три оркестратора, обязательная векторная база и триста строк конфигурационного YAML. Все это ради агента, который отправляет вам прогноз погоды. Абсурд.
Jarvis Pattern - это реакция на эту идиотию. Это не новый фреймворк. Это архитектурный подход, который выбрасывает 90% инфраструктуры и оставляет только то, что действительно работает. Секрет в том, что сложные мультиагентные системы - это одно, а ваш личный помощник для календаря и почты - совсем другое. Для второго не нужен Kubernetes.
Если ваш агент делает больше трех вызовов к LLM для выполнения одной задачи - вы уже проиграли. Сложность растет экспоненциально, а отдача - линейно.
Почему фреймворки для агентов - это ловушка
Возьмите любой популярный фреймворк для AI-агентов. У них общая болезнь: они решают проблемы создателей фреймворков, а не ваши проблемы. Вам нужен агент, который в 9 утро напоминает о встрече? Фреймворк предлагает вам распределенную систему сообщений, persistence layer и плагин для мониторинга.
Реальность: 95% персональных агентов выполняют меньше 10 типов задач. Календарь, почта, заметки, поиск в интернете. Зачем вам для этого граф исполнения?
- Ненужная абстракция: Фреймворки скрывают логику за слоями конфигурации. Когда что-то ломается, вы тратите часы на отладку черного ящика.
- Over-engineering: Вам предлагают масштабируемость на миллион агентов, когда у вас один.
- Привязка к вендору: Многие фреймворки заточены под конкретные облачные AI-сервисы. Попробуйте сменить модель - получите рефакторинг половины кода.
В статье "Когда фреймворки слишком сложны" я уже показывал, что иногда проще использовать готовые приложения. Но если вы хотите контроль - читайте дальше.
Сердце Jarvis Pattern: одна функция, один цикл, один контекст
Архитектура до неприличия проста. Представьте один Python-скрипт, который работает в бесконечном цикле. Он слушает события (новое письмо, напоминание в календаре, голосовая команда). Для каждого события он вызывает LLM с контекстом и списком доступных действий. LLM возвращает команду для выполнения. Скрипт выполняет команду. Все.
Почему это работает? Потому что современные LLM на 03.04.2026 (я смотрю на вас, GPT-4.5 Turbo, Claude 3.7 Sonnet и открытые аналоги) достаточно умны, чтобы понимать контекст без векторного поиска. Им не нужен RAG для того, чтобы вспомнить, что вы вчера обсуждали с коллегой в Slack. Достаточно сохранить последние 10 сообщений в текстовом файле.
1Шаг 1: Режем функционал до костей
Возьмите лист бумаги. Выпишите все, что должен делать ваш агент. Теперь вычеркните 70%. Оставьте только то, что используете ежедневно. Например:
- Читать вслух утренние письма
- Создавать встречи в календаре по голосовой команде
- Искать документацию по ключевым словам
- Логировать потраченное время в Notion
Не больше 5-7 пунктов. Если больше - вы создаете монстра, который будет сломан на 80%. Лучше работающий минимум, чем неработающий максимум.
2Шаг 2: Выбираем модель - последнюю, но не обязательно самую умную
На 03.04.2026 выбор огромен. Но для персонального агента критерии другие:
| Критерий | Почему это важно | Примеры на 2026 |
|---|---|---|
| Скорость ответа | Агент должен отвечать за 1-2 секунды, иначе вы будете его ненавидеть | Llama 3.2 3B, Qwen 2.5 4B, локальные оптимизированные версии |
| Контекстное окно | Достаточно 8K токенов. Больше - переплата за ненужное | Почти все современные small models |
| Цена API-вызова | Если используете облако. Локальные модели - цена нулевая | OpenAI o1-mini, Anthropic Claude Haiku |
Мой совет: начните с локальной модели через Ollama. Как в статье "Клиппи возвращается". Никаких счетов, полная приватность. Только убедитесь, что модель поддерживает function calling или JSON mode - это критично.
3Шаг 3: Пишем ядро - 100 строк кода, не больше
Вот скелет. Это все, что нужно:
import json
import time
from datetime import datetime
from typing import List, Dict
import your_llm_client # Выберите клиент для вашей модели
class JarvisCore:
def __init__(self, llm_client, tools: List[Dict]):
self.llm = llm_client
self.tools = tools # Список доступных инструментов
self.context_file = "context.json" # Да, просто JSON файл
self.load_context()
def load_context(self):
"""Загружаем последние 10 событий из файла"""
try:
with open(self.context_file, 'r') as f:
self.context = json.load(f)[-10:] # Только последние 10
except FileNotFoundError:
self.context = []
def save_event(self, event: Dict):
"""Сохраняем событие в историю"""
self.context.append({
"timestamp": datetime.now().isoformat(),
"event": event
})
# Держим только последние 100 событий
if len(self.context) > 100:
self.context = self.context[-100:]
with open(self.context_file, 'w') as f:
json.dump(self.context, f)
def process_event(self, event: Dict) -> str:
"""Главный метод: событие -> действие"""
self.save_event(event)
# Готовим промпт с контекстом и инструментами
prompt = self.build_prompt(event)
# Вызываем LLM
response = self.llm.call(
prompt=prompt,
tools=self.tools,
response_format="json" # Требуем JSON!
)
# Выполняем действие
result = self.execute_action(response)
return result
def build_prompt(self, event) -> str:
"""Собираем промпт из события и контекста"""
# Просто шаблон, можно адаптировать
return f"""
Ты персональный ассистент.
Последние события: {json.dumps(self.context[-5:])}
Новое событие: {json.dumps(event)}
Доступные инструменты: {json.dumps(self.tools, indent=2)}
Верни JSON: {"action": "имя_инструмента", "args": {...}}
"""
def execute_action(self, response: Dict) -> str:
"""Выполняем действие из ответа LLM"""
# Здесь диспетчеризация по инструментам
action = response.get("action")
args = response.get("args", {})
# Простой маппинг на функции
if action == "send_email":
return self.tool_send_email(**args)
elif action == "create_event":
return self.tool_create_event(**args)
# ... другие инструменты
return f"Действие {action} не поддерживается"
# Реализации инструментов (упрощенные)
def tool_send_email(self, to, subject, body):
# Интеграция с вашим почтовым клиентом
return f"Письмо отправлено {to}"
def tool_create_event(self, title, start_time, duration):
# Интеграция с календарем
return f"Встреча '{title}' создана"
# Запуск
if __name__ == "__main__":
# Инициализируем клиент LLM (пример для Ollama)
llm_client = OllamaClient(model="llama3.2:3b")
# Определяем инструменты
tools = [
{
"name": "send_email",
"description": "Отправить письмо",
"parameters": {"to": "str", "subject": "str", "body": "str"}
},
{
"name": "create_event",
"description": "Создать встречу в календаре",
"parameters": {"title": "str", "start_time": "str", "duration": "int"}
}
]
jarvis = JarvisCore(llm_client, tools)
# Главный цикл (в реальности здесь будут события из очереди)
while True:
event = wait_for_event() # Ваша реализация получения событий
result = jarvis.process_event(event)
print(f"Result: {result}")
time.sleep(0.1)
Это весь фреймворк. Серьезно. Остальное - интеграции с конкретными сервисами.
Не копируйте этот код слепо. Это концепт. В реальности добавьте обработку ошибок, логирование и валидацию входных данных. Но структура останется такой же.
4Шаг 4: Интеграции - одна за другой, без паники
Теперь подключаем реальные сервисы. Правило: одна интеграция в неделю. Не больше.
- Календарь: Google Calendar API или CalDAV. Начните с чтения событий, потом добавьте создание.
- Почта: IMAP для входящих, SMTP для отправки. Или Gmail API, если используете Google.
- Мессенджеры: Slack/Discord/Telegram бот. Выберите один, который используете чаще.
- Файлы: Мониторинг папки с документами. Просто отслеживайте изменения в ~/Documents.
Каждую интеграцию оформляйте как отдельный класс. Не создавайте монолитный код. Если что-то сломается - вы сможете отключить один модуль, не затрагивая остальные.
5Шаг 5: Контекст без векторных баз - это просто текст
Самое большое заблуждение: для контекста нужна векторная база. Не нужно. Для персонального агента достаточно:
- history.txt: Последние 100 действий агента (что сделал, когда)
- preferences.json: Ваши предпочтения ("не назначай встречи до 10 утра", "сокращай длинные письма")
- projects/: Папка с текстовыми файлами по текущим проектам
Когда агент получает запрос "напомни, что я обсуждал с Алексеем вчера", он ищет в history.txt строки с "Алексей" и вчерашней датой. Все. Не нужны эмбеддинги, не нужен косинусный поиск.
Если вам действительно нужен семантический поиск по документам - тогда да, используйте векторную базу. Но для 95% персональных задач хватит grep.
Где это сломается и как чинить
Jarvis Pattern не серебряная пуля. Он сломается. Вот частые точки отказа:
| Проблема | Симптом | Решение |
|---|---|---|
| LLM возвращает некорректный JSON | Ошибка парсинга, агент зависает | Добавить ретраи с более строгим промптом. Или использовать режим JSON, который поддерживает модель. |
| Инструмент не отвечает | Таймаут, агент блокируется | Вынести инструменты в отдельные потоки с timeout. Или использовать circuit breaker. |
| Контекст переполняется | Промпт становится слишком длинным, растет цена | Агрегировать старые события. Вместо 100 отдельных событий хранить 10 сводок. |
| LLM выбирает неправильный инструмент | Запрос на отправку письма, а агент создает встречу | Улучшить описания инструментов. Добавить few-shot примеры в промпт. |
Главный принцип отладки: логируйте ВСЕ. Каждый запрос к LLM, каждый ответ, каждое выполнение инструмента. В простой текстовый файл. Когда что-то сломается - у вас будет полная история.
А что насчет масштабирования и безопасности?
Вы спрашиваете: "А если я захочу подключить еще пять сервисов? А если нужно обрабатывать 100 событий в минуту?"
Ответ: тогда вы выходите за рамки персонального агента. Вам нужна другая архитектура. Например, на основе BPMN, как в статье "AI-агенты против веб-форм". Или распределенная система, как у Джеффа Эмануэля.
Безкость: ваш агент имеет доступ к почте, календарю, возможно, даже к банковским уведомлениям. Меры минимальные, но обязательные:
- Никаких API-ключей в коде. Используйте переменные окружения или vault.
- Валидация всех входных данных от LLM. Если модель просит отправить письмо на незнакомый адрес - требуйте подтверждения.
- Отдельная учетная запись для агента с ограниченными правами. Не давайте ему доступ ко всему вашему Google-аккаунту.
Мой прогноз: фреймворки умрут, паттерны останутся
К 2027 году текущий хайп вокруг фреймворков для AI-агентов схлынет. Останется несколько проверенных паттернов для разных сценариев. Jarvis Pattern - для персональных помощников. Более сложные архитектуры - для корпоративных систем.
Неочевидный совет: начните с Jarvis Pattern, но пишите код так, будто завтра вам придется его выбросить. Потому что так и будет. Через полгода появятся новые модели с новыми возможностями. Ваша архитектура должна позволять заменить LLM-слой, не переписывая интеграции.
И последнее: ваш персональный агент - это не проект, который однажды будет "завершен". Это живой инструмент, который evolves вместе с вами. Сегодня он читает почту, завтра - резюмирует звонки, послезавтра - предсказывает вашу загрузку на следующей неделе. Главное - не утонуть в сложности, которую сами же и создали.