LangGraph упёрся в GraphRecursionError: найдите условие выхода из цикла
Агент несколько раз ищет документы, уточняет ответ и должен закончить, когда доказательств достаточно. Вместо ответа приложение получает GraphRecursionError или код GRAPH_RECURSION_LIMIT. Первое желание — поднять recursion_limit. Но если условный переход продолжает возвращать тот же узел, большее значение только продлит цикл и увеличит число вызовов модели и инструментов. Сначала надо увидеть, какое поле состояния должно было остановить граф и почему оно не изменилось.
Где искать петлю
Нарисуйте путь последнего запуска: имя узла, значения полей, по которым ветвится граф, и выбранный следующий узел. Например, search → evaluate → search повторяется, потому что needs_retry остаётся истинным после успешного поиска. Узел мог обновить другое поле, а функция в add_conditional_edges всё ещё читает старый флаг. Или узел вернул новое значение, но reducer слил его со старым так, что флаг остался прежним. Ошибка лимита говорит о количестве шагов, а причина обычно в логике состояния и переходов.
Начните с пары контрольных входов. Для первого ответ находится после одной попытки; для второго поиск действительно должен повториться дважды, а затем закончиться. В журнале фиксируйте номер попытки, оценку достаточности контекста и выбранную ветку. Не пишите только «итерация 17»: по этому числу нельзя понять, почему произошёл переход. Для LLM-решения о достаточности полезно сохранять структурированный результат с причиной и проверять, соответствует ли он найденным фрагментам.
Минимальный граф с явным выходом
Следующий пример использует настоящий StateGraph. Узел увеличивает счётчик, а условное ребро отправляет его в END после третьей попытки. Это маленькая модель перехода, которую можно запустить без внешней LLM; в рабочем графе на месте счётчика будет проверенный результат поиска или инструмента.
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
class State(TypedDict):
tries: int
def attempt(state: State) -> dict:
return {"tries": state["tries"] + 1}
def next_step(state: State):
return END if state["tries"] >= 3 else "attempt"
builder = StateGraph(State)
builder.add_node("attempt", attempt)
builder.add_edge(START, "attempt")
builder.add_conditional_edges("attempt", next_step)
graph = builder.compile()
result = graph.invoke({"tries": 0})
print(result["tries"])
Ожидаемый вывод — 3: каждый проход увеличивает tries, а функция маршрутизации читает уже обновлённое состояние. Если условие заменить на return "attempt" без выхода, граф будет повторяться до защитного лимита. Если ограничить recursion_limit ниже числа шагов, корректный, но длинный граф тоже остановится. Поэтому после проверки веток сравнивайте нормальную длину вашего процесса с установленным лимитом.
Когда лимит действительно надо менять
У некоторых процессов много законных шагов: например, обработка двадцати независимых документов по одному. Тогда задайте более высокий recursion_limit в конфигурации вызова, как предусмотрено LangGraph, и отдельно контролируйте бизнес-лимит работы: число документов, вызовов модели и общую стоимость. recursion_limit ограничивает шаги графа, а не токены и не деньги. Поднимать его следует после того, как на тестовом наборе видно конечный маршрут и предельное ожидаемое число шагов.
Если граф циклически вызывает внешний инструмент, сначала остановите повторные побочные эффекты. Логика выхода должна быть проверена до отправки платежа, письма или изменения CRM. Соседний разбор Command и статического ребра помогает, когда неожиданная ветка запускается вместе с нужной: это другой конкретный источник лишних шагов в графе.
В платном курсе AI Agents PRO: LangGraph, AutoGen и LLMOps в продакшне вы проектируете граф состояний агента, подключаете инструменты и добавляете трассировку и метрики. По трассе можно увидеть, какое решение привело к повтору, а тесты переходов не дадут незаметно вернуть бесконечную петлю. Откройте программу курса, чтобы довести такой граф до сервиса с контролируемыми шагами.
Продолжить на практике
- AI Agents PRO: LangGraph, AutoGen и LLMOps в продакшне ↗
Практический курс по AI-агентам. Соберёте продакшн RAG-сервис: от индекса и графа состояний до API, Docker, метрик качества и контроля стоимости. Плюс профессиональные блоки: LangGraph/AutoGen, Qdrant/FAISS+rerank, eval (RAGAS/custom), quality-гейты, OpenTelemetry+Prometheus/Grafana, CI/CD, ретраи/DLQ/идемпотентность, PII/RBAC.
