Skip to content

Kimi K2.6 Agent Mode tool calls fail on duplicate-index streaming fragments #657

Description

@AnthonyRonning

Summary

Kimi K2.6 is currently unable to make ordinary Agent Mode shell calls reliably. A request such as “please investigate a few files here” produces a failed tool row with:

-32602: The model's response was truncated — it hit the output token limit while generating this tool call.
Received 69 characters; cut off at: command": "ls -la /path/to/project"}

The displayed output-token diagnosis is misleading. The provider finishes the tool call normally, but Goose drops the opening fragment of Kimi's streamed JSON arguments before parsing them.

This was discovered while testing #650, but it is not caused by #650.

Reproduction

  1. Open desktop Agent Mode with an enabled Pro test account.
  2. Select Kimi K2.6.
  3. Start a new task in a local project.
  4. Ask: please investigate a few files here
  5. Observe the first shell tool call fail. Kimi retries and the same failure repeats.

This reproduced in two fresh Agent tasks. The stored model configuration was:

{"model_name":"kimi-k2-6","max_tokens":null}

Root cause

A direct request through Maple's loopback proxy shows the difference:

  • A non-streaming Kimi response returns valid arguments: {"command":"ls -la"}.
  • A streaming Kimi response finishes with finish_reason: "tool_calls" (50 completion tokens in the probe), but its first tool-call SSE event contains two entries with the same index:
"tool_calls": [
  {
    "index": 0,
    "id": "functions.shell:0",
    "type": "function",
    "function": {"name": "shell"}
  },
  {
    "index": 0,
    "function": {"arguments": " {\""}
  }
]

Later events continue with fragments such as command": "ls and -la"}.

Maple pins Goose at 3c1fdd692cc8aaa5f09b9175410c09a09d4dfe49 (Cargo.toml). Goose's streaming decoder initializes a call only from an entry containing both the ID and function name, so it ignores the second same-index entry carrying {\". It then appends later fragments and tries to parse command": "ls -la"}, which exactly matches the UI failure (pinned Goose decoder).

The malformed-JSON heuristic treats an unmatched closing brace as truncation, which is why the UI recommends increasing max_tokens; the actual stream ended normally. Current Goose main still has the same aggregation behavior as of 2026-07-21.

Why this predates #650

  • Give completed Agent thoughts descriptive labels #650 changes the React thought-label presentation and its separate Gemma summarization requests. It does not change Rust, Cargo, the Agent provider, the proxy, or the Goose revision.
  • The rebased PR and current master use the same Goose decoder.
  • The original Agent Mode PR Add direct Goose Agent Mode #607 explicitly left Kimi available on a “best-effort basis” pending provider compatibility.
  • During Add direct Goose Agent Mode #607 development, Maple briefly had the exact duplicate-index coalescer in commit 027e32c4, then removed the app-specific normalizer once GLM's serving path became compatible. Kimi was not verified at launch.

Expected behavior

Goose should merge all streamed tool_calls fragments by index, including multiple entries for the same index within the initial SSE event, and execute the resulting valid tool call.

Suggested fix

Prefer fixing this in Goose rather than restoring Maple-specific stream parsing:

  1. Merge ID, name, arguments, type, and extra fields for every same-index entry in both the initial and subsequent SSE events.
  2. Add the Kimi event above as a regression fixture.
  3. Distinguish a provider finish_reason: "length" from malformed/incompatibly aggregated arguments so the UI does not falsely report a token-limit problem.
  4. Update Maple's pinned Goose revision once the upstream fix lands.

A short-term Maple proxy normalizer is possible (the discarded #607 implementation already demonstrates it), but that would reintroduce provider-format coupling at the application layer.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions