Skip to content

[Bug]: Ollama qwen2.5-coder tool calls in content field, not tool_calls — Hermes doesn't execute them #5867

Description

@marsdream

Bug Description

When using Ollama with qwen2.5-coder:14b (and likely other Ollama models), tool calls are returned as a JSON string in the content field rather than as a structured tool_calls array. This causes Hermes to treat the response as a regular text reply and never actually execute the tools.

Environment

  • Hermes version: (latest)
  • Ollama version: (Mac app, latest)
  • Model: qwen2.5-coder:14b
  • OS: macOS

Steps to Reproduce

  1. Configure Hermes with Ollama provider using qwen2.5-coder:14b
  2. Send a message that requires a tool (e.g., "搜索今天北京的天气")
  3. Model returns tool call as plain text in content field

Actual Response Format from Ollama

{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "{\"name\": \"search\", \"arguments\": {\"query\": \"北京今天的天气\"}}",
      "finish_reason": "stop"
    }
  }]
}

Note: no tool_calls field — the tool call is serialized as a JSON string inside content.

Expected Response Format (OpenAI standard)

{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": null,
      "tool_calls": [{
        "id": "call_xxx",
        "type": "function",
        "function": {
          "name": "search",
          "arguments": "{\"query\": \"北京今天的天气\"}"
        }
      }],
      "finish_reason": "tool_calls"
    }
  }]
}

Root Cause

Hermes checks for tool calls via:

  • response.choices[0].message.tool_calls (OpenAI SDK attribute)
  • msg.get("tool_calls") (dict key lookup)

When a model returns the tool call embedded in content as a JSON string, neither check fires, so Hermes never routes to handle_function_call().

Suggested Fix

Add a fallback in the API response parsing: if no tool_calls found but content is a valid JSON string matching the pattern {"name": "<tool>", "arguments": {...}}, parse it and treat it as a tool call.

This would handle Ollama's non-standard tool call format without breaking standard tool_calls behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/agentCore agent runtime: loop, agent_init, prompt builder, context-compression, responses endpointprovider/ollamaOllama / local modelstype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions