mingo
A small agent runtime in one Go file.Small enough to understand. Built to do real work.
1Minimize machinery, not capability.
mingo is a tool loop over any OpenAI-compatible endpoint: a llama-server on your own machine, DeepSeek, OpenRouter, or OpenAI's Responses API. It is built so that a 4B model on a laptop CPU can deliver, not demo. The harness checks what the model claims, refuses what it cannot verify, closes every loop the model leaves open, and keeps the transcript small.
the loop
Tool rounds until the model answers without a tool. Budgets are terminal. A cut reply runs nothing. A batch is judged whole before any of it runs.
the sandbox
An os.Root jail for files, an allowlist that splits commands the way sh does, and an OS fence (bwrap, seatbelt) that the banner names. Asks fail closed.
the session
Append-only JSONL, fsynced per line, locked while open. A torn tail is repaired on disk before anything is appended. Resume, and every open call is closed.
2Run it.
# build, then talk to a model
go build -o mingo . && DEEPSEEK_API_KEY=... ./mingo
# a 4B model on this machine, no key
./mingo -provider local
# one key, a few hundred models
OPENROUTER_API_KEY=... ./mingo -provider openrouter -model openai/gpt-6-astra
# headless: the answer on stdout, the outcome in the exit code
./mingo -json -p "Add has a bug. Fix it, verify with go vet, and report."
{"outcome":"done","written":["add.go"],"requests":5, ...}
3What the loop guarantees.
Properties of the program, not of the model's manners. Each has a test that tries to break it.
- No tool runs from an incomplete reply, and a batch with a missing or duplicate id runs nothing.
- Budgets are terminal: at the round cap the open batch is closed unexecuted and the turn ends with exit 3.
- Every batch is closed, so a cancelled turn never earns a 400 on the next message.
- A repeated failing call is not run again.
- Missing arguments are not empty ones:
writewithout content cannot empty a file. - Compaction is a transaction, and it shrinks, checked: a cut, empty or growing summary is refused.
- A retry never prints twice.
- The receipt says what changed on disk. A model that says "fixed" over an empty receipt is caught on the spot.
4Providers.
| provider | wire | default model | thinking |
|---|---|---|---|
| deepseek | chat completions | deepseek-flash | reasoning_content replayed, as the API requires |
| openai | Responses API | gpt-6-astra | encrypted reasoning items replayed; nothing stored server-side |
| openrouter | chat completions | deepseek/deepseek-v4.1-flash | unified reasoning switch; any model id |
| local | chat completions | whatever is loaded | chat template switch; context read from /props; 4096-token cap |