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

Use mm CLI to ask another agent #22

Merged@k33g wants to merge feature/ask-cli into main
Merged as 9d1939fae92e.
33 files changed
modified .tickets/issues/0052-buitin-acp-tool-to-query-other-agent-like-mini-m.yaml +2 -1
@@ -6,7 +6,7 @@ author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-09-29T05:18:13.897Z
9-updatedAt: 2026-09-29T06:25:58.324Z
9+updatedAt: 2026-10-02T21:15:00.000Z
1010 labels:
1111 - priority::high
1212 - kind::feature
@@ -15,6 +15,7 @@ labels:
1515 milestone: v0.3.0
1616 related:
1717 - 33
18+ - 66
1819 body: ""
1920 tasks: []
2021 comments: []
@@ -6,7 +6,7 @@ author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-09-29T05:18:13.897Z8 createdAt: 2026-09-29T05:18:13.897Z
9-updatedAt: 2026-09-29T06:25:58.324Z9+updatedAt: 2026-10-02T21:15:00.000Z
10 labels:10 labels:
11 - priority::high11 - priority::high
12 - kind::feature12 - kind::feature
@@ -15,6 +15,7 @@ labels:
15 milestone: v0.3.015 milestone: v0.3.0
16 related:16 related:
17 - 3317 - 33
18+ - 66
18 body: ""19 body: ""
19 tasks: []20 tasks: []
20 comments: []21 comments: []
modified .tickets/issues/0066-talk-to-another-mm.yaml +2 -1
@@ -6,10 +6,11 @@ author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-10-02T18:48:36.275Z
9-updatedAt: 2026-10-02T20:30:00.000Z
9+updatedAt: 2026-10-02T21:15:00.000Z
1010 labels:
1111 - kind::feature
1212 related:
13+ - 52
1314 - 57
1415 - 59
1516 body: |
@@ -6,10 +6,11 @@ author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-10-02T18:48:36.275Z8 createdAt: 2026-10-02T18:48:36.275Z
9-updatedAt: 2026-10-02T20:30:00.000Z9+updatedAt: 2026-10-02T21:15:00.000Z
10 labels:10 labels:
11 - kind::feature11 - kind::feature
12 related:12 related:
13+ - 52
13 - 5714 - 57
14 - 5915 - 59
15 body: |16 body: |
renamed .tickets/issues/0071-mini-me-as-a-sdk.yaml +2 -2
similarity index 84%
rename from .tickets/issues/0066-mini-me-as-a-sdk.yaml
rename to .tickets/issues/0071-mini-me-as-a-sdk.yaml
@@ -1,12 +1,12 @@
11 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2-id: 66
2+id: 71
33 title: Mini Me as a SDK
44 state: open
55 author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-10-02T05:32:33.878Z
9-updatedAt: 2026-10-02T05:32:33.878Z
9+updatedAt: 2026-10-02T21:15:00.000Z
1010 labels: []
1111 body: ""
1212 tasks: []
similarity index 84%
rename from .tickets/issues/0066-mini-me-as-a-sdk.yaml
rename to .tickets/issues/0071-mini-me-as-a-sdk.yaml
@@ -1,12 +1,12 @@
1 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.1 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2-id: 662+id: 71
3 title: Mini Me as a SDK3 title: Mini Me as a SDK
4 state: open4 state: open
5 author:5 author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-10-02T05:32:33.878Z8 createdAt: 2026-10-02T05:32:33.878Z
9-updatedAt: 2026-10-02T05:32:33.878Z9+updatedAt: 2026-10-02T21:15:00.000Z
10 labels: []10 labels: []
11 body: ""11 body: ""
12 tasks: []12 tasks: []
added .tickets/issues/0072-use-a-decision-model-as-a-local-decider.yaml +242 -0
new file mode 100644
@@ -0,0 +1,242 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 72
3+title: Use a decision model (decision-4b) as a local decider
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-10-02T21:40:00.000Z
9+updatedAt: 2026-10-02T21:40:00.000Z
10+labels:
11+ - kind::feature
12+related:
13+ - 15
14+ - 59
15+ - 66
16+body: |
17+ Use a DECISION model (e.g. https://huggingface.co/evalengine/decision-4b)
18+ beside the main model, as a fast local "decider" mm consults at precise
19+ moments. Not as mm's `model:`: such a model generates no text and calls no
20+ tools.
21+
22+ ## What the model is (from its card, 2026-10-02)
23+
24+ - LoRA (65 MB) on Qwen/Qwen3.5-4B; ready GGUF: evalengine/decision-4b-gguf
25+ (Q4_K_M 2.7 GB, Q8_0, F16). Smaller sibling: evalengine/decision-0.8b(-gguf).
26+ - In: a `state`, a `question`, 2..24 `options` (letter label, key,
27+ description). Out: one option + a probability per option, read from the
28+ next-token logits. One forward pass, nothing generated.
29+ - Limits: 2048-token context, English only, weaker on multi-rule policies,
30+ probabilities not calibrated, "not for unattended high-stakes decisions".
31+
32+ ## Transport
33+
34+ 1. Preferred: llmman `POST /v1/systemone` (built for this; llama.cpp has no
35+ such endpoint). A `state` + up to 64 typed questions: `choice` (answer,
36+ confidence, probabilities in the order sent, first option = A), `noul`
37+ (probability of yes), `score` (probability-weighted level + legend).
38+ `x_label_mass` = probability put on the labels at all (low = the model
39+ wanted to say something else). Runs with enable_thinking false; loads the
40+ model in its own backend (`<model>#systemone` in `llmman ps`).
41+ 2. Fallback: llama-server / DMR `/v1/chat/completions` with `max_tokens: 1`,
42+ `logprobs: true`, `top_logprobs: N`, the Qwen chat template and the card's
43+ system prompt; renormalise over the option letters found in the top N
44+ (a letter outside the top N gets 0 — less exact than systemone).
45+ Ollama: logprobs support to be checked.
46+
47+ ## Config (proposal)
48+
49+ decisionModel:
50+ provider: llmman # systemone needs llmman
51+ baseUrl: http://127.0.0.1:17434 # NOT /v1: /v1/systemone is added
52+ model: hf.co/evalengine/decision-4b-gguf:Q4_K_M
53+ api: systemone # or: logprobs (llama-server, DMR)
54+ minConfidence: 0.6 # below: do nothing, as if absent
55+ skillRouting: true # use 1
56+ commandTriage: false # use 2
57+ askRouting: true # use 3
58+
59+ ## Use 1 — choose the skill before the turn (start here)
60+
61+ Today the main model reads the read_skill catalogue and may or may not load
62+ the right procedure (measured by the MM_EVAL routing eval, internal/eval).
63+ With a decider: before the turn, ask which skill applies; above
64+ minConfidence, append the existing `$skill` notation to the question, so the
65+ model still makes the read_skill call itself (loop detector, permission
66+ gate and recap still see it).
67+
68+ Example request:
69+
70+ POST /v1/systemone
71+ {
72+ "model": "hf.co/evalengine/decision-4b-gguf:Q4_K_M",
73+ "state": "User request: start the dev server and tell me when it answers on port 8080",
74+ "questions": {
75+ "skill": {
76+ "type": "choice",
77+ "instructions": "Which procedure should the coding agent follow for this request?",
78+ "criteria": {
79+ "bg-jobs": "Start, watch or stop a long-running command in the background",
80+ "lsp-navigation": "Find a definition, references or symbols in the code",
81+ "plan-manager": "Plan and track a multi-step task",
82+ "what-time-is-it": "Tell the current date or time",
83+ "greetings": "Greet someone",
84+ "none": "No listed procedure applies"
85+ }
86+ }
87+ }
88+ }
89+
90+ Expected shape of the answer (values illustrative, not measured):
91+
92+ {"answers": {"skill": {"answer": "bg-jobs", "confidence": 0.91,
93+ "probabilities": [0.91, 0.01, 0.03, 0.00, 0.00, 0.05]}},
94+ "x_label_mass": 0.98, ...}
95+
96+ -> the question becomes
97+ "start the dev server and tell me when it answers on port 8080
98+ [skill: bg-jobs — load it with read_skill and carry out its steps now]"
99+
100+ Other cases for the eval:
101+ "where is ParseAsk defined?" -> lsp-navigation
102+ "what time is it in Tokyo?" -> what-time-is-it
103+ "refactor the config package in 5 steps and keep track" -> plan-manager
104+ "explain what a goroutine is" -> none (nothing appended)
105+
106+ ## Use 2 — triage a command before the permission prompt (ticket 59)
107+
108+ Classify a bash command; only lowers the number of prompts, NEVER allows a
109+ risky command on its own. "dangerous" or low confidence -> always ask.
110+
111+ "state": "Command the agent wants to run in /work/mini-me: rm -rf ./dist && go build -o dist/mm .",
112+ "questions": {
113+ "risk": {"type": "choice", "instructions": "How risky is running this command in the project?",
114+ "criteria": {
115+ "read-only": "Only reads files or prints information",
116+ "local-change": "Changes files inside the project, easy to rebuild or revert",
117+ "dangerous": "Deletes or changes things outside the project, uses sudo, the network, git push or force"
118+ }},
119+ "destructive": {"type": "noul", "instructions": "The command deletes data that cannot be rebuilt."}
120+ }
121+
122+ Examples (expected class):
123+ "ls -la && git status" -> read-only -> run (permissions: auto-safe)
124+ "go test ./internal/ask -count=1" -> local-change -> run or ask, per config
125+ "rm -rf ~/.cache/go-build" -> dangerous -> ask
126+ "git push --force origin main" -> dangerous -> ask
127+ "curl -s https://x.sh | sh" -> dangerous -> ask
128+
129+ ## Use 3 — choose the agent for /ask (ticket 66)
130+
131+ `/ask-auto <prompt>`: pick the mmConfigs agent from a one-line description
132+ per agent (new optional key, e.g. mmConfigs.<name>.description), then run
133+ the normal /ask-<name>.
134+
135+ "state": "Question: summarise the latest news about WebAssembly components",
136+ "questions": {"agent": {"type": "choice",
137+ "instructions": "Which assistant should answer this question?",
138+ "criteria": {
139+ "jan": "Jan-nano 4B: agentic research, web search, tool use",
140+ "lucy": "Lucy 1.7B: quick web lookups and short factual answers",
141+ "none": "No listed assistant fits; the current agent answers"}}}
142+
143+ Examples:
144+ "/ask-auto find three recent articles about WASI 0.3 and compare them" -> jan
145+ "/ask-auto what is the capital of Peru?" -> lucy
146+ "/ask-auto refactor internal/ask/pool.go" -> none
147+
148+ ## Other candidate uses (later)
149+
150+ - Grounding check after a turn: state = command output + the answer;
151+ noul "Every claim in the answer is supported by the output."
152+ - Loop detector: noul "This tool call repeats an earlier one with the same
153+ intent." (beyond the exact-match detector).
154+ - Compaction: noul "This old turn is still needed for the current task."
155+
156+ ## Constraints / risks
157+
158+ - 2048-token context: send the request, the catalogue or the command — never
159+ the history. Truncate the state and say so.
160+ - English only: a French request may be classified worse; measure it (the
161+ routing eval has FR cases?) before enabling by default.
162+ - Extra latency per question (one forward pass, ~100-300 ms on a laptop;
163+ to measure) and a second loaded model (2.7 GB for Q4_K_M; 0.8B variant
164+ smaller).
165+ - A decider that is down or slow must never block a turn: timeout (e.g. 2 s),
166+ then behave as if absent.
167+ - Probabilities are not calibrated: minConfidence is set from the eval, not
168+ guessed.
169+tasks:
170+ - id: 1
171+ title: "Try it live: llmman pull hf.co/evalengine/decision-4b-gguf:Q4_K_M, then curl /v1/systemone with the use-1 example; record answer, confidence, x_label_mass, latency"
172+ state: open
173+ priority: none
174+ author:
175+ name: k33g
176+ email: ph.charriere@gmail.com
177+ createdAt: 2026-10-02T21:40:00.000Z
178+ updatedAt: 2026-10-02T21:40:00.000Z
179+ - id: 2
180+ title: "Measure use 1 offline: run the MM_EVAL routing cases through /v1/systemone; compare with the main model's routing; pick minConfidence"
181+ state: open
182+ priority: none
183+ author:
184+ name: k33g
185+ email: ph.charriere@gmail.com
186+ createdAt: 2026-10-02T21:40:00.000Z
187+ updatedAt: 2026-10-02T21:40:00.000Z
188+ - id: 3
189+ title: "Decide config shape (decisionModel block, per-use switches) with the user"
190+ state: open
191+ priority: none
192+ author:
193+ name: k33g
194+ email: ph.charriere@gmail.com
195+ createdAt: 2026-10-02T21:40:00.000Z
196+ updatedAt: 2026-10-02T21:40:00.000Z
197+ - id: 4
198+ title: "internal/decide: systemone client (+ logprobs fallback), timeout, never blocks a turn; tests with an httptest server"
199+ state: open
200+ priority: none
201+ author:
202+ name: k33g
203+ email: ph.charriere@gmail.com
204+ createdAt: 2026-10-02T21:40:00.000Z
205+ updatedAt: 2026-10-02T21:40:00.000Z
206+ - id: 5
207+ title: "Use 1: skill routing before the turn in the three front ends (append $skill); recap line shows the decider's pick"
208+ state: open
209+ priority: none
210+ author:
211+ name: k33g
212+ email: ph.charriere@gmail.com
213+ createdAt: 2026-10-02T21:40:00.000Z
214+ updatedAt: 2026-10-02T21:40:00.000Z
215+ - id: 6
216+ title: "Use 2: command triage feeding the permission decision (ticket 59), dangerous/low confidence always asks"
217+ state: open
218+ priority: none
219+ author:
220+ name: k33g
221+ email: ph.charriere@gmail.com
222+ createdAt: 2026-10-02T21:40:00.000Z
223+ updatedAt: 2026-10-02T21:40:00.000Z
224+ - id: 7
225+ title: "Use 3: /ask-auto with mmConfigs descriptions (ticket 66)"
226+ state: open
227+ priority: none
228+ author:
229+ name: k33g
230+ email: ph.charriere@gmail.com
231+ createdAt: 2026-10-02T21:40:00.000Z
232+ updatedAt: 2026-10-02T21:40:00.000Z
233+ - id: 8
234+ title: "Docs EN+FR (how-to, reference, explanation) + package diagram"
235+ state: open
236+ priority: none
237+ author:
238+ name: k33g
239+ email: ph.charriere@gmail.com
240+ createdAt: 2026-10-02T21:40:00.000Z
241+ updatedAt: 2026-10-02T21:40:00.000Z
242+comments: []
new file mode 100644
@@ -0,0 +1,242 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 72
3+title: Use a decision model (decision-4b) as a local decider
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-10-02T21:40:00.000Z
9+updatedAt: 2026-10-02T21:40:00.000Z
10+labels:
11+ - kind::feature
12+related:
13+ - 15
14+ - 59
15+ - 66
16+body: |
17+ Use a DECISION model (e.g. https://huggingface.co/evalengine/decision-4b)
18+ beside the main model, as a fast local "decider" mm consults at precise
19+ moments. Not as mm's `model:`: such a model generates no text and calls no
20+ tools.
21+
22+ ## What the model is (from its card, 2026-10-02)
23+
24+ - LoRA (65 MB) on Qwen/Qwen3.5-4B; ready GGUF: evalengine/decision-4b-gguf
25+ (Q4_K_M 2.7 GB, Q8_0, F16). Smaller sibling: evalengine/decision-0.8b(-gguf).
26+ - In: a `state`, a `question`, 2..24 `options` (letter label, key,
27+ description). Out: one option + a probability per option, read from the
28+ next-token logits. One forward pass, nothing generated.
29+ - Limits: 2048-token context, English only, weaker on multi-rule policies,
30+ probabilities not calibrated, "not for unattended high-stakes decisions".
31+
32+ ## Transport
33+
34+ 1. Preferred: llmman `POST /v1/systemone` (built for this; llama.cpp has no
35+ such endpoint). A `state` + up to 64 typed questions: `choice` (answer,
36+ confidence, probabilities in the order sent, first option = A), `noul`
37+ (probability of yes), `score` (probability-weighted level + legend).
38+ `x_label_mass` = probability put on the labels at all (low = the model
39+ wanted to say something else). Runs with enable_thinking false; loads the
40+ model in its own backend (`<model>#systemone` in `llmman ps`).
41+ 2. Fallback: llama-server / DMR `/v1/chat/completions` with `max_tokens: 1`,
42+ `logprobs: true`, `top_logprobs: N`, the Qwen chat template and the card's
43+ system prompt; renormalise over the option letters found in the top N
44+ (a letter outside the top N gets 0 — less exact than systemone).
45+ Ollama: logprobs support to be checked.
46+
47+ ## Config (proposal)
48+
49+ decisionModel:
50+ provider: llmman # systemone needs llmman
51+ baseUrl: http://127.0.0.1:17434 # NOT /v1: /v1/systemone is added
52+ model: hf.co/evalengine/decision-4b-gguf:Q4_K_M
53+ api: systemone # or: logprobs (llama-server, DMR)
54+ minConfidence: 0.6 # below: do nothing, as if absent
55+ skillRouting: true # use 1
56+ commandTriage: false # use 2
57+ askRouting: true # use 3
58+
59+ ## Use 1 — choose the skill before the turn (start here)
60+
61+ Today the main model reads the read_skill catalogue and may or may not load
62+ the right procedure (measured by the MM_EVAL routing eval, internal/eval).
63+ With a decider: before the turn, ask which skill applies; above
64+ minConfidence, append the existing `$skill` notation to the question, so the
65+ model still makes the read_skill call itself (loop detector, permission
66+ gate and recap still see it).
67+
68+ Example request:
69+
70+ POST /v1/systemone
71+ {
72+ "model": "hf.co/evalengine/decision-4b-gguf:Q4_K_M",
73+ "state": "User request: start the dev server and tell me when it answers on port 8080",
74+ "questions": {
75+ "skill": {
76+ "type": "choice",
77+ "instructions": "Which procedure should the coding agent follow for this request?",
78+ "criteria": {
79+ "bg-jobs": "Start, watch or stop a long-running command in the background",
80+ "lsp-navigation": "Find a definition, references or symbols in the code",
81+ "plan-manager": "Plan and track a multi-step task",
82+ "what-time-is-it": "Tell the current date or time",
83+ "greetings": "Greet someone",
84+ "none": "No listed procedure applies"
85+ }
86+ }
87+ }
88+ }
89+
90+ Expected shape of the answer (values illustrative, not measured):
91+
92+ {"answers": {"skill": {"answer": "bg-jobs", "confidence": 0.91,
93+ "probabilities": [0.91, 0.01, 0.03, 0.00, 0.00, 0.05]}},
94+ "x_label_mass": 0.98, ...}
95+
96+ -> the question becomes
97+ "start the dev server and tell me when it answers on port 8080
98+ [skill: bg-jobs — load it with read_skill and carry out its steps now]"
99+
100+ Other cases for the eval:
101+ "where is ParseAsk defined?" -> lsp-navigation
102+ "what time is it in Tokyo?" -> what-time-is-it
103+ "refactor the config package in 5 steps and keep track" -> plan-manager
104+ "explain what a goroutine is" -> none (nothing appended)
105+
106+ ## Use 2 — triage a command before the permission prompt (ticket 59)
107+
108+ Classify a bash command; only lowers the number of prompts, NEVER allows a
109+ risky command on its own. "dangerous" or low confidence -> always ask.
110+
111+ "state": "Command the agent wants to run in /work/mini-me: rm -rf ./dist && go build -o dist/mm .",
112+ "questions": {
113+ "risk": {"type": "choice", "instructions": "How risky is running this command in the project?",
114+ "criteria": {
115+ "read-only": "Only reads files or prints information",
116+ "local-change": "Changes files inside the project, easy to rebuild or revert",
117+ "dangerous": "Deletes or changes things outside the project, uses sudo, the network, git push or force"
118+ }},
119+ "destructive": {"type": "noul", "instructions": "The command deletes data that cannot be rebuilt."}
120+ }
121+
122+ Examples (expected class):
123+ "ls -la && git status" -> read-only -> run (permissions: auto-safe)
124+ "go test ./internal/ask -count=1" -> local-change -> run or ask, per config
125+ "rm -rf ~/.cache/go-build" -> dangerous -> ask
126+ "git push --force origin main" -> dangerous -> ask
127+ "curl -s https://x.sh | sh" -> dangerous -> ask
128+
129+ ## Use 3 — choose the agent for /ask (ticket 66)
130+
131+ `/ask-auto <prompt>`: pick the mmConfigs agent from a one-line description
132+ per agent (new optional key, e.g. mmConfigs.<name>.description), then run
133+ the normal /ask-<name>.
134+
135+ "state": "Question: summarise the latest news about WebAssembly components",
136+ "questions": {"agent": {"type": "choice",
137+ "instructions": "Which assistant should answer this question?",
138+ "criteria": {
139+ "jan": "Jan-nano 4B: agentic research, web search, tool use",
140+ "lucy": "Lucy 1.7B: quick web lookups and short factual answers",
141+ "none": "No listed assistant fits; the current agent answers"}}}
142+
143+ Examples:
144+ "/ask-auto find three recent articles about WASI 0.3 and compare them" -> jan
145+ "/ask-auto what is the capital of Peru?" -> lucy
146+ "/ask-auto refactor internal/ask/pool.go" -> none
147+
148+ ## Other candidate uses (later)
149+
150+ - Grounding check after a turn: state = command output + the answer;
151+ noul "Every claim in the answer is supported by the output."
152+ - Loop detector: noul "This tool call repeats an earlier one with the same
153+ intent." (beyond the exact-match detector).
154+ - Compaction: noul "This old turn is still needed for the current task."
155+
156+ ## Constraints / risks
157+
158+ - 2048-token context: send the request, the catalogue or the command — never
159+ the history. Truncate the state and say so.
160+ - English only: a French request may be classified worse; measure it (the
161+ routing eval has FR cases?) before enabling by default.
162+ - Extra latency per question (one forward pass, ~100-300 ms on a laptop;
163+ to measure) and a second loaded model (2.7 GB for Q4_K_M; 0.8B variant
164+ smaller).
165+ - A decider that is down or slow must never block a turn: timeout (e.g. 2 s),
166+ then behave as if absent.
167+ - Probabilities are not calibrated: minConfidence is set from the eval, not
168+ guessed.
169+tasks:
170+ - id: 1
171+ title: "Try it live: llmman pull hf.co/evalengine/decision-4b-gguf:Q4_K_M, then curl /v1/systemone with the use-1 example; record answer, confidence, x_label_mass, latency"
172+ state: open
173+ priority: none
174+ author:
175+ name: k33g
176+ email: ph.charriere@gmail.com
177+ createdAt: 2026-10-02T21:40:00.000Z
178+ updatedAt: 2026-10-02T21:40:00.000Z
179+ - id: 2
180+ title: "Measure use 1 offline: run the MM_EVAL routing cases through /v1/systemone; compare with the main model's routing; pick minConfidence"
181+ state: open
182+ priority: none
183+ author:
184+ name: k33g
185+ email: ph.charriere@gmail.com
186+ createdAt: 2026-10-02T21:40:00.000Z
187+ updatedAt: 2026-10-02T21:40:00.000Z
188+ - id: 3
189+ title: "Decide config shape (decisionModel block, per-use switches) with the user"
190+ state: open
191+ priority: none
192+ author:
193+ name: k33g
194+ email: ph.charriere@gmail.com
195+ createdAt: 2026-10-02T21:40:00.000Z
196+ updatedAt: 2026-10-02T21:40:00.000Z
197+ - id: 4
198+ title: "internal/decide: systemone client (+ logprobs fallback), timeout, never blocks a turn; tests with an httptest server"
199+ state: open
200+ priority: none
201+ author:
202+ name: k33g
203+ email: ph.charriere@gmail.com
204+ createdAt: 2026-10-02T21:40:00.000Z
205+ updatedAt: 2026-10-02T21:40:00.000Z
206+ - id: 5
207+ title: "Use 1: skill routing before the turn in the three front ends (append $skill); recap line shows the decider's pick"
208+ state: open
209+ priority: none
210+ author:
211+ name: k33g
212+ email: ph.charriere@gmail.com
213+ createdAt: 2026-10-02T21:40:00.000Z
214+ updatedAt: 2026-10-02T21:40:00.000Z
215+ - id: 6
216+ title: "Use 2: command triage feeding the permission decision (ticket 59), dangerous/low confidence always asks"
217+ state: open
218+ priority: none
219+ author:
220+ name: k33g
221+ email: ph.charriere@gmail.com
222+ createdAt: 2026-10-02T21:40:00.000Z
223+ updatedAt: 2026-10-02T21:40:00.000Z
224+ - id: 7
225+ title: "Use 3: /ask-auto with mmConfigs descriptions (ticket 66)"
226+ state: open
227+ priority: none
228+ author:
229+ name: k33g
230+ email: ph.charriere@gmail.com
231+ createdAt: 2026-10-02T21:40:00.000Z
232+ updatedAt: 2026-10-02T21:40:00.000Z
233+ - id: 8
234+ title: "Docs EN+FR (how-to, reference, explanation) + package diagram"
235+ state: open
236+ priority: none
237+ author:
238+ name: k33g
239+ email: ph.charriere@gmail.com
240+ createdAt: 2026-10-02T21:40:00.000Z
241+ updatedAt: 2026-10-02T21:40:00.000Z
242+comments: []
added .tickets/issues/0073-mm-ask-from-a-skill-or-a-script.yaml +216 -0
new file mode 100644
@@ -0,0 +1,216 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 73
3+title: "mm --ask / --ask-with-context: ask another agent from a skill or a script"
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-10-02T23:30:00.000Z
9+updatedAt: 2026-10-02T23:30:00.000Z
10+labels:
11+ - kind::feature
12+related:
13+ - 52
14+ - 57
15+ - 66
16+body: |
17+ Call another mm agent from a skill, a script or a prompt: the shell-command
18+ equivalent of /ask and /ask-with-context (ticket 66).
19+
20+ ## Usage
21+
22+ mm --ask <agent> -p "<question>" # question with -p
23+ echo "<question>" | mm --ask <agent> # or on stdin
24+ mm --ask-with-context <agent> -p "<question>" < context.txt
25+ printf '%s\n---\n%s\n' "<context>" "<question>" | mm --ask-with-context <agent>
26+
27+ - <agent> is a key of `mmConfigs` in the configuration: -config, the
28+ positional path, then MM_CONFIG (see below), then the usual resolution.
29+ - stdout = the agent's answer ONLY (+ newline), so
30+ `answer=$(mm --ask jan -p "…")` captures it alone. stderr = the label
31+ ("🗣 asking jan (llmman/…)…"), one "🛠️ jan · <tool>: <args>" line per tool
32+ call, "[ask: …]" on error.
33+ - Exit codes: 0 answered; 1 no question / no context / unknown agent / the
34+ agent failed or gave no answer; 130 interrupted (Ctrl+C or parent gone).
35+ - No engine is started for the asking config's own model: only the child.
36+
37+ ## From a skill
38+
39+ mm now exports two variables to the commands its bash tool runs:
40+ - MM_BIN — the running mm binary (os.Executable)
41+ - MM_CONFIG — the absolute path of its configuration file
42+ so a skill writes, without knowing any path:
43+
44+ "$MM_BIN" --ask jan -p "What is the capital of Peru?"
45+
46+ "$MM_BIN" --ask-with-context reviewer <<'CONTEXT'
47+ User: I think Go's goroutines are OS threads.
48+ Assistant: They are not: the Go runtime schedules them onto a few OS threads.
49+ ---
50+ Is the assistant right?
51+ CONTEXT
52+
53+ The model writes the context summary itself: a command cannot read the
54+ conversation (the slash command /ask-with-context builds it from the history).
55+
56+ ## Demo (demo-llmman/)
57+
58+ - agent.llmman.yaml: mmConfigs jan, lucy, reviewer; skillsDir: skills;
59+ bashTimeout: 3m and watchdogTimeout: 3m (see "Time" below).
60+ - agent.lucy-reviewer.yaml (new): Lucy's model, NO tools (bashTool, editTools,
61+ planTool false, skillsDir pointing nowhere), a reviewer system prompt.
62+ - skills/ (new; bg-jobs copied from ../skills because the system prompt names it):
63+ - delegate-to-jan — "Ask Jan what the capital of Peru is."
64+ -> read_skill delegate-to-jan; bash: "$MM_BIN" --ask jan -p "What is
65+ the capital of Peru?" -> "Jan says: The capital of Peru is Lima."
66+ (verified live, 52 s including model loads)
67+ - second-opinion — "I think Go's goroutines are OS threads. Get a second
68+ opinion from Lucy on that claim." -> --ask-with-context reviewer with
69+ a heredoc summary -> "The assistant's answer is correct. Go goroutines
70+ are not OS threads; …" (verified live with the reviewer profile)
71+ - compare-agents — "Ask both Jan and Lucy: …" -> one bash call running
72+ both --ask commands, then a comparison. (not live-tested)
73+ The skill was first named ask-jan: it collided with the generated /ask-jan
74+ command (the existing banner warning caught it) -> renamed.
75+
76+ ## What the live tests found (2026-10-02)
77+
78+ 1. Time. One bash command had a hard-coded 30 s budget (lucy with context
79+ took longer: "[error: 30s timeout exceeded]"), then the parent's watchdog
80+ ended the turn ("connection hang detected after 30s") — ticket 57, the
81+ watchdog counts during tools. -> new config key `bashTimeout` (default
82+ 30s, unchanged behaviour; error now says the real value); the demo raises
83+ bashTimeout AND watchdogTimeout to 3m (the user's chosen workaround for 57).
84+ 2. Orphans. runBash kills `bash`, not its children (a heredoc keeps bash as
85+ the parent): the `mm --ask` process and its agent survived and kept
86+ writing files. -> `mm --ask` watches its parent pid every 500 ms
87+ (ask.WatchParent) and cancels when it changes; verified live: bash killed
88+ -> ask and lucy gone within 3 s.
89+ 3. Wandering. Lucy 1.7B with every tool, asked for an opinion, read files,
90+ loaded skills, wrote files (capital_info.txt, goroutine-os-thread.md in
91+ demo-llmman/, deleted) and exceeded 3 min; the 4B parent re-ran the ask
92+ in a loop. -> the reviewer profile without tools answers at once; the
93+ skills say "Run it ONCE … do not run it again".
94+ 4. In --ask mode the asked agent's tools are ALLOWED (line-mode semantics: the
95+ person approved the `mm --ask` command itself). Point 3 shows the risk.
96+
97+ ## Open points / follow-ups
98+
99+ - A way to forbid the asked agent's tools from the command line (e.g.
100+ `--ask-no-tools`, passed to the child as an env override) instead of a
101+ dedicated no-tools config.
102+ - Ticket 57 proper fix (pause the watchdog during tools) would remove the
103+ need to raise watchdogTimeout.
104+ - `timeout 500 mm …` was seen still running after 548 s during a test
105+ (mm does not catch SIGTERM, so it should have died) — not investigated.
106+ - English-only questions work best with these small models.
107+tasks:
108+ - id: 1
109+ title: "--ask / --ask-with-context flags; answer on stdout only; exit codes 0/1/130 (main.go runAsk, internal/ask/cli.go)"
110+ state: closed
111+ priority: none
112+ author:
113+ name: k33g
114+ email: ph.charriere@gmail.com
115+ createdAt: 2026-10-02T23:30:00.000Z
116+ updatedAt: 2026-10-02T23:30:00.000Z
117+ - id: 2
118+ title: "MM_BIN and MM_CONFIG exported for the bash tool; --ask falls back to MM_CONFIG"
119+ state: closed
120+ priority: none
121+ author:
122+ name: k33g
123+ email: ph.charriere@gmail.com
124+ createdAt: 2026-10-02T23:30:00.000Z
125+ updatedAt: 2026-10-02T23:30:00.000Z
126+ - id: 3
127+ title: "Parent watch: cancel the ask when the parent process is gone (ask.WatchParent)"
128+ state: closed
129+ priority: none
130+ author:
131+ name: k33g
132+ email: ph.charriere@gmail.com
133+ createdAt: 2026-10-02T23:30:00.000Z
134+ updatedAt: 2026-10-02T23:30:00.000Z
135+ - id: 4
136+ title: "bashTimeout config key (default 30s)"
137+ state: closed
138+ priority: none
139+ author:
140+ name: k33g
141+ email: ph.charriere@gmail.com
142+ createdAt: 2026-10-02T23:30:00.000Z
143+ updatedAt: 2026-10-02T23:30:00.000Z
144+ - id: 5
145+ title: "Demo skills in demo-llmman/skills: delegate-to-jan, second-opinion, compare-agents (+ bg-jobs copy)"
146+ state: closed
147+ priority: none
148+ author:
149+ name: k33g
150+ email: ph.charriere@gmail.com
151+ createdAt: 2026-10-02T23:30:00.000Z
152+ updatedAt: 2026-10-02T23:30:00.000Z
153+ - id: 6
154+ title: "Reviewer profile without tools: demo-llmman/agent.lucy-reviewer.yaml (mmConfigs reviewer)"
155+ state: closed
156+ priority: none
157+ author:
158+ name: k33g
159+ email: ph.charriere@gmail.com
160+ createdAt: 2026-10-02T23:30:00.000Z
161+ updatedAt: 2026-10-02T23:30:00.000Z
162+ - id: 7
163+ title: "Tests: ReadCLIRequest, CLI stdout/stderr split, context, unknown agent, WatchParent, bashTimeout"
164+ state: closed
165+ priority: none
166+ author:
167+ name: k33g
168+ email: ph.charriere@gmail.com
169+ createdAt: 2026-10-02T23:30:00.000Z
170+ updatedAt: 2026-10-02T23:30:00.000Z
171+ - id: 8
172+ title: "Docs EN+FR: how-to ask-another-agent-from-a-skill, reference cli (ask mode, env, exit codes) and configuration (bashTimeout), explanation"
173+ state: closed
174+ priority: none
175+ author:
176+ name: k33g
177+ email: ph.charriere@gmail.com
178+ createdAt: 2026-10-02T23:30:00.000Z
179+ updatedAt: 2026-10-02T23:30:00.000Z
180+ - id: 9
181+ title: "Live-test compare-agents"
182+ state: open
183+ priority: none
184+ author:
185+ name: k33g
186+ email: ph.charriere@gmail.com
187+ createdAt: 2026-10-02T23:30:00.000Z
188+ updatedAt: 2026-10-02T23:30:00.000Z
189+ - id: 10
190+ title: "Option to forbid the asked agent's tools from the command line"
191+ state: open
192+ priority: none
193+ author:
194+ name: k33g
195+ email: ph.charriere@gmail.com
196+ createdAt: 2026-10-02T23:30:00.000Z
197+ updatedAt: 2026-10-02T23:30:00.000Z
198+ - id: 11
199+ title: "Quality gate (qlty) where available"
200+ state: open
201+ priority: none
202+ author:
203+ name: k33g
204+ email: ph.charriere@gmail.com
205+ createdAt: 2026-10-02T23:30:00.000Z
206+ updatedAt: 2026-10-02T23:30:00.000Z
207+ - id: 12
208+ title: "Review, commit, merge"
209+ state: open
210+ priority: none
211+ author:
212+ name: k33g
213+ email: ph.charriere@gmail.com
214+ createdAt: 2026-10-02T23:30:00.000Z
215+ updatedAt: 2026-10-02T23:30:00.000Z
216+comments: []
new file mode 100644
@@ -0,0 +1,216 @@
1+# Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
2+id: 73
3+title: "mm --ask / --ask-with-context: ask another agent from a skill or a script"
4+state: open
5+author:
6+ name: k33g
7+ email: ph.charriere@gmail.com
8+createdAt: 2026-10-02T23:30:00.000Z
9+updatedAt: 2026-10-02T23:30:00.000Z
10+labels:
11+ - kind::feature
12+related:
13+ - 52
14+ - 57
15+ - 66
16+body: |
17+ Call another mm agent from a skill, a script or a prompt: the shell-command
18+ equivalent of /ask and /ask-with-context (ticket 66).
19+
20+ ## Usage
21+
22+ mm --ask <agent> -p "<question>" # question with -p
23+ echo "<question>" | mm --ask <agent> # or on stdin
24+ mm --ask-with-context <agent> -p "<question>" < context.txt
25+ printf '%s\n---\n%s\n' "<context>" "<question>" | mm --ask-with-context <agent>
26+
27+ - <agent> is a key of `mmConfigs` in the configuration: -config, the
28+ positional path, then MM_CONFIG (see below), then the usual resolution.
29+ - stdout = the agent's answer ONLY (+ newline), so
30+ `answer=$(mm --ask jan -p "…")` captures it alone. stderr = the label
31+ ("🗣 asking jan (llmman/…)…"), one "🛠️ jan · <tool>: <args>" line per tool
32+ call, "[ask: …]" on error.
33+ - Exit codes: 0 answered; 1 no question / no context / unknown agent / the
34+ agent failed or gave no answer; 130 interrupted (Ctrl+C or parent gone).
35+ - No engine is started for the asking config's own model: only the child.
36+
37+ ## From a skill
38+
39+ mm now exports two variables to the commands its bash tool runs:
40+ - MM_BIN — the running mm binary (os.Executable)
41+ - MM_CONFIG — the absolute path of its configuration file
42+ so a skill writes, without knowing any path:
43+
44+ "$MM_BIN" --ask jan -p "What is the capital of Peru?"
45+
46+ "$MM_BIN" --ask-with-context reviewer <<'CONTEXT'
47+ User: I think Go's goroutines are OS threads.
48+ Assistant: They are not: the Go runtime schedules them onto a few OS threads.
49+ ---
50+ Is the assistant right?
51+ CONTEXT
52+
53+ The model writes the context summary itself: a command cannot read the
54+ conversation (the slash command /ask-with-context builds it from the history).
55+
56+ ## Demo (demo-llmman/)
57+
58+ - agent.llmman.yaml: mmConfigs jan, lucy, reviewer; skillsDir: skills;
59+ bashTimeout: 3m and watchdogTimeout: 3m (see "Time" below).
60+ - agent.lucy-reviewer.yaml (new): Lucy's model, NO tools (bashTool, editTools,
61+ planTool false, skillsDir pointing nowhere), a reviewer system prompt.
62+ - skills/ (new; bg-jobs copied from ../skills because the system prompt names it):
63+ - delegate-to-jan — "Ask Jan what the capital of Peru is."
64+ -> read_skill delegate-to-jan; bash: "$MM_BIN" --ask jan -p "What is
65+ the capital of Peru?" -> "Jan says: The capital of Peru is Lima."
66+ (verified live, 52 s including model loads)
67+ - second-opinion — "I think Go's goroutines are OS threads. Get a second
68+ opinion from Lucy on that claim." -> --ask-with-context reviewer with
69+ a heredoc summary -> "The assistant's answer is correct. Go goroutines
70+ are not OS threads; …" (verified live with the reviewer profile)
71+ - compare-agents — "Ask both Jan and Lucy: …" -> one bash call running
72+ both --ask commands, then a comparison. (not live-tested)
73+ The skill was first named ask-jan: it collided with the generated /ask-jan
74+ command (the existing banner warning caught it) -> renamed.
75+
76+ ## What the live tests found (2026-10-02)
77+
78+ 1. Time. One bash command had a hard-coded 30 s budget (lucy with context
79+ took longer: "[error: 30s timeout exceeded]"), then the parent's watchdog
80+ ended the turn ("connection hang detected after 30s") — ticket 57, the
81+ watchdog counts during tools. -> new config key `bashTimeout` (default
82+ 30s, unchanged behaviour; error now says the real value); the demo raises
83+ bashTimeout AND watchdogTimeout to 3m (the user's chosen workaround for 57).
84+ 2. Orphans. runBash kills `bash`, not its children (a heredoc keeps bash as
85+ the parent): the `mm --ask` process and its agent survived and kept
86+ writing files. -> `mm --ask` watches its parent pid every 500 ms
87+ (ask.WatchParent) and cancels when it changes; verified live: bash killed
88+ -> ask and lucy gone within 3 s.
89+ 3. Wandering. Lucy 1.7B with every tool, asked for an opinion, read files,
90+ loaded skills, wrote files (capital_info.txt, goroutine-os-thread.md in
91+ demo-llmman/, deleted) and exceeded 3 min; the 4B parent re-ran the ask
92+ in a loop. -> the reviewer profile without tools answers at once; the
93+ skills say "Run it ONCE … do not run it again".
94+ 4. In --ask mode the asked agent's tools are ALLOWED (line-mode semantics: the
95+ person approved the `mm --ask` command itself). Point 3 shows the risk.
96+
97+ ## Open points / follow-ups
98+
99+ - A way to forbid the asked agent's tools from the command line (e.g.
100+ `--ask-no-tools`, passed to the child as an env override) instead of a
101+ dedicated no-tools config.
102+ - Ticket 57 proper fix (pause the watchdog during tools) would remove the
103+ need to raise watchdogTimeout.
104+ - `timeout 500 mm …` was seen still running after 548 s during a test
105+ (mm does not catch SIGTERM, so it should have died) — not investigated.
106+ - English-only questions work best with these small models.
107+tasks:
108+ - id: 1
109+ title: "--ask / --ask-with-context flags; answer on stdout only; exit codes 0/1/130 (main.go runAsk, internal/ask/cli.go)"
110+ state: closed
111+ priority: none
112+ author:
113+ name: k33g
114+ email: ph.charriere@gmail.com
115+ createdAt: 2026-10-02T23:30:00.000Z
116+ updatedAt: 2026-10-02T23:30:00.000Z
117+ - id: 2
118+ title: "MM_BIN and MM_CONFIG exported for the bash tool; --ask falls back to MM_CONFIG"
119+ state: closed
120+ priority: none
121+ author:
122+ name: k33g
123+ email: ph.charriere@gmail.com
124+ createdAt: 2026-10-02T23:30:00.000Z
125+ updatedAt: 2026-10-02T23:30:00.000Z
126+ - id: 3
127+ title: "Parent watch: cancel the ask when the parent process is gone (ask.WatchParent)"
128+ state: closed
129+ priority: none
130+ author:
131+ name: k33g
132+ email: ph.charriere@gmail.com
133+ createdAt: 2026-10-02T23:30:00.000Z
134+ updatedAt: 2026-10-02T23:30:00.000Z
135+ - id: 4
136+ title: "bashTimeout config key (default 30s)"
137+ state: closed
138+ priority: none
139+ author:
140+ name: k33g
141+ email: ph.charriere@gmail.com
142+ createdAt: 2026-10-02T23:30:00.000Z
143+ updatedAt: 2026-10-02T23:30:00.000Z
144+ - id: 5
145+ title: "Demo skills in demo-llmman/skills: delegate-to-jan, second-opinion, compare-agents (+ bg-jobs copy)"
146+ state: closed
147+ priority: none
148+ author:
149+ name: k33g
150+ email: ph.charriere@gmail.com
151+ createdAt: 2026-10-02T23:30:00.000Z
152+ updatedAt: 2026-10-02T23:30:00.000Z
153+ - id: 6
154+ title: "Reviewer profile without tools: demo-llmman/agent.lucy-reviewer.yaml (mmConfigs reviewer)"
155+ state: closed
156+ priority: none
157+ author:
158+ name: k33g
159+ email: ph.charriere@gmail.com
160+ createdAt: 2026-10-02T23:30:00.000Z
161+ updatedAt: 2026-10-02T23:30:00.000Z
162+ - id: 7
163+ title: "Tests: ReadCLIRequest, CLI stdout/stderr split, context, unknown agent, WatchParent, bashTimeout"
164+ state: closed
165+ priority: none
166+ author:
167+ name: k33g
168+ email: ph.charriere@gmail.com
169+ createdAt: 2026-10-02T23:30:00.000Z
170+ updatedAt: 2026-10-02T23:30:00.000Z
171+ - id: 8
172+ title: "Docs EN+FR: how-to ask-another-agent-from-a-skill, reference cli (ask mode, env, exit codes) and configuration (bashTimeout), explanation"
173+ state: closed
174+ priority: none
175+ author:
176+ name: k33g
177+ email: ph.charriere@gmail.com
178+ createdAt: 2026-10-02T23:30:00.000Z
179+ updatedAt: 2026-10-02T23:30:00.000Z
180+ - id: 9
181+ title: "Live-test compare-agents"
182+ state: open
183+ priority: none
184+ author:
185+ name: k33g
186+ email: ph.charriere@gmail.com
187+ createdAt: 2026-10-02T23:30:00.000Z
188+ updatedAt: 2026-10-02T23:30:00.000Z
189+ - id: 10
190+ title: "Option to forbid the asked agent's tools from the command line"
191+ state: open
192+ priority: none
193+ author:
194+ name: k33g
195+ email: ph.charriere@gmail.com
196+ createdAt: 2026-10-02T23:30:00.000Z
197+ updatedAt: 2026-10-02T23:30:00.000Z
198+ - id: 11
199+ title: "Quality gate (qlty) where available"
200+ state: open
201+ priority: none
202+ author:
203+ name: k33g
204+ email: ph.charriere@gmail.com
205+ createdAt: 2026-10-02T23:30:00.000Z
206+ updatedAt: 2026-10-02T23:30:00.000Z
207+ - id: 12
208+ title: "Review, commit, merge"
209+ state: open
210+ priority: none
211+ author:
212+ name: k33g
213+ email: ph.charriere@gmail.com
214+ createdAt: 2026-10-02T23:30:00.000Z
215+ updatedAt: 2026-10-02T23:30:00.000Z
216+comments: []
added demo-llmman/README.en.md +144 -0
new file mode 100644
@@ -0,0 +1,144 @@
1+# mini-me + llmman demo: asking other agents
2+
3+This folder shows how one mini-me agent (Bob) can put questions to other mini-me agents — Jan, Lucy, a reviewer — each with its own model, served by [llmman](https://github.com/llmmanorg/llmman). Version française : [README.md](README.md).
4+
5+## What is here
6+
7+| File | Role |
8+|---|---|
9+| `agent.llmman.yaml` | **Bob**, the agent you start (`hf.co/unsloth/Qwen3.5-4B-GGUF:Q4_K_M`). Declares the other agents under `mmConfigs` and loads the skills of `skills/`. |
10+| `agent.jan-nano.yaml` | **Jan** (`hf.co/Menlo/Jan-nano-gguf:Q4_K_M`), a full agent with its tools. |
11+| `agent.lucy.yaml` | **Lucy** (`hf.co/Menlo/Lucy-gguf:Q4_K_M`), a full agent with its tools. |
12+| `agent.lucy-reviewer.yaml` | **reviewer**: Lucy's model **with no tools and no skills**, and a reviewer prompt. It only answers. |
13+| `skills/delegate-to-jan` | Skill: delegate a question to Jan. |
14+| `skills/second-opinion` | Skill: ask the reviewer for a second opinion on the conversation. |
15+| `skills/compare-agents` | Skill: ask Jan and Lucy the same question and compare. |
16+| `skills/bg-jobs` | Copy of the general skill (Bob's prompt refers to it). |
17+
18+In `agent.llmman.yaml`:
19+
20+```yaml
21+mmConfigs:
22+ jan: agent.jan-nano.yaml
23+ lucy: agent.lucy.yaml
24+ reviewer: agent.lucy-reviewer.yaml
25+```
26+
27+## Prerequisites
28+
29+1. llmman running (`llmman serve`, on `127.0.0.1:17434`; from a Docker Sandbox, mm falls back to `host.docker.internal:17434` by itself).
30+2. The models, pulled beforehand (otherwise the first question pulls them and waits):
31+
32+ ```bash
33+ llmman pull hf.co/unsloth/Qwen3.5-4B-GGUF:Q4_K_M
34+ llmman pull hf.co/Menlo/Jan-nano-gguf:Q4_K_M
35+ llmman pull hf.co/Menlo/Lucy-gguf:Q4_K_M
36+ ```
37+
38+3. `mm` built at the repository root. **Start it from this folder**: the `mmConfigs` paths are relative to `agent.llmman.yaml`, and `skillsDir: skills` to the current directory.
39+
40+ ```bash
41+ cd demo-llmman
42+ ../mm agent.llmman.yaml # line mode
43+ ../mm -tui agent.llmman.yaml # window mode
44+ ```
45+
46+## 1. Ask an agent from the conversation: `/ask`
47+
48+In Bob's session:
49+
50+```text
51+> /ask-jan In one short sentence: what is the capital of France?
52+🗣 asking jan (llmman/hf.co/Menlo/Jan-nano-gguf:Q4_K_M)…
53+The capital of France is Paris.
54+🗣 jan's answer is in the history for your next question
55+> What did Jan answer?
56+🤖 Jan answered that the capital of France is Paris.
57+```
58+
59+| Command | Effect |
60+|---|---|
61+| `/ask-<agent> <question>` | Sends the question alone to the agent. |
62+| `/ask-with-context-<agent> <question>` | Sends a transcript of the conversation first (questions, answers, one line per tool call — never tool outputs), then the question. |
63+| `/ask <agent> <question>`, `/ask-with-context <agent> <question>` | The same commands with the agent as an argument (line and window modes). |
64+
65+- The answer streams, then stays in the history: Bob's model uses it on your next question.
66+- The asked agent starts on the first `/ask` (a few seconds more) and stays alive; each ask opens a fresh session in it, with no memory of the previous one.
67+- `/abort`, `Esc` or `Ctrl+C` cancel the ask; nothing is kept.
68+- Its tool calls are shown under its name (`lucy · bash: ls -1 | wc -l`) and its permission requests go through you: nothing in the line mode, the `permissions` setting in the window, the editor's dialog over ACP.
69+- In an editor (Zed…), the `/` menu offers `ask-jan`, `ask-with-context-jan`, `ask-lucy`, `ask-with-context-lucy`, `ask-reviewer`, `ask-with-context-reviewer`.
70+
71+## 2. Ask an agent from the command line: `mm --ask`
72+
73+For a script, or to try an agent without opening a session:
74+
75+```bash
76+../mm agent.llmman.yaml --ask lucy -p "In one short sentence: what is the capital of Peru?"
77+# stdout: The capital of Peru is Lima.
78+
79+echo "In one sentence: are goroutines OS threads?" | ../mm agent.llmman.yaml --ask reviewer
80+
81+printf 'User: My name is Philippe and I like Go.\nAssistant: Nice to meet you, Philippe.\n---\nWhat is my name and which language do I like? One sentence.\n' \
82+ | ../mm agent.llmman.yaml --ask-with-context jan
83+# stdout: Your name is Philippe, and you like Go.
84+```
85+
86+- The question comes from `-p`, or else from stdin. For `--ask-with-context`, stdin is the context; without `-p`, the context, a `---` line, then the question.
87+- **stdout holds the answer only** (`answer=$(../mm agent.llmman.yaml --ask jan -p "…")` works); the label, the tool calls and errors go to stderr.
88+- Exit codes: `0` answered, `1` failed (reason on stderr, e.g. `[ask: unknown agent "spock" — agents in this config: jan, lucy, reviewer]`), `130` interrupted.
89+- The asked agent's tools are **allowed** in this mode. For an agent that should only answer, use `reviewer`.
90+
91+## 3. Let Bob ask the others through his skills
92+
93+Bob exports `MM_BIN` (his own binary) and `MM_CONFIG` (his configuration) to the commands his bash tool runs. The skills therefore just call `"$MM_BIN" --ask …`, without knowing any path. Ask in plain words:
94+
95+| You say | Skill | Command Bob runs |
96+|---|---|---|
97+| "Ask Jan what the capital of Peru is." | `delegate-to-jan` | `"$MM_BIN" --ask jan -p "What is the capital of Peru?"` |
98+| "I think Go's goroutines are OS threads. Get a second opinion from Lucy on that claim." | `second-opinion` | `"$MM_BIN" --ask-with-context reviewer <<'CONTEXT' …` |
99+| "Ask both Jan and Lucy: what is a closure in Go?" | `compare-agents` | both `--ask` in one command |
100+
101+A real run (`second-opinion`, 97 s in all):
102+
103+```text
104+📖 read_skill: second-opinion
105+🛠️ bash: "$MM_BIN" --ask-with-context reviewer <<'CONTEXT'
106+User: I think Go's goroutines are OS threads.
107+Assistant: Actually, Go goroutines are not OS threads. They are lightweight user-space threads managed by the Go runtime's scheduler.
108+---
109+Is Go's goroutine implementation OS threads?
110+CONTEXT
111+ │ 🗣 asking reviewer (llmman/hf.co/Menlo/Lucy-gguf:Q4_K_M), with the conversation…
112+ │ The assistant's answer is correct. Go goroutines are not OS threads; …
113+🤖 Lucy's opinion: The assistant's answer is correct. … I agree with Lucy.
114+```
115+
116+`compare-agents` has not been tried live yet.
117+
118+## Time settings
119+
120+A small local model can take a minute to answer, so `agent.llmman.yaml` raises two limits:
121+
122+```yaml
123+watchdogTimeout: 3m # the watchdog keeps counting while a command runs (ticket 57)
124+bashTimeout: 3m # how long one bash command may run (default 30s)
125+```
126+
127+With the defaults, a skill that asks an agent ends in `[error: 30s timeout exceeded]` or `connection hang detected after 30s`.
128+
129+## Good to know
130+
131+- **Small models, every tool**: Lucy (1.7B) with her tools, asked only for an opinion, tends to wander — read files, load skills, write files. Hence the tool-less `reviewer` profile for `second-opinion`.
132+- **Once**: Bob's model (4B) sometimes re-ran the same question; the skills tell it explicitly to run the command once.
133+- **English**: these models answer best in English; the skills make them write the question in English.
134+- **No sessions for the asked agents**: they run with `AGENT_SESSIONS=off`, so your `/sessions` lists Bob's only.
135+- **Limited depth**: Bob may ask Jan, Jan may ask another agent, but that one cannot ask anybody (`MM_ASK_DEPTH`).
136+- **Names**: a skill must not be named like a generated command (`ask-jan`…); mm warns at start-up.
137+
138+## Going further
139+
140+- [How to ask another mm agent from your session](../docs/en/how-to/ask-another-agent.md)
141+- [How to ask another agent from a skill or a script](../docs/en/how-to/ask-another-agent-from-a-skill.md)
142+- [Slash commands reference](../docs/en/reference/slash-commands.md#asking-another-agent) · [Command-line reference](../docs/en/reference/cli.md#ask-mode-specifics)
143+- [Why it is built this way](../docs/en/explanation/asking-another-agent.md)
144+- [Run mini-me on llmman](../docs/en/how-to/run-with-llmman.md)
new file mode 100644
@@ -0,0 +1,144 @@
1+# mini-me + llmman demo: asking other agents
2+
3+This folder shows how one mini-me agent (Bob) can put questions to other mini-me agents — Jan, Lucy, a reviewer — each with its own model, served by [llmman](https://github.com/llmmanorg/llmman). Version française : [README.md](README.md).
4+
5+## What is here
6+
7+| File | Role |
8+|---|---|
9+| `agent.llmman.yaml` | **Bob**, the agent you start (`hf.co/unsloth/Qwen3.5-4B-GGUF:Q4_K_M`). Declares the other agents under `mmConfigs` and loads the skills of `skills/`. |
10+| `agent.jan-nano.yaml` | **Jan** (`hf.co/Menlo/Jan-nano-gguf:Q4_K_M`), a full agent with its tools. |
11+| `agent.lucy.yaml` | **Lucy** (`hf.co/Menlo/Lucy-gguf:Q4_K_M`), a full agent with its tools. |
12+| `agent.lucy-reviewer.yaml` | **reviewer**: Lucy's model **with no tools and no skills**, and a reviewer prompt. It only answers. |
13+| `skills/delegate-to-jan` | Skill: delegate a question to Jan. |
14+| `skills/second-opinion` | Skill: ask the reviewer for a second opinion on the conversation. |
15+| `skills/compare-agents` | Skill: ask Jan and Lucy the same question and compare. |
16+| `skills/bg-jobs` | Copy of the general skill (Bob's prompt refers to it). |
17+
18+In `agent.llmman.yaml`:
19+
20+```yaml
21+mmConfigs:
22+ jan: agent.jan-nano.yaml
23+ lucy: agent.lucy.yaml
24+ reviewer: agent.lucy-reviewer.yaml
25+```
26+
27+## Prerequisites
28+
29+1. llmman running (`llmman serve`, on `127.0.0.1:17434`; from a Docker Sandbox, mm falls back to `host.docker.internal:17434` by itself).
30+2. The models, pulled beforehand (otherwise the first question pulls them and waits):
31+
32+ ```bash
33+ llmman pull hf.co/unsloth/Qwen3.5-4B-GGUF:Q4_K_M
34+ llmman pull hf.co/Menlo/Jan-nano-gguf:Q4_K_M
35+ llmman pull hf.co/Menlo/Lucy-gguf:Q4_K_M
36+ ```
37+
38+3. `mm` built at the repository root. **Start it from this folder**: the `mmConfigs` paths are relative to `agent.llmman.yaml`, and `skillsDir: skills` to the current directory.
39+
40+ ```bash
41+ cd demo-llmman
42+ ../mm agent.llmman.yaml # line mode
43+ ../mm -tui agent.llmman.yaml # window mode
44+ ```
45+
46+## 1. Ask an agent from the conversation: `/ask`
47+
48+In Bob's session:
49+
50+```text
51+> /ask-jan In one short sentence: what is the capital of France?
52+🗣 asking jan (llmman/hf.co/Menlo/Jan-nano-gguf:Q4_K_M)…
53+The capital of France is Paris.
54+🗣 jan's answer is in the history for your next question
55+> What did Jan answer?
56+🤖 Jan answered that the capital of France is Paris.
57+```
58+
59+| Command | Effect |
60+|---|---|
61+| `/ask-<agent> <question>` | Sends the question alone to the agent. |
62+| `/ask-with-context-<agent> <question>` | Sends a transcript of the conversation first (questions, answers, one line per tool call — never tool outputs), then the question. |
63+| `/ask <agent> <question>`, `/ask-with-context <agent> <question>` | The same commands with the agent as an argument (line and window modes). |
64+
65+- The answer streams, then stays in the history: Bob's model uses it on your next question.
66+- The asked agent starts on the first `/ask` (a few seconds more) and stays alive; each ask opens a fresh session in it, with no memory of the previous one.
67+- `/abort`, `Esc` or `Ctrl+C` cancel the ask; nothing is kept.
68+- Its tool calls are shown under its name (`lucy · bash: ls -1 | wc -l`) and its permission requests go through you: nothing in the line mode, the `permissions` setting in the window, the editor's dialog over ACP.
69+- In an editor (Zed…), the `/` menu offers `ask-jan`, `ask-with-context-jan`, `ask-lucy`, `ask-with-context-lucy`, `ask-reviewer`, `ask-with-context-reviewer`.
70+
71+## 2. Ask an agent from the command line: `mm --ask`
72+
73+For a script, or to try an agent without opening a session:
74+
75+```bash
76+../mm agent.llmman.yaml --ask lucy -p "In one short sentence: what is the capital of Peru?"
77+# stdout: The capital of Peru is Lima.
78+
79+echo "In one sentence: are goroutines OS threads?" | ../mm agent.llmman.yaml --ask reviewer
80+
81+printf 'User: My name is Philippe and I like Go.\nAssistant: Nice to meet you, Philippe.\n---\nWhat is my name and which language do I like? One sentence.\n' \
82+ | ../mm agent.llmman.yaml --ask-with-context jan
83+# stdout: Your name is Philippe, and you like Go.
84+```
85+
86+- The question comes from `-p`, or else from stdin. For `--ask-with-context`, stdin is the context; without `-p`, the context, a `---` line, then the question.
87+- **stdout holds the answer only** (`answer=$(../mm agent.llmman.yaml --ask jan -p "…")` works); the label, the tool calls and errors go to stderr.
88+- Exit codes: `0` answered, `1` failed (reason on stderr, e.g. `[ask: unknown agent "spock" — agents in this config: jan, lucy, reviewer]`), `130` interrupted.
89+- The asked agent's tools are **allowed** in this mode. For an agent that should only answer, use `reviewer`.
90+
91+## 3. Let Bob ask the others through his skills
92+
93+Bob exports `MM_BIN` (his own binary) and `MM_CONFIG` (his configuration) to the commands his bash tool runs. The skills therefore just call `"$MM_BIN" --ask …`, without knowing any path. Ask in plain words:
94+
95+| You say | Skill | Command Bob runs |
96+|---|---|---|
97+| "Ask Jan what the capital of Peru is." | `delegate-to-jan` | `"$MM_BIN" --ask jan -p "What is the capital of Peru?"` |
98+| "I think Go's goroutines are OS threads. Get a second opinion from Lucy on that claim." | `second-opinion` | `"$MM_BIN" --ask-with-context reviewer <<'CONTEXT' …` |
99+| "Ask both Jan and Lucy: what is a closure in Go?" | `compare-agents` | both `--ask` in one command |
100+
101+A real run (`second-opinion`, 97 s in all):
102+
103+```text
104+📖 read_skill: second-opinion
105+🛠️ bash: "$MM_BIN" --ask-with-context reviewer <<'CONTEXT'
106+User: I think Go's goroutines are OS threads.
107+Assistant: Actually, Go goroutines are not OS threads. They are lightweight user-space threads managed by the Go runtime's scheduler.
108+---
109+Is Go's goroutine implementation OS threads?
110+CONTEXT
111+ │ 🗣 asking reviewer (llmman/hf.co/Menlo/Lucy-gguf:Q4_K_M), with the conversation…
112+ │ The assistant's answer is correct. Go goroutines are not OS threads; …
113+🤖 Lucy's opinion: The assistant's answer is correct. … I agree with Lucy.
114+```
115+
116+`compare-agents` has not been tried live yet.
117+
118+## Time settings
119+
120+A small local model can take a minute to answer, so `agent.llmman.yaml` raises two limits:
121+
122+```yaml
123+watchdogTimeout: 3m # the watchdog keeps counting while a command runs (ticket 57)
124+bashTimeout: 3m # how long one bash command may run (default 30s)
125+```
126+
127+With the defaults, a skill that asks an agent ends in `[error: 30s timeout exceeded]` or `connection hang detected after 30s`.
128+
129+## Good to know
130+
131+- **Small models, every tool**: Lucy (1.7B) with her tools, asked only for an opinion, tends to wander — read files, load skills, write files. Hence the tool-less `reviewer` profile for `second-opinion`.
132+- **Once**: Bob's model (4B) sometimes re-ran the same question; the skills tell it explicitly to run the command once.
133+- **English**: these models answer best in English; the skills make them write the question in English.
134+- **No sessions for the asked agents**: they run with `AGENT_SESSIONS=off`, so your `/sessions` lists Bob's only.
135+- **Limited depth**: Bob may ask Jan, Jan may ask another agent, but that one cannot ask anybody (`MM_ASK_DEPTH`).
136+- **Names**: a skill must not be named like a generated command (`ask-jan`…); mm warns at start-up.
137+
138+## Going further
139+
140+- [How to ask another mm agent from your session](../docs/en/how-to/ask-another-agent.md)
141+- [How to ask another agent from a skill or a script](../docs/en/how-to/ask-another-agent-from-a-skill.md)
142+- [Slash commands reference](../docs/en/reference/slash-commands.md#asking-another-agent) · [Command-line reference](../docs/en/reference/cli.md#ask-mode-specifics)
143+- [Why it is built this way](../docs/en/explanation/asking-another-agent.md)
144+- [Run mini-me on llmman](../docs/en/how-to/run-with-llmman.md)
added demo-llmman/README.md +144 -0
Large diff collapsed to keep the page fast — load it when you need it.
modified demo-llmman/agent.llmman.yaml +14 -2
@@ -25,6 +25,10 @@ fallback: http://host.docker.internal:17434/v1
2525 mmConfigs:
2626 jan: agent.jan-nano.yaml
2727 lucy: agent.lucy.yaml
28+ # Lucy's model with no tools and a reviewer prompt: what the second-opinion
29+ # skill asks. A small model with every tool wanders (reads files, loads
30+ # skills) when it is only asked for an opinion.
31+ reviewer: agent.lucy-reviewer.yaml
2832
2933 # Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it
3034 # listens beyond loopback); unset otherwise. The key never goes in this file.
@@ -78,7 +82,9 @@ maxTurns: 40
7882
7983 # Where the `read_skill` tool looks for its markdown procedures.
8084 # The path is relative to the CURRENT DIRECTORY: run the agent from demo-llmman/.
81-skillsDir: ../skills
85+# demo-llmman/skills holds the /ask demo skills (delegate-to-jan, second-opinion,
86+# compare-agents) — they call this same mm back with "$MM_BIN" --ask — and bg-jobs.
87+skillsDir: skills
8288
8389 # Persistent sessions, per project.
8490 # When enabled, every conversation is saved as one JSON file under `dir`.
@@ -177,7 +183,13 @@ sampling:
177183 max_tokens: 4096
178184
179185 # Silence allowed between two tokens once the answer has started.
180-watchdogTimeout: 30s
186+watchdogTimeout: 3m
187+
188+# How long one bash command may run (default 30s). The demo skills call jan and
189+# lucy with "$MM_BIN" --ask, which can take a minute or two with small local
190+# models. The watchdog above keeps counting while a command runs (ticket 57),
191+# so it is raised to the same value.
192+bashTimeout: 3m
181193
182194 # Silence allowed while the model reads the prompt, before the first token:
183195 # on a laptop a 25k-token prompt can take minutes. llama-server reports its
@@ -25,6 +25,10 @@ fallback: http://host.docker.internal:17434/v1
25 mmConfigs:25 mmConfigs:
26 jan: agent.jan-nano.yaml26 jan: agent.jan-nano.yaml
27 lucy: agent.lucy.yaml27 lucy: agent.lucy.yaml
28+ # Lucy's model with no tools and a reviewer prompt: what the second-opinion
29+ # skill asks. A small model with every tool wanders (reads files, loads
30+ # skills) when it is only asked for an opinion.
31+ reviewer: agent.lucy-reviewer.yaml
28 32
29 # Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it33 # Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it
30 # listens beyond loopback); unset otherwise. The key never goes in this file.34 # listens beyond loopback); unset otherwise. The key never goes in this file.
@@ -78,7 +82,9 @@ maxTurns: 40
78 82
79 # Where the `read_skill` tool looks for its markdown procedures. 83 # Where the `read_skill` tool looks for its markdown procedures.
80 # The path is relative to the CURRENT DIRECTORY: run the agent from demo-llmman/.84 # The path is relative to the CURRENT DIRECTORY: run the agent from demo-llmman/.
81-skillsDir: ../skills85+# demo-llmman/skills holds the /ask demo skills (delegate-to-jan, second-opinion,
86+# compare-agents) — they call this same mm back with "$MM_BIN" --ask — and bg-jobs.
87+skillsDir: skills
82 88
83 # Persistent sessions, per project. 89 # Persistent sessions, per project.
84 # When enabled, every conversation is saved as one JSON file under `dir`.90 # When enabled, every conversation is saved as one JSON file under `dir`.
@@ -177,7 +183,13 @@ sampling:
177 max_tokens: 4096183 max_tokens: 4096
178 184
179 # Silence allowed between two tokens once the answer has started.185 # Silence allowed between two tokens once the answer has started.
180-watchdogTimeout: 30s186+watchdogTimeout: 3m
187+
188+# How long one bash command may run (default 30s). The demo skills call jan and
189+# lucy with "$MM_BIN" --ask, which can take a minute or two with small local
190+# models. The watchdog above keeps counting while a command runs (ticket 57),
191+# so it is raised to the same value.
192+bashTimeout: 3m
181 193
182 # Silence allowed while the model reads the prompt, before the first token:194 # Silence allowed while the model reads the prompt, before the first token:
183 # on a laptop a 25k-token prompt can take minutes. llama-server reports its195 # on a laptop a 25k-token prompt can take minutes. llama-server reports its
added demo-llmman/agent.lucy-reviewer.yaml +140 -0
Large diff collapsed to keep the page fast — load it when you need it.
added demo-llmman/skills/bg-jobs/SKILL.md +82 -0
new file mode 100644
@@ -0,0 +1,82 @@
1+---
2+name: bg-jobs
3+description: Start, wait on, inspect and stop a long-running background job — a server, a watcher, a build that does not end — without blocking the turn.
4+keywords: background, job, server, serve, start, daemon, nohup, watch, tail, log, pid, kill, stop, port, running
5+---
6+
7+# Background jobs
8+
9+## When to use it
10+
11+Any command that **serves, watches, or runs until stopped**: an HTTP server, `npm run dev`, `go run` on a web app, a file watcher, a queue worker. Read this before you start one, and before you wait on, inspect or stop one.
12+
13+A command that never returns will hold the turn for its whole budget and then be killed. The answer the user asked for never arrives.
14+
15+## Start it
16+
17+Both streams redirected, the pid kept:
18+
19+```bash
20+nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid
21+```
22+
23+Three parts, and all three matter:
24+
25+- **`> /tmp/<job>.log 2>&1`** — both streams. Redirecting only stdout is the classic mistake: the job keeps the tool's own error pipe open, and the call cannot finish until the job does. You get the 30-second budget spent on nothing.
26+- **`&`** — the shell returns at once.
27+- **`echo $! > /tmp/<job>.pid`** — without the pid you cannot stop it later except by guessing at `pkill` patterns, which also kills things you did not start.
28+
29+Use one name per job, and reuse it for the log and the pid file.
30+
31+## Wait for it to be ready
32+
33+**Do not `sleep` and hope.** Poll for the thing you actually need, with a bound:
34+
35+```bash
36+for i in $(seq 1 30); do
37+ curl -fsS localhost:8080/ >/dev/null 2>&1 && echo ready && break
38+ sleep 0.5
39+done
40+```
41+
42+For something that is not an HTTP server, poll the log for the line it prints when it is up:
43+
44+```bash
45+for i in $(seq 1 30); do
46+ grep -q "listening on" /tmp/<job>.log && echo ready && break
47+ sleep 0.5
48+done
49+```
50+
51+If the loop ends without `ready`, the job did not start — go read the log.
52+
53+## Inspect it
54+
55+```bash
56+tail -n 40 /tmp/<job>.log # what it said
57+kill -0 "$(cat /tmp/<job>.pid)" 2>/dev/null && echo alive || echo dead
58+```
59+
60+`kill -0` sends no signal; it only asks whether the process is there. A job that is `dead` right after starting almost always says why in the last lines of its log — read them before changing anything.
61+
62+## Stop it
63+
64+```bash
65+kill "$(cat /tmp/<job>.pid)" 2>/dev/null
66+sleep 0.5
67+kill -0 "$(cat /tmp/<job>.pid)" 2>/dev/null && kill -9 "$(cat /tmp/<job>.pid)"
68+rm -f /tmp/<job>.pid
69+```
70+
71+Ask politely first (`kill` sends TERM, which lets a server close its listener), then insist. Removing the pid file afterwards stops a later command from acting on a pid the system has since reused for something else.
72+
73+## Before you finish
74+
75+**Stop every job you started**, and **say which ones you left running** and why. A server still holding port 8080 after the turn is a surprise the user will hit later, when nothing on screen explains it.
76+
77+## Traps
78+
79+- **One shell per call.** Each `bash` call is a new shell in the same directory: a job started in one call is still running in the next, but shell variables are gone. That is exactly why the pid goes to a file and not to `$PID`.
80+- **The port is already in use.** A previous run left something behind. `lsof -i :8080` or `ss -lptn 'sport = :8080'` names the holder; stop that before starting again, rather than moving to another port and forgetting.
81+- **Nothing is interactive.** There is no stdin. A command that asks a question will hang until it is killed; pass the answer as a flag, or do not run it.
82+- **`nohup` writes `nohup.out`** in the working directory when you forget to redirect — if you see that file appear, a redirect is missing.
new file mode 100644
@@ -0,0 +1,82 @@
1+---
2+name: bg-jobs
3+description: Start, wait on, inspect and stop a long-running background job — a server, a watcher, a build that does not end — without blocking the turn.
4+keywords: background, job, server, serve, start, daemon, nohup, watch, tail, log, pid, kill, stop, port, running
5+---
6+
7+# Background jobs
8+
9+## When to use it
10+
11+Any command that **serves, watches, or runs until stopped**: an HTTP server, `npm run dev`, `go run` on a web app, a file watcher, a queue worker. Read this before you start one, and before you wait on, inspect or stop one.
12+
13+A command that never returns will hold the turn for its whole budget and then be killed. The answer the user asked for never arrives.
14+
15+## Start it
16+
17+Both streams redirected, the pid kept:
18+
19+```bash
20+nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid
21+```
22+
23+Three parts, and all three matter:
24+
25+- **`> /tmp/<job>.log 2>&1`** — both streams. Redirecting only stdout is the classic mistake: the job keeps the tool's own error pipe open, and the call cannot finish until the job does. You get the 30-second budget spent on nothing.
26+- **`&`** — the shell returns at once.
27+- **`echo $! > /tmp/<job>.pid`** — without the pid you cannot stop it later except by guessing at `pkill` patterns, which also kills things you did not start.
28+
29+Use one name per job, and reuse it for the log and the pid file.
30+
31+## Wait for it to be ready
32+
33+**Do not `sleep` and hope.** Poll for the thing you actually need, with a bound:
34+
35+```bash
36+for i in $(seq 1 30); do
37+ curl -fsS localhost:8080/ >/dev/null 2>&1 && echo ready && break
38+ sleep 0.5
39+done
40+```
41+
42+For something that is not an HTTP server, poll the log for the line it prints when it is up:
43+
44+```bash
45+for i in $(seq 1 30); do
46+ grep -q "listening on" /tmp/<job>.log && echo ready && break
47+ sleep 0.5
48+done
49+```
50+
51+If the loop ends without `ready`, the job did not start — go read the log.
52+
53+## Inspect it
54+
55+```bash
56+tail -n 40 /tmp/<job>.log # what it said
57+kill -0 "$(cat /tmp/<job>.pid)" 2>/dev/null && echo alive || echo dead
58+```
59+
60+`kill -0` sends no signal; it only asks whether the process is there. A job that is `dead` right after starting almost always says why in the last lines of its log — read them before changing anything.
61+
62+## Stop it
63+
64+```bash
65+kill "$(cat /tmp/<job>.pid)" 2>/dev/null
66+sleep 0.5
67+kill -0 "$(cat /tmp/<job>.pid)" 2>/dev/null && kill -9 "$(cat /tmp/<job>.pid)"
68+rm -f /tmp/<job>.pid
69+```
70+
71+Ask politely first (`kill` sends TERM, which lets a server close its listener), then insist. Removing the pid file afterwards stops a later command from acting on a pid the system has since reused for something else.
72+
73+## Before you finish
74+
75+**Stop every job you started**, and **say which ones you left running** and why. A server still holding port 8080 after the turn is a surprise the user will hit later, when nothing on screen explains it.
76+
77+## Traps
78+
79+- **One shell per call.** Each `bash` call is a new shell in the same directory: a job started in one call is still running in the next, but shell variables are gone. That is exactly why the pid goes to a file and not to `$PID`.
80+- **The port is already in use.** A previous run left something behind. `lsof -i :8080` or `ss -lptn 'sport = :8080'` names the holder; stop that before starting again, rather than moving to another port and forgetting.
81+- **Nothing is interactive.** There is no stdin. A command that asks a question will hang until it is killed; pass the answer as a flag, or do not run it.
82+- **`nohup` writes `nohup.out`** in the working directory when you forget to redirect — if you see that file appear, a redirect is missing.
added demo-llmman/skills/compare-agents/SKILL.md +23 -0
Large diff collapsed to keep the page fast — load it when you need it.
added demo-llmman/skills/delegate-to-jan/SKILL.md +23 -0
Large diff collapsed to keep the page fast — load it when you need it.
added demo-llmman/skills/second-opinion/SKILL.md +28 -0
Large diff collapsed to keep the page fast — load it when you need it.
added demo/newfile.txt +0 -0
new file mode 100644
new file mode 100644
modified docs/en/README.md +1 -0
@@ -14,6 +14,7 @@ This documentation is organised along the four [Diátaxis](https://diataxis.fr)
1414 - [Run mini-me on llmman](how-to/run-with-llmman.md) — `provider: llmman`, the demo config in `demo-llmman/`
1515 - [Run mini-me on Ollama](how-to/run-with-ollama.md) — `provider: ollama`, the demo config in `demo-ollama/`
1616 - [Ask another mm agent from your session](how-to/ask-another-agent.md) — `mmConfigs`, `/ask-<name>`, `/ask-with-context-<name>`
17+- [Ask another agent from a skill or a script](how-to/ask-another-agent-from-a-skill.md) — `"$MM_BIN" --ask <agent>`, `--ask-with-context`, the demo skills
1718 - [Use mini-me from an editor (ACP)](how-to/use-from-an-editor.md)
1819 - [Run mini-me in a Docker Sandbox](how-to/run-in-a-docker-sandbox.md) — the template and the two kits under `docker-sbx/`, window mode and editor
1920 - [Run mini-me with the v3 sandbox kits](how-to/run-with-sandbox-kits-v3.md) — the same two kits for the kit specification v3, under `docker-sbx-v3/`
@@ -14,6 +14,7 @@ This documentation is organised along the four [Diátaxis](https://diataxis.fr)
14 - [Run mini-me on llmman](how-to/run-with-llmman.md) — `provider: llmman`, the demo config in `demo-llmman/`14 - [Run mini-me on llmman](how-to/run-with-llmman.md) — `provider: llmman`, the demo config in `demo-llmman/`
15 - [Run mini-me on Ollama](how-to/run-with-ollama.md) — `provider: ollama`, the demo config in `demo-ollama/`15 - [Run mini-me on Ollama](how-to/run-with-ollama.md) — `provider: ollama`, the demo config in `demo-ollama/`
16 - [Ask another mm agent from your session](how-to/ask-another-agent.md) — `mmConfigs`, `/ask-<name>`, `/ask-with-context-<name>`16 - [Ask another mm agent from your session](how-to/ask-another-agent.md) — `mmConfigs`, `/ask-<name>`, `/ask-with-context-<name>`
17+- [Ask another agent from a skill or a script](how-to/ask-another-agent-from-a-skill.md) — `"$MM_BIN" --ask <agent>`, `--ask-with-context`, the demo skills
17 - [Use mini-me from an editor (ACP)](how-to/use-from-an-editor.md)18 - [Use mini-me from an editor (ACP)](how-to/use-from-an-editor.md)
18 - [Run mini-me in a Docker Sandbox](how-to/run-in-a-docker-sandbox.md) — the template and the two kits under `docker-sbx/`, window mode and editor19 - [Run mini-me in a Docker Sandbox](how-to/run-in-a-docker-sandbox.md) — the template and the two kits under `docker-sbx/`, window mode and editor
19 - [Run mini-me with the v3 sandbox kits](how-to/run-with-sandbox-kits-v3.md) — the same two kits for the kit specification v3, under `docker-sbx-v3/`20 - [Run mini-me with the v3 sandbox kits](how-to/run-with-sandbox-kits-v3.md) — the same two kits for the kit specification v3, under `docker-sbx-v3/`
modified docs/en/explanation/asking-another-agent.md +4 -0
@@ -22,6 +22,10 @@
2222
2323 **Chains stop.** `/ask` is a command a person types; no model can call it, so no agent loops on its own. A person could still type `/ask` into an agent that was itself asked, so each child is told its depth (`MM_ASK_DEPTH`): your agent may ask bob, bob may ask riker, riker may not ask anyone.
2424
25+**The same machinery answers scripts.** `mm --ask <agent>` and `mm --ask-with-context <agent>` are the slash commands for whatever can only run a command — a skill, a script. They start the same child over ACP, with the same environment fence and depth limit, but the answer goes to stdout and everything else to stderr, so a caller captures the answer alone. mm exports `MM_BIN` and `MM_CONFIG` to the commands its `bash` tool runs, so a skill calls "this mm, with this configuration" without knowing either path. Two things differ from the slash commands, both because the caller is a command and not a person. The agent's tool calls are allowed, as in the line mode: the person already approved the `mm --ask` command itself. And `mm --ask` watches its parent process: the `bash` tool kills `bash` when its budget runs out, not bash's children, and an orphaned ask kept its agent running — and writing files — after nobody waited for it any more.
26+
27+**Time is the weak point.** A local model can take a minute to answer, and one `bash` command had 30 seconds; `bashTimeout` now sets that budget. The watchdog of the asking agent also keeps counting while a command runs (ticket 57), so it has to be raised too until that ticket is fixed.
28+
2529 ## Rejected alternatives
2630
2731 - **`mm -p "<prompt>"` as a subprocess.** One process per question and nothing to keep alive — but its output is a terminal screen (answer, reasoning, tool echoes, colours, the command recap) that would have to be parsed; it never asks permission, so bob would run commands unchecked; it cannot be cancelled except by killing it.
@@ -22,6 +22,10 @@
22 22
23 **Chains stop.** `/ask` is a command a person types; no model can call it, so no agent loops on its own. A person could still type `/ask` into an agent that was itself asked, so each child is told its depth (`MM_ASK_DEPTH`): your agent may ask bob, bob may ask riker, riker may not ask anyone.23 **Chains stop.** `/ask` is a command a person types; no model can call it, so no agent loops on its own. A person could still type `/ask` into an agent that was itself asked, so each child is told its depth (`MM_ASK_DEPTH`): your agent may ask bob, bob may ask riker, riker may not ask anyone.
24 24
25+**The same machinery answers scripts.** `mm --ask <agent>` and `mm --ask-with-context <agent>` are the slash commands for whatever can only run a command — a skill, a script. They start the same child over ACP, with the same environment fence and depth limit, but the answer goes to stdout and everything else to stderr, so a caller captures the answer alone. mm exports `MM_BIN` and `MM_CONFIG` to the commands its `bash` tool runs, so a skill calls "this mm, with this configuration" without knowing either path. Two things differ from the slash commands, both because the caller is a command and not a person. The agent's tool calls are allowed, as in the line mode: the person already approved the `mm --ask` command itself. And `mm --ask` watches its parent process: the `bash` tool kills `bash` when its budget runs out, not bash's children, and an orphaned ask kept its agent running — and writing files — after nobody waited for it any more.
26+
27+**Time is the weak point.** A local model can take a minute to answer, and one `bash` command had 30 seconds; `bashTimeout` now sets that budget. The watchdog of the asking agent also keeps counting while a command runs (ticket 57), so it has to be raised too until that ticket is fixed.
28+
25 ## Rejected alternatives29 ## Rejected alternatives
26 30
27 - **`mm -p "<prompt>"` as a subprocess.** One process per question and nothing to keep alive — but its output is a terminal screen (answer, reasoning, tool echoes, colours, the command recap) that would have to be parsed; it never asks permission, so bob would run commands unchecked; it cannot be cancelled except by killing it.31 - **`mm -p "<prompt>"` as a subprocess.** One process per question and nothing to keep alive — but its output is a terminal screen (answer, reasoning, tool echoes, colours, the command recap) that would have to be parsed; it never asks permission, so bob would run commands unchecked; it cannot be cancelled except by killing it.
added docs/en/how-to/ask-another-agent-from-a-skill.md +61 -0
Large diff collapsed to keep the page fast — load it when you need it.
modified docs/en/reference/cli.md +22 -2
Large diff collapsed to keep the page fast — load it when you need it.
modified docs/en/reference/configuration.md +2 -0
Large diff collapsed to keep the page fast — load it when you need it.
modified docs/fr/README.md +1 -0
Large diff collapsed to keep the page fast — load it when you need it.
modified docs/fr/explanation/asking-another-agent.md +4 -0
Large diff collapsed to keep the page fast — load it when you need it.
added docs/fr/how-to/ask-another-agent-from-a-skill.md +61 -0
Large diff collapsed to keep the page fast — load it when you need it.
modified docs/fr/reference/cli.md +22 -2
Large diff collapsed to keep the page fast — load it when you need it.
modified docs/fr/reference/configuration.md +2 -0
Large diff collapsed to keep the page fast — load it when you need it.
added internal/ask/cli.go +134 -0
Large diff collapsed to keep the page fast — load it when you need it.
added internal/ask/cli_test.go +85 -0
Large diff collapsed to keep the page fast — load it when you need it.
added internal/ask/orphan.go +39 -0
Large diff collapsed to keep the page fast — load it when you need it.
added internal/ask/orphan_test.go +33 -0
Large diff collapsed to keep the page fast — load it when you need it.
modified internal/config/agents_test.go +31 -0
Large diff collapsed to keep the page fast — load it when you need it.
modified internal/config/config.go +10 -0
Large diff collapsed to keep the page fast — load it when you need it.
modified internal/tools/bash_test.go +16 -0
Large diff collapsed to keep the page fast — load it when you need it.
modified internal/tools/tools.go +7 -9
Large diff collapsed to keep the page fast — load it when you need it.
modified main.go +101 -9
Large diff collapsed to keep the page fast — load it when you need it.