Skip to content

Gemma 4 (e4b) tool calling fails via Ollama OpenAI-compatible API — streaming tool_calls not recognized #20995

Closed as not planned

Description

@noxgle

Description

Gemma 4 (e4b) tool calling fails via Ollama OpenAI-compatible API — streaming tool_calls not recognized

Summary

When using Gemma 4 (e4b) via Ollama (ollama/gemma4:e4b) as a provider, the model correctly returns tool_calls in the response, but OpenCode does not recognize them and the model responds with "I do not have the capability to execute system commands" instead of calling tools.

Reproduction

  1. Configure Ollama as a provider in opencode.json:
{
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama",
      "options": {
        "baseURL": "http://localhost:11434/v1"
      },
      "models": {
        "gemma4:e4b": {
          "name": "Gemma 4 e4b",
          "tools": true,
          "limit": {
            "context": 128000,
            "output": 8192
          }
        }
      }
    }
  }
}
  1. Run opencode -m ollama/gemma4:e4b
  2. Ask: "list files in /tmp"

Expected behavior

The model should call the bash tool with ls /tmp.

Actual behavior

The model responds with: "I do not have the capability to execute system commands like listing directory contents."

Root cause analysis

I investigated and found that:

  1. Ollama API works correctly — both native (/api/chat) and OpenAI-compatible (/v1/chat/completions) endpoints return proper tool_calls with finish_reason: "tool_calls" for gemma4.
  2. Streaming also works at the API level — The streaming response includes tool_calls in the delta and ends with finish_reason: "tool_calls".
  3. The issue is on the opencode side — The AI SDK (@ai-sdk/openai-compatible) or opencode is not properly parsing/recognizing the tool calls from gemma4 in streaming mode.

API verification

Non-streaming (works):

curl -s http://localhost:11434/v1/chat/completions -d '{
  "model": "gemma4:e4b",
  "messages": [{"role": "user", "content": "list files in /tmp"}],
  "stream": false,
  "tools": [{"type": "function", "function": {"name": "bash", "description": "Execute a shell command", "parameters": {"type": "object", "required": ["command"], "properties": {"command": {"type": "string"}}}}}]
}'
# Returns: finish_reason: "tool_calls", tool_calls: [{function: {name: "bash", arguments: "{\"command\":\"ls /tmp\"}"}}]

Streaming (also works at API level):

# Streaming includes tool_calls in delta and finish_reason: "tool_calls" in final chunk

Environment

  • OpenCode version: 1.3.13
  • Ollama version: 0.20.2 (Docker)
  • Model: gemma4:e4b
  • OS: Linux

Workaround

Using qwen3.5:9b works correctly with tool calling. The issue is specific to gemma4.

Related

  • ollama/ollama#15241 — Gemma4 tool call parsing fixed in Ollama 0.20.2
  • PR #16531 — OpenAI-compatible custom tool compat layer (unmerged)
  • Issue #20669 — Default agent brittle against local tool-call quirks
  • PR #15306 — Ollama-side tool calling rework for Gemma4

Suggested fix

