Use case
Decisions API for agent next-action selection
An agent loop is a series of finite decisions: call a tool, ask the user, finish. A decision call picks the next action and returns a probability for every option — no free text to parse, no tool schema to validate.
Updated
The agent loop as a choice question
Each loop iteration hands the model the current state and asks one finite question: what should happen next. The answer is one of your named actions plus a confidence score — exactly the contract a loop runner needs.
Because the options are declared, the model can never return an action your loop does not implement. Invalid output is impossible by construction, not by prompt discipline.
Next-action decision
// 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.
}Give the agent an honest exit
Always include an escape action — ask_user or finish — in the criteria. An agent with no way to stop will invent work; an honest exit turns 'I am done' or 'I am stuck' into a first-class answer.
You can also ask a separate noul question in the same call — 'is the task fully complete' — as an independent check on the choice.
Gate autonomy on confidence
Confidence turns the answer into a policy. Let high-confidence steps run unattended — say 0.8 and above — and route low-confidence steps to ask_user or a human review. The probability of the runner-up option tells you how contested the step was.
Log the distribution, not just the winner: a step that was 0.51 against 0.49 deserves a second look even when it passes your threshold.
What a step costs
One successful call costs 1 credit, whether it carries 1 or 6 questions — so a next-action choice plus a done-check still costs one credit per loop step.
FAQ
How is this different from tool calling?
Tool calling picks a function and generates its arguments — the shape is open-ended. A decision call picks one of your named actions with a probability per option and no free-form arguments, so the output is constrained by construction.
What goes into the state?
Whatever the model needs to decide: a compact summary of progress, the last tool result, remaining steps, and any constraints. state accepts a string, a JSON object, or an array of text.
Can one call check more than the next action?
Yes — a single call holds up to 6 questions. Pair the next-action choice with a noul 'is the task done' check or a score for how risky the pending step is.
What if confidence is always low?
That usually means the action list is too fine or the state lacks the signal. Merge near-duplicate actions, enrich the state, and keep ask_user as the fallback the model can honestly pick.
Drive an agent step
One free trial decision for new visitors — paste your loop state into the playground and see the next-action distribution.