A practical guide to not over-engineering your AI stack.
Before you reach for a frontier model, ask yourself: does this actually need a trillion-parameter model?
Most tasks don't. This repo helps you figure out which ones.
This repo is an Agent Skill called bonsai — an open standard for extending AI agents with reusable expertise, supported by Claude Code, opencode, Cursor, Gemini CLI, OpenAI Codex, GitHub Copilot, VS Code, Goose, Roo Code, Amp, and 70+ other tools. The decision logic lives in skills/bonsai/SKILL.md; this README is the full human-readable guide.
This skill follows the Agent Skills standard, so it installs into any compatible harness. Two ways:
skills is the CLI for the open agent skills ecosystem — npm for skills. It auto-detects your installed agents, writes the skill to each one's discovery directory, and symlinks (or copies) so a single source of truth stays updateable. Zero install via npx:
npx skills add nehmeailabs/bonsaiThat's it. The repo is the source; the skill inside is bonsai. Pick your agent (detected ones are pre-selected), confirm, done. Works across 72+ agents — Claude Code, Cursor, Codex, Gemini CLI, opencode, GitHub Copilot, Windsurf, Aider, and the rest.
Common flags:
npx skills add nehmeailabs/bonsai --list # preview before installing
npx skills add nehmeailabs/bonsai --skill bonsai -g # install just bonsai, globally
npx skills add nehmeailabs/bonsai -a claude-code -a opencode # target specific agents
npx skills add nehmeailabs/bonsai --skill bonsai -g -a claude-code -y # non-interactive (CI/CD)Other commands: npx skills list, npx skills find <query>, npx skills update, npx skills remove, npx skills use <source> (use without installing).
No package manager needed — each harness discovers skills from its own directory. The .agents/skills/ path is the cross-harness discovery alias: opencode, Cursor, Gemini CLI, Codex, GitHub Copilot, and Amp all pick it up, so a single clone covers several tools. The skill lives at skills/bonsai/ in the repo, so clone to that name.
# Universal — opencode, Cursor, Gemini CLI, Codex, Copilot, Amp, and any .agents/-aware harness
git clone https://github.com/nehmeailabs/bonsai.git ~/.agents/skills/bonsai # global
git clone https://github.com/nehmeailabs/bonsai.git .agents/skills/bonsai # project-localSome harnesses only read their own directory. Clone into the path your harness scans:
| Harness | Global path | Project path |
|---|---|---|
| Claude Code | ~/.claude/skills/bonsai |
.claude/skills/bonsai |
| opencode | ~/.config/opencode/skills/bonsai |
.opencode/skills/bonsai |
| Cursor | ~/.cursor/skills/bonsai |
.cursor/skills/bonsai |
| Gemini CLI | ~/.gemini/skills/bonsai |
.gemini/skills/bonsai |
| OpenAI Codex | ~/.codex/skills/bonsai |
.codex/skills/bonsai |
| Goose | ~/.config/goose/skills/bonsai |
.goose/skills/bonsai |
| Roo Code | ~/.roo/skills/bonsai |
.roo/skills/bonsai |
Gemini CLI also ships a native install command:
gemini skills install https://github.com/nehmeailabs/bonsai.git --consentAfter installing, restart your harness (Gemini CLI picks up new skills with /skills reload). The skill loads automatically and is surfaced when you ask about model selection, RAG, agent architecture, structured output, or extraction. In Claude Code, invoke it directly with /bonsai.
npx skills-ref validate .Checks that skills/bonsai/SKILL.md frontmatter follows the Agent Skills spec.
You have a task.
│
▼
┌─────────────────────────────────┐
│ Can regex, rules, or lookup │
│ tables solve it? │──── YES ───► Use that. Stop.
└─────────────────────────────────┘
│ NO
▼
┌─────────────────────────────────┐
│ Is it structured/tabular data? │──── YES ───► XGBoost, random forest,
│ (predictions from features) │ or logistic regression.
└─────────────────────────────────┘ Often beats LLMs here.
│ NO
▼
┌─────────────────────────────────┐
│ Is it search/retrieval? │──── YES ───► BM25 first. Add vector
│ │ search if needed.
└─────────────────────────────────┘
│ NO
▼
┌─────────────────────────────────┐
│ Does it need external knowledge│──── YES ───► <100 pages? Stuff in context.
│ beyond the input text? │ Larger? Then consider RAG.
└─────────────────────────────────┘
│ NO
▼
┌─────────────────────────────────┐
│ Is the task simple? │──── YES ───► Small model (1B-8B).
│ (classification, extraction, │ Test it first.
│ summarization) │
└─────────────────────────────────┘
│ NO
▼
You might need a frontier
model. But measure first.
If yes → probably a small model task.
- "Extract the company name from this email" → Gemma 4B (or regex, if the pattern is stable)
- "Classify this support ticket as billing/technical/other" → Gemma 1B
- "Summarize this paragraph in 2 sentences" → Phi-4
If no → you might have an architecture problem, not a model problem.
| Accuracy needed | Model size | Why |
|---|---|---|
| 70-80% | 1B-4B | Good enough for suggestions, drafts, triage |
| 85-95% | 4B-12B | Production-ready for most tasks |
| 95%+ | Consider fine-tuning a small model, not scaling up |
Scaling to frontier models rarely buys you more than 5% accuracy on simple tasks. That 5% costs 50x more.
Output tokens are the bottleneck. They determine latency and cost.
| Output type | Tokens | Consider |
|---|---|---|
| Yes/No, True/False | 1-5 | Tiny model. Constrained decoding guarantees the format — no parsing. |
| Category label | 1-10 | 1B model. Constrained decoding limits output to valid labels. |
| Short extraction | 10-50 | Delimiter-separated, or grammar-constrained output > JSON |
| Paragraph | 50-200 | 4B-8B models |
| Long generation | 500+ | Maybe you need a bigger model |
Everyone defaults to JSON for structured output. But JSON has overhead:
# JSON output (35 tokens)
{"name": "John Smith", "company": "Acme Corp", "title": "CTO", "status": "lead"}
# Delimiter output (11 tokens)
John Smith::Acme Corp::CTO::lead
For simple extraction tasks:
- 3x fewer output tokens
- 3x faster inference
- 3x cheaper
The strongest option: constrained decoding. Grammar-constrained generation (llama.cpp GBNF, Outlines, xgrammar) forces the model to emit valid JSON — or any format — at the sampler level. Zero invalid outputs, no retries, no parse failures. The JSON-vs-delimiter tradeoff disappears: JSON's token cost is real, but its parse failures go to zero. For local small models this is usually the right default.
When to use JSON: nested structures, optional fields, API contracts. When to use delimiters: simple extraction, high-volume pipelines, when you can't constrain decoding. When to use constrained decoding: you control inference (local model, or an API that exposes it) and want guaranteed-valid output.
Best for: classification, yes/no, simple extraction
| Model | Params | Good at |
|---|---|---|
| Gemma 3 1B | 1B | Classification, simple Q&A |
| Phi-4-mini | 3.8B | Reasoning, function calling |
| Gemma 3 4B | 4B | Best tiny all-rounder |
Best for: most production tasks, RAG, extraction, summarization
| Model | Params | Good at |
|---|---|---|
| Qwen 3 8B | 8B | Multilingual, reasoning |
| Gemma 3 12B | 12B | Quality/speed balance |
| Phi-4 | 14B | Reasoning, math |
| Llama 4 Scout | 17B | Multimodal, long context (10M tokens) |
Best for: complex reasoning, long context, multi-step tasks
| Model | Params | Good at |
|---|---|---|
| Gemma 3 27B | 27B | Near-frontier quality |
| Qwen 3 32B | 32B | Complex tasks |
Best for: novel tasks, complex reasoning, when nothing else works
| Model | Params | Good at |
|---|---|---|
| Llama 4 Maverick | 400B (17B active) | MoE, strong all-rounder, 10M context |
Before you use these, ask: have you tried a smaller model?
That's not a flex. That's a $50K/month cloud bill waiting to happen.
Your enterprise customers care about latency, reliability, and cost. Not model prestige.
Did you test? With the right prompt? On your actual data?
You'll optimize never. The technical debt compounds. Start right-sized.
For simple extraction, it's industry waste. See: The JSON Tax.
For small document sets? No you don't.
Context windows are now 2M-10M tokens. That's thousands of pages. If your knowledge base is <100 pages, just stuff it in context. Preprocess, convert to markdown, include directly.
RAG adds complexity: chunking strategies, embedding models, vector databases, retrieval tuning, reranking. All that infrastructure for documents that fit in a single prompt.
When RAG makes sense:
- Millions of documents
- Frequently changing content (re-embedding is cheaper than re-caching)
- Cost-sensitive at scale (RAG is 8-80x cheaper per query for large, static corpora)
When to skip RAG:
- <100 pages of docs
- Static content that rarely changes
- You value simplicity over marginal retrieval precision
Start with smallest model. Verify output. Escalate only on failure.
Input Text
│
▼
┌─────────┐ ┌────────────┐ verified? ┌──────────┐
│ Gemma 4B│ ───────────► │ Verifier │ ───────────────► │ Return │
└─────────┘ output └────────────┘ yes └──────────┘
│ no
▼
┌─────────────┐ ┌────────────┐ verified? ┌──────────┐
│ Llama Scout │ ───────► │ Verifier │ ───────────────► │ Return │
└─────────────┘ └────────────┘ └──────────┘
Verifier can be: format validation, a classifier, or FlashCheck for grounding checks.
See skills/bonsai/examples/cascade.py for a working extraction example.
One model per task type, sized appropriately.
- Classification → 1B
- Extraction → 4B
- Summarization → 8B
- Complex reasoning → Frontier
Before adding a bigger model:
- Benchmark current model on 100 real examples
- Identify failure modes
- Try prompt engineering
- Try fine-tuning small model
- Only then consider scaling
For research tasks, don't reach for computer use or Puppeteer.
Search API → Fetch URL → HTML to Markdown → LLM synthesis
Three tools. No browser. No screenshots. No vision model.
Browser automation is only for: login walls, dynamic forms, actions (booking, purchasing).
See skills/bonsai/patterns/agents.md for the full agent decision tree.
- Extraction patterns — regex → NER → small LLM ladder
- Agent patterns — when to use simple tools vs browser automation
Test your prompts against multiple model sizes. See what's actually needed.
Verify LLM outputs with tiny specialized models. Sub-10ms verification.
Found a pattern that works? Open a PR.
Keep it practical. Keep it measured. No vibes-based claims.
MIT. Use it. Share it. Don't over-engineer it.
Built by Nehme AI Labs — AI architecture consultancy.