# 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.

| Member | Type | Default | Purpose |
|---|---|---|---|
| `input` | String | required | The example input as a JSON string. It must match the parameter schema. |
| `output` | String | `""` | The expected output, or what it should look like |
| `description` | String | `""` | What the example shows |
| `negative` | boolean | `false` | Marks a call the model should not make |
| `whyBad` | String | `""` | 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"`.

```java
@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.

| Provider | What the model receives |
|---|---|
| Anthropic, Bedrock | Positive examples go to `input_examples`. Negative examples are added to the description under `AVOID:`. |
| Every other provider with tool calls | All 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.

## Related

- [Custom tools](custom.md): the tools examples describe.
- [Actions](../agents/actions.md): `@ActionSpec` and its other members.
- [Anthropic: Introducing advanced tool use](https://www.anthropic.com/engineering/advanced-tool-use): reports that examples raised accuracy from 72% to 90% on complex parameters.
- [Claude API: Tool reference](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference): the `input_examples` field.