The toolParser compat layer from PR #16531 should be merged to handle gemma4 tool call format differences, particularly in streaming mod

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 4, 2026
  2. LohanGuedes commented on Apr 5, 2026

    @LohanGuedes

    Somehow this actually works with gemma4:e4b if you use @ then explicitly say "this current folder"

    I don't know if this is something regarding the model, but seems to me that gemma4 is just dumb...

    EDIT: fun enough qwen3.5:9b didn't work in my case.

  3. noxgle commented on Apr 5, 2026

    @noxgle
    Author

    This model gemma 4:e4b is for edge devices, but such simply job like "show files " should work.

  4. A-Risoli commented on Apr 5, 2026

    @A-Risoli

    On Ubuntu :

    ollama launch claude --model gemma4:26b

    /init

    ● I apologize, but I cannot execute system commands directly through a bash tool as it is not available in my current environment.

    Same scenario using Codex :

    ollama launch codex --model gemma4:26b

    /init

    I am sorry, but I cannot execute shell commands directly. I am an AI model designed to process and generate text and code.

    If you have a specific command you are trying to run or a script you need help writing, please provide the details, and I will be happy to help you debug, explain, or write the code for it!

  5. jazzista88 commented on Apr 5, 2026

    @jazzista88

    Same issue here with opencode, i would use gemma4 as coder executor, no thinking or planning.
    Is there already a fix on this ?

  6. ErcinDedeoglu commented on Apr 6, 2026

    @ErcinDedeoglu

    Can confirm this issue on Apple M5 Max (128GB) with Ollama v0.20.2 and OpenCode v1.3.16. Tested with gemma4:31b, aratan/gemma-4-31B-it-uncensores, and juilpark/gemma-4-31B-it-uncensored-heretic — all exhibit the same behavior.

    Root cause identified

    The issue is specifically caused by Gemma 4's thinking/reasoning mode in streaming responses via the /v1/chat/completions endpoint.

    When Gemma 4 streams with thinking enabled (default), the delta chunks include a non-standard reasoning field:

    {"delta":{"role":"assistant","content":"","reasoning":"The user wants to..."}}

    @ai-sdk/openai-compatible doesn't recognize the reasoning field — it only sees empty content strings across ~30+ chunks, then misses the tool_calls that arrive in the final chunk. The model's tool intent is correctly expressed at the API level but never reaches OpenCode's tool execution pipeline.

    Workaround: reasoning_effort: "none"

    Sending "reasoning_effort":"none" in the request body disables Gemma 4's thinking mode on the /v1 endpoint and produces fully standard-compliant streaming:

    # Without reasoning_effort (broken) — 34 chunks of reasoning, then tool_calls
    curl -s http://localhost:11434/v1/chat/completions \
      -d '{"model":"gemma4:31b","stream":true,"messages":[{"role":"user","content":"list files in /tmp"}],"tools":[...]}'
    
    # With reasoning_effort: "none" (works) — clean tool_calls in first chunk
    curl -s http://localhost:11434/v1/chat/completions \
      -d '{"model":"gemma4:31b","stream":true,"reasoning_effort":"none","messages":[{"role":"user","content":"list files in /tmp"}],"tools":[...]}'

    With reasoning_effort: "none":

    • Zero reasoning field chunks
    • Tool calls arrive immediately in standard format
    • finish_reason: "tool_calls" properly set
    • Content responses go directly into content field (not buried in reasoning)

    Suggested fix

    Either:

    1. Merge PR feat(provider): add openai-compatible custom tool compat #16531 (toolParser compat layer) to handle the non-standard reasoning field
    2. Allow model-level config to inject extra body parameters (like reasoning_effort) for custom providers — this would let users work around thinking-mode models without code changes
    3. Auto-detect Ollama + Gemma 4 and inject reasoning_effort: "none" when the model doesn't need extended thinking for tool calls

    Note: Ollama's tool call parsing for Gemma 4 was fixed in PR ollama/ollama#15306 (merged into v0.20.1/v0.20.2), so the Ollama side is resolved — this is purely an OpenCode/AI SDK streaming parsing issue now.

  7. metcalfdaniel-dotcom commented on Apr 8, 2026

    @metcalfdaniel-dotcom

    Subscribing to this issue - same problem with gemma4:e2b on local Ollama. Tool calling works via direct API but not through OpenCode.

  8. noxgle commented on Apr 8, 2026

    @noxgle
    Author

    Temporary solution: Running OpenCode with Gemma 4: https://gist.github.com/daniel-farina/87dc1c394b94e45bb700d27e9ea03193

  9. brunostc commented on Apr 8, 2026

    @brunostc

    Can we get some attention here?

  10. BrutchsamaJeanLouis commented on Apr 8, 2026

    @BrutchsamaJeanLouis

    YES 31b have been same looping issue
    there is also issue 16531 that blocks gemma4 support

  11. jj15warrior commented on Apr 10, 2026

    @jj15warrior

    also subscribed, having the same issue with gemma4:e4b and huihui_ai/gemma-4-abliterated:e4b. the abiliterated version did try to run nonexistent tools in opencode tho.

  12. MominAlZaraa commented on Apr 12, 2026

    @MominAlZaraa

    The same on UBUNUTU, local LLM gemma4:31b, other gemma4 as well, don't work. Error not finding directory, although ran/openned OpenCode within directory also in Cursor with the same problem. On Opencode Zen though they work normally using API free options.

  13. appetrosyan commented on Apr 12, 2026

    @appetrosyan

    OpenCode isn't the only one that's affected. I tried running gemma4 with Claude Code and it failed in the exact same way.

  14. 18 remaining items

  15. Bazmundi commented on Jun 8, 2026

    @Bazmundi

    using 1.16.2 with gemma4:latest and still doesn't work.

  16. rkuo2000 commented on Jun 8, 2026

    @rkuo2000

    you can try LM Studio, it has more detail settings, including context length, multiple GPUs on/off, ...

  17. X-Ryl669 commented on Jun 8, 2026

    @X-Ryl669

    Seems like the gemma model itself has issues depending on which one you have downloaded. Updates to the chat_template.jinja in the model should fix it (not tested)

  18. TomLucidor commented on Jul 8, 2026

    @TomLucidor

    Are there similar issues with tool-calling with E4B in general? Hermes got the same issues NousResearch/hermes-agent#6626 (comment) NousResearch/hermes-agent#19887

  19. ToeiRei commented on Jul 8, 2026

    @ToeiRei

    as said in my previous comment, I assume this is an issue with gemma4

  20. djmaxus commented on Jul 9, 2026

    @djmaxus

    as said in my previous comment, I assume this is an issue with gemma4

    If this is the case, how come gemma4 works great via ollama + Pi?

  21. ToeiRei commented on Jul 9, 2026

    @ToeiRei

    As to my understanding it's about thinking tags and stuff that engines like ollama have patched in their latest versions and some agent frameworks do still trip up on these quirks

  22. X-Ryl669 commented on Jul 9, 2026

    @X-Ryl669

    You dont need to patch the engine, only the jinja chat template.

  23. TomLucidor commented on Jul 10, 2026

    @TomLucidor

    @raullenchai could you help out here checking the messages by @ToeiRei so that Rapid-MLX can have stability? I do not know who else to call with this one

  24. mlzl1426 commented on Jul 10, 2026

    @mlzl1426

    我遇到了同样的问题。根本原因:httpx 默认启用 HTTP/2,而 Ollama 不支持它。解决方法是 http2=False。详情复现脚本:https://github.com/mlzl1426/fix-ollama-httpx-http2
    I ran into the same issue. Root cause: httpx enables HTTP/2 by default and Ollama doesn't support it. Fix is http2=False. Details + repro script: https://github.com/mlzl1426/fix-ollama-httpx-http2

  25. github-actions commented on Sep 9, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

  26. djmaxus commented on Oct 4, 2026

    @djmaxus

    To stay organized issues are automatically closed after 60 days of no activity

    But the devs were the ones who were inactive...

  27. TomLucidor commented on Oct 5, 2026

    @TomLucidor

    @djmaxus do a reopen, and then cite all the other related issues. Carry the torch

  28. djmaxus commented on Oct 5, 2026

    @djmaxus

    @TomLucidor fair enough

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions