Ollama ships no tool template for some models (Gemma 3, Gemma 2). Any request carrying a tools field is rejected:
{"error":{"message":"registry.ollama.ai/library/gemma3:4b does not support tools","type":"invalid_request_error"}}
OpenAiProvider.chat attaches tools whenever the turn has any (app/src/lib/assistant/providers/openai.ts:629) and nothing catches the resulting 400, so it reaches the panel as a bad-request failure.
The failure is partial, which makes it look random: runAssistantTurn takes its tool list from opts.tools (agent.ts:221), so turns triaged CHAT or ACTION carry no tools and succeed, while every turn triaged ZONEMINDER fails. Greetings work, camera questions do not.
probeToolSupport / toolSupportFromError (openai.ts:355,427) already detect this exact condition, but are only wired into the settings UI (AssistantOllamaSection.tsx:170). The user gets a warning; the runtime still sends tools.
The portable JSON envelope already works for these models over the same path. Measured on the local prompt-eval harness (2 runs/case, temp 0):
| Model |
native tool |
envelope |
qwen3:8b |
56/60 |
56/60 |
qwen3:4b-instruct |
46/60 |
42/60 |
gemma3:4b |
HTTP 400 |
48/60 |
Fix: when a server rejects a request with "does not support tools", record that baseUrl::model and retry the turn without the tools field, teaching the portable envelope instead. Mirror of the existing NATIVE_TOOL_SERVERS set.
This is the narrow fix. Whether to drop the tools field for everyone is a separate question that needs the envelope path measured across more models first.
Ollama ships no tool template for some models (Gemma 3, Gemma 2). Any request carrying a
toolsfield is rejected:OpenAiProvider.chatattachestoolswhenever the turn has any (app/src/lib/assistant/providers/openai.ts:629) and nothing catches the resulting 400, so it reaches the panel as a bad-request failure.The failure is partial, which makes it look random:
runAssistantTurntakes its tool list fromopts.tools(agent.ts:221), so turns triaged CHAT or ACTION carry no tools and succeed, while every turn triaged ZONEMINDER fails. Greetings work, camera questions do not.probeToolSupport/toolSupportFromError(openai.ts:355,427) already detect this exact condition, but are only wired into the settings UI (AssistantOllamaSection.tsx:170). The user gets a warning; the runtime still sendstools.The portable JSON envelope already works for these models over the same path. Measured on the local prompt-eval harness (2 runs/case, temp 0):
qwen3:8bqwen3:4b-instructgemma3:4bFix: when a server rejects a request with "does not support tools", record that
baseUrl::modeland retry the turn without thetoolsfield, teaching the portable envelope instead. Mirror of the existingNATIVE_TOOL_SERVERSset.This is the narrow fix. Whether to drop the
toolsfield for everyone is a separate question that needs the envelope path measured across more models first.