bots-garden/mini-mepublic Fork
⑂ feature/decider-no-tools
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
🛟 Updated. 9a5c4ec · on feature/decider-no-tools · k33g · 2d ago
mm-init.md · 119 lines · 10.6 KBmarkdown
Blame HistoryOpen raw

mm init: where a generated agent's settings come from — explanation

What is this about?

mm init (or mm --init) writes a commented agent.yaml from a few answers: the model server, the model, the usage (developer, translator, docs…), the machine, and whether to ask before each change. No model runs while the wizard runs. Every value in the file comes from one of four sources, and each value says which one in its comment. This page explains what those sources are, how they were put together, and why the wizard trusts them in that order. The steps are in Create an agent with mm init and the flags in the command line reference.

The four sources, most specific first

The code is in internal/agentinit. Decide (decide.go) applies the sources in a fixed order of trust: the server's facts about this model, then the family table, then the usage profile, then the machine row. Each source only fills in what the sources before it do not know.

1. What the model server says about the model (facts.go)

The server knows the exact model that is loaded, so it is the most specific source there is. The wizard asks it before choosing anything else:

Provider Asked What it gives
llmman, ollama /api/tags, then /api/show the model list, the family the server reports (details.family), the native context window, the sampling written in the GGUF (temperature, top_p, top_k, min_p), the chat template
llamacpp /props the window and the chat template
dmr /models the model list only
openai /models (with the key) the model list only

From the chat template, templateThinking reads how the model's reasoning is switched on or off. It finds enable_thinking and its default (on or off), or reasoning_effort and the values the template accepts. A model whose template knows neither gets no reasoning switch.

These rules were not written for mm init. They are a Go port of skills/create-agent/model_facts.py, the script the agent-creating agent (agent.creator.yaml) already used to read a model from llmman: the same endpoints, the same way of reading the template.

When the server gives the GGUF's own sampling, those numbers replace the family table's. The GGUF is the most specific source, because it was written for that very file. When the server says nothing beyond the model's name (DMR, the generic openai provider, an unknown model), the file says so in its closing notes, and the family table decides.

2. The family table (presets.yaml)

The family is guessed from the model id: the first family whose match words all appear in the lower-cased name wins. qwen-coder (qwen + coder) therefore comes before qwen, and other matches anything. The server's family is used when the name does not tell. A family gives:

  • the sampling for normal use (general) and with reasoning on (thinking);
  • a precise temperature, for agents that use tools without reasoning;
  • the reasoning switch;
  • sometimes a note, for example "a guard model, not a general agent".

Every number has a source line, and the table was filled from two kinds of source only:

  • Model cards and published files. The Qwen cards (thinking 0.6 / 0.95 / 20, non-thinking 0.7 / 0.8 / 20), the Gemma 4 GGUF sampling, Llama 3.1 8B Instruct's generation_config.json (0.6 / 0.9, read from a mirror because Meta's repository needs a login), the Mistral Small 3.1 card ("a relatively low temperature, such as temperature=0.15"), and the OpenAI API reference for hosted models.
  • This repository's measured demos. For each family, the demos that run the model were searched for the sampling they use (demos/*/agent*.yaml). For example, demos/qwen-style (Qwen3-Coder-Next), demos/coding-helpers (Mellum2 12B Thinking, MiniCPM5 2B), demos/team (Ornith 1.5 9B), demos/guard (Granite Guardian), demos/codex-style (gpt-oss 20B) and demos/llmman (Jan-nano, Lucy). Qwen's precise 0.0 comes from runs with Qwen3.5 4B, reasoning off (demos/docs-search, memory-search, plans).

When nothing is published, other uses the rule of the skills/create-agent skill: 0.7 / 0.9, and 0.2 for a code agent that does not reason.

3. The usage profile (presets.yaml, usages)

The usage says what the agent is for, which the model cannot tell. A profile sets:

  • which tool switches are on (a translator has no tool at all; a developer has bash, the file tools and the plan tool);
  • whether to reason when the model can;
  • whether to use the family's precise temperature;
  • maxTurns;
  • the default for asking before each change (yolo);
  • a starting system prompt.

Some usages switch on one feature each: docs turns on the documentation search, json writes a structuredOutput example (which forbids every tool), and coordinator hands the questions to other agents. The prompts are in English, by the user's choice in ticket 97. They repeat rules the demos' prompts share, for example "Never state the output of a command you did not run in this answer".

4. The machine row (presets.yaml, machines)

