Agent routing
Let an AI agent pick its first tool and decide when a task really needs a large language model, with the Agent Routing template.
Goal: before an agent spends a large-model call planning, decide cheaply which tool it should use first — and send only the tasks that need multi-step reasoning to the LLM.
Create the decision
Templates → Agent Routing → Create decision:
| Part | Content |
|---|---|
| State | task (string, required) — what the user asked the agent |
selected_tool | choice — search (needs fresh information from the web), database (needs data from our own records), calculator (needs a calculation), none (can answer directly), other |
needs_reasoning | probability — does this task need multi-step reasoning from a large language model? |
| Policies | 1. needs_reasoning ≥ 0.8 → fallback |
Call it
curl -X POST https://api.dcision.io/v1/decisions/agent-routing \
-H "Authorization: Bearer $DCISION_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "state": { "task": "How many orders did we ship to Germany last week?" } }'{
"decision_id": "dec_Ka9Wd4Tm1Xq7Rz3Ln8Bv",
"execution_id": "exec_Pq2Zr8Hv5Nc1Jt6Mw3Ds",
"schema": "agent-routing",
"version": 1,
"result": { "selected_tool": "database", "needs_reasoning": 0.31 },
"confidence": { "selected_tool": 0.8625, "needs_reasoning": 0.38 },
"action": "continue",
"action_reason": { "type": "default" },
"metrics": { "latency_ms": 301, "engine": "jev", "model": "jev-1.13.0", "estimated_cost_usd": 0.00000882, "input_tokens": 210, "output_tokens": 22 }
}A lookup in your own data with little reasoning: call the database tool directly. A task such as "Compare our churn by plan over the last three quarters and suggest pricing changes" would come back with a high needs_reasoning, and rule 0 would return fallback.
Act on it
type Decision = {
action: "continue" | "block" | "escalate" | "fallback";
result: { selected_tool: "search" | "database" | "calculator" | "none" | "other"; needs_reasoning: number };
};
async function handle(task: string) {
const response = await fetch("https://api.dcision.io/v1/decisions/agent-routing", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.DCISION_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ state: { task } }),
});
if (!response.ok) return planner.run(task); // on errors, fall back to the full agent
const decision = (await response.json()) as Decision;
if (decision.action !== "continue") return planner.run(task); // fallback or escalate: full LLM planning
switch (decision.result.selected_tool) {
case "database":
return tools.database(task);
case "search":
return tools.search(task);
case "calculator":
return tools.calculator(task);
case "none":
return llm.answer(task); // a direct, single-step answer
default:
return planner.run(task); // "other": no tool fits
}
}A selected_tool of other with no policy match returns the fallback action (escalate by default) — handled above by the action !== "continue" branch.
Tune it
- Describe each tool by what it can answer, with exclusions: "our orders, customers and invoices — not product documentation". A JSON description such as
{ "what": "…", "not_for": "…", "examples": ["…"] }makes the boundaries explicit. - Add your tools as options — up to 254, plus
other— and keepnonefor tasks the agent can answer directly. Jev can lean toward the first option: reorder the tools in the Playground and check that the answers hold. - Move the threshold: lower the
needs_reasoningrule to 0.7 if your tools often fail on complex tasks, raise it to save LLM calls. - Pass the conversation: add fields such as
historyoruser_roleto the state — undeclared fields are forwarded to the engine. Send the last turns, not the whole history: unrelated context lowers accuracy. - Pick arguments too. When a tool takes a closed-set argument (a region, a report type), add a choice question per argument in the same decision — one call answers the tool and its arguments. This is the intent routing pattern applied to tools.
Spam detection
Classify free text as allow, review or block and estimate its spam probability with the Spam Detection template — a decision with a text state.
RAG relevance
Check whether a retrieved chunk answers the query before calling the LLM, and decide when to retrieve more context, with the RAG Relevance template.