Skip to content
tnsaiDocs
GitHub

Tool examples

A tool example is a sample call, or a call to avoid, that travels with the tool definition to the model. It shows the call shapes the tool expects, including ones that read as reasonable but break its contract.

Use examples when:

  • a tool has non-obvious parameter combinations, such as date ranges, optional filters or sentinel values;
  • a tool has a contract that is easy to break, such as a cursor that must advance once per turn or a DONE value that must not be paraphrased;
  • the description has grown past two short paragraphs of rules.

Skip them for trivial tools. Examples are sent with every request that carries the tool.

@ToolExample

@ToolExample is only valid inside @ActionSpec(examples = …). It cannot stand alone, and @Tool has no examples member.

MemberTypeDefaultPurpose
inputStringrequiredThe example input as a JSON string. It must match the parameter schema.
outputString""The expected output, or what it should look like
descriptionString""What the example shows
negativebooleanfalseMarks a call the model should not make
whyBadString""Why a negative example is wrong

A worked example

getNextQuestion drives a quiz. Each call advances a cursor and returns the next question, until it returns "DONE".

@ActionSpec(
    type = ActionType.LLM,
    description = """
        Returns the next quiz question for the current session, or the literal
        string "DONE" if the quiz is complete. Advances the session cursor by
        exactly one position per call.
        """,
    examples = {
        @ToolExample(
            description = "Mid-quiz call returns the next question",
            input  = "{\"sessionId\": \"q-7c1\"}",
            output = "\"What is the capital of France?\""
        ),
        @ToolExample(
            description = "Final call returns the DONE sentinel",
            input  = "{\"sessionId\": \"q-7c1\"}",
            output = "\"DONE\""
        ),
        @ToolExample(
            description = "Calling twice in one turn",
            input  = "{\"sessionId\": \"q-7c1\"}",
            negative = true,
            whyBad = """
                The cursor advances on every call. Calling twice in the same
                turn skips a question. Wait for the user's answer before
                calling again.
                """
        ),
        @ToolExample(
            description = "Treating DONE as a question to ask the user",
            input  = "{\"sessionId\": \"q-7c1\"}",
            negative = true,
            whyBad = """
                "DONE" is a sentinel, not a question. If the tool returns
                "DONE", finish the session. Do not pass it on to the user
                as the next question.
                """
        )
    }
)
public String getNextQuestion(String sessionId) { … }

The two positive examples cover the usual call and the last one. The two negative examples cover the likely mistakes: calling twice and passing the sentinel on. Each whyBad names the rule.

Examples and mustAlways / mustNever

@ActionSpec also takes mustAlways and mustNever rules. They are rendered into the system prompt next to the action they constrain.

Use a rule for an abstract constraint, such as "refund only authorized orders". Use an example for a pattern the model is likely to get wrong, such as "the cursor advances on every call". The two work together.

What each provider receives

The schema generator puts the examples in a function.examples array. Each provider client then maps them onto what its API accepts.

ProviderWhat the model receives
Anthropic, BedrockPositive examples go to input_examples. Negative examples are added to the description under AVOID:.
Every other provider with tool callsAll examples are added to the description, under EXAMPLES: and AVOID:.

"Every other provider" covers OpenAI, Azure OpenAI, Gemini, Cohere, Ollama, MiniMax, Zhipu, watsonx and the OpenAI-compatible providers, such as Mistral, Groq and OpenRouter.

Best practices

  • Two or three examples per tool. Cover the usual case and one boundary. More than four dilutes attention and grows every request.
  • Give every negative example a whyBad. Name the rule it breaks.
  • Use realistic input. {"query": "machine learning", "limit": 10} beats {"q": "x", "n": 1}. The model copies the shape it sees.
  • Keep negatives for non-obvious mistakes, such as sentinels, cursors and repeated side effects. Tool choice is not one of them.
  • Count the cost. A tool called once per session can carry more examples than one called every turn.