The timeouts and the size of tool outputs depend on the machine, not on the model. The three rows small, medium and large (firstTokenTimeout, watchdogTimeout, bashTimeout, maxOutput) are copied from the "Summary: typical profiles" table of the settings guide, written for ticket 98.

The rules the code adds

A few values follow from the answers rather than from a table. Each rule writes its reason above the value it sets:

  • Reasoning on means a temperature of at least 0.6 and max_tokens: 16384. A thinking model loops at a low temperature, and its thoughts need room besides the tool call. With reasoning off, the limit is 4096.
  • The precise temperature applies only without reasoning. It is used when the usage asks for it (developer, reviewer, docs, json…).
  • With bash on, watchdogTimeout is aligned on bashTimeout, as section 3 of the settings guide says. Otherwise a long command would look like a stalled model.
  • parallel_tool_calls: false for any agent with tools. Otherwise small models run a check before the change it checks has landed.
  • contextWindow: 0 and context.threshold: 75. mm asks the server for the window it actually serves. The proposal planned a threshold computed from the model's native window. It was dropped while writing the code: Ollama often serves 4k–8k, so a percentage of the native window would compress almost at once.
  • skillsDir: no-skills. A new agent starts without skills, and the comment says how to add some.

Every number says how it was obtained

Since ticket 121, each number about the model carries a tag in its comment. The file's header explains the tags it uses:

Tag Meaning After a model or quantization change
[server] read from the model server when the file was written run mm init again
[measured] a demo of this repository ran with it measure again
[card] copied from the model card, the GGUF or the API reference, not measured here read the card again
[rule] a rule of thumb, nothing specific to the model check it still fits
[guide] the settings guide's row for the machine —

A comment above model: lists what to redo when the model changes. The comments make the file teach as it configures, the way the demos' agent.yaml files are written: a reader sees which numbers were measured on a real run and which were only copied.

The file is checked before the wizard says it is done

The wizard never overwrites an existing file. After writing, it loads the file with mm's own config.Load, so a file mm would refuse is reported at once. With --check, it also runs the same mm on the new file with one question (Say hello in one line.), to prove the model answers.

Why it is designed this way

A generator with no model. Ticket 97 asked for an agent.yaml from the command line, by model family and usage. The proposal written for the ticket first listed what already existed: agent.creator.yaml with its create-agent skill, model_facts.py, the settings guide, config.samples/ and the demos' tested settings. Instead of a new source of knowledge, mm init puts those pieces together in deterministic Go code. It is instant and works before any agent exists.

A server first, a table second. A table can only know a family, while the server knows the very file that is loaded: its window, its GGUF sampling, its template. The table covers the servers that say nothing, such as Docker Model Runner.

Sourced values only. The user decided that the family table would use model cards and measured demos. A number with no source does not go in. A family with neither falls back to other, and the file says that its sampling is only a starting point.

One table. presets.yaml is embedded in the binary. Its header says it is meant to be shared with the Claude skill of ticket 111 (a skill built from the settings guide). That ticket is still open, and the mm-agent-creator skill does not read the file today.

Rejected alternatives

  • Generating the file with a model (agent.creator.yaml). Kept for the unusual cases, but not the default: it needs a 27B model loaded and minutes per agent.
  • A threshold computed from the native window. Rejected, see above: it would compress almost at once on the windows Ollama serves.
  • Skills, MCP servers, hooks and mmConfigs in the wizard. Left out of the first version. The file's closing comment points to the how-to guides instead.
  • Prompts in the user's language. Rejected by the user's choice: the generated prompts are in English.

Known limits

  • Live checks were run against llmman only (Qwen3.5 4B, gemma-4-E4B). Ollama, Docker Model Runner and llama-server were tested against fake servers recorded in the tests. The OpenAI API itself was not tried; its constraints come from its reference.
  • A [card] number was copied, not measured in this repository.
  • The families are matched on words in the model id: a model renamed by its publisher may land in other.

How it relates to the rest

  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
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# `mm init`: where a generated agent's settings come from — explanation

## What is this about?

