Tool Integrations8 июля 2026 г.Flatkey

Мультимодельная маршрутизация в LangGraph: проверки через шлюз для рабочих процессов агентов

Маршрутизируйте узлы агентов LangGraph между моделями через Flatkey с проверками через шлюз для бюджетов, инструментов, повторных попыток, логов и отката.

Мультимодельная маршрутизация в LangGraph: проверки через шлюз для рабочих процессов агентов

Мультимодельная маршрутизация в LangGraph — это в первую очередь проблема проектирования графа, а во вторую — проблема шлюза. Граф решает, какой тип работы выполняется, клиент модели решает, какой OpenAI-совместимый маршрут вызывать, а шлюз должен проверять, остался ли каждый вызов в рамках правил бюджета, инструментов, повторных попыток, ведения журнала и условий остановки.

Flatkey подходит для этой границы шлюза. Его общедоступный сайт показывает OpenAI-совместимый маршрут чата по адресу https://router.flatkey.ai/v1/chat/completions, с одним ключом, видимостью использования, контролем биллинга и маршрутизацией моделей в одном месте. Это руководство показывает практическую настройку мультимодельной маршрутизации в LangGraph для рабочих процессов агентов, не предполагая, что каждый псевдоним модели, поведение инструмента или резервный маршрут уже проверены в вашей учетной записи.

Краткий ответ по мультимодельной маршрутизации в LangGraph

Безопасная настройка мультимодельной маршрутизации в LangGraph разделяет маршрутизацию на три уровня.

УровеньЧто он решаетПроверка через шлюз
Маршрут графаДолжен ли рабочий процесс использовать узел простого ответа, узел сложного рассуждения, узел с интенсивным использованием инструментов или путь остановкиСохранять имя маршрута и причину с временной меткой запроса.
Маршрут моделиКакой OpenAI-совместимый псевдоним модели вызывает каждый узел через FlatkeyПроверить, существует ли псевдоним для ключа и семейства конечных точек.
Операционные ограниченияДолжен ли запрос продолжаться, повторяться, использовать резервный вариант или остановитьсяПроверить бюджет, количество вызовов инструментов, количество повторных попыток, тайм-аут и журналы запросов.
ПодтверждениеДействительно ли маршрут сработалСопоставить ответ приложения с данными об использовании или журналами запросов Flatkey.

Не скрывайте мультимодельную маршрутизацию в LangGraph внутри одного длинного промпта. Размещайте политику в узлах графа, условных ребрах и проверках шлюза, которые ваша команда может инспектировать.

Почему маршрутизация моделей должна находиться на границах графа

Большинство примеров LangGraph сосредоточены на управлении потоком графа: состоянии, узлах, ребрах, инструментах и персистентности. Это правильная отправная точка, но производственным агентам также нужны границы маршрутов, которые могут анализировать команды платформы и финансов.

Используйте маршруты на уровне графа, когда рабочий процесс имеет явно различные профили затрат, задержек или рисков, связанных с инструментами:

Тип работыПримерФорма маршрута
Простой ответСуммировать короткую заметку поддержкиБыстрый, недорогой псевдоним модели.
Сложное рассуждениеСогласовать противоречивый текст политикиБолее сильный псевдоним модели с более высоким бюджетом на вызов.
Действие с интенсивным использованием инструментовЗапрашивать системы, создавать тикеты, обновлять записиПсевдоним модели, способный использовать инструменты, с более строгими ограничениями на вызовы.
Путь остановкиБюджет исчерпан, слишком много повторных попыток, небезопасное состояниеВернуть контролируемое сообщение вместо вызова другой модели.

Именно на этой границе может помочь Flatkey. Вместо того чтобы разбрасывать отдельные ключи провайдеров по каждому узлу, каждый маршрут может вызывать базовый URL OpenAI-совместимого API, в то время как Flatkey обеспечивает видимость на уровне шлюза. Для смежного проектирования политик см. руководство Flatkey по элементам управления шлюзом для AI-агентов.

Проверки источника перед настройкой маршрута

Используйте актуальную документацию и проверки в реальной учетной записи, прежде чем рассматривать шаблоны как производственный код.

ПроверкаЧто проверить
Состояние и ребра LangGraphВаш граф может выполнять маршрутизацию с помощью StateGraph, функций узлов и условных ребер.
Клиент модели LangChainВаша установленная версия LangChain поддерживает init_chat_model с провайдером OpenAI, base_url и api_key, или эквивалентный конструктор ChatOpenAI.
Вызов инструментовВыбранный маршрут модели поддерживает схему инструментов и поведение вызова инструментов, необходимое вашему узлу.
Конечная точка FlatkeyВаш ключ может вызывать выбранный псевдоним модели через OpenAI-совместимый базовый URL Flatkey.
Бюджет и журналыРеальный запрос появляется в данных об использовании или журналах запросов Flatkey с ожидаемым ключом, псевдонимом модели и временной меткой.

Приведенный ниже код является шаблоном. Запустите его с вашими текущими версиями langchain, langchain-openai и langgraph, прежде чем внедрять политику мультимодельной маршрутизации в LangGraph.

Настройка чат-моделей с использованием Flatkey

Установите актуальные пакеты в среде, где выполняется ваш граф.

pip install -U langgraph langchain langchain-openai

Держите корень API отдельно от пути конечной точки. Клиенты LangChain должны получать базовый URL; клиент добавляет путь Chat Completions для OpenAI-совместимых вызовов чата.

FLATKEY_API_KEY=sk-fk-your-key
FLATKEY_BASE_URL=https://router.flatkey.ai/v1
FLATKEY_FAST_MODEL=your-fast-model-alias
FLATKEY_REASONING_MODEL=your-reasoning-model-alias
FLATKEY_TOOL_MODEL=your-tool-capable-model-alias

Затем создайте явные клиенты моделей для каждого маршрута.

import os
from langchain.chat_models import init_chat_model

BASE_URL = os.getenv("FLATKEY_BASE_URL", "https://router.flatkey.ai/v1")
API_KEY = os.environ["FLATKEY_API_KEY"]

fast_model = init_chat_model(
    model=os.environ["FLATKEY_FAST_MODEL"],
    model_provider="openai",
    base_url=BASE_URL,
    api_key=API_KEY,
)

reasoning_model = init_chat_model(
    model=os.environ["FLATKEY_REASONING_MODEL"],
    model_provider="openai",
    base_url=BASE_URL,
    api_key=API_KEY,
)

tool_model = init_chat_model(
    model=os.environ["FLATKEY_TOOL_MODEL"],
    model_provider="openai",
    base_url=BASE_URL,
    api_key=API_KEY,
)

Это самая простая полезная форма для мультимодельной маршрутизации в LangGraph: у каждого маршрута есть именованный клиент модели, но все вызовы используют одну и ту же границу шлюза. Не предполагайте, что псевдоним модели поддерживает потоковую передачу или инструменты только потому, что это делает другой псевдоним. Тестируйте каждый маршрут отдельно.

Создание шаблона маршрутизации LangGraph

Используйте узел-классификатор, чтобы записать маршрут в состояние. Затем позвольте условным рёбрам решать, какой узел будет выполняться следующим.

from typing import Annotated, Literal, TypedDict

from langchain_core.messages import AIMessage, BaseMessage
from langchain_core.tools import tool
from langgraph.graph import END, StateGraph
from langgraph.graph.message import add_messages


class RouteState(TypedDict):
    messages: Annotated[list[BaseMessage], add_messages]
    route: Literal["simple", "complex", "tools", "stop"]
    budget_cents: float
    errors: int
    tool_calls: int


@tool
def lookup_account_status(account_id: str) -> str:
    """Шаблонный инструмент. Замените его на ваш реальный инструмент для поиска только для чтения."""
    return "active"


tool_ready_model = tool_model.bind_tools([lookup_account_status])


def choose_route(state: RouteState) -> dict:
    last_message = state["messages"][-1].content.lower()

    if state.get("budget_cents", 0) <= 0:
        return {"route": "stop"}
    if state.get("errors", 0) >= 2:
        return {"route": "stop"}
    if "lookup" in last_message or "account" in last_message:
        return {"route": "tools"}
    if len(last_message) > 600:
        return {"route": "complex"}
    return {"route": "simple"}


def simple_answer(state: RouteState) -> dict:
    return {"messages": [fast_model.invoke(state["messages"])]}


def complex_answer(state: RouteState) -> dict:
    return {"messages": [reasoning_model.invoke(state["messages"])]}


def tool_answer(state: RouteState) -> dict:
    if state.get("tool_calls", 0) >= 3:
        return {"messages": [AIMessage(content="Tool-call limit reached.")] }
    return {"messages": [tool_ready_model.invoke(state["messages"])]}


workflow = StateGraph(RouteState)
workflow.add_node("choose_route", choose_route)
workflow.add_node("simple_answer", simple_answer)
workflow.add_node("complex_answer", complex_answer)
workflow.add_node("tool_answer", tool_answer)

workflow.set_entry_point("choose_route")
workflow.add_conditional_edges(
    "choose_route",
    lambda state: state["route"],
    {
        "simple": "simple_answer",
        "complex": "complex_answer",
        "tools": "tool_answer",
        "stop": END,
    },
)
workflow.add_edge("simple_answer", END)
workflow.add_edge("complex_answer", END)
workflow.add_edge("tool_answer", END)

