Decision-модели в OpenClaw: «умный if» перед агентом

Новая роль модели в OpenClaw отвечает не текстом, а выбором, оценкой или вероятностью «да». Разбираем, где ей место и почему решение лучше оставлять коду, а не агенту.

· 8 мин чтения

Коротко

  • Decision-модель — третья роль модели в OpenClaw: на вопрос она отвечает меткой, числом или вероятностью, а не текстом.
  • Ставьте её в коде до агента, чтобы она решала, будить ли агента вообще. Агенту в руки её отдавать не нужно.
  • Провайдеры вышли совсем недавно. Начните с гейта ниже и подберите порог на 20–30 своих сообщениях.

Проверено по документации OpenClaw 2026.9.7 и 2026.9.6 и по подкасту ClawCast #12, 1 октября 2026. Плагины мы не ставили, код не запускали.

Зачем это нужно

Каждое входящее сообщение будит агента. Он читает его целиком, тратит токены и думает, что делать, даже если это мем от брата. Обычно это лечат правилами: белый список контактов, обязательное упоминание бота. Но правила режут и нужное. Один из участников подкаста ClawCast рассказал, что отсекает по списку контактов переписку с родными, а вместе с ней и деловую.

Ставить перед агентом ещё одну чат-модель дорого и медленно, и её ответ потом надо разбирать. Decision-модель делает один вызов и возвращает ответ заранее известной формы. По нему ваш код выбирает ветку. Элли Лаабс из TypeSafe AI, компании-автора модели Jev, назвала это на подкасте if или switch со встроенным интеллектом.

Как это устроено

В OpenClaw теперь три роли модели. Основная ведёт разговор и вызывает инструменты. utilityModel пишет короткие тексты вроде заголовков и сводок. decisionModel классифицирует, оценивает по шкале и проверяет условия.

Decision-модель выбирают в отдельном списке Decision в Control UI. Чат-модель она не заменяет и сама ничего не запускает. Если провайдер недоступен, OpenClaw не подставит вместо него чат-модель: решения просто не будет.

{
  agents: {
    ownership: "explicit",
    defaults: { decisionModel: "onnx/gliclass-edge-v3.0" },
    entries: {
      support: { decisionModel: "typesafe/jev-latest" },
      quiet: { decisionModel: "" },
    },
  },
}

Агент без своей настройки берёт глобальную. Пустая строка у агента выключает для него решения. Если глобальная не задана, роль выключена.

Запрос — это общее состояние state (текст, JSON или null) и набор вопросов. Вопросы бывают трёх типов:

  • choice — выбрать метку из списка. Вернёт метку и вероятности всех меток.
  • score — поставить на шкалу. Вернёт дробную позицию и вероятности уровней.
  • boolean — да или нет. Вернёт probabilityTrue от 0 до 1.

У score есть ловушка. Это позиция, считая от нуля, а не уверенность. На шкале из четырёх уровней 2.85 значит «почти самый тяжёлый уровень».

Кто отвечает

TypeSafe (@openclaw/typesafe) подключает облачную модель Jev. Всё, что вы кладёте в вопрос, уходит в TypeSafe, и каждый вызов оплачивается по их тарифам. Тот же плагин умеет работать с Kev — открытыми моделями, которые вы поднимаете у себя на Mac с Apple Silicon или на видеокарте с CUDA. Адрес сервера должен быть локальным: localhost, 127.0.0.1 или [::1].

ONNX (@openclaw/onnx) запускает небольшие классификаторы на процессоре. Данные никуда не уходят:

openclaw onnx models
openclaw onnx download gliclass-edge-v3.0
openclaw onnx probe gliclass-edge-v3.0

probe задаёт по одному пробному вопросу каждого типа. Вход вместе с вопросом должен укладываться в 512 токенов, иначе запрос отклоняется целиком. В задачах, где нужно рассуждать, эти классификаторы Jev не заменят.

О скорости и цене Jev есть только данные самой TypeSafe: ответ за 70–500 мс и $0,042 за миллион входных токенов, выходные бесплатно. По их же словам, замеряли с ноутбуков на западном побережье США, рядом с их сервисом. Независимых замеров мы не видели.

Что уже есть, а что обещано

  • Роль и API есть в ядре. В заметках к 2026.9.6 роль и оба плагина значатся вышедшими.
  • Плагины лежат в npm, но вышли только что. Страницы документации ещё называют их кандидатами, так что это ранняя стадия.
  • Инструмент агента decision_evaluate появился в 2026.9.7. Агент получает его сам, как только у него настроена decisionModel, если политика инструментов его не запрещает.
  • Встраиваний в сам OpenClaw пока нет. Переключатель Decision assistance в Labs ничего не запускает. На подкасте прозвучало, что гейт для групповых чатов («говорить агенту или молчать») сейчас на ревью. Ещё прозвучала идея решать внутри цикла агента, нужны ли в этом ответе инструменты. Всё это планы, а не функции.

Решает код, а не агент

Первое, что приходит в голову, — дать агенту инструмент «спроси Jev». Джош Леман рассказал на подкасте, что с этого и начал: работало, но выглядело неправильным решением. Элли Лаабс объяснила почему. Агенты плохо понимают, когда им нужна чужая оценка. Чтобы вызвать такой инструмент, агент уже должен знать, где он ненадёжен.

Отсюда правило. Будить ли агента, решает код до агента. Агент не отфильтрует сообщение, которое уже прочитал: деньги и внимание к этому моменту уже потрачены. decision_evaluate в руках агента полезен в другом случае: когда агент сам разбирает пачку данных и ему нужны быстрые однотипные оценки.

Сценарий 1. Гейт перед агентом

