Jev AI Hub
Start Learning

Agents · Mixed

Select an Agent Tool with Jev

Jev tool-selection example inspired by TypeSafe's skill-suggestion cookbook: a Choice over tool names plus a Noul for 'should we call anything?'.

Published
Sep 20, 2026
Updated
Sep 20, 2026
Last verified
Sep 20, 2026

Quick answer

Pick at most one tool from a closed catalog, and ask a Noul whether any tool should run.

Problem

An agent turn can search docs, create a ticket, or do nothing. Letting the LLM emit a free-form tool name hallucinates functions you do not have.

Why Jev fits this task

Official skill-suggestion cookbook ranks a catalog with TypeSafe questions, then decides whether to suggest a skill at all. Choice is relative (which tool). Each Noul is absolute (whether to fire). Those are different questions.

Input state

Send only the fields the questions name. Official docs warn that extra unrelated state costs accuracy.

{
  "available_tools": [
    "search_docs",
    "create_ticket",
    "lookup_order",
    "none"
  ],
  "user_turn": "Where do we document the 14-day refund window for annual plans?"
}

Question

Which registered tool, if any, should this turn call?

Question type: Mixed.

Jev schema

{
  "model": "jev-latest",
  "state": {
    "available_tools": [
      "search_docs",
      "create_ticket",
      "lookup_order",
      "none"
    ],
    "user_turn": "Where do we document the 14-day refund window for annual plans?"
  },
  "questions": {
    "tool": {
      "type": "choice",
      "instructions": "Which entry in `available_tools` should handle `user_turn`?",
      "criteria": {
        "search_docs": "The user wants existing documentation or a policy look-up.",
        "create_ticket": "The user wants a human ticket created.",
        "lookup_order": "The user names an order, invoice, or shipment to fetch.",
        "none": "No registered tool fits, or the user is only chatting."
      }
    },
    "needs_tool": {
      "type": "noul",
      "instructions": "Does `user_turn` require calling a tool before the agent replies?",
      "criteria": {
        "true": "A look-up or write action is required to answer correctly",
        "false": "The agent can reply from the turn text alone"
      }
    }
  }
}

Python example

from typesafe_sdk import Choice, Noul, TypeSafeClient

state = {
    "available_tools": [
        "search_docs",
        "create_ticket",
        "lookup_order",
        "none",
    ],
    "user_turn": "Where do we document the 14-day refund window for annual plans?",
}

with TypeSafeClient() as client:
    response = client.system_one(
        state=state,
        questions={
        "tool": Choice(
            instructions="Which entry in `available_tools` should handle `user_turn`?",
            criteria={
                            "search_docs": "The user wants existing documentation or a policy look-up.",
                            "create_ticket": "The user wants a human ticket created.",
                            "lookup_order": "The user names an order, invoice, or shipment to fetch.",
                            "none": "No registered tool fits, or the user is only chatting.",
                        },
        ),
        "needs_tool": Noul(
            instructions="Does `user_turn` require calling a tool before the agent replies?",
            criteria={
                            "true": "A look-up or write action is required to answer correctly",
                            "false": "The agent can reply from the turn text alone",
                        },
        ),
        },
    )

print(response.answers["tool"].choice)
print(response.model)

TypeScript example

import { choice, noul, TypeSafeClient } from "@typesafe-ai/sdk";

const client = new TypeSafeClient();

const response = await client.systemOne({
  state: {
    "available_tools": [
      "search_docs",
      "create_ticket",
      "lookup_order",
      "none"
    ],
    "user_turn": "Where do we document the 14-day refund window for annual plans?"
  },
  questions: {
    tool: choice("Which entry in `available_tools` should handle `user_turn`?", {
      search_docs: "The user wants existing documentation or a policy look-up.",
      create_ticket: "The user wants a human ticket created.",
      lookup_order: "The user names an order, invoice, or shipment to fetch.",
      none: "No registered tool fits, or the user is only chatting.",
    }),
    needs_tool: {
      type: "noul",
      instructions: "Does `user_turn` require calling a tool before the agent replies?",
      criteria: {"true":"A look-up or write action is required to answer correctly","false":"The agent can reply from the turn text alone"},
    },
  },
});

