К 2026 году «построить агента» перестало быть исследовательским проектом. Anthropic SDK из коробки умеет tool use, в продакшене у любой серьёзной команды крутится хотя бы один цикл на Claude Sonnet или Opus, и вопрос уже не в том, получится ли, а в том, какой паттерн взять. Ответ честный и неудобный: большинство команд усложняют. Они берут Tree-of-Thoughts там, где ReAct-цикл на 30 строк был бы готов ко вторнику.
В статье четыре паттерна, которые действительно важны: ReAct, Plan-and-Execute, Reflexion и Tree-of-Thoughts. К ним прилагается рабочий код для https://api.codexkey.ru/v1, заметки о том, когда посреди цикла переключаться с Sonnet на Opus, и практики наблюдаемости, без которых такую систему в проде не отладить.
Какие паттерны остались в 2026
Зоопарк агентных паттернов сжался. Пять лет статей и фреймворков осели в небольшой набор циклов, которые реально двигают результат:
- ReAct: чередуем рассуждение и вызовы инструментов. Вариант по умолчанию.
- Plan-and-Execute: сначала целиком генерируем план, затем выполняем шаги.
- Reflexion: модель критикует собственный вывод и переделывает его.
- Tree-of-Thoughts: параллельно разворачиваем несколько веток рассуждения и выбираем победителя голосованием.
Всё остальное (CoT, ReWOO, LATS, бесконечные циклы в духе AutoGPT) либо влилось в один из этих четырёх, либо тихо умерло. Claude Sonnet 4.6 настолько силён, что сложная обвязка вредит больше, чем помогает. Базовая модель уже сама планирует, исправляет себя и понимает, когда нужен инструмент. Ваше дело дать ей правильный цикл, а не строить мозг.
ReAct: вариант по умолчанию
С ReAct стоит начинать. Модель думает, вызывает инструмент, смотрит на результат, думает снова и так до готовности. API tool use у Anthropic построен ровно под этот ритм, и фреймворк даже не нужен.
from anthropic import Anthropic
client = Anthropic(base_url="https://api.codexkey.ru/v1")
tools = [
{
"name": "search_docs",
"description": "Search internal documentation",
"input_schema": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"],
},
},
{
"name": "run_sql",
"description": "Run a read-only SQL query",
"input_schema": {
"type": "object",
"properties": {"sql": {"type": "string"}},
"required": ["sql"],
},
},
]
def react_loop(user_msg: str, max_turns: int = 10):
messages = [{"role": "user", "content": user_msg}]
for turn in range(max_turns):
resp = client.messages.create(
model="claude-sonnet-5",
max_tokens=4096,
tools=tools,
messages=messages,
)
messages.append({"role": "assistant", "content": resp.content})
if resp.stop_reason == "end_turn":
return resp
tool_results = []
for block in resp.content:
if block.type == "tool_use":
result = dispatch_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
messages.append({"role": "user", "content": tool_results})
raise RuntimeError("max turns exceeded")
Вот и весь паттерн. Ни графа, ни конечного автомата, ни оркестратора. Состоянием служит сама история диалога. На таком цикле Sonnet без напряга проводит workflow из 5-15 шагов.
ReAct подходит, когда:
- Следующее действие зависит от предыдущего наблюдения (так устроено большинство реальных workflow).
- Инструменты дешёвые и быстрые, задержка меньше секунды.
- Заранее неизвестно, сколько понадобится шагов.
- Пользователю нужен потоковый вывод.
ReAct мешает, когда:
- Шаги независимы и могли бы идти параллельно.
- Каждый вызов инструмента стоит реальных денег или времени.
- План нужно показать человеку до выполнения.
Plan-and-Execute: когда шаги независимы
Plan-and-Execute делит задачу на две части. Первый вызов выдаёт нумерованный план. Второй проход исполняет шаги, часто параллельно и часто на более дешёвой модели. Планирует Opus или Sonnet, исполняет gpt-5.6-luna.
Haiku в каталоге тоже есть: claude-haiku-5.5 и claude-haiku-4.5, цены смотрите на странице моделей. Они доступны в канале Premium, в канале Cheap Haiku нет.
def plan_and_execute(goal: str):
plan_resp = client.messages.create(
model="claude-opus-4.8",
max_tokens=2048,
messages=[{
"role": "user",
"content": f"Produce a JSON plan to accomplish: {goal}\n"
f"Format: {{\"steps\": [{{\"id\": 1, \"action\": \"...\", "
f"\"depends_on\": []}}]}}",
}],
)
plan = json.loads(extract_json(plan_resp.content[0].text))
results = {}
for step in topological_sort(plan["steps"]):
deps = {d: results[d] for d in step["depends_on"]}
results[step["id"]] = execute_step(step["action"], deps)
return results
def execute_step(action: str, context: dict) -> str:
resp = client.messages.create(
model="gpt-5.6-luna",
max_tokens=1024,
tools=tools,
messages=[{
"role": "user",
"content": f"Context: {json.dumps(context)}\nDo: {action}",
}],
)
return resp.content[0].text
Экономика здесь настоящая. План от Opus обойдётся примерно в $0.05, десять исполнений на gpt-5.6-luna стоят копейки. Против прогона всего workflow целиком на Opus выходит сокращение затрат в 5-10 раз при сопоставимом качестве на хорошо раскладываемых задачах.
Подвох: если шаг 3 покажет, что допущение шага 2 было неверным, статичный план не справится. Чистый Plan-and-Execute хрупок там, где реальность сопротивляется. Лечится это перепланированием: после каждого шага спрашиваем у планировщика, остаётся ли остаток плана разумным. Именно такой гибрид (его иногда зовут Plan-Execute-Replan) и уезжает в прод.
Plan-and-Execute подходит, когда:
- Работа чисто раскладывается на независимые шаги.
- Шаги можно запускать параллельно, и ускорение нужно.
- Человеку или аудиту нужно увидеть план до исполнения.
- Большинство шагов простые, и с ними справится gpt-5.6-luna.
Reflexion: качество за утроенный расход токенов
Reflexion добавляет проход самокритики. Агент пробует решить задачу, затем второй промпт просит оценить собственный ответ относительно исходной цели, найти провалы и повторить попытку с этой критикой в контексте. Работает, но дорого.
def reflexion(task: str, max_attempts: int = 3):
history = []
for attempt in range(max_attempts):
attempt_resp = client.messages.create(
model="claude-sonnet-5",
max_tokens=4096,
messages=[{
"role": "user",
"content": f"Task: {task}\n"
f"Previous attempts and critiques:\n{format_history(history)}",
}],
)
answer = attempt_resp.content[0].text
critique_resp = client.messages.create(
model="claude-opus-4.8",
max_tokens=2048,
messages=[{
"role": "user",
"content": f"Task: {task}\nProposed answer:\n{answer}\n\n"
f"Is this correct and complete? If not, identify "
f"specific failures. Reply with PASS or detailed critique.",
}],
)
critique = critique_resp.content[0].text
if critique.strip().startswith("PASS"):
return answer
history.append({"answer": answer, "critique": critique})
return answer
Расход токенов примерно утраивается: за каждую успешную задачу вы платите попыткой и критикой, а каждый ретрай добавляет ещё один круг. На открытых задачах генерации (тексты, код, аналитика) Reflexion заметно поднимает качество. На чётких задачах с инструментами он только добавляет задержку.
Оставьте Reflexion для процессов, где критичны безопасность или качество. Юридическое резюме для клиента? Утроенный расход оправдан. Заведение тикета в Jira? Хватит ReAct.
Tree-of-Thoughts: в 2026 редко окупается
Tree-of-Thoughts (ToT) ведёт несколько веток рассуждения параллельно, оценивает их и выбирает победителя. В 2023 году с GPT-4 и Claude 2 это давало реальный выигрыш на сложных рассуждениях. В 2026 с Sonnet 4.6 и Opus 4.8 однопроходное рассуждение базовой модели настолько хорошо, что накладные расходы на параллельные ветки почти никогда не отбиваются.
Мы всё ещё встречаем ToT в двух нишах:
- Состязательный поиск (игры, головоломки), где действительно нужен lookahead.
- Generative design, когда нужен набор разных кандидатов, а не единственный лучший ответ.
Для бизнес-workflow, RAG и tool use? Пропускайте. Вычисления, которые ушли бы на три параллельных дерева рассуждений, лучше потратить на Reflexion или просто перейти на Opus.
Переход с Sonnet на Opus посреди цикла
Паттерн, который тихо стал стандартом в 2025 году: цикл стартует на Sonnet и переключается на Opus, только когда Sonnet подаёт признаки неуверенности. Их ловят двумя способами: разбирают оговорки самой модели («не уверен», «это неоднозначно») либо проверяют, не ходят ли вызовы инструментов по кругу.
def adaptive_react(user_msg: str):
model = "claude-sonnet-5"
messages = [{"role": "user", "content": user_msg}]
consecutive_tool_failures = 0
for turn in range(15):
resp = client.messages.create(model=model, max_tokens=4096, tools=tools, messages=messages)
messages.append({"role": "assistant", "content": resp.content})
if resp.stop_reason == "end_turn":
return resp
if detect_uncertainty(resp.content) or consecutive_tool_failures >= 2:
model = "claude-opus-4.8"
# ... обработка tool_use блоков, обновление consecutive_tool_failures ...
Математика затрат сходится. Большинство шагов идёт на дешёвом Sonnet, цены Opus вы платите только за трудные. На нагрузках смешанной сложности это стабильно режет расходы на 60-70% против работы целиком на Opus, а на лёгких шагах качество не падает в пределах измеримого.
Наблюдаемость: логируйте всё
Самая большая ошибка, которую мы видим в продовых агентных системах, это непрозрачное логирование. Команды пишут «агент отработал 8 шагов и завершился», и когда появляется регрессия, причину понять не из чего.
Минимум наблюдаемости для агентного цикла:
- Каждый блок
tool_use: имя инструмента, аргументы, время, номер шага. - Каждый блок
tool_result: tool_use_id, вывод (обрезанный, если огромный), задержка, успех или провал. - Каждый ответ модели: имя модели, input tokens, output tokens, stop_reason.
- Полная история сообщений на конец цикла, хранить не меньше 30 дней.
У OpenTelemetry для этого уже есть вменяемые конвенции: span на каждый шаг, атрибуты под имена инструментов и счётчики токенов. Что бы вы ни выбрали, проверка одна. Сможет ли человек через шесть недель понять, почему агент поступил так, как поступил, во вторник в 15:00? Если нет, вы летите вслепую.
Небольшая, но недооценённая практика: логируйте промпт, породивший ответ, вместе с самим ответом. Когда промпты дрейфуют от деплоя к деплою, их нужно уметь сравнивать диффом.
Итог: что выбирать
Два года мы гоняем эти паттерны в проде. Вывод такой:
- ReAct по умолчанию. Самый простой цикл, который тянет 80% реальной работы. Начните с него.
- Plan-and-Execute берите, когда шаги независимы и параллелятся или когда план должен увидеть человек.
- Reflexion добавляйте только к выводу, где критичны безопасность или качество. Утроенный расход токенов настоящий, платите за него осознанно.
- Tree-of-Thoughts пропускайте, если не занимаетесь состязательным поиском или generative design. Современный Claude слишком способен, чтобы накладные расходы окупались на обычных нагрузках.
- Переключайтесь с Sonnet на Opus прямо в цикле ради экономии. Большинству шагов Opus не нужен.
- Логируйте каждый tool_use и tool_result. Вы из будущего скажете спасибо.
Циклы простые. Вся дисциплина в том, чтобы не строить цикл сложнее, чем нужно.