#Help | Agent returning raw JSON instead of executing tools (Ollama)

1 messages · Page 1 of 1 (latest)

silk barn
#

Hey! My agent is outputting the tool call as plain text instead of actually executing the tools.

Expected behavior:
The agent should execute the tool (e.g. sessions_send or memory_search) and return the result.

Actual behavior:
The agent returns the raw JSON of the tool call as a message, like this:

{"name": "sessions_send", "parameters": {"message": "Schedule a test appointment...", "agentId": "1", "sessionKey": "teste_01"}}
{"name": "memory_search", "parameters": {"query": "...", "maxResults": 1, "minScore": 0.1}}

My setup:

  • Provider: Ollama (local)
  • Agent ID: 1
  • Session Key: teste_01

What I've checked:

  • The agent is receiving the user message correctly
  • Tools are defined in the agent
  • It seems like the model is "printing" the tool call instead of executing it

Is this a known issue with Ollama providers? Could it be related to the model not supporting native function calling, a system prompt config, or how OpenClaw parses the response? Any help appreciated!

rare flameBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

waxen thunderBOT
#

Yep — this is a known failure mode when Ollama is being used via the OpenAI-compatible /v1 endpoint (or api: "openai-completions"). In that mode, tool calling isn’t reliable, and models often “roleplay” the tool call by printing JSON like the examples you posted instead of returning an actual tool-use block that OpenClaw can execute.

The Ollama docs call this out explicitly (including “models may output raw tool JSON as plain text”):
https://docs.openclaw.ai/providers/ollama

What to check / fix

  1. Version (first)
  • Run: openclaw --version
  1. Confirm you’re not pointing at /v1
  • If your Ollama baseUrl looks like http://127.0.0.1:11434/v1 (or any /v1), that’s the problem.
  1. Use native Ollama API mode
    Configure the provider to use the native endpoint (no /v1) and api: "ollama":
#
{
  models: {
    providers: {
      ollama: {
        baseUrl: "http://127.0.0.1:11434", // NOTE: no /v1
        api: "ollama"
      }
    }
  }
}

Also make sure Ollama is “enabled” for discovery by setting an API key (any string works):

  • env: OLLAMA_API_KEY=ollama-local
    or
  • config: models.providers.ollama.apiKey = "ollama-local"
#
  1. Verify OpenClaw sees a tool-capable model
  • openclaw models status
  • openclaw models list --local

OpenClaw’s auto-discovery will typically only show Ollama models that report tool capability; if your model doesn’t support tools, you can still use it for chat, but tool execution will be flaky/non-working.


If you paste (a) openclaw --version and (b) the relevant part of openclaw models status (the ollama provider section, with tokens redacted), I can tell you immediately whether you’re in the /v1 OpenAI-compat path or the native Ollama path.

#

Got it — that config is already in the “native Ollama API” lane (api: "ollama" + no /v1), so if you’re still seeing the model print {"name": "...", "parameters": ...} as plain text, it’s usually one of these:

1) You’re not actually running that provider/model in the session

With multiple providers/models configured, it’s easy to think you’re on custom-127-0-0-1-11434/... but the session is actually using some other model (often an OpenAI-compat one).

Check in-chat:

  • Run /model status and confirm the exact resolved model ref.

2) That DeepSeek R1 variant isn’t tool-capable in Ollama

OpenClaw can only execute tools if the model returns real tool calls (structured) via Ollama’s tool calling. If the model doesn’t support tools (or its template doesn’t), it will often “fake it” by printing JSON.

Verify what Ollama thinks the model supports:

ollama show rns96/deepseek-R1-ablated:f16_Q4KM --json

Look for something like capabilities including "tools" (wording varies by Ollama version). If there’s no tools support, OpenClaw can’t magically make it native-call tools — you’ll get exactly what you’re seeing: JSON printed as text.

#