Плагин перехватывает ход до вызова модели и задаёт один вопрос: просит ли сообщение ответа. Если вероятность «да» низкая, агент молчит. Иначе всё идёт как обычно. Это набросок из двух примеров документации, мы его не собирали:

import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";

export default definePluginEntry({
  id: "reply-gate",
  name: "Reply gate",
  description: "Молчать, если сообщение не просит ответа.",
  register(api) {
    api.on(
      "before_agent_reply",
      async (event, ctx) => {
        const outcome = await api.runtime.decisions.evaluate(
          {
            state: { message: event.cleanedBody },
            questions: {
              respond: {
                type: "boolean",
                instructions: "Is this message asking the assistant to respond?",
                criteria: {
                  true: "The message asks the assistant to respond",
                  false: "The message does not ask the assistant to respond",
                },
              },
            },
          },
          {
            agentId: ctx.agentId,
            purpose: "reply-gate.respond",
            rubricVersion: "1",
            timeoutMs: 1500,
            signal: AbortSignal.timeout(2000),
          },
        );
        if (outcome.status !== "ok") return; // нет решения — пропускаем
        const respond = outcome.result.answers.respond;
        if (respond?.type === "boolean" && respond.probabilityTrue < 0.2) {
          return { handled: true }; // молчим
        }
      },
      { eligibleTriggers: ["user"] }, // только сообщения людей
    );
  },
});

Порог 0.2 взят для примера. Вероятность — оценка модели, а не гарантия, поэтому порог подбирают на своих сообщениях.

Сломанный гейт пропускает сообщения к агенту, а не глотает их. Если хук упал, OpenClaw пишет ошибку в лог и идёт обычным путём. Для фильтра шума это то, что нужно. Для фильтра, который обязан что-то не пропустить, такой гейт не годится.

Та же схема годится для маршрутизации. Вопрос choice с метками «быстрый факт», «задача для команды агентов», «не для бота» говорит, куда отправить сообщение.

Сценарий 2. Агент пишет программу

Code Mode — экспериментальный режим OpenClaw. В нём модель пишет короткую программу на JavaScript, а инструменты доступны в ней как функции. Общая настройка — в Settings → Agents & Tools → Labs → Code Mode.

Этот сценарий — идея с подкаста, а не готовая функция. Вы спрашиваете: «Были ли сегодня письма про X?» Агент не тащит все письма в контекст. Он пишет программу, которая по каждому письму спрашивает decision-модель «это про X?», и получает назад только итоги. Части для этого в документации есть, но целиком сценарий там не описан, и мы его не проверяли. Участник, объяснявший Code Mode, сам не был уверен, что агенты уже это умеют.

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

Как писать вопросы

Совет Элли Лаабс: одна проверка на вопрос, и не в стиле промпта. Когда поле в API называлось prompts, туда писали «ты опытный инженер…». После переименования в questions агенты стали чаще писать правильный запрос с первого раза.

Плохо:

«Ты внимательный ассистент. Прочитай сообщение и реши, важное ли оно, срочное ли и нужно ли подключать агента».

Хорошо — три отдельных вопроса:

  • boolean «Просит ли сообщение что-то сделать?» с описаниями обоих ответов;
  • score «Насколько срочно?» с уровнями, которые видно со стороны: «ничего не сломано», «есть обходной путь», «важный процесс встал», «массовый сбой»;
  • choice «Кому это?» с понятным описанием у каждой метки.

Ещё несколько правил из документации. Варианты описывайте словами, а не голыми идентификаторами. Для ONNX у boolean обязательно описывайте и true, и false. Если важен ответ «данных недостаточно», сделайте его отдельной меткой: рассчитывать на вероятность около 0.5 нельзя. Метки в choice соревнуются друг с другом, поэтому независимые признаки задавайте отдельными boolean. Поменяли смысл вопросов — поменяйте rubricVersion, чтобы в журнале было видно, по какой версии принято решение.

Подводные камни

  • Нет решения — значит, нет решения. При сбое, перегрузке или таймауте вы получите unavailable. Повторов и подмены на чат-модель нет, запасной путь пишете сами.
  • Отказ не значит «нет». Сбой нельзя трактовать как отрицательный ответ.
  • Ответ не даёт разрешения. Метка или вероятность — входные данные для вашего кода, а не право что-то отправить.
  • Облако — это передача данных. Всё, что попало в state, уходит в TypeSafe. В гейте выше это ещё и служебный контекст канала из cleanedBody.
  • Стороннему плагину нужен доступ к разговору: plugins.entries.<id>.hooks.allowConversationAccess: true.
  • Нет agentId — нет настроек агента. В хуках его может не быть, и тогда решение идёт по глобальной decisionModel.
  • Отменённый вызов падает с ошибкой. Тогда хук падает, и сообщение уходит агенту.
  • Холодный старт ONNX на слабой машине может съесть весь 30-секундный лимит решения.
  • Вопросы не видят ответов друг друга. Если вопрос зависит от предыдущего ответа, нужен второй вызов.

Когда не применять

  • Правило уже работает. Хватает белого списка, регулярного выражения или поля в метаданных — оставьте их. В TypeSafe сами говорят про своё демо, где Jev играет в Doom: бота для Doom можно и нужно писать обычным кодом, демо показывает скорость.
  • Задаче нужно рассуждение. Несколько шагов с поиском и уточнениями — работа агента, а не классификатора.
  • Нечем проверить порог. Без двух-трёх десятков своих сообщений, где вы сравнили ответы модели со своими, любой порог — гадание.
  • Данные нельзя отдавать, а локальная модель не справляется. Если вопрос не влезает в 512 токенов ONNX, гейт лучше не ставить.