You've found a local model that's great at chat — clear reasoning, solid code explanations, maybe even vision — and then you ask it to read a file or run an MCP tool.
Nothing happens. Or worse: the hub silently swaps in a second model for the tool loop, and you lose the persona you picked.
Gemma 3 12B is in that bucket for many Ollama installs: strong mid-tier model, no native tools capability in /api/show. Until now, Neural Junkie handled that the same way we handle biology chat models — route the tool loop through Qwen.
That works. It also means two models in RAM, split reasoning, and routing telemetry that says tool_fallback instead of one coherent brain.
The problem in one sentence
Good chat model + no native tool calling = either no tools, or a different model runs the loop.
What we shipped: three-tier tool routing
Neural Junkie now picks a tool path in order:
- Native tools — Ollama
tool_callsor Claudetool_usewhen the model supports it (Qwen, coder models). - ReAct on the same model — for allowlisted tags like
gemma3:12b, the hub wraps the chat provider and runs an MCP loop via structured text. - Qwen swap fallback — if ReAct hits the iteration cap or can't parse a tool call, we fall back to the existing tool-loop model.
You see which path ran on the typing indicator: chat: gemma3:12b (react_tools) or (react_fallback_swap) when the safety net kicks in.
The contract: tagged JSON, not free-form Yao ReAct
We tried to keep parsing reliable. The model emits one block per tool step:
<tool_call>{"name":"read_file","arguments":{"path":"src/App.tsx"}}</tool_call>
When it's done gathering data, it replies normally — no <tool_call> block.
The hub executes the MCP tool, feeds the observation back into the loop, and continues until the model answers or hits the configured iteration cap (same guardrails as native tool loops).
Why Gemma 3 12B first
- Single ~8 GB model for chat + light MCP (read, grep, list) without pulling Qwen.
- Benchmarked well for Assistant chat in our release profiles — it was already the optional upgrade; now it can act, not just talk.
- Honest limits: heavy implementation loops (
search_replace, multi-file edits) are still harder than native Qwen tool calling. That's why tier 3 exists.
Biology and CAD domain LoRAs stay on the Qwen swap by default — different use case, different default list.
Configuration
In config.json under ollama:
"react_tools_enabled": true,
"react_tool_models": ["gemma3:12b"]
Add other non-native tags when you've validated them. Turn off react_tools_enabled to restore swap-only behavior.
Agent info in the desktop app shows react on the tool loop badge when this path is active.
What this is not
- Not a replacement for native tool calling when your model already supports it.
- On LM Studio / OpenAI-compat, ReAct auto-engages when the loaded model rejects native
tool_calls; tool-capable models use native OpenAI tool loops. - Not magic: smaller models will still drift format under pressure. The fallback exists because production agents need a floor.
Try it
- Pull
gemma3:12bin Ollama. - Point an agent or Assistant at that tag.
- Ask it to read a file in a shared workspace.
- Watch routing show
(react_tools)and the tool execute without loading Qwen.
Neural Junkie is local-first, open source, and built for specialists that share tools, approvals, and routing policy — not one monolithic planner guessing in a vacuum.
Repo: https://github.com/camronwood/neural-junkie