bots-garden/mini-mepublic Fork
⑂ main
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. 8d8d1e8 · on main · k33g · 2d ago
write-decision-questions.md · 276 lines · 14.5 KBmarkdown
Blame HistoryOpen raw

How to write the questions of a decider

This guide shows how to build the decision: block of a decider step by step: which words are fixed, which ones you choose, which type to pick for each question, and how to read the answers. It assumes you already have a decider that runs — if not, start with How to ask a decision model.

What is fixed, what is yours

decision:                      # fixed
  timeout: 60s                 # fixed (optional)
  questions:                   # fixed
    hurry:                     # YOURS: any name
      type: noul               # fixed word, one of: choice, noul, score
      instructions: The message contains a word asking for speed, such as quick, fast, asap or now.   # YOURS
    level:                     # YOURS
      type: choice
      instructions: How familiar is the person with git?                                              # YOURS
      criteria:                # fixed word
        beginner: New to git   # YOURS: the option (key) and what it means (text)
        expert: Knows git well

hurry, upset, level, beginner… are names you choose, not keywords. mm and the model attach no meaning to them: the model reads only the instructions and the criteria texts. The name is the key you will find in the answer (answers.hurry), so pick one your script or your prompt can use.

The keywords are decision, timeout, questions, type, instructions, criteria, and the three type names.

Steps

1. Say what the decider reads

The decider reads one message, alone — the "state": a ticket, a command, the description of a game situation. No history, no system prompt. Everything it must know has to be in that message.

2. Split the decision into questions

One question per thing you want to know. "How serious is this ticket?" may become three: how soon (a level), is there a danger sign (yes or no), who should handle it (one option). All the questions are answered together, in one pass, a fraction of a second.

3. Pick a type for each question

