MoonshotAI / MoonshotAI/kimi-code

Managed k3 stream emits corrupted tool names with literal '?' fragments; engine should validate unknown tool names

Open
#3,230 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
7.5k
Forks
1.2k
Avg merge
11h 53m
Merged PRs (30d)
350

Description

Summary

Since ~Aug 24, tool calls over managed:kimi-code (k3) intermittently arrive with corrupted names streamed in fragments — e.g. mcp__linear__list_issu?list_issues (a literal ?, 0x3F, mid-name). The engine rejects them (Tool "..." not found), the model retries the identical garbage, and the turn stalls.

This is distinct from #3220's parser defect: there, the client dropped name fragments; here, the bytes arriving from the API are themselves malformed — verified by reassembling the stream with a patched parser and hex-dumping the recorded tool call. The corruption is on the wire, not introduced client-side.

Environment

  • kimi 0.36.0 (released Aug 13) and a source build of main @ 41f1eae (0.38.0); Windows 11
  • Provider managed:kimi-code, model k3, thinking effort high
  • MCP: 8 servers, ~130 tools; failures observed on the Linear http server (55 tools, long shared mcp__linear__ prefix)

Evidence

Session wire (~/.kimi-code/sessions/<wd>/<session>/agents/main/wire.jsonl):

{"type":"tool.call","name":"mcp__linear__list_issu?list_issues","args":{}}
{"type":"tool.call","name":"mcp__linear__get_issu?get_issue","args":{}}
  • The ? is a literal 0x3F byte, not a rendering artifact (od hex-dump verified).
  • The model's reasoning immediately before one retry read: "Typo in tool name. Use mcp__linear__list_issues." — it then emitted the same corrupted name again. The intent is correct; the serialization is broken.
  • First occurrence Aug 24 across all sessions; none in months of prior history on the same client version. #3220 (independent reporter, macOS, 0.38.0) was opened the same day — consistent with a serving-side change around Aug 23–24, not a client regression.
  • Matches the vLLM K3 deployment note quoted in #3220: K3 occasionally emits a tool-call format its own parser does not expect.

Why this needs a server-side fix

No client parser can reconstruct intent from bytes that are wrong at the source. The model clearly intends mcp__linear__list_issues; the stream delivers mcp__linear__list_issu?list_issues.

What the client could still do (proposal)

Even with a server fix, the engine currently treats these as ordinary tool results (Tool "..." not found) and burns the step budget until the turn dies. Two complementary guards, aligned with #3220's "Suggested handling":

  1. Classify an unknown-tool-name call as a retryable step failure so loopControl.maxAttemptsPerStep engages, instead of silently advancing.
  2. Optionally, constrained name recovery: when a name is unknown, sanitize it (split on non-[A-Za-z0-9_]) and rewrite to a catalog tool only on a unique match — exact segment, then _-bounded suffix, then prefix, in that priority. Ambiguous or unmatched names keep the current rejection. In local testing this rescued every corrupted call observed (list_issu?list_issueslist_issues, get_issu?get_issueget_issue) while correctly rejecting ambiguous truncations (list_issu alone matches 3 catalog tools → rejected).

I have both the #3220 parser patch and this recovery guard implemented with unit tests in a local fork (suites green, typecheck/lint clean) and can contribute either under an /approve. Per the contributing guide, behavior changes are maintainer-gated — so treat this as the discussion issue first.

Reproduction

With a large MCP catalog (Linear's 55-tool http server makes it frequent), start a fresh session and ask the agent to list or review Linear issues. Intermittent — but when it triggers, it repeats within the session. Happy to attach a kimi export debug zip if useful.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Begin with the recorded wire.jsonl session data under ~/.kimi-code/sessions/.../agents/main/wire.jsonl and reproduce the failure using a large MCP catalog. Then inspect the engine's unknown-tool handling and loopControl.maxAttemptsPerStep behavior, comparing the proposed guards with #3220. Done means the malformed-name case no longer stalls a turn and the recovery behavior remains safe for ambiguous or unmatched names.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design, cli
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.