`mm init` (or `mm --init`) writes a commented `agent.yaml` from a few answers: the model server, the model, the usage (developer, translator, docs…), the machine, and whether to ask before each change. No model runs while the wizard runs. Every value in the file comes from one of four sources, and each value says which one in its comment. This page explains what those sources are, how they were put together, and why the wizard trusts them in that order. The steps are in [Create an agent with `mm init`](../how-to/create-an-agent.md) and the flags in the [command line reference](../reference/cli.md#mm-init--the-agentyaml-wizard).

## The four sources, most specific first

The code is in `internal/agentinit`. `Decide` (`decide.go`) applies the sources in a fixed order of trust: **the server's facts about this model, then the family table, then the usage profile, then the machine row.** Each source only fills in what the sources before it do not know.

### 1. What the model server says about the model (`facts.go`)

The server knows the exact model that is loaded, so it is the most specific source there is. The wizard asks it before choosing anything else:

| Provider | Asked | What it gives |
|---|---|---|
| `llmman`, `ollama` | `/api/tags`, then `/api/show` | the model list, the family the server reports (`details.family`), the native context window, the sampling written in the GGUF (`temperature`, `top_p`, `top_k`, `min_p`), the chat template |
| `llamacpp` | `/props` | the window and the chat template |
| `dmr` | `/models` | the model list only |
| `openai` | `/models` (with the key) | the model list only |

From the chat template, `templateThinking` reads how the model's reasoning is switched on or off. It finds `enable_thinking` and its default (on or off), or `reasoning_effort` and the values the template accepts. A model whose template knows neither gets no reasoning switch.

These rules were not written for `mm init`. They are a Go port of `skills/create-agent/model_facts.py`, the script the agent-creating agent (`agent.creator.yaml`) already used to read a model from llmman: the same endpoints, the same way of reading the template.

When the server gives the GGUF's own sampling, those numbers **replace** the family table's. The GGUF is the most specific source, because it was written for that very file. When the server says nothing beyond the model's name (DMR, the generic `openai` provider, an unknown model), the file says so in its closing notes, and the family table decides.

### 2. The family table (`presets.yaml`)

The family is guessed from the model id: the first family whose `match` words all appear in the lower-cased name wins. `qwen-coder` (`qwen` + `coder`) therefore comes before `qwen`, and `other` matches anything. The server's family is used when the name does not tell. A family gives:

- the sampling for normal use (`general`) and with reasoning on (`thinking`);
- a `precise` temperature, for agents that use tools without reasoning;
- the reasoning switch;
- sometimes a note, for example "a guard model, not a general agent".

Every number has a `source` line, and the table was filled from two kinds of source only:

- **Model cards and published files.** The Qwen cards (thinking 0.6 / 0.95 / 20, non-thinking 0.7 / 0.8 / 20), the Gemma 4 GGUF sampling, Llama 3.1 8B Instruct's `generation_config.json` (0.6 / 0.9, read from a mirror because Meta's repository needs a login), the Mistral Small 3.1 card ("a relatively low temperature, such as temperature=0.15"), and the OpenAI API reference for hosted models.
- **This repository's measured demos.** For each family, the demos that run the model were searched for the sampling they use (`demos/*/agent*.yaml`). For example, `demos/qwen-style` (Qwen3-Coder-Next), `demos/coding-helpers` (Mellum2 12B Thinking, MiniCPM5 2B), `demos/team` (Ornith 1.5 9B), `demos/guard` (Granite Guardian), `demos/codex-style` (gpt-oss 20B) and `demos/llmman` (Jan-nano, Lucy). Qwen's `precise` 0.0 comes from runs with Qwen3.5 4B, reasoning off (`demos/docs-search`, `memory-search`, `plans`).

When nothing is published, `other` uses the rule of the `skills/create-agent` skill: 0.7 / 0.9, and 0.2 for a code agent that does not reason.

### 3. The usage profile (`presets.yaml`, `usages`)

The usage says what the agent is for, which the model cannot tell. A profile sets:

- which tool switches are on (a translator has no tool at all; a developer has bash, the file tools and the plan tool);
- whether to reason when the model can;
- whether to use the family's precise temperature;
- `maxTurns`;
- the default for asking before each change (`yolo`);
- a starting system prompt.

Some usages switch on one feature each: `docs` turns on the documentation search, `json` writes a `structuredOutput` example (which forbids every tool), and `coordinator` hands the questions to other agents. The prompts are in English, by the user's choice in ticket 97. They repeat rules the demos' prompts share, for example "Never state the output of a command you did not run in this answer".

### 4. The machine row (`presets.yaml`, `machines`)

The timeouts and the size of tool outputs depend on the machine, not on the model. The three rows `small`, `medium` and `large` (`firstTokenTimeout`, `watchdogTimeout`, `bashTimeout`, `maxOutput`) are copied from the "Summary: typical profiles" table of [the settings guide](../../../guides/agent-settings-for-small-models.md), written for ticket 98.

