MoonshotAI / MoonshotAI/kimi-cli
bug: Tool call arguments double-encoding breaks array/dict parameters (Moonshot API)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 11.4k
- Forks
- 1.3k
- Avg merge
- 9h 47m
- Merged PRs (30d)
- 2
Description
Problem
Tool calls with array or object parameters (e.g. SetTodoList, ExitPlanMode, StrReplaceFile) fail with Pydantic validation errors:
Error validating JSON arguments: 1 validation error for Params
todos
Input should be a valid list [type=list_type, input_value=[{"title": ...}], input_type=str]
The todos parameter is received as a JSON string instead of a parsed list/array.
Root Cause
In KimiToolset.handle() (kimi_cli/soul/toolset.py:301):
arguments: JsonType = json.loads(tool_call.function.arguments or "{}", strict=False)
The Moonshot API returns function.arguments with double-encoded JSON strings for nested array/object values. After json.loads parses the outer JSON, inner values like todos remain as strings:
API returns: {"todos": "[{\"title\": \"test\", \"status\": \"in_progress\"}]"}
^--- string, not array!
json.loads → {"todos": "[{\"title\": \"test\", \"status\": \"in_progress\"}]"}
^--- still a string!
Pydantic → ERROR: expected list, got str
Affected Tools
| Tool | Parameter | Type |
|---|---|---|
SetTodoList |
todos |
list[Todo] |
ExitPlanMode |
options |
list[Option] |
StrReplaceFile |
edit |
dict or list[Edit] |
| Any tool with array/dict params | varies | varies |
Reproduction
- Call
SetTodoListwithtodos=[{"title": "test", "status": "in_progress"}] - Observe Pydantic validation error
Proposed Fix
In kimi_cli/soul/toolset.py, KimiToolset.handle() method, replace:
arguments: JsonType = json.loads(tool_call.function.arguments or "{}", strict=False)
with:
raw = tool_call.function.arguments or "{}"
if isinstance(raw, dict):
arguments: JsonType = raw
else:
arguments = json.loads(raw, strict=False)
# Moonshot API quirk: double-encoded JSON strings
if isinstance(arguments, dict):
for k, v in list(arguments.items()):
if isinstance(v, str) and v and v[0] in ("[", "{"):
try:
arguments[k] = json.loads(v, strict=False)
except (json.JSONDecodeError, ValueError):
pass
Environment
- Kimi CLI: 1.46.0
- Pydantic: 2.12.5
- OpenAI SDK: 2.14.0
- Python: 3.14
- OS: Linux
Additional Context
The same issue exists in SimpleToolset.handle() in kosong/tooling/simple.py (the upstream library), but the Kimi CLI uses KimiToolset instead, which has its own handle() method with the same bug.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in kimi_cli/soul/toolset.py at KimiToolset.handle(), then reproduce the SetTodoList call described in the issue and inspect the parsed arguments before Pydantic validation. Compare the behavior with the stated Moonshot double-encoding case; done means array and object parameters reach the affected tools as parsed values without validation errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100