Сценарий
Decisions API для следующего действия агента
Цикл агента — это серия конечных решений: вызвать инструмент, спросить пользователя, завершить. Вызов решения выбирает следующее действие и возвращает вероятность каждого варианта — без разбора свободного текста и валидации схемы инструментов.
Обновлено
Цикл агента как вопрос choice
Каждая итерация передаёт модели текущее состояние и задаёт один конечный вопрос: что делать дальше. Ответ — одно из ваших именованных действий плюс confidence — ровно тот контракт, который нужен исполнителю цикла.
Поскольку варианты объявлены, модель не может вернуть действие, которое ваш цикл не реализует. Невалидный вывод невозможен конструктивно, а не за счёт дисциплины промпта.
Решение о следующем действии
// Agent loop: decisions-1 picks the next action each step.
type Action = "search_docs" | "call_tool" | "ask_user" | "finish";
async function decideNext(state: unknown): Promise<{ action: Action; confidence: number }> {
const res = await fetch("https://decisions-api.net/api/v1/decisions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "decisions-1",
state, // string, JSON object, or array of text
questions: {
next: {
type: "choice",
instructions: "What should the agent do next?",
criteria: {
search_docs: "Look up documentation before acting.",
call_tool: "Run the next planned tool call.",
ask_user: "Stop and ask the user for clarification.",
finish: "The task is complete; produce the final answer.",
},
},
done: { type: "noul", instructions: "Is the user's task fully complete?" },
},
}),
});
const { answers } = await res.json();
return { action: answers.next.choice, confidence: answers.next.confidence };
}
const MAX_STEPS = 8;
async function runAgent(agentState: unknown) {
for (let step = 0; step < MAX_STEPS; step++) {
const { action, confidence } = await decideNext(agentState);
// Illustrative response: { action: "call_tool", confidence: 0.83 }
if (confidence < 0.8) { await askUser(agentState); continue; }
switch (action) {
case "finish": return;
case "search_docs": await searchDocs(agentState); break;
case "call_tool": await runTool(agentState); break;
case "ask_user": await askUser(agentState); break;
}
}
// MAX_STEPS reached: hand off to a human instead of looping forever.
}Дайте агенту честный выход
Всегда включайте в criteria действие-выход — ask_user или finish. Агент без способа остановиться будет выдумывать работу; честный выход делает «я закончил» и «я застрял» полноценными ответами.
Можно также задать в том же вызове независимый вопрос noul — «полностью ли завершена задача» — как перекрёстную проверку choice.
Ограничивайте автономию по confidence
Confidence превращает ответ в политику: шаги с высокой уверенностью — скажем, от 0,8 — выполняются без присмотра, сомнительные уходят в ask_user или на ревью к человеку. Вероятность второго варианта показывает, насколько спорным был шаг.
Логируйте распределение, а не только победителя: шаг, прошедший порог со счётом 0,51 против 0,49, заслуживает второго взгляда.
Сколько стоит шаг
Один успешный вызов стоит 1 кредит — с 1 или 6 вопросами. Так что choice следующего действия плюс проверка завершения по-прежнему стоят один кредит за шаг цикла.
Частые вопросы
Чем это отличается от вызова инструментов?
Вызов инструментов выбирает функцию и генерирует её аргументы — форма открытая. Вызов решения выбирает одно из ваших именованных действий с вероятностью по каждому варианту и без свободных аргументов — вывод ограничен конструктивно.
Что класть в state?
Всё, что нужно модели для решения: компактную сводку прогресса, результат последнего инструмента, оставшиеся шаги и ограничения. state принимает строку, JSON-объект или массив текста.
Может ли один вызов проверять больше, чем следующее действие?
Да — в одном вызове до 6 вопросов. Сочетайте choice следующего действия с noul «задача завершена?» или score риска предстоящего шага.
Что если confidence всегда низкая?
Обычно это значит, что список действий слишком дробный или в state не хватает сигнала. Объедините почти одинаковые действия, обогатите state и оставьте ask_user честным запасным вариантом.
Запустите шаг агента
Одно бесплатное пробное решение для новых посетителей — вставьте состояние цикла в песочницу и посмотрите распределение следующего действия.