You want… Type instructions is… criteria You get back
one option out of a list choice a question a mapping option: description, at least 2 choice (the option's key), probabilities (one per option), confidence
a yes or a no noul a statement about the message none noul: the probability, from 0 to 1, that the statement is true
a level on a scale score a question a list of 2 to 10 levels, lowest first score (from 0 to n−1, may fall between two levels), legend (number → level), probabilities, confidence

noul is the yes-or-no type. You do not ask a question, you write a statement — "The message describes chest pain" — and the decider gives the probability that it is true for this message: 0.96 means "almost certainly yes", 0.01 "almost certainly no". Your script decides where yes starts (0.5 is a common threshold, higher when a false yes is costly).

score returns a number, not a level: 2.81 on four levels means "between today and now, much closer to now". Round it to read the level in legend.

4. Write the instructions

  • choice and score: a question — "Which spell should I cast now?".
  • noul: a statement — "My character is badly hurt." A yes-or-no question works too: on five git questions, "Is the person upset?" and "The person is worried, stressed or upset." gave the same verdicts (0.97 and 0.99 on the two upset messages, 0.14 at most on the three calm ones).
  • Name what is in the text, not an intention. Measured with LiquidAI d1-3B: "The person is in a hurry or asks for a short answer" scored 0.5 to 0.7 on calm questions too; "The message contains a word asking for speed, such as quick, fast, asap or now" gave 0.03 on a calm question and 0.98 on "quick: …". Likewise "signs of a stroke" scored 0.27 on a textbook stroke, "a sudden weakness of an arm or a leg, slurred speech" 0.96.

5. Write the criteria

  • choice: the key is what you get back (fireball), the text is what the model reads to choose — say when to pick that option: fireball: Many enemies close together, far enough from my friends.
  • score: the levels, lowest first, as short phrases: [harmless, risky, deadly].
  • noul: nothing.

The order of the file is kept: in the request, in the answer, and in the line display.

6. Try it

With spell.yaml from demos/decision-questions/ (the complete file is in the examples):

mm -config spell.yaml -p "An ogre is raising its club to hit me right now."
{"model":"hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M","answers":{"spell":{"type":"choice","choice":"shield","probabilities":{"fireball":0.024,"magic_missile":0.043,"shield":0.878,"misty_step":0.043,"sleep":0.011},"confidence":0.848}},"usage":{"input_tokens":109,"output_tokens":0}}

(numbers shortened here; the server gives them in full.) Without -p, mm -config spell.yaml shows one line per question for each message you type, then the same JSON.

7. Read the answers

The envelope is always the same — model, answers, usage — and answers has one entry per question, under the name you chose, with the fields of its type (step 3). What changes from one decider to another is only the names and the number of questions.

  • choice: read choice; treat a low confidence (under 0.5 or so) as "unsure".
  • noul: compare noul with your threshold.
  • score: read legend[round(score)], or compare score itself (> 2.5).

Examples

Each example is a complete agent file in demos/decision-questions/: copy it, or run it from that folder with mm -config <file> -p "<message>". All answers below were measured on 2026-10-24 with LiquidAI d1-3B Q4_K_M on llmman.

Symptom tickets: how serious is it?

symptoms.yaml:

# A decider: Symptom tickets: how serious is it?
# An example of the guide docs/{en,fr}/how-to/write-decision-questions.md.
#
#   mm -config symptoms.yaml -p "My father suddenly cannot lift his right arm and his speech is slurred, it started 20 minutes ago."
#
# Pull the model once:  llmman pull hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
provider: llmman
model: hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
baseUrl: http://127.0.0.1:17434/v1
fallback: http://host.docker.internal:17434/v1

decision:
  questions:
    severity:
      type: score
      instructions: How soon should this person see a doctor?
      criteria: [it can wait for a usual appointment, within a few days, today, now - call the emergency number]
    red_flag:
      type: noul
      instructions: The message describes a sudden weakness of an arm or a leg, slurred speech, chest pain, trouble breathing, heavy bleeding or fainting.
    who:
      type: choice
      instructions: Who should see this person first?
      criteria:
        pharmacist: A minor problem a pharmacist can advise on
        family_doctor: A usual problem for a general practitioner
        specialist: A known long-term condition followed by a specialist
        emergency: A problem that cannot wait

# A decider gets no tool and ignores AGENTS.md: mm turns bash, the file tools,
# plan, ask_user, skills and AGENTS.md off by itself (no `…: false` lines needed).
Ticket severity red_flag who
My father suddenly cannot lift his right arm and his speech is slurred, it started 20 minutes ago. 2.81 → now (0.81) 0.96 emergency (0.86)
I have a tight pain in my chest and my left arm since an hour. 2.60 → now (0.60) 0.56 emergency (0.83)
I have had a sore throat and a runny nose for two days, no fever. 0.82 → within a few days (0.49) 0.01 pharmacist (0.30)

Put the danger signs in a noul of their own and let it win over the score: the chest pain got only 0.56 on red_flag, so a threshold of 0.5 catches it and 0.8 would not. A decider sorts tickets; it does not make a diagnosis, and a person must read what it sends to "can wait".

421: which dice to throw again?

dice421.yaml:

# A decider: 421: how many dice to throw again? The script writes what is missing: a decider reads, it does not count.
# An example of the guide docs/{en,fr}/how-to/write-decision-questions.md.
#
#   mm -config dice421.yaml -p "Dice: 4, 2, 6. In place for 421: 4 and 2. Missing: 1."
#
# Pull the model once:  llmman pull hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
provider: llmman
model: hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
baseUrl: http://127.0.0.1:17434/v1
fallback: http://host.docker.internal:17434/v1

decision:
  questions:
    reroll:
      type: choice
      instructions: How many dice should the player throw again?
      criteria:
        none: Nothing is missing
        one: One die is missing
        two: Two dice are missing
        all: All three are missing

# A decider gets no tool and ignores AGENTS.md: mm turns bash, the file tools,
# plan, ask_user, skills and AGENTS.md off by itself (no `…: false` lines needed).
State sent reroll
Dice: 4, 2, 6. none (0.33) — wrong
Dice: 4, 2, 6. In place for 421: 4 and 2. Missing: 1. one (0.80)
Dice: 4, 5, 6. In place for 421: 4. Missing: 2 and 1. two (0.62)
Dice: 3, 5, 6. In place for 421: nothing. Missing: 4, 2 and 1. all (0.76)
Dice: 4, 2, 1. In place for 421: 4, 2 and 1. Missing: nothing. none (0.96)

A decision model reads; it does not count. Given the dice alone it was wrong; once the script wrote what is missing into the state, it was right four times out of four. But then the script had already done the work: a rule like this one is better written in code. Keep the decider for what a rule cannot say — "is my opponent's score worth taking the risk?", described in words.

Dungeons & Dragons: which spell for my wizard?

spell.yaml:

# A decider: Dungeons & Dragons: which spell for my wizard?
# An example of the guide docs/{en,fr}/how-to/write-decision-questions.md.
#
#   mm -config spell.yaml -p "An ogre is raising its club to hit me right now."
#
# Pull the model once:  llmman pull hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
provider: llmman
model: hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
baseUrl: http://127.0.0.1:17434/v1
fallback: http://host.docker.internal:17434/v1

decision:
  questions:
    spell:
      type: choice
      instructions: I am the party's wizard. Which spell should I cast now?
      criteria:
        fireball: Many enemies close together, far enough from my friends
        magic_missile: One weak enemy to finish off, or one that is hard to hit
        shield: An enemy is about to hit me
        misty_step: I am surrounded or grabbed and must get away
        sleep: Several weak enemies, and we would rather not kill them

# A decider gets no tool and ignores AGENTS.md: mm turns bash, the file tools,
# plan, ask_user, skills and AGENTS.md off by itself (no `…: false` lines needed).
Situation spell
Five goblins are standing in a tight group 40 feet away. My friends are behind me. fireball (0.50)
An ogre is raising its club to hit me right now. shield (0.85)
Two wolves have grabbed me and the rest of the party is far away. misty_step (0.47)
One goblin is left, almost dead, hiding behind a crate. magic_missile (0.58)

Each description says when to cast the spell, not what it does: the decider matches the situation against these conditions.

Dungeons & Dragons: fight or flee?

fight.yaml:

# A decider: Dungeons & Dragons: fight, flee or talk?
# An example of the guide docs/{en,fr}/how-to/write-decision-questions.md.
#
#   mm -config fight.yaml -p "A troll guards the bridge. It says it will let us pass if we pay one gold coin."
#
# Pull the model once:  llmman pull hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
provider: llmman
model: hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
baseUrl: http://127.0.0.1:17434/v1
fallback: http://host.docker.internal:17434/v1

decision:
  questions:
    action:
      type: choice
      instructions: What should my character do now?
      criteria:
        fight: We can win this fight
        flee: We would probably lose, and there is a way out
        talk: The enemy might listen, a fight is not needed
    danger:
      type: score
      instructions: How dangerous is this situation for my character?
      criteria: [harmless, risky, deadly]
    hurt:
      type: noul
      instructions: My character is badly hurt.

# A decider gets no tool and ignores AGENTS.md: mm turns bash, the file tools,
# plan, ask_user, skills and AGENTS.md off by itself (no `…: false` lines needed).
Situation action danger hurt
We are four, full health, facing two tired bandits on an open road. fight (0.17) 1.15 → risky 0.18
I am alone with 3 hit points left, a red dragon lands in front of me, the cave exit is behind me. flee (0.56) 1.76 → deadly 0.97
A troll guards the bridge. It says it will let us pass if we pay one gold coin. talk (0.64) 0.64 → risky 0.31

The bandits got fight with a confidence of 0.17: the right option, but barely ahead of talk. Asking danger and hurt as well lets your script decide when action is unsure — for example, flee when hurt is above 0.8, whatever action says.

Common mistakes

Mistake Effect Fix
An intention or a diagnosis ("is in a hurry", "signs of a stroke") middling probabilities on every message name what can be read in the text
choice descriptions that say what an option is the decider cannot match the situation say when to pick it
score levels highest first the score reads backwards lowest first
Arithmetic or counting in the question wrong answers compute in the script, or put the result in the state
Context only in the history the decider never sees it put it in the message: the decider reads nothing else

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
 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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# How to write the questions of a decider

This guide shows how to build the `decision:` block of a decider step by step: which words are fixed, which ones you choose, which type to pick for each question, and how to read the answers. It assumes you already have a decider that runs — if not, start with [How to ask a decision model](ask-a-decision-model.md).

## What is fixed, what is yours

```yaml
decision:                      # fixed
  timeout: 60s                 # fixed (optional)
  questions:                   # fixed
    hurry:                     # YOURS: any name
      type: noul               # fixed word, one of: choice, noul, score
      instructions: The message contains a word asking for speed, such as quick, fast, asap or now.   # YOURS
    level:                     # YOURS
      type: choice
      instructions: How familiar is the person with git?                                              # YOURS
      criteria:                # fixed word
        beginner: New to git   # YOURS: the option (key) and what it means (text)
        expert: Knows git well
```

`hurry`, `upset`, `level`, `beginner`… are **names you choose**, not keywords. mm and the model attach no meaning to them: the model reads only the `instructions` and the `criteria` texts. The name is the key you will find in the answer (`answers.hurry`), so pick one your script or your prompt can use.

The keywords are `decision`, `timeout`, `questions`, `type`, `instructions`, `criteria`, and the three type names.

## Steps

### 1. Say what the decider reads

The decider reads **one message**, alone — the "state": a ticket, a command, the description of a game situation. No history, no system prompt. Everything it must know has to be in that message.

### 2. Split the decision into questions

One question per thing you want to know. "How serious is this ticket?" may become three: how soon (a level), is there a danger sign (yes or no), who should handle it (one option). All the questions are answered together, in one pass, a fraction of a second.

### 3. Pick a type for each question

| You want… | Type | `instructions` is… | `criteria` | You get back |
|-----------|------|--------------------|------------|--------------|
| one option out of a list | `choice` | a question | a mapping `option: description`, at least 2 | `choice` (the option's key), `probabilities` (one per option), `confidence` |
| a yes or a no | `noul` | a **statement** about the message | none | `noul`: the probability, from 0 to 1, that the statement is true |
| a level on a scale | `score` | a question | a list of 2 to 10 levels, **lowest first** | `score` (from 0 to n−1, may fall between two levels), `legend` (number → level), `probabilities`, `confidence` |

**`noul`** is the yes-or-no type. You do not ask a question, you write a statement — "The message describes chest pain" — and the decider gives the probability that it is true for this message: `0.96` means "almost certainly yes", `0.01` "almost certainly no". Your script decides where yes starts (0.5 is a common threshold, higher when a false yes is costly).

**`score`** returns a number, not a level: `2.81` on four levels means "between *today* and *now*, much closer to *now*". Round it to read the level in `legend`.

### 4. Write the `instructions`

- `choice` and `score`: a question — "Which spell should I cast now?".
- `noul`: a statement — "My character is badly hurt." A yes-or-no question works too: on five git questions, "Is the person upset?" and "The person is worried, stressed or upset." gave the same verdicts (0.97 and 0.99 on the two upset messages, 0.14 at most on the three calm ones).
- **Name what is in the text, not an intention.** Measured with LiquidAI d1-3B: "The person is in a hurry or asks for a short answer" scored 0.5 to 0.7 on calm questions too; "The message contains a word asking for speed, such as quick, fast, asap or now" gave 0.03 on a calm question and 0.98 on "quick: …". Likewise "signs of a stroke" scored 0.27 on a textbook stroke, "a sudden weakness of an arm or a leg, slurred speech" 0.96.

### 5. Write the `criteria`

- `choice`: the key is what you get back (`fireball`), the text is what the model reads to choose — say **when** to pick that option: `fireball: Many enemies close together, far enough from my friends`.
- `score`: the levels, lowest first, as short phrases: `[harmless, risky, deadly]`.
- `noul`: nothing.

The order of the file is kept: in the request, in the answer, and in the line display.

### 6. Try it

With `spell.yaml` from `demos/decision-questions/` (the complete file is in the [examples](#dungeons--dragons-which-spell-for-my-wizard)):

```bash
mm -config spell.yaml -p "An ogre is raising its club to hit me right now."
```

```json
{"model":"hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M","answers":{"spell":{"type":"choice","choice":"shield","probabilities":{"fireball":0.024,"magic_missile":0.043,"shield":0.878,"misty_step":0.043,"sleep":0.011},"confidence":0.848}},"usage":{"input_tokens":109,"output_tokens":0}}
```

(numbers shortened here; the server gives them in full.) Without `-p`, `mm -config spell.yaml` shows one line per question for each message you type, then the same JSON.

### 7. Read the answers

The envelope is always the same — `model`, `answers`, `usage` — and `answers` has one entry per question, under the name you chose, with the fields of its type (step 3). What changes from one decider to another is only the names and the number of questions.

- `choice`: read `choice`; treat a low `confidence` (under 0.5 or so) as "unsure".
- `noul`: compare `noul` with your threshold.
- `score`: read `legend[round(score)]`, or compare `score` itself (`> 2.5`).

## Examples

Each example is a complete agent file in [`demos/decision-questions/`](../../../demos/decision-questions/README.en.md): copy it, or run it from that folder with `mm -config <file> -p "<message>"`. All answers below were measured on 2026-10-24 with LiquidAI d1-3B Q4_K_M on llmman.

### Symptom tickets: how serious is it?

`symptoms.yaml`:

```yaml
# A decider: Symptom tickets: how serious is it?
# An example of the guide docs/{en,fr}/how-to/write-decision-questions.md.
#
#   mm -config symptoms.yaml -p "My father suddenly cannot lift his right arm and his speech is slurred, it started 20 minutes ago."
#
# Pull the model once:  llmman pull hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
provider: llmman
model: hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
baseUrl: http://127.0.0.1:17434/v1
fallback: http://host.docker.internal:17434/v1

decision:
  questions:
    severity:
      type: score
      instructions: How soon should this person see a doctor?
      criteria: [it can wait for a usual appointment, within a few days, today, now - call the emergency number]
    red_flag:
      type: noul
      instructions: The message describes a sudden weakness of an arm or a leg, slurred speech, chest pain, trouble breathing, heavy bleeding or fainting.
    who:
      type: choice
      instructions: Who should see this person first?
      criteria:
        pharmacist: A minor problem a pharmacist can advise on
        family_doctor: A usual problem for a general practitioner
        specialist: A known long-term condition followed by a specialist
        emergency: A problem that cannot wait

# A decider gets no tool and ignores AGENTS.md: mm turns bash, the file tools,
# plan, ask_user, skills and AGENTS.md off by itself (no `…: false` lines needed).
```

| Ticket | severity | red_flag | who |
|--------|----------|----------|-----|
| My father suddenly cannot lift his right arm and his speech is slurred, it started 20 minutes ago. | 2.81 → now (0.81) | 0.96 | emergency (0.86) |
| I have a tight pain in my chest and my left arm since an hour. | 2.60 → now (0.60) | 0.56 | emergency (0.83) |
| I have had a sore throat and a runny nose for two days, no fever. | 0.82 → within a few days (0.49) | 0.01 | pharmacist (0.30) |

Put the danger signs in a `noul` of their own and let it win over the score: the chest pain got only 0.56 on `red_flag`, so a threshold of 0.5 catches it and 0.8 would not. A decider sorts tickets; it does not make a diagnosis, and a person must read what it sends to "can wait".

### 421: which dice to throw again?

`dice421.yaml`:

```yaml
# A decider: 421: how many dice to throw again? The script writes what is missing: a decider reads, it does not count.
# An example of the guide docs/{en,fr}/how-to/write-decision-questions.md.
#
#   mm -config dice421.yaml -p "Dice: 4, 2, 6. In place for 421: 4 and 2. Missing: 1."
#
# Pull the model once:  llmman pull hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
provider: llmman
model: hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
baseUrl: http://127.0.0.1:17434/v1
fallback: http://host.docker.internal:17434/v1

decision:
  questions:
    reroll:
      type: choice
      instructions: How many dice should the player throw again?
      criteria:
        none: Nothing is missing
        one: One die is missing
        two: Two dice are missing
        all: All three are missing

# A decider gets no tool and ignores AGENTS.md: mm turns bash, the file tools,
# plan, ask_user, skills and AGENTS.md off by itself (no `…: false` lines needed).
```

| State sent | reroll |
|------------|--------|
| `Dice: 4, 2, 6.` | none (0.33) — wrong |
| `Dice: 4, 2, 6. In place for 421: 4 and 2. Missing: 1.` | one (0.80) |
| `Dice: 4, 5, 6. In place for 421: 4. Missing: 2 and 1.` | two (0.62) |
| `Dice: 3, 5, 6. In place for 421: nothing. Missing: 4, 2 and 1.` | all (0.76) |
| `Dice: 4, 2, 1. In place for 421: 4, 2 and 1. Missing: nothing.` | none (0.96) |

A decision model reads; it does not count. Given the dice alone it was wrong; once the script wrote what is missing into the state, it was right four times out of four. But then the script had already done the work: a rule like this one is better written in code. Keep the decider for what a rule cannot say — "is my opponent's score worth taking the risk?", described in words.

### Dungeons & Dragons: which spell for my wizard?

`spell.yaml`:

```yaml
# A decider: Dungeons & Dragons: which spell for my wizard?
# An example of the guide docs/{en,fr}/how-to/write-decision-questions.md.
#
#   mm -config spell.yaml -p "An ogre is raising its club to hit me right now."
#
# Pull the model once:  llmman pull hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
provider: llmman
model: hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
baseUrl: http://127.0.0.1:17434/v1
fallback: http://host.docker.internal:17434/v1

decision:
  questions:
    spell:
      type: choice
      instructions: I am the party's wizard. Which spell should I cast now?
      criteria:
        fireball: Many enemies close together, far enough from my friends
        magic_missile: One weak enemy to finish off, or one that is hard to hit
        shield: An enemy is about to hit me
        misty_step: I am surrounded or grabbed and must get away
        sleep: Several weak enemies, and we would rather not kill them

# A decider gets no tool and ignores AGENTS.md: mm turns bash, the file tools,
# plan, ask_user, skills and AGENTS.md off by itself (no `…: false` lines needed).
```

| Situation | spell |
|-----------|-------|
| Five goblins are standing in a tight group 40 feet away. My friends are behind me. | fireball (0.50) |
| An ogre is raising its club to hit me right now. | shield (0.85) |
| Two wolves have grabbed me and the rest of the party is far away. | misty_step (0.47) |
| One goblin is left, almost dead, hiding behind a crate. | magic_missile (0.58) |

Each description says when to cast the spell, not what it does: the decider matches the situation against these conditions.

### Dungeons & Dragons: fight or flee?

`fight.yaml`:

```yaml
# A decider: Dungeons & Dragons: fight, flee or talk?
# An example of the guide docs/{en,fr}/how-to/write-decision-questions.md.
#
#   mm -config fight.yaml -p "A troll guards the bridge. It says it will let us pass if we pay one gold coin."
#
# Pull the model once:  llmman pull hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
provider: llmman
model: hf.co/LiquidAI/d1-3B-GGUF:Q4_K_M
baseUrl: http://127.0.0.1:17434/v1
fallback: http://host.docker.internal:17434/v1

decision:
  questions:
    action:
      type: choice
      instructions: What should my character do now?
      criteria:
        fight: We can win this fight
        flee: We would probably lose, and there is a way out
        talk: The enemy might listen, a fight is not needed
    danger:
      type: score
      instructions: How dangerous is this situation for my character?
      criteria: [harmless, risky, deadly]
    hurt:
      type: noul
      instructions: My character is badly hurt.

# A decider gets no tool and ignores AGENTS.md: mm turns bash, the file tools,
# plan, ask_user, skills and AGENTS.md off by itself (no `…: false` lines needed).
```

| Situation | action | danger | hurt |
|-----------|--------|--------|------|
| We are four, full health, facing two tired bandits on an open road. | fight (0.17) | 1.15 → risky | 0.18 |
| I am alone with 3 hit points left, a red dragon lands in front of me, the cave exit is behind me. | flee (0.56) | 1.76 → deadly | 0.97 |
| A troll guards the bridge. It says it will let us pass if we pay one gold coin. | talk (0.64) | 0.64 → risky | 0.31 |

The bandits got `fight` with a confidence of 0.17: the right option, but barely ahead of `talk`. Asking `danger` and `hurt` as well lets your script decide when `action` is unsure — for example, flee when `hurt` is above 0.8, whatever `action` says.

## Common mistakes

| Mistake | Effect | Fix |
|---------|--------|-----|
| An intention or a diagnosis ("is in a hurry", "signs of a stroke") | middling probabilities on every message | name what can be read in the text |
| `choice` descriptions that say what an option *is* | the decider cannot match the situation | say **when** to pick it |
| `score` levels highest first | the score reads backwards | lowest first |
| Arithmetic or counting in the question | wrong answers | compute in the script, or put the result in the state |
| Context only in the history | the decider never sees it | put it in the message: the decider reads nothing else |

## See also

- [Configuration reference — `decision`](../reference/configuration.md#decision): every key and every field of the answers
- [How to ask a decision model](ask-a-decision-model.md): serve the model, write the agent file, ask it from a script, a hook or another agent
- [Decision models — explanation](../explanation/decision-models.md): why a decider is an agent, what was measured
- Demos: `demos/decision-only/`, `demos/decision-reviews/`, `demos/decision-moderation/` (a decider alone), `demos/decision-chat/` (a decider before a chat agent)