## The rules the code adds

A few values follow from the answers rather than from a table. Each rule writes its reason above the value it sets:

- **Reasoning on means a temperature of at least 0.6 and `max_tokens: 16384`.** A thinking model loops at a low temperature, and its thoughts need room besides the tool call. With reasoning off, the limit is 4096.
- **The precise temperature applies only without reasoning.** It is used when the usage asks for it (developer, reviewer, docs, json…).
- **With bash on, `watchdogTimeout` is aligned on `bashTimeout`**, as section 3 of the settings guide says. Otherwise a long command would look like a stalled model.
- **`parallel_tool_calls: false` for any agent with tools.** Otherwise small models run a check before the change it checks has landed.
- **`contextWindow: 0` and `context.threshold: 75`.** mm asks the server for the window it actually serves. The proposal planned a threshold computed from the model's native window. It was dropped while writing the code: Ollama often serves 4k–8k, so a percentage of the native window would compress almost at once.
- **`skillsDir: no-skills`.** A new agent starts without skills, and the comment says how to add some.

## Every number says how it was obtained

Since ticket 121, each number about the model carries a tag in its comment. The file's header explains the tags it uses:

| Tag | Meaning | After a model or quantization change |
|---|---|---|
| `[server]` | read from the model server when the file was written | run `mm init` again |
| `[measured]` | a demo of this repository ran with it | measure again |
| `[card]` | copied from the model card, the GGUF or the API reference, not measured here | read the card again |
| `[rule]` | a rule of thumb, nothing specific to the model | check it still fits |
| `[guide]` | the settings guide's row for the machine | — |

A comment above `model:` lists what to redo when the model changes. The comments make the file teach as it configures, the way the demos' `agent.yaml` files are written: a reader sees which numbers were measured on a real run and which were only copied.

## The file is checked before the wizard says it is done

The wizard never overwrites an existing file. After writing, it loads the file with mm's own `config.Load`, so a file mm would refuse is reported at once. With `--check`, it also runs the same mm on the new file with one question (`Say hello in one line.`), to prove the model answers.

## Why it is designed this way

**A generator with no model.** Ticket 97 asked for an `agent.yaml` from the command line, by model family and usage. The proposal written for the ticket first listed what already existed: `agent.creator.yaml` with its `create-agent` skill, `model_facts.py`, the settings guide, `config.samples/` and the demos' tested settings. Instead of a new source of knowledge, `mm init` puts those pieces together in deterministic Go code. It is instant and works before any agent exists.

**A server first, a table second.** A table can only know a family, while the server knows the very file that is loaded: its window, its GGUF sampling, its template. The table covers the servers that say nothing, such as Docker Model Runner.

**Sourced values only.** The user decided that the family table would use model cards **and** measured demos. A number with no source does not go in. A family with neither falls back to `other`, and the file says that its sampling is only a starting point.

**One table.** `presets.yaml` is embedded in the binary. Its header says it is meant to be shared with the Claude skill of ticket 111 (a skill built from the settings guide). That ticket is still open, and the `mm-agent-creator` skill does not read the file today.

## Rejected alternatives

- **Generating the file with a model** (`agent.creator.yaml`). Kept for the unusual cases, but not the default: it needs a 27B model loaded and minutes per agent.
- **A threshold computed from the native window.** Rejected, see above: it would compress almost at once on the windows Ollama serves.
- **Skills, MCP servers, hooks and `mmConfigs` in the wizard.** Left out of the first version. The file's closing comment points to the how-to guides instead.
- **Prompts in the user's language.** Rejected by the user's choice: the generated prompts are in English.

## Known limits

- Live checks were run against llmman only (Qwen3.5 4B, gemma-4-E4B). Ollama, Docker Model Runner and llama-server were tested against fake servers recorded in the tests. The OpenAI API itself was not tried; its constraints come from its reference.
- A `[card]` number was copied, not measured in this repository.
- The families are matched on words in the model id: a model renamed by its publisher may land in `other`.

## How it relates to the rest

- [Providers](providers.md): the five servers the wizard can ask, and why each has its own entry.
- [Thinking models](thinking-models.md): what the reasoning switch the wizard sets does at run time.
- [Context compression](context-compression.md): what `context.threshold` triggers.
- [Structured output](structured-output.md): why the `json` usage has no tools.
- [Asking another agent](asking-another-agent.md): what the `coordinator` usage relies on.