graph = workflow.compile()

Этот шаблон делает мультимодельную маршрутизацию в LangGraph наглядной. Рецензент может видеть, почему запрос был направлен в simple_answer, complex_answer, tool_answer или stop, без необходимости реконструировать промпт.

Узел tool_answer выше проверяет маршрут модели, который может предлагать вызовы инструментов. Если ваш граф должен выполнять инструменты, добавьте ToolNode из LangGraph или ваш собственный исполнитель после этого узла модели, а затем направьте результат инструмента обратно в граф с теми же проверками бюджета и условий остановки.

Добавление проверок через шлюз для каждого вызова модели

Маршрут графа не должен быть единственным защитным механизмом. Добавьте небольшую обёртку, которая проверяет бюджеты перед вызовом модели и записывает данные после вызова модели.

from dataclasses import dataclass
from time import time


@dataclass
class GatewayDecision:
    route: str
    model_alias: str
    allowed: bool
    reason: str
    started_at: float


def preflight(route: str, model_alias: str, state: RouteState) -> GatewayDecision:
    if state.get("budget_cents", 0) <= 0:
        return GatewayDecision(route, model_alias, False, "budget_exhausted", time())
    if route == "tools" and state.get("tool_calls", 0) >= 3:
        return GatewayDecision(route, model_alias, False, "tool_limit_reached", time())
    if state.get("errors", 0) >= 2:
        return GatewayDecision(route, model_alias, False, "retry_limit_reached", time())
    return GatewayDecision(route, model_alias, True, "allowed", time())


def record_gateway_result(decision: GatewayDecision, response: BaseMessage) -> None:
    # Замените это на структурированное логирование. Включите отредактированную метку ключа,
    # имя маршрута, псевдоним модели, временную метку запроса и метаданные ответа.
    print(
        {
            "route": decision.route,
            "model_alias": decision.model_alias,
            "allowed": decision.allowed,
            "reason": decision.reason,
            "started_at": decision.started_at,
            "response_type": response.type,
        }
    )

В производственной среде не ограничивайтесь локальными логами. Сопоставляйте временную метку и псевдоним модели с логами использования или запросов Flatkey. Это будет доказательством того, что мультимодельная маршрутизация в LangGraph использовала именно тот маршрут шлюза, который вы предполагали.

Проверяйте инструменты, прежде чем доверять маршруту с их интенсивным использованием

Узлы с интенсивным использованием инструментов заслуживают собственного пакета верификации. Модель может хорошо справляться с обычным чатом, но не соответствовать вашей схеме инструментов, по-другому передавать дельты инструментов или генерировать аргументы инструментов, которые ваш исполнитель отклоняет. Для более глубоких проверок совместимости используйте руководство Flatkey по совместимости вызова инструментов у разных провайдеров.

Проверка инструментаУсловие прохождения
Схема принятаМаршрут модели принимает определение инструмента без ошибки запроса.
Инструмент выбранОтвет содержит ожидаемый вызов инструмента для детерминированного промпта.
Аргументы разбираютсяАргументы инструмента проходят валидацию по вашей схеме перед выполнением.
Количество инструментов ограниченоМаршрут останавливается после максимального количества вызовов инструментов.
Сбой обработанОшибки инструментов приводят к контролируемому состоянию графа, а не к бесконечному циклу повторных попыток.
Лог виденЛоги Flatkey показывают запрос под ожидаемым ключом и псевдонимом модели.

Здесь вы также решаете, относится ли маршрут к Chat Completions или Responses. Держите семейства конечных точек раздельно; если вы оцениваете маршруты агентов в стиле Responses, используйте это руководство вместе с совместимым с OpenAI маршрутизатором Responses API от Flatkey.

Политика повторных попыток, резервирования и условий остановки

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

УсловиеРекомендуемое действиеПочему
401 или 403Остановиться и исправить ключПовторная попытка не исправит аутентификацию.
404 model not foundОстановиться и проверить псевдоним модели или семейство конечных точекМаршрут может вызывать не ту модель.
429 или ошибка емкостиПовторить один раз с экспоненциальной задержкой или переключиться на утвержденный резервный псевдонимИзбегайте неконтролируемого роста затрат и видимых пользователю циклов.
Ошибка валидации инструментаОстановить маршрут инструмента и вернуть контролируемое сообщениеПовторение неверных аргументов инструмента редко бывает полезным.
Достигнут порог бюджетаОстановиться перед следующим вызовом моделиПолитика шлюза должна защищать расходы до вызова.

Промежуточное ПО LangChain может помочь с повторными попытками на уровне агента, резервированием и ограничениями вызовов. Для созданных вручную рабочих процессов LangGraph придерживайтесь той же политики рядом с узлом, который вызывает модель, а затем подтверждайте результат в логах Flatkey.

