bots-garden/mini-mepublic Fork
⑂ v1.0.7
Commits
⬇ Clone ▾
git clone https://git.rickub.com/bots-garden/mini-me.git
git clone ssh://git@rickub.com/bots-garden/mini-me.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP
use-a-model-that-reads-xml-tools.md · 47 lines · 3.4 KBmarkdown
Blame HistoryOpen raw

How to give tools to a model whose template reads xml_tools (SmolLM3)

This guide shows how to make a model like SmolLM3 call mm's tools. Its card says it supports tool calling, but through mm it never calls one: it describes the command instead of running it. It assumes you already have an agent file for that model (written by mm init, for example).

Why it does not work by default

mm sends its tools in the OpenAI API's tools field, and llama-server (behind llmman, Ollama, DMR…) hands them to the model's chat template under that name. SmolLM3's template never reads tools: it reads xml_tools (the argument of apply_chat_template(xml_tools=…) in its card's example). The model therefore never sees a tool. Given xml_tools, it answers with the call as text — <tool_call>{"name": "bash", "arguments": {"command": "ls"}}</tool_call> — which the server does not turn into a tool call.

Steps

  1. In the agent file, add:

    toolFormat: xml_tools
    

    mm then sends the tools in chat_template_kwargs.xml_tools, writes earlier calls back into the history as <tool_call> text (the template shows a message by its text only), and turns the <tool_call> blocks of the answer into tool calls — streamed or not. They do not appear in the answer's text.

  2. Turn the reasoning off — SmolLM3's template turns it on by default:

    sampling:
      chat_template_kwargs:
        enable_thinking: false
    

    With reasoning on, SmolLM3-3B repeats its call after the tool's answer instead of answering (measured: 3 runs out of 3; with it off, 6 out of 6 answered).

  3. Start mm and ask for something a tool answers: List the files of this directory. A 🛠️ bash: ls line, the command's output under it and the ⚙ 1 command(s) counter show the call ran.

Variants

  • A new agent. For the smollm3 family, mm init does both steps: it writes toolFormat: xml_tools when the usage has tools, and enable_thinking: false whatever the usage, with a note at the end of the file.
  • A usage without tools (translator, json): nothing to do, toolFormat changes nothing without tools.
  • See what goes over the wire. With trace: {enabled: true}, the request files show chat_template_kwargs.xml_tools and no tools; the response files show the server's raw <tool_call> text, before mm reads it. See How to see the JSON sent to the model.
  • A broken call. A <tool_call> whose JSON is cut (by max_tokens) or malformed is handed back to the model with a note, as for any model, as long as its tool name can be read; otherwise it stays in the answer's text.

Limits

  • Tasks of several steps stay fragile with SmolLM3-3B: in the tests, it sometimes took a tool's output for something the user said (the template shows a tool's answer as a user message). Wrapping the output in <tool_response> tags made no measured difference.
  • llama.cpp's common/chat.cpp had no SmolLM3-specific handling when this was written (2026-11-13), and the llama-server used by llmman did not parse the calls: hence the work on mm's side.

See also

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# How to give tools to a model whose template reads `xml_tools` (SmolLM3)

This guide shows how to make a model like SmolLM3 call mm's tools. Its card says it supports tool calling, but through mm it never calls one: it describes the command instead of running it. It assumes you already have an agent file for that model (written by `mm init`, for example).

## Why it does not work by default

mm sends its tools in the OpenAI API's `tools` field, and llama-server (behind llmman, Ollama, DMR…) hands them to the model's chat template under that name. SmolLM3's template never reads `tools`: it reads `xml_tools` (the argument of `apply_chat_template(xml_tools=…)` in its card's example). The model therefore never sees a tool. Given `xml_tools`, it answers with the call as text — `<tool_call>{"name": "bash", "arguments": {"command": "ls"}}</tool_call>` — which the server does not turn into a tool call.

## Steps

1. In the agent file, add:

   ```yaml
   toolFormat: xml_tools
   ```

   mm then sends the tools in `chat_template_kwargs.xml_tools`, writes earlier calls back into the history as `<tool_call>` text (the template shows a message by its text only), and turns the `<tool_call>` blocks of the answer into tool calls — streamed or not. They do not appear in the answer's text.

2. Turn the reasoning off — SmolLM3's template turns it on by default:

   ```yaml
   sampling:
     chat_template_kwargs:
       enable_thinking: false
   ```

   With reasoning on, SmolLM3-3B repeats its call after the tool's answer instead of answering (measured: 3 runs out of 3; with it off, 6 out of 6 answered).

3. Start `mm` and ask for something a tool answers: `List the files of this directory.` A `🛠️  bash: ls` line, the command's output under it and the `⚙ 1 command(s)` counter show the call ran.

## Variants

- **A new agent.** For the `smollm3` family, `mm init` does both steps: it writes `toolFormat: xml_tools` when the usage has tools, and `enable_thinking: false` whatever the usage, with a note at the end of the file.
- **A usage without tools** (`translator`, `json`): nothing to do, `toolFormat` changes nothing without tools.
- **See what goes over the wire.** With `trace: {enabled: true}`, the request files show `chat_template_kwargs.xml_tools` and no `tools`; the response files show the server's raw `<tool_call>` text, before mm reads it. See [How to see the JSON sent to the model](inspect-model-traffic.md).
- **A broken call.** A `<tool_call>` whose JSON is cut (by `max_tokens`) or malformed is handed back to the model with a note, as for any model, as long as its tool name can be read; otherwise it stays in the answer's text.

## Limits

- Tasks of several steps stay fragile with SmolLM3-3B: in the tests, it sometimes took a tool's output for something the user said (the template shows a tool's answer as a user message). Wrapping the output in `<tool_response>` tags made no measured difference.
- llama.cpp's `common/chat.cpp` had no SmolLM3-specific handling when this was written (2026-11-13), and the llama-server used by llmman did not parse the calls: hence the work on mm's side.

## See also

- The key: [Configuration reference](../reference/configuration.md) (`toolFormat`)
- Turning reasoning off for other servers: [How to turn a model's reasoning off](turn-reasoning-off.md)
- Where the `smollm3` numbers come from: [`mm init` explanation](../explanation/mm-init.md)