Начиная проект AI-агента с персистентной памятью, мы приняли необычное решение: никаких if/else в агентной логике.
Не "минимизируем". А ноль.
Полгода спустя — это лучшее архитектурное решение которое мы приняли.
Изучая код других агентных фреймворков, видели один паттерн:
if user_emotion == "angry":
apologize()
elif user_emotion == "happy":
celebrate()
elif context_length > 8000:
summarize()
... ещё 50 строк
Проблема очевидна: это не масштабируется. 10 условий → понятно. 100 условий → сложно. 1000 → невозможно.
Решили не идти этим путём с первого дня.
Принцип: всё вычисляется
Вместо категорий — непрерывные метрики
Классика:
if task.urgency == "high":
priority = 1
elif task.urgency == "medium":
priority = 2
Наш подход:
priority = (
deadline_pressure(task) * 0.4 +
importance_weight(task) * 0.3 +
context_multiplier() * 0.3
)
float от 0 до 1, не категории
Вместо ветв��ения — параллельный scoring
Классика:
if query_simple:
use_cache()
elif resources_available:
deep_search()
else:
hybrid()
Наш подход:
strategies = {
'cache': compute_cache_score(query),
'deep': compute_deep_score(query),
'hybrid': compute_hybrid_score(query)
}
best = max(strategies, key=strategies.get)
Каждый вариант оценивается независимо. Выбираем лучший.
Что это даёт
Модульность
Каждая scoring function тестируется отдельно. Нет coupling между компонентами.Композиция
Одни и те же базовые функции комбинируются по-разному:
score_v1 = urgency * 0.5 + importance * 0.5
score_v2 = urgency * 0.3 + importance * 0.3 + context * 0.4Обучаемость
Веса можно обновлять градиентно:
error = actual - expected
weights['urgency'] += learning_rate * errorОбъяснимость
Не "if на строке 342 сработал", а "X scored 0.85 (temporal: 0.3, semantic: 0.4, resource: 0.15)".
scoring/
├── temporal.py # urgency, deadlines
├── semantic.py # similarity, relevance
├── resource.py # efficiency
└── user.py # context, preferences
compose.py # weighted combinations
select.py # argmax + execution
Типичный flow:
Вычисляем компоненты
scores = {
'temporal': temporal_score(ctx),
'semantic': semantic_score(ctx),
'resource': resource_score(ctx)
}
Композиция
total = weighted_sum(scores, weights)
Решение
if total > threshold:
execute()
Где if/else остались
Мы не фанатики. Условия есть для:
Input validation (if data is None: raise Error)
Safety checks (if action_dangerous: confirm())
Type dispatch (if isinstance(x, dict))
Принцип: if/else для защиты, не для логики решений.
Неожиданные бонусы
A/B testing из коробки:
final = current * (1 - ratio) + experimental * ratio
Graceful degradation:
Всегда возвращается best available option, даже если все scores низкие.
Прозрачный debugging:
Видим scores всех вариантов, не трейсим вложенные условия.
Ограничения
Требует думать математически ("как оценить численно?")
Overhead для тривиальных случаев
Нужна дисциплина (scoring functions должны быть comparable)
Отказ от if/else — архитектурный выбор с trade-offs.
Для нас сработало. Агент развивается полгода. Если бы начинали с if/else — уже утонули бы в рефакторинге. Практический совет: если начинаете агентный проект — попробуйте этот подход хотя бы для одного модуля. Через неделю поймёте подходит ли вам.
Обсудим в комментариях? Интересно услышать опыт коллег.