console.log(response.answers.tool.choice);
console.log(response.model);

JavaScript example

import { choice, noul, TypeSafeClient } from "@typesafe-ai/sdk";

const client = new TypeSafeClient();

const response = await client.systemOne({
  state: {
    "available_tools": [
      "search_docs",
      "create_ticket",
      "lookup_order",
      "none"
    ],
    "user_turn": "Where do we document the 14-day refund window for annual plans?"
  },
  questions: {
    tool: choice("Which entry in `available_tools` should handle `user_turn`?", {
      search_docs: "The user wants existing documentation or a policy look-up.",
      create_ticket: "The user wants a human ticket created.",
      lookup_order: "The user names an order, invoice, or shipment to fetch.",
      none: "No registered tool fits, or the user is only chatting.",
    }),
    needs_tool: {
      type: "noul",
      instructions: "Does `user_turn` require calling a tool before the agent replies?",
      criteria: {"true":"A look-up or write action is required to answer correctly","false":"The agent can reply from the turn text alone"},
    },
  },
});

console.log(response.answers.tool.choice);
console.log(response.model);

cURL example

curl -s https://api.typesafe.ai/v1/systemone \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'EOF'
{
  "model": "jev-latest",
  "state": {
    "available_tools": [
      "search_docs",
      "create_ticket",
      "lookup_order",
      "none"
    ],
    "user_turn": "Where do we document the 14-day refund window for annual plans?"
  },
  "questions": {
    "tool": {
      "type": "choice",
      "instructions": "Which entry in `available_tools` should handle `user_turn`?",
      "criteria": {
        "search_docs": "The user wants existing documentation or a policy look-up.",
        "create_ticket": "The user wants a human ticket created.",
        "lookup_order": "The user names an order, invoice, or shipment to fetch.",
        "none": "No registered tool fits, or the user is only chatting."
      }
    },
    "needs_tool": {
      "type": "noul",
      "instructions": "Does `user_turn` require calling a tool before the agent replies?",
      "criteria": {
        "true": "A look-up or write action is required to answer correctly",
        "false": "The agent can reply from the turn text alone"
      }
    }
  }
}
EOF

Expected output

{
  "model": "jev-1.13.0",
  "answers": {
    "tool": {
      "type": "choice",
      "choice": "search_docs",
      "probabilities": {
        "search_docs": 0.9,
        "create_ticket": 0.03,
        "lookup_order": 0.02,
        "none": 0.05
      },
      "confidence": 0.86
    },
    "needs_tool": {
      "type": "noul",
      "noul": 0.84
    }
  },
  "usage": {
    "input_tokens": 270,
    "output_tokens": 34
  }
}

Confidence handling

Call a tool only if needs_tool is high and tool.confidence is high and tool.choice !== none. Official notes: do not reuse the Choice confidence as a Noul threshold.

Production considerations

Keep the catalog in code. If the catalog is huge, official skill-suggestion flow fetches full text for the top three and asks again. That second call is required only when the first answer must change the next state.

Coding agents, support agents, and any runtime with a fixed tool registry.

When to use Jev

The tool list is known and the model must not invent a name.

When not to use Jev

You need the agent to write the user-facing answer, or you have one tool and a regex already decides.

Official cookbook for 182 Hermes skills uses a two-request pattern: rank, then re-read the top few. This page is the first request only. Jev will not implement the tool.

Common mistakes

  • Omitting none, so every chit-chat becomes create_ticket.
  • Asking Jev to generate the search query. Extract or template the query in code; use Jev to pick the tool.

FAQ

Is this the official function-calling API?

No. TypeSafe publishes a function-calling cookbook that maps names and closed arguments to questions. This page is a small independent recipe using that idea.

Sources

  1. Skill suggestionTypeSafe · accessed 2026-09-20 · documentation
  2. Primitives (Questions)TypeSafe · accessed 2026-09-20 · documentation
  3. ConfidenceTypeSafe · accessed 2026-09-20 · documentation

All Jev examples