Skip to content

Ollama provider drops tools after the first tool call, breaking multi-step agent loops #13254

Description

@NVentimiglia

Before submitting your bug report

Relevant environment info

- OS: Windows 11
- Continue version: 2.0.0 (VS Code extension, win32-x64)
- IDE version: 1.137.0
- Model: Qwen3.8 27B
- config:
  
    provider: ollama
    capabilities:
      - tool_use
    roles:
      - chat
      - edit
      - apply

Description

In agent mode with an Ollama model, the agent executes exactly one tool call per user
message and then stops — it narrates its next intended step as plain text but never
emits the follow-up tool call. Re-prompting produces one more tool call, then stops again.

Root cause
In the Ollama provider's chat-args builder, the tools array is only attached when the
last message is a user message:

if (options.tools?.length && ollamaMessages.at(-1)?.role === "user") {
  chatOptions.tools = options.tools.map(...);
}

During an agent loop, the turn that immediately follows a tool execution has a tool
(tool-result) message as its last message, not user. So the tool schema is omitted on
exactly the turn where the model needs to decide on the next tool call. With no tools in
the request, the model can't continue the loop and falls back to prose.

Suggested fix

extension.js (line 524024)

Drop the ollamaMessages.at(-1)?.role === "user" condition:

if (options.tools?.length) {
chatOptions.tools = options.tools.map(...);
}

To reproduce

  1. Configure any tool-capable Ollama model in agent mode.
  2. Give it a task requiring 2+ sequential tool calls (e.g. "read file A, then read file B").
  3. Observe: it calls the tool for A, receives the result, then emits text like
  4. "Let me now check B…" and stops without calling the tool for B.

Log output

Minimal reproduction against Ollama /api/chat (no Continue needed), showing that
omitting the `tools` array on the turn whose last message is a tool result stops
the model from continuing — which is exactly what Continue's Ollama provider does.

Model under test: a tool-capable Ollama model (reproduced on a Qwen3-family GGUF).
Conversation state = [user, assistant(tool_call read_file A), tool(result for A)].

--- CASE 1: request WITHOUT tools (what Continue sends after a tool result) ---
POST http://localhost:11434/api/chat
{
  "model": "<tool-capable-model>",
  "stream": false,
  "messages": [
    {"role":"user","content":"Read fileA.cs then fileB.cs to understand the structure."},
    {"role":"assistant","content":"","tool_calls":[
      {"function":{"name":"read_file","arguments":{"filepath":"fileA.cs"}}}]},
    {"role":"tool","content":"public class A { void OnBar(){} }"}
  ]
}
Response:
  message.content    = ""       (no follow-up)
  message.tool_calls = (none)   <-- loop dead: model cannot continue

--- CASE 2: identical request but WITH tools resent ---
POST http://localhost:11434/api/chat
{
  "model": "<tool-capable-model>",
  "stream": false,
  "messages": [ ...same three messages as above... ],
  "tools": [
    {"type":"function","function":{
      "name":"read_file",
      "description":"Read a file",
      "parameters":{"type":"object","required":["filepath"],
        "properties":{"filepath":{"type":"string"}}}}}
  ]
}
Response:
  message.tool_calls = [
    {"function":{"name":"read_file","arguments":{"filepath":"fileB.cs"}}}
  ]   <-- correct: proceeds to the next file

The ONLY difference between the two requests is the presence of `tools`.
In agent mode the follow-up turn's last message is role `tool`, so the provider's
guard `ollamaMessages.at(-1)?.role === "user"` is false and `tools` is dropped,
producing CASE 1. Removing that role check produces CASE 2 on every turn.

Continue 2.0.0 (VS Code, win32-x64); Ollama 0.34.0; Windows 11.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    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