Контрольный список для тестирования перед публикацией

Выполните эти проверки, прежде чем сделать Flatkey маршрутом по умолчанию для агента.

  1. Отправьте один прямой запрос curl на https://router.flatkey.ai/v1/chat/completions с предполагаемым ключом и псевдонимом модели.
  2. Вызовите каждый клиент модели LangChain один раз вне LangGraph.
  3. Запустите граф с одним промптом для простого маршрута, одним для сложного маршрута и одним для маршрута с интенсивным использованием инструментов.
  4. Принудительно вызовите путь остановки, установив budget_cents в 0.
  5. Принудительно достигните лимита повторных попыток, установив errors на максимальное допустимое значение.
  6. Убедитесь, что каждый запрос появляется в логах Flatkey с ожидаемой временной меткой, меткой ключа, именем маршрута и псевдонимом модели.
  7. Сравните поля затрат или использования с владельцем, который утверждает бюджет рабочего процесса. Страница цен Flatkey — подходящее публичное место для начала этой проверки.

Результат этого контрольного списка становится приемочным пакетом для мультимодельной маршрутизации в LangGraph. Это полезнее, чем скриншот работающего промпта, потому что это доказывает, что граф, клиент модели и шлюз согласованы между собой.

Устранение неполадок мультимодельной маршрутизации в LangGraph

СимптомВероятная причинаЧто проверить
Каждый запрос использует одну и ту же модельУсловное ребро никогда не меняет состояниеВыведите значение маршрута после узла-классификатора.
401 или 403Неверный, отсутствующий или отозванный ключ FlatkeyСоздайте ключ заново и не храните его в системе контроля версий.
404Неверный корень API, дублирование /v1 или недоступный псевдоним моделиИспользуйте https://router.flatkey.ai/v1 в качестве базового URL и проверьте псевдоним.
Маршрут инструмента завершается сбоемПсевдоним модели не поддерживает вашу схему инструментовПротестируйте bind_tools с одним детерминированным промптом перед выполнением графа.
Повторные попытки увеличивают затратыПолитика повторных попыток находится в слишком многих местахВыберите одного владельца повторных попыток: узел графа, промежуточное ПО LangChain или политика шлюза.
Логи не совпадаютЗапрос обошел Flatkey или логи отфильтрованыИщите по временной метке, метке ключа, псевдониму модели и маршруту.
Финансовый отдел не может утвердить развертываниеВладелец затрат не может сопоставить маршруты с расходамиПомечайте ключи по рабочей нагрузке и держите псевдонимы моделей явными в конфигурации маршрута.

Если первый маршрут не работает, сведите к минимуму область отладки: ключ, базовый URL, псевдоним модели, один клиент модели, один узел графа и один просмотр лога Flatkey.

Часто задаваемые вопросы

Является ли мультимодельная маршрутизация в LangGraph тем же самым, что и отказоустойчивость провайдера?

Нет. Мультимодельная маршрутизация в LangGraph решает, какой маршрут подходит для задачи, до или во время выполнения графа. Отказоустойчивость провайдера — это то, что происходит, когда выбранный маршрут не может быть завершен. Вы можете использовать и то, и другое, но их следует тестировать отдельно.

Должен ли каждый узел LangGraph использовать свою модель?

Нет. Начните с двух или трех явных маршрутов. Слишком большое количество псевдонимов моделей усложняет проверку логов, бюджетов и откат.

Можно ли использовать Flatkey одновременно с маршрутами Chat Completions и Responses?

Flatkey предоставляет семейства конечных точек, совместимых с OpenAI, но каждый клиентский путь все равно требует отдельного тестирования. Разделяйте проверки для Chat Completions и Responses, особенно для вызовов инструментов, потоковой передачи, полей использования и резервного поведения.

Итоговый чек-лист

Ваша настройка мультимодельной маршрутизации LangGraph готова к выходу за рамки шаблона, когда:

  1. Маршрут графа виден в состоянии и логах.
  2. Каждый маршрут сопоставлен с именованным псевдонимом модели.
  3. Ключ Flatkey может вызывать каждый выбранный псевдоним через базовый URL, совместимый с OpenAI.
  4. Маршруты с интенсивным использованием инструментов проходят тесты схемы, аргументов, ограничений и ошибок.
  5. Условия остановки по бюджету и повторным попыткам срабатывают до следующего вызова модели.
  6. Логи использования или запросов Flatkey подтверждают выбранный маршрут.
  7. Откат — это изменение одной конфигурации, а не переписывание приложения.

Когда вы будете готовы направить трафик агентов LangGraph через один шлюз, получите ключ Flatkey, начните с одного маршрута графа с низким риском и расширяйте его только после того, как логи подтвердят, что политика работает.