Quick sanity test: pull and try a known tool-capable Ollama model (from the docs examples), then set it temporarily and see if tool calls execute:

ollama pull llama3.3

Then /model switch to it and retry a tool-y request.

3) Tiny config nit: trailing slash + missing apiKey

This shouldn’t be the main cause, but I’d still tighten it up:

  • remove the trailing /
  • add an apiKey (any string; Ollama ignores it, but OpenClaw uses it for “provider enabled” / discovery paths in some setups)
"custom-127-0-0-1-11434": {
  "baseUrl": "http://127.0.0.1:11434",
  "api": "ollama",
#
  "apiKey": "ollama-local",
  ...
}

What I need to pinpoint it fast

Paste these (redact anything sensitive):

  1. openclaw --version
  2. ollama --version
  3. /model status output (or screenshot) showing what model the session is actually using

Docs reference (this exact symptom is mentioned): https://docs.openclaw.ai/providers/ollama

silk barn
#

❯ openclaw --version
2026.2.25

~
❯ ollama --version
ollama version is 0.17.4

Current: custom-127-0-0-1-11434/ollama/llama3
Default: custom-127-0-0-1-11434/ollama/llama3
Agent: main
Auth file: ~/.openclaw/agents/main/agent/auth-profiles.json

[custom-127-0-0-1-11434] endpoint: http://127.0.0.1:11434/ api: ollama auth: missing
• custom-127-0-0-1-11434/ollama/llama3 (local)

  "name": "memory_use",
  "parameters": {
    "description": "Use available memory snippets for task continuation.",
    "files": [
      "WORKFLOW_AUTO.md",
      "memory/2026-03-01/03/03.md"
    ]
  }
}
waxen thunderBOT
#

If you’re on api: "ollama" + no /v1 and it’s still printing JSON tool calls, the remaining causes are almost always:

1) The model isn’t actually getting any tool schema (tools are being filtered out)

Your output includes this:

{"name":"memory_use", ...}

memory_use is not an OpenClaw tool (OpenClaw has memory_search + memory_get). When a model invents tool names like that, it’s a strong signal that the provider call did not include OpenClaw’s actual tool definitions, so the model is just “roleplaying” tool calling.

Temporarily set tools to wide-open to confirm:

{
  tools: { profile: "full" }
#
}

(or at least ensure you’re not on tools.profile: "minimal" / a restrictive tools.byProvider entry for your provider/model)

Docs for tool allow/deny + profiles: https://docs.openclaw.ai/tools/index.md

What to paste so we can confirm quickly:

  • openclaw config get tools

2) Your Ollama provider is “auth: missing” → enable it properly

Your /model status shows:

api: ollama auth: missing

Ollama doesn’t need a real key, but OpenClaw uses that “key present” signal in a few places (notably discovery / capability plumbing). Set a dummy key and remove the trailing slash:

#
models: {
  providers: {
    "custom-127-0-0-1-11434": {
      baseUrl: "http://127.0.0.1:11434",
      api: "ollama",
      apiKey: "ollama-local"
    }
  }
}

(or set OLLAMA_API_KEY=ollama-local)

Then restart the gateway.

Docs: https://docs.openclaw.ai/providers/ollama

#

3) The model tag you’re using might not be tool-capable in Ollama

Even with everything configured correctly, some Ollama model builds/templates just won’t emit real tool_calls and will print JSON instead.

Check the model’s capabilities:

ollama show ollama/llama3 --json

(and consider testing with a known “tools” capable tag like llama3.1:* or qwen2.5-coder:* to isolate whether it’s a model issue vs OpenClaw config)

4) Ollama is quite old (0.17.4)

Worth updating Ollama too — tool calling behavior has improved over time.


If you paste:

#
  1. openclaw config get tools
  2. openclaw config get models.providers.custom-127-0-0-1-11434
  3. ollama show ollama/llama3 --json

…I can tell you which of the three buckets you’re in (tools filtered vs provider not enabled vs model not tool-capable).

silk barn
#
  "wizard": {
    "lastRunAt": "2026-02-28T17:56:17.321Z",
    "lastRunVersion": "2026.2.25",
    "lastRunCommand": "onboard",
    "lastRunMode": "local"
  },
  "models": {
    "mode": "merge",
    "providers": {
      "custom-127-0-0-1-11434": {
        "baseUrl": "http://127.0.0.1:11434/",
        "api": "ollama-local",
        "models": [
          {
            "id": "ollama/llama3",
            "name": "ollama/llama3",
            "reasoning": false,
            "input": ["text"],
            "cost": {
              "input": 0,
              "output": 0,
              "cacheRead": 0,
              "cacheWrite": 0
            },
            "contextWindow": 20000,
            "maxTokens": 20000
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "custom-127-0-0-1-11434/ollama/llama3"
      },
      "models": {
        "custom-127-0-0-1-11434/ollama/llama3": {
          "alias": "local"
        }
      },
      "workspace": "/home/[REDACTED]/.openclaw/workspace"
    }
  },
  "commands": {
    "native": "auto",
    "nativeSkills": "auto",
    "restart": true,
    "ownerDisplay": "raw"
  },
  "session": {
    "dmScope": "per-channel-peer"
  },
  "channels": {
    "discord": {
      "enabled": true,
      "token": "[REDACTED]",
      "groupPolicy": "allowlist",
      "streaming": "off"
    }
  },
  "gateway": {
    "port": 18789,
    "mode": "local",
    "bind": "loopback",
    "auth": {
      "mode": "token",
      "token": "[REDACTED]"
    },
    "tailscale": {
      "mode": "off",
      "resetOnExit": false
    },
    "nodes": {
      "denyCommands": [
        "camera.snap",
        "camera.clip",
        "screen.record",
        "calendar.add",
        "contacts.add",
        "reminders.add"
      ]
    }
  },
  "messages": {
    "tts": {
      "auto": "off",
      "edge": {
        "enabled": false
      }
    }
}```
waxen thunderBOT
#

You’ve got a config bug in that snippet that would absolutely explain “model prints JSON tool calls”:

1) Your provider api is wrong

You currently have:

api: "ollama-local",

That’s not a valid provider API type. For native tool calling you need:

api: "ollama",

Docs: https://docs.openclaw.ai/providers/ollama

#

2) You’re also missing the dummy apiKey (shows as auth: missing)

Your earlier /model status showed auth: missing. Ollama doesn’t need auth, but OpenClaw expects a key present in some paths.

Add:

apiKey: "ollama-local"

(and I’d remove the trailing slash on baseUrl)

3) Your model id/ref format is weird (and easy to mis-wire)

You’re defining the model as id: "ollama/llama3" and then selecting custom-.../ollama/llama3.

That can work only if your Ollama model is literally named ollama/llama3. Usually it’s just llama3 (or llama3.3, etc). Easiest is: don’t invent a custom provider name at all—use the built-in ollama provider and keep refs simple.


#

Recommended fix (clean + known-good)

In ~/.openclaw/openclaw.json, switch to the built-in provider:

{
  env: { OLLAMA_API_KEY: "ollama-local" }, // any value works
  agents: {
    defaults: {
      model: { primary: "ollama/llama3.3" }
    }
  }
}

(And make sure you actually have it: ollama pull llama3.3)

If you must keep the custom provider id, make it:

#
models: {
  providers: {
    "custom-127-0-0-1-11434": {
      baseUrl: "http://127.0.0.1:11434",
      api: "ollama",
      apiKey: "ollama-local",
      models: [{ id: "llama3.3", name: "llama3.3", contextWindow: 8192, maxTokens: 8192 }]
    }
  }
},
agents: { defaults: { model: { primary: "custom-127-0-0-1-11434/llama3.3" } } }

Then restart the gateway.