CanIToolCall caniuse.com for tool calling

Kimi (K2.x section tokens, K3 XTML) on vllm 0.30.0

fail 45% strict pass 22 pass · 19 soft pass · 8 fail

Run

Engine
vllm 0.30.0
Run
to
Platform
linux-x86_64, Python 3.12.14, canitoolcall 0.1.0.dev0
Strategies
one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8 (normalization soft-v1)
Fixtures digest
a1e7b55367e195e8aa6e2ef746b2cc141b44f37caad0887ff8f30b104616f836 the fixture corpus used for this site matches the run
Engine details
{
  "huggingface-hub": "1.33.0",
  "mistral-common": "1.12.0",
  "openai-harmony": "0.0.8",
  "pinned_version": "0.30.0",
  "tokenizers": "0.23.2",
  "tokens_per_step": "many",
  "torch": "2.14.0+cpu",
  "transformers": "5.17.0",
  "wheel": "vllm-0.30.0-cp38-abi3-manylinux_2_28_x86_64.whl",
  "wheel_sha256": "ef52ee58c410ead0b8afb190838fa4cbcb52075596f67862a03859d984966ac4"
}
Results file
data/vllm-0.30.0.json

Checks

Per fixture, the worst result of each check over the non-streaming parse and every realistic chunking strategy.
CheckPassSoft FailErrorStrict pass rate
expected_match 20 19 7 0 43%
expected_error 2 0 1 0 67%
stream_equals_nonstream 43 0 6 0 88%
split_invariance 48 0 1 0 98%
no_leakage 47 0 2 0 96%
arguments_json 34 0 2 0 94%
arguments_schema 34 0 2 0 94%
parallel_order 4 0 0 0 100%

Fixtures needing attention

fail kimi/k26-marker-in-arguments expected_match, stream_equals_nonstream, split_invariance, no_leakage
Checks that did not pass for kimi/k26-marker-in-arguments
CheckStrategyResultDetail
expected_matchnonstream failreasoning_content (whitespace only): expected 'Document the tool-call markers.', got ' Document the tool-call markers.'; tool_calls[0].arguments: expected '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning."}', got '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; ends reasoning."}'
expected_matchone failcontent: expected None, got ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w...; reasoning_content (whitespace only): expected 'Document the tool-call markers.', got ' Document the tool-call markers.'; tool_calls: expected ['write_file'], got []
expected_matchspecial failcontent: expected None, got ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w...; reasoning_content (whitespace only): expected 'Document the tool-call markers.', got ' Document the tool-call markers.'; tool_calls: expected ['write_file'], got []
expected_matchtoken failreasoning_content (whitespace only): expected 'Document the tool-call markers.', got ' Document the tool-call markers.'; tool_calls[0].arguments: expected '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
expected_matchrand:1:8 failreasoning_content (whitespace only): expected 'Document the tool-call markers.', got ' Document the tool-call markers.'; tool_calls[0].arguments: expected '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
expected_matchrand:2:8 failreasoning_content (whitespace only): expected 'Document the tool-call markers.', got ' Document the tool-call markers.'; tool_calls[0].arguments: expected '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
expected_matchrand:3:8 failreasoning_content (whitespace only): expected 'Document the tool-call markers.', got ' Document the tool-call markers.'; tool_calls[0].arguments: expected '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
expected_matchrand:4:8 failreasoning_content (whitespace only): expected 'Document the tool-call markers.', got ' Document the tool-call markers.'; tool_calls[0].arguments: expected '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
expected_matchrand:5:8 failreasoning_content (whitespace only): expected 'Document the tool-call markers.', got ' Document the tool-call markers.'; tool_calls[0].arguments: expected '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
stream_equals_nonstreamone failcontent: nonstream None, got ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w...; tool_calls: nonstream ['write_file'], got []
stream_equals_nonstreamspecial failcontent: nonstream None, got ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w...; tool_calls: nonstream ['write_file'], got []
stream_equals_nonstreamtoken failtool_calls[0].arguments: nonstream '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
stream_equals_nonstreamrand:1:8 failtool_calls[0].arguments: nonstream '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
stream_equals_nonstreamrand:2:8 failtool_calls[0].arguments: nonstream '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
stream_equals_nonstreamrand:3:8 failtool_calls[0].arguments: nonstream '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
stream_equals_nonstreamrand:4:8 failtool_calls[0].arguments: nonstream '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
stream_equals_nonstreamrand:5:8 failtool_calls[0].arguments: nonstream '{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; ends reasoning."}', got ' {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|> ; </think> ends reasonin...
split_invariance* failvs one: token (fail): content: one ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w..., got None; tool_calls: one [], got ['write_file'] | rand:1:8 (fail): content: one ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w..., got None; tool_calls: one [], got ['write_file'] | rand:2:8 (fail): content: one ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w..., got None; tool_calls: one [], got ['write_file'] | rand:3:8 (fail): content: one ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w..., got None; tool_calls: one [], got ['write_file'] | rand:4:8 (fail): content: one ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w..., got None; tool_calls: one [], got ['write_file'] | rand:5:8 (fail): content: one ' <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {"path": "docs/kimi.md", "content": "A section opens w..., got None; tool_calls: one [], got ['write_file']
no_leakageone failcontent contains '<|tool_calls_section_begin|>'; content contains '<|tool_calls_section_end|>'; content contains '<|tool_call_begin|>'; content contains '<|tool_call_end|>'; content contains '<|tool_call_argument_begin|>'
no_leakagespecial failcontent contains '<|tool_calls_section_begin|>'; content contains '<|tool_calls_section_end|>'; content contains '<|tool_call_begin|>'; content contains '<|tool_call_end|>'; content contains '<|tool_call_argument_begin|>'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-marker-in-arguments --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 10 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream

--- expected
+++ observed
@@ -1,9 +1,9 @@
 {
   "content": null,
-  "reasoning_content": "Document the tool-call markers.",
+  "reasoning_content": " Document the tool-call markers.",
   "tool_calls": [
     {
       "arguments": {
-        "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning.",
+        "content": "A section opens with  <|tool_calls_section_begin|>  and each call with  <|tool_call_begin|> ;    ends reasoning.",
         "path": "docs/kimi.md"
       },

Strategies: one, special

--- expected
+++ observed
@@ -1,13 +1,5 @@
 {
-  "content": null,
-  "reasoning_content": "Document the tool-call markers.",
-  "tool_calls": [
-    {
-      "arguments": {
-        "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning.",
-        "path": "docs/kimi.md"
-      },
-      "name": "write_file"
-    }
-  ]
+  "content": " <|tool_calls_section_begin|> <|tool_call_begin|> functions.write_file:0 <|tool_call_argument_begin|> {\"path\": \"docs/kimi.md\", \"content\": \"A section opens with  <|tool_calls_section_begin|>  and each call with  <|tool_call_begin|> ;    ends reasoning.\"} <|tool_call_end|> <|tool_calls_section_end|>",
+  "reasoning_content": " Document the tool-call markers.",
+  "tool_calls": []
 }

Strategies: token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,9 +1,9 @@
 {
   "content": null,
-  "reasoning_content": "Document the tool-call markers.",
+  "reasoning_content": " Document the tool-call markers.",
   "tool_calls": [
     {
       "arguments": {
-        "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning.",
+        "content": "A section opens with  <|tool_calls_section_begin|>  and each call with  <|tool_call_begin|> ;  </think>  ends reasoning.",
         "path": "docs/kimi.md"
       },

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: single-call, marker-in-arguments, reasoning, x-think-no-open-tag, x-kimi-k2.

Raw output

Document the tool-call markers.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.write_file:0<|tool_call_argument_begin|>{"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning."}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "Document the tool-call markers.",
  "tool_calls": [
    {
      "arguments": {
        "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning.",
        "path": "docs/kimi.md"
      },
      "name": "write_file"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-marker-in-arguments", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Document the tool-call markers.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.write_file:0<|tool_call_argument_begin|>{\"path\": \"docs/kimi.md\", \"content\": \"A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning.\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [10360, 276, 4453, 72567, 39085, 13, 163607, 163595, 163597, 41937, 9189, 6101, 25, 15, 163598, 8264, 4953, 1289, 414, 12270, 12731, 30223, 6847, 665, 414, 4204, 1289, 414, 32, 6488, 21755, 472, 220, 163595, 316, 2458, 2390, 472, 220, 163597, 26, 220, 163607, 15739, 57753, 5046, 92, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Document the tool-call markers.", "tool_calls": [{"name": "write_file", "arguments": {"path": "docs/kimi.md", "content": "A section opens with <|tool_calls_section_begin|> and each call with <|tool_call_begin|>; </think> ends reasoning."}}]}, "tags": ["single-call", "marker-in-arguments", "reasoning", "x-think-no-open-tag", "x-kimi-k2"], "notes": "The JSON string contains opening markers and </think>; the official template tokenizes them as marker tokens. None of them ends the argument JSON, which is closed by <|tool_call_end|>."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
fail kimi/k26-marker-terminator-in-string expected_match, stream_equals_nonstream, arguments_json, arguments_schema
Checks that did not pass for kimi/k26-marker-terminator-in-string
CheckStrategyResultDetail
expected_matchnonstream failreasoning_content (whitespace only): expected 'Write the literal end marker into the file.', got ' Write the literal end marker into the file.'; tool_calls[0].arguments: expected '{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}', got '{"path": "end.txt", "content": "stop at'
expected_matchone failreasoning_content (whitespace only): expected 'Write the literal end marker into the file.', got ' Write the literal end marker into the file.'; tool_calls[0].arguments: expected '{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}', got ' {"path": "end.txt", "content": "stop at '
expected_matchspecial failreasoning_content (whitespace only): expected 'Write the literal end marker into the file.', got ' Write the literal end marker into the file.'; tool_calls[0].arguments: expected '{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}', got ' {"path": "end.txt", "content": "stop at '
expected_matchtoken failreasoning_content (whitespace only): expected 'Write the literal end marker into the file.', got ' Write the literal end marker into the file.'; tool_calls[0].arguments: expected '{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}', got ' {"path": "end.txt", "content": "stop at '
expected_matchrand:1:8 failreasoning_content (whitespace only): expected 'Write the literal end marker into the file.', got ' Write the literal end marker into the file.'; tool_calls[0].arguments: expected '{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}', got ' {"path": "end.txt", "content": "stop at '
expected_matchrand:2:8 failreasoning_content (whitespace only): expected 'Write the literal end marker into the file.', got ' Write the literal end marker into the file.'; tool_calls[0].arguments: expected '{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}', got ' {"path": "end.txt", "content": "stop at '
expected_matchrand:3:8 failreasoning_content (whitespace only): expected 'Write the literal end marker into the file.', got ' Write the literal end marker into the file.'; tool_calls[0].arguments: expected '{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}', got ' {"path": "end.txt", "content": "stop at '
expected_matchrand:4:8 failreasoning_content (whitespace only): expected 'Write the literal end marker into the file.', got ' Write the literal end marker into the file.'; tool_calls[0].arguments: expected '{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}', got ' {"path": "end.txt", "content": "stop at '
expected_matchrand:5:8 failreasoning_content (whitespace only): expected 'Write the literal end marker into the file.', got ' Write the literal end marker into the file.'; tool_calls[0].arguments: expected '{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}', got ' {"path": "end.txt", "content": "stop at '
stream_equals_nonstreamone failtool_calls[0].arguments: nonstream '{"path": "end.txt", "content": "stop at', got ' {"path": "end.txt", "content": "stop at '
stream_equals_nonstreamspecial failtool_calls[0].arguments: nonstream '{"path": "end.txt", "content": "stop at', got ' {"path": "end.txt", "content": "stop at '
stream_equals_nonstreamtoken failtool_calls[0].arguments: nonstream '{"path": "end.txt", "content": "stop at', got ' {"path": "end.txt", "content": "stop at '
stream_equals_nonstreamrand:1:8 failtool_calls[0].arguments: nonstream '{"path": "end.txt", "content": "stop at', got ' {"path": "end.txt", "content": "stop at '
stream_equals_nonstreamrand:2:8 failtool_calls[0].arguments: nonstream '{"path": "end.txt", "content": "stop at', got ' {"path": "end.txt", "content": "stop at '
stream_equals_nonstreamrand:3:8 failtool_calls[0].arguments: nonstream '{"path": "end.txt", "content": "stop at', got ' {"path": "end.txt", "content": "stop at '
stream_equals_nonstreamrand:4:8 failtool_calls[0].arguments: nonstream '{"path": "end.txt", "content": "stop at', got ' {"path": "end.txt", "content": "stop at '
stream_equals_nonstreamrand:5:8 failtool_calls[0].arguments: nonstream '{"path": "end.txt", "content": "stop at', got ' {"path": "end.txt", "content": "stop at '
arguments_jsonnonstream fail[0] write_file: arguments are not valid JSON text ('{"path": "end.txt", "content": "stop at': Unterminated string starting at: line 1 column 32 (char 31))
arguments_jsonone fail[0] write_file: arguments are not valid JSON text (' {"path": "end.txt", "content": "stop at ': Unterminated string starting at: line 1 column 33 (char 32))
arguments_jsonspecial fail[0] write_file: arguments are not valid JSON text (' {"path": "end.txt", "content": "stop at ': Unterminated string starting at: line 1 column 33 (char 32))
arguments_jsontoken fail[0] write_file: arguments are not valid JSON text (' {"path": "end.txt", "content": "stop at ': Unterminated string starting at: line 1 column 33 (char 32))
arguments_jsonrand:1:8 fail[0] write_file: arguments are not valid JSON text (' {"path": "end.txt", "content": "stop at ': Unterminated string starting at: line 1 column 33 (char 32))
arguments_jsonrand:2:8 fail[0] write_file: arguments are not valid JSON text (' {"path": "end.txt", "content": "stop at ': Unterminated string starting at: line 1 column 33 (char 32))
arguments_jsonrand:3:8 fail[0] write_file: arguments are not valid JSON text (' {"path": "end.txt", "content": "stop at ': Unterminated string starting at: line 1 column 33 (char 32))
arguments_jsonrand:4:8 fail[0] write_file: arguments are not valid JSON text (' {"path": "end.txt", "content": "stop at ': Unterminated string starting at: line 1 column 33 (char 32))
arguments_jsonrand:5:8 fail[0] write_file: arguments are not valid JSON text (' {"path": "end.txt", "content": "stop at ': Unterminated string starting at: line 1 column 33 (char 32))
arguments_schemanonstream fail[0] write_file: arguments are not a JSON object; not validated
arguments_schemaone fail[0] write_file: arguments are not a JSON object; not validated
arguments_schemaspecial fail[0] write_file: arguments are not a JSON object; not validated
arguments_schematoken fail[0] write_file: arguments are not a JSON object; not validated
arguments_schemarand:1:8 fail[0] write_file: arguments are not a JSON object; not validated
arguments_schemarand:2:8 fail[0] write_file: arguments are not a JSON object; not validated
arguments_schemarand:3:8 fail[0] write_file: arguments are not a JSON object; not validated
arguments_schemarand:4:8 fail[0] write_file: arguments are not a JSON object; not validated
arguments_schemarand:5:8 fail[0] write_file: arguments are not a JSON object; not validated

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-marker-terminator-in-string --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 11 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream

--- expected
+++ observed
@@ -1,10 +1,9 @@
 {
   "content": null,
-  "reasoning_content": "Write the literal end marker into the file.",
+  "reasoning_content": " Write the literal end marker into the file.",
   "tool_calls": [
     {
       "arguments": {
-        "content": "stop at <|tool_call_end|> please",
-        "path": "end.txt"
+        "<arguments_raw, not valid JSON>": "{\"path\": \"end.txt\", \"content\": \"stop at"
       },
       "name": "write_file"

Strategies: one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,10 +1,9 @@
 {
   "content": null,
-  "reasoning_content": "Write the literal end marker into the file.",
+  "reasoning_content": " Write the literal end marker into the file.",
   "tool_calls": [
     {
       "arguments": {
-        "content": "stop at <|tool_call_end|> please",
-        "path": "end.txt"
+        "<arguments_raw, not valid JSON>": " {\"path\": \"end.txt\", \"content\": \"stop at  "
       },
       "name": "write_file"

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: single-call, marker-in-arguments, reasoning, x-marker-terminator-in-string, x-think-no-open-tag, x-kimi-k2.

Raw output

Write the literal end marker into the file.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.write_file:0<|tool_call_argument_begin|>{"path": "end.txt", "content": "stop at <|tool_call_end|> please"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "Write the literal end marker into the file.",
  "tool_calls": [
    {
      "arguments": {
        "content": "stop at <|tool_call_end|> please",
        "path": "end.txt"
      },
      "name": "write_file"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-marker-terminator-in-string", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Write the literal end marker into the file.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.write_file:0<|tool_call_argument_begin|>{\"path\": \"end.txt\", \"content\": \"stop at <|tool_call_end|> please\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [9570, 276, 34459, 1565, 24894, 1576, 276, 1650, 13, 163607, 163595, 163597, 41937, 9189, 6101, 25, 15, 163598, 8264, 4953, 1289, 414, 517, 8842, 665, 414, 4204, 1289, 414, 18434, 623, 220, 163599, 5462, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Write the literal end marker into the file.", "tool_calls": [{"name": "write_file", "arguments": {"path": "end.txt", "content": "stop at <|tool_call_end|> please"}}]}, "tags": ["single-call", "marker-in-arguments", "reasoning", "x-marker-terminator-in-string", "x-think-no-open-tag", "x-kimi-k2"], "notes": "The JSON string contains <|tool_call_end|>, tokenized as the marker token by the template. Only a JSON-aware parser recovers the full argument; the call's real end is the second <|tool_call_end|>."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
fail kimi/k26-truncated-inside-arguments expected_error, stream_equals_nonstream, arguments_json, arguments_schema
Checks that did not pass for kimi/k26-truncated-inside-arguments
CheckStrategyResultDetail
expected_errornonstream failreturned 1 tool call(s) ['get_weather'] for max_tokens hit inside the argument JSON; the call never closes.
expected_errorone failreturned 1 tool call(s) ['get_weather'] for max_tokens hit inside the argument JSON; the call never closes.
expected_errorspecial failreturned 1 tool call(s) ['get_weather'] for max_tokens hit inside the argument JSON; the call never closes.
expected_errortoken failreturned 1 tool call(s) ['get_weather'] for max_tokens hit inside the argument JSON; the call never closes.
expected_errorrand:1:8 failreturned 1 tool call(s) ['get_weather'] for max_tokens hit inside the argument JSON; the call never closes.
expected_errorrand:2:8 failreturned 1 tool call(s) ['get_weather'] for max_tokens hit inside the argument JSON; the call never closes.
expected_errorrand:3:8 failreturned 1 tool call(s) ['get_weather'] for max_tokens hit inside the argument JSON; the call never closes.
expected_errorrand:4:8 failreturned 1 tool call(s) ['get_weather'] for max_tokens hit inside the argument JSON; the call never closes.
expected_errorrand:5:8 failreturned 1 tool call(s) ['get_weather'] for max_tokens hit inside the argument JSON; the call never closes.
stream_equals_nonstreamone failtool_calls[0].arguments: nonstream '{"city": "Madrid", "unit":', got ' {"city": "Madrid", "unit":'
stream_equals_nonstreamspecial failtool_calls[0].arguments: nonstream '{"city": "Madrid", "unit":', got ' {"city": "Madrid", "unit":'
stream_equals_nonstreamtoken failtool_calls[0].arguments: nonstream '{"city": "Madrid", "unit":', got ' {"city": "Madrid", "unit":'
stream_equals_nonstreamrand:1:8 failtool_calls[0].arguments: nonstream '{"city": "Madrid", "unit":', got ' {"city": "Madrid", "unit":'
stream_equals_nonstreamrand:2:8 failtool_calls[0].arguments: nonstream '{"city": "Madrid", "unit":', got ' {"city": "Madrid", "unit":'
stream_equals_nonstreamrand:3:8 failtool_calls[0].arguments: nonstream '{"city": "Madrid", "unit":', got ' {"city": "Madrid", "unit":'
stream_equals_nonstreamrand:4:8 failtool_calls[0].arguments: nonstream '{"city": "Madrid", "unit":', got ' {"city": "Madrid", "unit":'
stream_equals_nonstreamrand:5:8 failtool_calls[0].arguments: nonstream '{"city": "Madrid", "unit":', got ' {"city": "Madrid", "unit":'
arguments_jsonnonstream fail[0] get_weather: arguments are not valid JSON text ('{"city": "Madrid", "unit":': Expecting value: line 1 column 27 (char 26))
arguments_jsonone fail[0] get_weather: arguments are not valid JSON text (' {"city": "Madrid", "unit":': Expecting value: line 1 column 28 (char 27))
arguments_jsonspecial fail[0] get_weather: arguments are not valid JSON text (' {"city": "Madrid", "unit":': Expecting value: line 1 column 28 (char 27))
arguments_jsontoken fail[0] get_weather: arguments are not valid JSON text (' {"city": "Madrid", "unit":': Expecting value: line 1 column 28 (char 27))
arguments_jsonrand:1:8 fail[0] get_weather: arguments are not valid JSON text (' {"city": "Madrid", "unit":': Expecting value: line 1 column 28 (char 27))
arguments_jsonrand:2:8 fail[0] get_weather: arguments are not valid JSON text (' {"city": "Madrid", "unit":': Expecting value: line 1 column 28 (char 27))
arguments_jsonrand:3:8 fail[0] get_weather: arguments are not valid JSON text (' {"city": "Madrid", "unit":': Expecting value: line 1 column 28 (char 27))
arguments_jsonrand:4:8 fail[0] get_weather: arguments are not valid JSON text (' {"city": "Madrid", "unit":': Expecting value: line 1 column 28 (char 27))
arguments_jsonrand:5:8 fail[0] get_weather: arguments are not valid JSON text (' {"city": "Madrid", "unit":': Expecting value: line 1 column 28 (char 27))
arguments_schemanonstream fail[0] get_weather: arguments are not a JSON object; not validated
arguments_schemaone fail[0] get_weather: arguments are not a JSON object; not validated
arguments_schemaspecial fail[0] get_weather: arguments are not a JSON object; not validated
arguments_schematoken fail[0] get_weather: arguments are not a JSON object; not validated
arguments_schemarand:1:8 fail[0] get_weather: arguments are not a JSON object; not validated
arguments_schemarand:2:8 fail[0] get_weather: arguments are not a JSON object; not validated
arguments_schemarand:3:8 fail[0] get_weather: arguments are not a JSON object; not validated
arguments_schemarand:4:8 fail[0] get_weather: arguments are not a JSON object; not validated
arguments_schemarand:5:8 fail[0] get_weather: arguments are not a JSON object; not validated

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/truncated.jsonl --id kimi/k26-truncated-inside-arguments --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 1 of fixtures/kimi/truncated.jsonl.

Observed

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream

{
  "content": null,
  "reasoning_content": null,
  "tool_calls": [
    {
      "arguments": {
        "<arguments_raw, not valid JSON>": "{\"city\": \"Madrid\", \"unit\":"
      },
      "name": "get_weather"
    }
  ]
}

Strategies: one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

{
  "content": null,
  "reasoning_content": null,
  "tool_calls": [
    {
      "arguments": {
        "<arguments_raw, not valid JSON>": " {\"city\": \"Madrid\", \"unit\":"
      },
      "name": "get_weather"
    }
  ]
}

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: truncated, x-kimi-k2.

Expected graceful failure: max_tokens hit inside the argument JSON; the call never closes. (accept: no_tool_calls, content_passthrough, exception).

Raw output

<|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{"city": "Madrid", "unit":
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-truncated-inside-arguments", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "<|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{\"city\": \"Madrid\", \"unit\":", "output_token_ids": [163595, 163597, 41937, 1150, 21055, 2800, 25, 15, 163598, 8264, 37666, 1289, 414, 44, 12708, 338, 665, 414, 8175, 1289], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think></think>", "thinking": false, "expected_error": {"reason": "max_tokens hit inside the argument JSON; the call never closes.", "accept": ["no_tool_calls", "content_passthrough", "exception"]}, "tags": ["truncated", "x-kimi-k2"], "notes": "Token prefix of kimi/k26-thinking-disabled-call."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": false,
    "thinking": false
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think></think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": " tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think></think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
fail kimi/k2i-vllm-content-after-tool-section expected_match
Checks that did not pass for kimi/k2i-vllm-content-after-tool-section
CheckStrategyResultDetail
expected_matchnonstream failcontent: expected 'Before. After tools.', got ' Before. '
expected_matchone failcontent: expected 'Before. After tools.', got ' Before. '
expected_matchspecial failcontent: expected 'Before. After tools.', got ' Before. '
expected_matchtoken failcontent: expected 'Before. After tools.', got ' Before. '
expected_matchrand:1:8 failcontent: expected 'Before. After tools.', got ' Before. '
expected_matchrand:2:8 failcontent: expected 'Before. After tools.', got ' Before. '
expected_matchrand:3:8 failcontent: expected 'Before. After tools.', got ' Before. '
expected_matchrand:4:8 failcontent: expected 'Before. After tools.', got ' Before. '
expected_matchrand:5:8 failcontent: expected 'Before. After tools.', got ' Before. '

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/imported.jsonl --id kimi/k2i-vllm-content-after-tool-section --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 7 of fixtures/kimi/imported.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,4 +1,4 @@
 {
-  "content": "Before.  After tools.",
+  "content": " Before. ",
   "reasoning_content": null,
   "tool_calls": [

Fixture

Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L435-L458. Tags: single-call, text-before-call, text-after-call, x-policy, x-kimi-k2.

Raw output

Before. <|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0 <|tool_call_argument_begin|>{"city": "Tokyo"} <|tool_call_end|><|tool_calls_section_end|> After tools.

Expected parse

{
  "content": "Before.  After tools.",
  "reasoning_content": null,
  "tool_calls": [
    {
      "arguments": {
        "city": "Tokyo"
      },
      "name": "get_weather"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k2i-vllm-content-after-tool-section", "family": "kimi", "models": ["moonshotai/Kimi-K2-Instruct-0905"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L435-L458", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "generator": "scripts/fixtures/kimi/imported.py", "attribution": "Copyright contributors to the vLLM project (Apache-2.0)"}, "tools": [{"type": "function", "function": {"name": "get_weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}}}}], "raw_output": "Before. <|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0 <|tool_call_argument_begin|>{\"city\": \"Tokyo\"} <|tool_call_end|><|tool_calls_section_end|> After tools.", "output_token_ids": [13295, 13, 220, 163595, 163597, 41937, 1150, 21055, 2800, 25, 15, 220, 163598, 8264, 37666, 1289, 414, 39818, 18009, 16934, 220, 163599, 163596, 6671, 7697, 13], "tokenizer": {"repo": "moonshotai/Kimi-K2-Instruct-0905", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "mode": "hf"}, "expected": {"content": "Before.  After tools.", "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Tokyo"}}]}, "tags": ["single-call", "text-before-call", "text-after-call", "x-policy", "x-kimi-k2"], "notes": "The vLLM test exercises the parser without a tools list; the tool schemas here are minimal stand-ins. The deltas of the streaming test, concatenated. vLLM's test asserts the trailing text is DROPPED; this fixture expects it kept, because text outside the tool-calls section is ordinary content and dropping it loses model output. Content is the text before and after the section, concatenated verbatim (spec/README.md, 'Content around tool calls'). Tagged x-policy: the expected value encodes that spec rule, which neither the Kimi format nor the cited test fixes, so the matrix can show it apart from format conformance."}
Parser configuration
{
  "chat_template_kwargs": {},
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2-Instruct-0905",
  "model_rule": "Kimi-K2-Instruct",
  "model_type": "kimi_k2",
  "parser_source": "Kimi-K2-Instruct model card: non-thinking; --tool-call-parser kimi_k2",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "middle|>Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|>",
  "reasoning_parser": null,
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2-Instruct-0905",
    "requested_mode": "auto",
    "resolved_revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_hyphen_Instruct_hyphen_0905.ac6c49f04883bd0a0598b790693a72061c676629.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
fail kimi/k3-bug-response-only-completion expected_match, stream_equals_nonstream, no_leakage
Checks that did not pass for kimi/k3-bug-response-only-completion
CheckStrategyResultDetail
expected_matchone failcontent: expected 'Hello world', got None; reasoning_content: expected None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
expected_matchspecial failcontent: expected 'Hello world', got None; reasoning_content: expected None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
expected_matchtoken failcontent: expected 'Hello world', got None; reasoning_content: expected None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
expected_matchrand:1:8 failcontent: expected 'Hello world', got None; reasoning_content: expected None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
expected_matchrand:2:8 failcontent: expected 'Hello world', got None; reasoning_content: expected None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
expected_matchrand:3:8 failcontent: expected 'Hello world', got None; reasoning_content: expected None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
expected_matchrand:4:8 failcontent: expected 'Hello world', got None; reasoning_content: expected None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
expected_matchrand:5:8 failcontent: expected 'Hello world', got None; reasoning_content: expected None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
stream_equals_nonstreamone failcontent: nonstream 'Hello world', got None; reasoning_content: nonstream None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
stream_equals_nonstreamspecial failcontent: nonstream 'Hello world', got None; reasoning_content: nonstream None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
stream_equals_nonstreamtoken failcontent: nonstream 'Hello world', got None; reasoning_content: nonstream None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
stream_equals_nonstreamrand:1:8 failcontent: nonstream 'Hello world', got None; reasoning_content: nonstream None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
stream_equals_nonstreamrand:2:8 failcontent: nonstream 'Hello world', got None; reasoning_content: nonstream None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
stream_equals_nonstreamrand:3:8 failcontent: nonstream 'Hello world', got None; reasoning_content: nonstream None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
stream_equals_nonstreamrand:4:8 failcontent: nonstream 'Hello world', got None; reasoning_content: nonstream None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
stream_equals_nonstreamrand:5:8 failcontent: nonstream 'Hello world', got None; reasoning_content: nonstream None, got '<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>'
no_leakageone failreasoning_content contains '<|open|>'; reasoning_content contains '<|close|>'; reasoning_content contains '<|sep|>'
no_leakagespecial failreasoning_content contains '<|open|>'; reasoning_content contains '<|close|>'; reasoning_content contains '<|sep|>'
no_leakagetoken failreasoning_content contains '<|open|>'; reasoning_content contains '<|close|>'; reasoning_content contains '<|sep|>'
no_leakagerand:1:8 failreasoning_content contains '<|open|>'; reasoning_content contains '<|close|>'; reasoning_content contains '<|sep|>'
no_leakagerand:2:8 failreasoning_content contains '<|open|>'; reasoning_content contains '<|close|>'; reasoning_content contains '<|sep|>'
no_leakagerand:3:8 failreasoning_content contains '<|open|>'; reasoning_content contains '<|close|>'; reasoning_content contains '<|sep|>'
no_leakagerand:4:8 failreasoning_content contains '<|open|>'; reasoning_content contains '<|close|>'; reasoning_content contains '<|sep|>'
no_leakagerand:5:8 failreasoning_content contains '<|open|>'; reasoning_content contains '<|close|>'; reasoning_content contains '<|sep|>'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/imported.jsonl --id kimi/k3-bug-response-only-completion --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 13 of fixtures/kimi/imported.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
-  "content": "Hello world",
-  "reasoning_content": null,
+  "content": null,
+  "reasoning_content": "<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>",
   "tool_calls": []
 }

Strategies: nonstream

Matches the expected parse.

{
  "content": "Hello world",
  "reasoning_content": null,
  "tool_calls": []
}

Fixture

Provenance: bug_report, https://github.com/vllm-project/vllm/issues/57688. Tags: no-call, regression, x-skip-think-channel, x-kimi-k3.

Raw output

<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>

Expected parse

{
  "content": "Hello world",
  "reasoning_content": null,
  "tool_calls": []
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k3-bug-response-only-completion", "family": "kimi", "models": ["moonshotai/Kimi-K3"], "spec_version": "0.1", "provenance": {"kind": "bug_report", "source_url": "https://github.com/vllm-project/vllm/issues/57688", "revision": "issue opened 2026-09-19", "license": "NOASSERTION", "generator": "scripts/fixtures/kimi/imported.py", "attribution": "Shape A of the issue's probe, written there in shorthand as '◁response▷Hello world◁/response▷◁/message▷'."}, "tools": [{"type": "function", "function": {"name": "calc", "parameters": {"type": "object", "properties": {}}}}], "raw_output": "<|open|>response<|sep|>Hello world<|close|>response<|sep|><|close|>message<|sep|>", "output_token_ids": [163587, 12092, 163589, 19180, 2695, 163588, 12092, 163589, 163588, 2778, 163589], "tokenizer": {"repo": "moonshotai/Kimi-K3", "revision": "f831ab66814297da540d832a5235f8e904f29d06", "mode": "hf"}, "thinking": true, "expected": {"content": "Hello world", "reasoning_content": null, "tool_calls": []}, "tags": ["no-call", "regression", "x-skip-think-channel", "x-kimi-k3"], "notes": "The issue abbreviates <|open|>X<|sep|> as ◁X▷ and <|close|>X<|sep|> as ◁/X▷; this raw_output spells the markers out. The model skipped the think channel and answered in the response channel, so everything is content (the non-streaming vLLM result the issue treats as correct)."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|open|>message role=\"assistant\"<|sep|><|open|>think<|sep|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K3",
  "model_rule": "Kimi-K3",
  "model_type": "kimi_k3",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "<|sep|><|end_of_msg|><|open|>message role=\"assistant\"<|sep|><|open|>think<|sep|>",
  "reasoning_parser": "kimi_k3",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": null,
    "source": "vLLM tokenizer_mode=kimi_k3 (tokenizer.apply_chat_template, repo encoder)"
  },
  "tokenizer": {
    "mode": "kimi_k3",
    "repo": "moonshotai/Kimi-K3",
    "requested_mode": "auto",
    "resolved_revision": "f831ab66814297da540d832a5235f8e904f29d06",
    "revision": "f831ab66814297da540d832a5235f8e904f29d06",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K3.f831ab66814297da540d832a5235f8e904f29d06.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k3",
  "units_source": "fixture.output_token_ids"
}
fail kimi/k3-bug-truncated-reasoning-recorded expected_match, stream_equals_nonstream
Checks that did not pass for kimi/k3-bug-truncated-reasoning-recorded
CheckStrategyResultDetail
expected_matchnonstream failcontent: expected None, got 'The user asks to reason step by step about a math problem. I only need '; reasoning_content: expected 'The user asks to reason step by step about a math problem. I only need ', got None
stream_equals_nonstreamone failcontent: nonstream 'The user asks to reason step by step about a math problem. I only need ', got None; reasoning_content: nonstream None, got 'The user asks to reason step by step about a math problem. I only need '
stream_equals_nonstreamspecial failcontent: nonstream 'The user asks to reason step by step about a math problem. I only need ', got None; reasoning_content: nonstream None, got 'The user asks to reason step by step about a math problem. I only need '
stream_equals_nonstreamtoken failcontent: nonstream 'The user asks to reason step by step about a math problem. I only need ', got None; reasoning_content: nonstream None, got 'The user asks to reason step by step about a math problem. I only need '
stream_equals_nonstreamrand:1:8 failcontent: nonstream 'The user asks to reason step by step about a math problem. I only need ', got None; reasoning_content: nonstream None, got 'The user asks to reason step by step about a math problem. I only need '
stream_equals_nonstreamrand:2:8 failcontent: nonstream 'The user asks to reason step by step about a math problem. I only need ', got None; reasoning_content: nonstream None, got 'The user asks to reason step by step about a math problem. I only need '
stream_equals_nonstreamrand:3:8 failcontent: nonstream 'The user asks to reason step by step about a math problem. I only need ', got None; reasoning_content: nonstream None, got 'The user asks to reason step by step about a math problem. I only need '
stream_equals_nonstreamrand:4:8 failcontent: nonstream 'The user asks to reason step by step about a math problem. I only need ', got None; reasoning_content: nonstream None, got 'The user asks to reason step by step about a math problem. I only need '
stream_equals_nonstreamrand:5:8 failcontent: nonstream 'The user asks to reason step by step about a math problem. I only need ', got None; reasoning_content: nonstream None, got 'The user asks to reason step by step about a math problem. I only need '

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/imported.jsonl --id kimi/k3-bug-truncated-reasoning-recorded --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 12 of fixtures/kimi/imported.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
-  "content": null,
-  "reasoning_content": "The user asks to reason step by step about a math problem. I only need ",
+  "content": "The user asks to reason step by step about a math problem. I only need ",
+  "reasoning_content": null,
   "tool_calls": []
 }

Strategies: one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

Matches the expected parse.

{
  "content": null,
  "reasoning_content": "The user asks to reason step by step about a math problem. I only need ",
  "tool_calls": []
}

Fixture

Provenance: bug_report, https://github.com/vllm-project/vllm/issues/57353. Tags: truncated, reasoning, regression, x-think-no-open-tag, x-kimi-k3.

Raw output

The user asks to reason step by step about a math problem. I only need 

Expected parse

{
  "content": null,
  "reasoning_content": "The user asks to reason step by step about a math problem. I only need ",
  "tool_calls": []
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k3-bug-truncated-reasoning-recorded", "family": "kimi", "models": ["moonshotai/Kimi-K3"], "spec_version": "0.1", "provenance": {"kind": "bug_report", "source_url": "https://github.com/vllm-project/vllm/issues/57353", "revision": "issue opened 2026-09-17", "license": "NOASSERTION", "generator": "scripts/fixtures/kimi/imported.py", "attribution": "Quoted from the issue's repro output (Kimi K3, max_tokens=10, no tools)."}, "tools": [], "raw_output": "The user asks to reason step by step about a math problem. I only need ", "output_token_ids": [1008, 2742, 32155, 308, 4224, 5367, 673, 5367, 1215, 261, 15601, 5264, 13, 374, 1609, 1362, 220], "tokenizer": {"repo": "moonshotai/Kimi-K3", "revision": "f831ab66814297da540d832a5235f8e904f29d06", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "The user asks to reason step by step about a math problem. I only need ", "tool_calls": []}, "tags": ["truncated", "reasoning", "regression", "x-think-no-open-tag", "x-kimi-k3"], "notes": "A real K3 generation cut by max_tokens inside the think channel. vLLM's non-streaming path returned it as content; with thinking enabled the template opens the think channel, so it is reasoning."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|open|>message role=\"assistant\"<|sep|><|open|>think<|sep|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K3",
  "model_rule": "Kimi-K3",
  "model_type": "kimi_k3",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "<|sep|><|end_of_msg|><|open|>message role=\"assistant\"<|sep|><|open|>think<|sep|>",
  "reasoning_parser": "kimi_k3",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": null,
    "source": "vLLM tokenizer_mode=kimi_k3 (tokenizer.apply_chat_template, repo encoder)"
  },
  "tokenizer": {
    "mode": "kimi_k3",
    "repo": "moonshotai/Kimi-K3",
    "requested_mode": "auto",
    "resolved_revision": "f831ab66814297da540d832a5235f8e904f29d06",
    "revision": "f831ab66814297da540d832a5235f8e904f29d06",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K3.f831ab66814297da540d832a5235f8e904f29d06.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k3",
  "units_source": "fixture.output_token_ids"
}
fail kimi/k3-control-marker-text-in-value expected_match
Checks that did not pass for kimi/k3-control-marker-text-in-value
CheckStrategyResultDetail
expected_matchnonstream failtool_calls[0].arguments: expected '{"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}', got '{"path": "x.txt", "content": ""}'
expected_matchone failtool_calls[0].arguments: expected '{"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}', got '{"path": "x.txt", "content": ""}'
expected_matchspecial failtool_calls[0].arguments: expected '{"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}', got '{"path": "x.txt", "content": ""}'
expected_matchtoken failtool_calls[0].arguments: expected '{"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}', got '{"path": "x.txt", "content": ""}'
expected_matchrand:1:8 failtool_calls[0].arguments: expected '{"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}', got '{"path": "x.txt", "content": ""}'
expected_matchrand:2:8 failtool_calls[0].arguments: expected '{"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}', got '{"path": "x.txt", "content": ""}'
expected_matchrand:3:8 failtool_calls[0].arguments: expected '{"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}', got '{"path": "x.txt", "content": ""}'
expected_matchrand:4:8 failtool_calls[0].arguments: expected '{"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}', got '{"path": "x.txt", "content": ""}'
expected_matchrand:5:8 failtool_calls[0].arguments: expected '{"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}', got '{"path": "x.txt", "content": ""}'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k3-render.jsonl --id kimi/k3-control-marker-text-in-value --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 9 of fixtures/kimi/k3-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -5,5 +5,5 @@
     {
       "arguments": {
-        "content": "<|close|>argument<|sep|> is how args end",
+        "content": "",
         "path": "x.txt"
       },

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K3/blob/f831ab66814297da540d832a5235f8e904f29d06/encoding_k3.py. Tags: single-call, marker-in-arguments, reasoning, x-control-token-vs-text, x-think-no-open-tag, x-kimi-k3.

Raw output

Write the literal XTML marker text.<|close|>think<|sep|><|open|>response<|sep|><|close|>response<|sep|><|open|>tools<|sep|><|open|>call tool="write_file" index="1"<|sep|><|open|>argument key="path" type="string"<|sep|>x.txt<|close|>argument<|sep|><|open|>argument key="content" type="string"<|sep|><|close|>argument<|sep|> is how args end<|close|>argument<|sep|><|close|>call<|sep|><|close|>tools<|sep|><|close|>message<|sep|>

Expected parse

{
  "content": null,
  "reasoning_content": "Write the literal XTML marker text.",
  "tool_calls": [
    {
      "arguments": {
        "content": "<|close|>argument<|sep|> is how args end",
        "path": "x.txt"
      },
      "name": "write_file"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k3-control-marker-text-in-value", "family": "kimi", "models": ["moonshotai/Kimi-K3"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K3/blob/f831ab66814297da540d832a5235f8e904f29d06/encoding_k3.py", "revision": "f831ab66814297da540d832a5235f8e904f29d06", "license": "LicenseRef-kimi-k3", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "49ff03305fdc4be26867972788d36150b67f8a9e852e62bb7959d87482223676"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}, {"type": "function", "function": {"name": "save_answer", "description": "Store an answer under odd-looking keys.", "parameters": {"type": "object", "properties": {"q&a": {"type": "string"}, "say \"hi\"": {"type": "string"}}}}}], "raw_output": "Write the literal XTML marker text.<|close|>think<|sep|><|open|>response<|sep|><|close|>response<|sep|><|open|>tools<|sep|><|open|>call tool=\"write_file\" index=\"1\"<|sep|><|open|>argument key=\"path\" type=\"string\"<|sep|>x.txt<|close|>argument<|sep|><|open|>argument key=\"content\" type=\"string\"<|sep|><|close|>argument<|sep|> is how args end<|close|>argument<|sep|><|close|>call<|sep|><|close|>tools<|sep|><|close|>message<|sep|>", "output_token_ids": [9570, 276, 34459, 115921, 4920, 24894, 2913, 13, 163588, 39964, 163589, 163587, 12092, 163589, 163588, 12092, 163589, 163587, 25385, 163589, 163587, 10257, 4453, 878, 8124, 6101, 1, 4002, 878, 16, 1, 163589, 163587, 47185, 2355, 878, 4953, 1, 1798, 878, 2033, 1, 163589, 87, 8842, 163588, 47185, 163589, 163587, 47185, 2355, 878, 4204, 1, 1798, 878, 2033, 1, 163589, 27, 91, 10794, 91, 29, 47185, 27, 91, 40433, 91, 29, 387, 1632, 5924, 1565, 163588, 47185, 163589, 163588, 10257, 163589, 163588, 25385, 163589, 163588, 2778, 163589], "tokenizer": {"repo": "moonshotai/Kimi-K3", "revision": "f831ab66814297da540d832a5235f8e904f29d06", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Write the literal XTML marker text.", "tool_calls": [{"name": "write_file", "arguments": {"path": "x.txt", "content": "<|close|>argument<|sep|> is how args end"}}]}, "tags": ["single-call", "marker-in-arguments", "reasoning", "x-control-token-vs-text", "x-think-no-open-tag", "x-kimi-k3"], "notes": "encoding_k3 encodes argument text with allow_special=False, so the value's <|close|>/<|sep|> are ORDINARY tokens while the real markers are control tokens. The text is identical; only output_token_ids tell them apart."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|open|>message role=\"assistant\"<|sep|><|open|>think<|sep|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K3",
  "model_rule": "Kimi-K3",
  "model_type": "kimi_k3",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "<|sep|><|end_of_msg|><|open|>message role=\"assistant\"<|sep|><|open|>think<|sep|>",
  "reasoning_parser": "kimi_k3",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": null,
    "source": "vLLM tokenizer_mode=kimi_k3 (tokenizer.apply_chat_template, repo encoder)"
  },
  "tokenizer": {
    "mode": "kimi_k3",
    "repo": "moonshotai/Kimi-K3",
    "requested_mode": "auto",
    "resolved_revision": "f831ab66814297da540d832a5235f8e904f29d06",
    "revision": "f831ab66814297da540d832a5235f8e904f29d06",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K3.f831ab66814297da540d832a5235f8e904f29d06.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k3",
  "units_source": "fixture.output_token_ids"
}
fail kimi/k3-truncated-in-reasoning expected_match, stream_equals_nonstream
Checks that did not pass for kimi/k3-truncated-in-reasoning
CheckStrategyResultDetail
expected_matchnonstream failcontent: expected None, got 'The user wants the weather in Paris'; reasoning_content: expected 'The user wants the weather in Paris', got None
stream_equals_nonstreamone failcontent: nonstream 'The user wants the weather in Paris', got None; reasoning_content: nonstream None, got 'The user wants the weather in Paris'
stream_equals_nonstreamspecial failcontent: nonstream 'The user wants the weather in Paris', got None; reasoning_content: nonstream None, got 'The user wants the weather in Paris'
stream_equals_nonstreamtoken failcontent: nonstream 'The user wants the weather in Paris', got None; reasoning_content: nonstream None, got 'The user wants the weather in Paris'
stream_equals_nonstreamrand:1:8 failcontent: nonstream 'The user wants the weather in Paris', got None; reasoning_content: nonstream None, got 'The user wants the weather in Paris'
stream_equals_nonstreamrand:2:8 failcontent: nonstream 'The user wants the weather in Paris', got None; reasoning_content: nonstream None, got 'The user wants the weather in Paris'
stream_equals_nonstreamrand:3:8 failcontent: nonstream 'The user wants the weather in Paris', got None; reasoning_content: nonstream None, got 'The user wants the weather in Paris'
stream_equals_nonstreamrand:4:8 failcontent: nonstream 'The user wants the weather in Paris', got None; reasoning_content: nonstream None, got 'The user wants the weather in Paris'
stream_equals_nonstreamrand:5:8 failcontent: nonstream 'The user wants the weather in Paris', got None; reasoning_content: nonstream None, got 'The user wants the weather in Paris'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/truncated.jsonl --id kimi/k3-truncated-in-reasoning --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 4 of fixtures/kimi/truncated.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
-  "content": null,
-  "reasoning_content": "The user wants the weather in Paris",
+  "content": "The user wants the weather in Paris",
+  "reasoning_content": null,
   "tool_calls": []
 }

Strategies: one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

Matches the expected parse.

{
  "content": null,
  "reasoning_content": "The user wants the weather in Paris",
  "tool_calls": []
}

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K3/blob/f831ab66814297da540d832a5235f8e904f29d06/encoding_k3.py. Tags: truncated, reasoning, x-think-no-open-tag, x-kimi-k3.

Raw output

The user wants the weather in Paris

Expected parse

{
  "content": null,
  "reasoning_content": "The user wants the weather in Paris",
  "tool_calls": []
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k3-truncated-in-reasoning", "family": "kimi", "models": ["moonshotai/Kimi-K3"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K3/blob/f831ab66814297da540d832a5235f8e904f29d06/encoding_k3.py", "revision": "f831ab66814297da540d832a5235f8e904f29d06", "license": "LicenseRef-kimi-k3", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "49ff03305fdc4be26867972788d36150b67f8a9e852e62bb7959d87482223676"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}, {"type": "function", "function": {"name": "save_answer", "description": "Store an answer under odd-looking keys.", "parameters": {"type": "object", "properties": {"q&a": {"type": "string"}, "say \"hi\"": {"type": "string"}}}}}], "raw_output": "The user wants the weather in Paris", "output_token_ids": [1008, 2742, 11333, 276, 10666, 306, 17374], "tokenizer": {"repo": "moonshotai/Kimi-K3", "revision": "f831ab66814297da540d832a5235f8e904f29d06", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "The user wants the weather in Paris", "tool_calls": []}, "tags": ["truncated", "reasoning", "x-think-no-open-tag", "x-kimi-k3"], "notes": "Token prefix of kimi/k3-single-call. The generation prompt opened the think channel, so the unterminated text is reasoning (see https://github.com/vllm-project/vllm/issues/57353 for K3)."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|open|>message role=\"assistant\"<|sep|><|open|>think<|sep|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K3",
  "model_rule": "Kimi-K3",
  "model_type": "kimi_k3",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "<|sep|><|end_of_msg|><|open|>message role=\"assistant\"<|sep|><|open|>think<|sep|>",
  "reasoning_parser": "kimi_k3",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": null,
    "source": "vLLM tokenizer_mode=kimi_k3 (tokenizer.apply_chat_template, repo encoder)"
  },
  "tokenizer": {
    "mode": "kimi_k3",
    "repo": "moonshotai/Kimi-K3",
    "requested_mode": "auto",
    "resolved_revision": "f831ab66814297da540d832a5235f8e904f29d06",
    "revision": "f831ab66814297da540d832a5235f8e904f29d06",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K3.f831ab66814297da540d832a5235f8e904f29d06.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k3",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-content-before-call expected_match
Checks that did not pass for kimi/k26-content-before-call
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you. '; reasoning_content (whitespace only): expected 'Live data needed.', got ' Live data needed.'
expected_matchone soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you. '; reasoning_content (whitespace only): expected 'Live data needed.', got ' Live data needed.'
expected_matchspecial soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you. '; reasoning_content (whitespace only): expected 'Live data needed.', got ' Live data needed.'
expected_matchtoken soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you. '; reasoning_content (whitespace only): expected 'Live data needed.', got ' Live data needed.'
expected_matchrand:1:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you. '; reasoning_content (whitespace only): expected 'Live data needed.', got ' Live data needed.'
expected_matchrand:2:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you. '; reasoning_content (whitespace only): expected 'Live data needed.', got ' Live data needed.'
expected_matchrand:3:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you. '; reasoning_content (whitespace only): expected 'Live data needed.', got ' Live data needed.'
expected_matchrand:4:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you. '; reasoning_content (whitespace only): expected 'Live data needed.', got ' Live data needed.'
expected_matchrand:5:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you. '; reasoning_content (whitespace only): expected 'Live data needed.', got ' Live data needed.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-content-before-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 4 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
-  "content": "Let me check that for you.",
-  "reasoning_content": "Live data needed.",
+  "content": " Let me check that for you. ",
+  "reasoning_content": " Live data needed.",
   "tool_calls": [
     {

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: single-call, text-before-call, reasoning, x-think-no-open-tag, x-kimi-k2.

Raw output

Live data needed.</think>Let me check that for you.<|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{"city": "Berlin"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": "Let me check that for you.",
  "reasoning_content": "Live data needed.",
  "tool_calls": [
    {
      "arguments": {
        "city": "Berlin"
      },
      "name": "get_weather"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-content-before-call", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Live data needed.</think>Let me check that for you.<|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{\"city\": \"Berlin\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [25730, 1544, 5593, 13, 163607, 9413, 1019, 2598, 473, 395, 398, 13, 163595, 163597, 41937, 1150, 21055, 2800, 25, 15, 163598, 8264, 37666, 1289, 414, 67347, 4797, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": "Let me check that for you.", "reasoning_content": "Live data needed.", "tool_calls": [{"name": "get_weather", "arguments": {"city": "Berlin"}}]}, "tags": ["single-call", "text-before-call", "reasoning", "x-think-no-open-tag", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-empty-arguments expected_match
Checks that did not pass for kimi/k26-empty-arguments
CheckStrategyResultDetail
expected_matchnonstream soft passreasoning_content (whitespace only): expected 'Just get the time.', got ' Just get the time.'
expected_matchone soft passreasoning_content (whitespace only): expected 'Just get the time.', got ' Just get the time.'
expected_matchspecial soft passreasoning_content (whitespace only): expected 'Just get the time.', got ' Just get the time.'
expected_matchtoken soft passreasoning_content (whitespace only): expected 'Just get the time.', got ' Just get the time.'
expected_matchrand:1:8 soft passreasoning_content (whitespace only): expected 'Just get the time.', got ' Just get the time.'
expected_matchrand:2:8 soft passreasoning_content (whitespace only): expected 'Just get the time.', got ' Just get the time.'
expected_matchrand:3:8 soft passreasoning_content (whitespace only): expected 'Just get the time.', got ' Just get the time.'
expected_matchrand:4:8 soft passreasoning_content (whitespace only): expected 'Just get the time.', got ' Just get the time.'
expected_matchrand:5:8 soft passreasoning_content (whitespace only): expected 'Just get the time.', got ' Just get the time.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-empty-arguments --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 8 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
   "content": null,
-  "reasoning_content": "Just get the time.",
+  "reasoning_content": " Just get the time.",
   "tool_calls": [
     {

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: single-call, empty-arguments, reasoning, x-think-no-open-tag, x-kimi-k2.

Raw output

Just get the time.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.get_time:0<|tool_call_argument_begin|>{}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "Just get the time.",
  "tool_calls": [
    {
      "arguments": {},
      "name": "get_time"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-empty-arguments", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Just get the time.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.get_time:0<|tool_call_argument_begin|>{}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [14752, 922, 276, 1169, 13, 163607, 163595, 163597, 41937, 1150, 6618, 25, 15, 163598, 13071, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Just get the time.", "tool_calls": [{"name": "get_time", "arguments": {}}]}, "tags": ["single-call", "empty-arguments", "reasoning", "x-think-no-open-tag", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-multi-turn-second-call expected_match
Checks that did not pass for kimi/k26-multi-turn-second-call
CheckStrategyResultDetail
expected_matchnonstream soft passreasoning_content (whitespace only): expected 'Now convert it.', got ' Now convert it.'
expected_matchone soft passreasoning_content (whitespace only): expected 'Now convert it.', got ' Now convert it.'
expected_matchspecial soft passreasoning_content (whitespace only): expected 'Now convert it.', got ' Now convert it.'
expected_matchtoken soft passreasoning_content (whitespace only): expected 'Now convert it.', got ' Now convert it.'
expected_matchrand:1:8 soft passreasoning_content (whitespace only): expected 'Now convert it.', got ' Now convert it.'
expected_matchrand:2:8 soft passreasoning_content (whitespace only): expected 'Now convert it.', got ' Now convert it.'
expected_matchrand:3:8 soft passreasoning_content (whitespace only): expected 'Now convert it.', got ' Now convert it.'
expected_matchrand:4:8 soft passreasoning_content (whitespace only): expected 'Now convert it.', got ' Now convert it.'
expected_matchrand:5:8 soft passreasoning_content (whitespace only): expected 'Now convert it.', got ' Now convert it.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-multi-turn-second-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 14 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
   "content": null,
-  "reasoning_content": "Now convert it.",
+  "reasoning_content": " Now convert it.",
   "tool_calls": [
     {

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: single-call, multi-turn, reasoning, x-global-idx, x-think-no-open-tag, x-kimi-k2.

Raw output

Now convert it.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.convert_units:1<|tool_call_argument_begin|>{"value": 21.5, "from_unit": "celsius", "to_unit": "fahrenheit"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "Now convert it.",
  "tool_calls": [
    {
      "arguments": {
        "from_unit": "celsius",
        "to_unit": "fahrenheit",
        "value": 21.5
      },
      "name": "convert_units"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-multi-turn-second-call", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Now convert it.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.convert_units:1<|tool_call_argument_begin|>{\"value\": 21.5, \"from_unit\": \"celsius\", \"to_unit\": \"fahrenheit\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [10048, 9101, 483, 13, 163607, 163595, 163597, 41937, 42406, 51629, 25, 16, 163598, 8264, 2035, 1289, 220, 2714, 13, 20, 11, 414, 3701, 26505, 1289, 414, 78841, 14211, 665, 414, 1753, 26505, 1289, 414, 69, 101942, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Now convert it.", "tool_calls": [{"name": "convert_units", "arguments": {"value": 21.5, "from_unit": "celsius", "to_unit": "fahrenheit"}}]}, "tags": ["single-call", "multi-turn", "reasoning", "x-global-idx", "x-think-no-open-tag", "x-kimi-k2"], "notes": "K2's idx is a global counter, so the second turn's call is functions.convert_units:1. K3's index restarts at 1 in every message."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-nested-json expected_match
Checks that did not pass for kimi/k26-nested-json
CheckStrategyResultDetail
expected_matchnonstream soft passreasoning_content (whitespace only): expected 'Create the event with a structured location.', got ' Create the event with a structured location.'
expected_matchone soft passreasoning_content (whitespace only): expected 'Create the event with a structured location.', got ' Create the event with a structured location.'
expected_matchspecial soft passreasoning_content (whitespace only): expected 'Create the event with a structured location.', got ' Create the event with a structured location.'
expected_matchtoken soft passreasoning_content (whitespace only): expected 'Create the event with a structured location.', got ' Create the event with a structured location.'
expected_matchrand:1:8 soft passreasoning_content (whitespace only): expected 'Create the event with a structured location.', got ' Create the event with a structured location.'
expected_matchrand:2:8 soft passreasoning_content (whitespace only): expected 'Create the event with a structured location.', got ' Create the event with a structured location.'
expected_matchrand:3:8 soft passreasoning_content (whitespace only): expected 'Create the event with a structured location.', got ' Create the event with a structured location.'
expected_matchrand:4:8 soft passreasoning_content (whitespace only): expected 'Create the event with a structured location.', got ' Create the event with a structured location.'
expected_matchrand:5:8 soft passreasoning_content (whitespace only): expected 'Create the event with a structured location.', got ' Create the event with a structured location.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-nested-json --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 6 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
   "content": null,
-  "reasoning_content": "Create the event with a structured location.",
+  "reasoning_content": " Create the event with a structured location.",
   "tool_calls": [
     {

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: single-call, nested-json, numeric-arguments, reasoning, x-think-no-open-tag, x-kimi-k2.

Raw output

Create the event with a structured location.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.create_event:0<|tool_call_argument_begin|>{"title": "Offsite", "attendees": ["ana@example.com", "bo@example.com"], "location": {"name": "HQ", "geo": {"lat": 47.3769, "lon": 8.5417}, "floors": [1, 2]}}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "Create the event with a structured location.",
  "tool_calls": [
    {
      "arguments": {
        "attendees": [
          "ana@example.com",
          "bo@example.com"
        ],
        "location": {
          "floors": [
            1,
            2
          ],
          "geo": {
            "lat": 47.3769,
            "lon": 8.5417
          },
          "name": "HQ"
        },
        "title": "Offsite"
      },
      "name": "create_event"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-nested-json", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Create the event with a structured location.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.create_event:0<|tool_call_argument_begin|>{\"title\": \"Offsite\", \"attendees\": [\"ana@example.com\", \"bo@example.com\"], \"location\": {\"name\": \"HQ\", \"geo\": {\"lat\": 47.3769, \"lon\": 8.5417}, \"floors\": [1, 2]}}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [6431, 276, 2940, 472, 261, 36068, 5802, 13, 163607, 163595, 163597, 41937, 6000, 12411, 25, 15, 163598, 8264, 6621, 1289, 414, 5329, 19535, 665, 414, 2534, 105194, 1289, 8681, 5060, 31, 17480, 1304, 665, 414, 6917, 31, 17480, 1304, 17326, 414, 5791, 1289, 9392, 1152, 1289, 414, 73028, 665, 414, 43957, 1289, 9392, 18293, 1289, 220, 4934, 13, 40278, 24, 11, 414, 29087, 1289, 220, 23, 13, 43150, 22, 3589, 414, 147411, 1118, 1289, 793, 16, 11, 220, 17, 60, 5375, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Create the event with a structured location.", "tool_calls": [{"name": "create_event", "arguments": {"title": "Offsite", "attendees": ["ana@example.com", "bo@example.com"], "location": {"name": "HQ", "geo": {"lat": 47.3769, "lon": 8.5417}, "floors": [1, 2]}}}]}, "tags": ["single-call", "nested-json", "numeric-arguments", "reasoning", "x-think-no-open-tag", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-no-call expected_match
Checks that did not pass for kimi/k26-no-call
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'; reasoning_content (whitespace only): expected 'A simple fact; no tool needed.', got ' A simple fact; no tool needed.'
expected_matchone soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'; reasoning_content (whitespace only): expected 'A simple fact; no tool needed.', got ' A simple fact; no tool needed.'
expected_matchspecial soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'; reasoning_content (whitespace only): expected 'A simple fact; no tool needed.', got ' A simple fact; no tool needed.'
expected_matchtoken soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'; reasoning_content (whitespace only): expected 'A simple fact; no tool needed.', got ' A simple fact; no tool needed.'
expected_matchrand:1:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'; reasoning_content (whitespace only): expected 'A simple fact; no tool needed.', got ' A simple fact; no tool needed.'
expected_matchrand:2:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'; reasoning_content (whitespace only): expected 'A simple fact; no tool needed.', got ' A simple fact; no tool needed.'
expected_matchrand:3:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'; reasoning_content (whitespace only): expected 'A simple fact; no tool needed.', got ' A simple fact; no tool needed.'
expected_matchrand:4:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'; reasoning_content (whitespace only): expected 'A simple fact; no tool needed.', got ' A simple fact; no tool needed.'
expected_matchrand:5:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'; reasoning_content (whitespace only): expected 'A simple fact; no tool needed.', got ' A simple fact; no tool needed.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-no-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 5 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
-  "content": "Paris is the capital of France.",
-  "reasoning_content": "A simple fact; no tool needed.",
+  "content": " Paris is the capital of France.",
+  "reasoning_content": " A simple fact; no tool needed.",
   "tool_calls": []
 }

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: no-call, reasoning, x-think-no-open-tag, x-kimi-k2.

Raw output

A simple fact; no tool needed.</think>Paris is the capital of France.

Expected parse

{
  "content": "Paris is the capital of France.",
  "reasoning_content": "A simple fact; no tool needed.",
  "tool_calls": []
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-no-call", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "A simple fact; no tool needed.</think>Paris is the capital of France.", "output_token_ids": [32, 5216, 3303, 26, 1495, 4453, 5593, 13, 163607, 113476, 387, 276, 10484, 318, 15383, 13], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": "Paris is the capital of France.", "reasoning_content": "A simple fact; no tool needed.", "tool_calls": []}, "tags": ["no-call", "reasoning", "x-think-no-open-tag", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-parallel-same-tool expected_match
Checks that did not pass for kimi/k26-parallel-same-tool
CheckStrategyResultDetail
expected_matchnonstream soft passreasoning_content (whitespace only): expected 'Two cities, two lookups.', got ' Two cities, two lookups.'
expected_matchone soft passreasoning_content (whitespace only): expected 'Two cities, two lookups.', got ' Two cities, two lookups.'
expected_matchspecial soft passreasoning_content (whitespace only): expected 'Two cities, two lookups.', got ' Two cities, two lookups.'
expected_matchtoken soft passreasoning_content (whitespace only): expected 'Two cities, two lookups.', got ' Two cities, two lookups.'
expected_matchrand:1:8 soft passreasoning_content (whitespace only): expected 'Two cities, two lookups.', got ' Two cities, two lookups.'
expected_matchrand:2:8 soft passreasoning_content (whitespace only): expected 'Two cities, two lookups.', got ' Two cities, two lookups.'
expected_matchrand:3:8 soft passreasoning_content (whitespace only): expected 'Two cities, two lookups.', got ' Two cities, two lookups.'
expected_matchrand:4:8 soft passreasoning_content (whitespace only): expected 'Two cities, two lookups.', got ' Two cities, two lookups.'
expected_matchrand:5:8 soft passreasoning_content (whitespace only): expected 'Two cities, two lookups.', got ' Two cities, two lookups.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-parallel-same-tool --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 2 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
   "content": null,
-  "reasoning_content": "Two cities, two lookups.",
+  "reasoning_content": " Two cities, two lookups.",
   "tool_calls": [
     {

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: parallel-calls, reasoning, x-global-idx, x-think-no-open-tag, x-kimi-k2.

Raw output

Two cities, two lookups.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{"city": "Paris"}<|tool_call_end|><|tool_call_begin|>functions.get_weather:1<|tool_call_argument_begin|>{"city": "Tokyo"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "Two cities, two lookups.",
  "tool_calls": [
    {
      "arguments": {
        "city": "Paris"
      },
      "name": "get_weather"
    },
    {
      "arguments": {
        "city": "Tokyo"
      },
      "name": "get_weather"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-parallel-same-tool", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Two cities, two lookups.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{\"city\": \"Paris\"}<|tool_call_end|><|tool_call_begin|>functions.get_weather:1<|tool_call_argument_begin|>{\"city\": \"Tokyo\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [17285, 14509, 11, 2069, 138897, 13, 163607, 163595, 163597, 41937, 1150, 21055, 2800, 25, 15, 163598, 8264, 37666, 1289, 414, 113476, 16934, 163599, 163597, 41937, 1150, 21055, 2800, 25, 16, 163598, 8264, 37666, 1289, 414, 39818, 18009, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Two cities, two lookups.", "tool_calls": [{"name": "get_weather", "arguments": {"city": "Paris"}}, {"name": "get_weather", "arguments": {"city": "Tokyo"}}]}, "tags": ["parallel-calls", "reasoning", "x-global-idx", "x-think-no-open-tag", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-parallel-three-tools expected_match
Checks that did not pass for kimi/k26-parallel-three-tools
CheckStrategyResultDetail
expected_matchnonstream soft passreasoning_content (whitespace only): expected 'Weather, time and a search.', got ' Weather, time and a search.'
expected_matchone soft passreasoning_content (whitespace only): expected 'Weather, time and a search.', got ' Weather, time and a search.'
expected_matchspecial soft passreasoning_content (whitespace only): expected 'Weather, time and a search.', got ' Weather, time and a search.'
expected_matchtoken soft passreasoning_content (whitespace only): expected 'Weather, time and a search.', got ' Weather, time and a search.'
expected_matchrand:1:8 soft passreasoning_content (whitespace only): expected 'Weather, time and a search.', got ' Weather, time and a search.'
expected_matchrand:2:8 soft passreasoning_content (whitespace only): expected 'Weather, time and a search.', got ' Weather, time and a search.'
expected_matchrand:3:8 soft passreasoning_content (whitespace only): expected 'Weather, time and a search.', got ' Weather, time and a search.'
expected_matchrand:4:8 soft passreasoning_content (whitespace only): expected 'Weather, time and a search.', got ' Weather, time and a search.'
expected_matchrand:5:8 soft passreasoning_content (whitespace only): expected 'Weather, time and a search.', got ' Weather, time and a search.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-parallel-three-tools --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 3 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
   "content": null,
-  "reasoning_content": "Weather, time and a search.",
+  "reasoning_content": " Weather, time and a search.",
   "tool_calls": [
     {

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: parallel-calls, nested-json, reasoning, x-global-idx, x-think-no-open-tag, x-kimi-k2.

Raw output

Weather, time and a search.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{"city": "Zürich"}<|tool_call_end|><|tool_call_begin|>functions.get_time:1<|tool_call_argument_begin|>{}<|tool_call_end|><|tool_call_begin|>functions.search_web:2<|tool_call_argument_begin|>{"query": "cafés", "filters": {"site": "example.com", "max_results": 3}}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "Weather, time and a search.",
  "tool_calls": [
    {
      "arguments": {
        "city": "Zürich"
      },
      "name": "get_weather"
    },
    {
      "arguments": {},
      "name": "get_time"
    },
    {
      "arguments": {
        "filters": {
          "max_results": 3,
          "site": "example.com"
        },
        "query": "cafés"
      },
      "name": "search_web"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-parallel-three-tools", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Weather, time and a search.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{\"city\": \"Zürich\"}<|tool_call_end|><|tool_call_begin|>functions.get_time:1<|tool_call_argument_begin|>{}<|tool_call_end|><|tool_call_begin|>functions.search_web:2<|tool_call_argument_begin|>{\"query\": \"cafés\", \"filters\": {\"site\": \"example.com\", \"max_results\": 3}}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [65512, 11, 1169, 316, 261, 4580, 13, 163607, 163595, 163597, 41937, 1150, 21055, 2800, 25, 15, 163598, 8264, 37666, 1289, 414, 57, 14541, 969, 16934, 163599, 163597, 41937, 1150, 6618, 25, 16, 163598, 13071, 163599, 163597, 41937, 20329, 41998, 25, 17, 163598, 8264, 4964, 1289, 414, 122583, 11336, 665, 414, 51859, 1289, 9392, 19535, 1289, 414, 17480, 1304, 665, 414, 5354, 28137, 1289, 220, 18, 5375, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Weather, time and a search.", "tool_calls": [{"name": "get_weather", "arguments": {"city": "Zürich"}}, {"name": "get_time", "arguments": {}}, {"name": "search_web", "arguments": {"query": "cafés", "filters": {"site": "example.com", "max_results": 3}}}]}, "tags": ["parallel-calls", "nested-json", "reasoning", "x-global-idx", "x-think-no-open-tag", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-single-call expected_match
Checks that did not pass for kimi/k26-single-call
CheckStrategyResultDetail
expected_matchnonstream soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris in Celsius.', got ' The user wants the weather in Paris in Celsius.'
expected_matchone soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris in Celsius.', got ' The user wants the weather in Paris in Celsius.'
expected_matchspecial soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris in Celsius.', got ' The user wants the weather in Paris in Celsius.'
expected_matchtoken soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris in Celsius.', got ' The user wants the weather in Paris in Celsius.'
expected_matchrand:1:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris in Celsius.', got ' The user wants the weather in Paris in Celsius.'
expected_matchrand:2:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris in Celsius.', got ' The user wants the weather in Paris in Celsius.'
expected_matchrand:3:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris in Celsius.', got ' The user wants the weather in Paris in Celsius.'
expected_matchrand:4:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris in Celsius.', got ' The user wants the weather in Paris in Celsius.'
expected_matchrand:5:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris in Celsius.', got ' The user wants the weather in Paris in Celsius.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-single-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 1 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
   "content": null,
-  "reasoning_content": "The user wants the weather in Paris in Celsius.",
+  "reasoning_content": " The user wants the weather in Paris in Celsius.",
   "tool_calls": [
     {

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: single-call, reasoning, x-id-encodes-name, x-think-no-open-tag, x-kimi-k2.

Raw output

The user wants the weather in Paris in Celsius.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{"city": "Paris", "unit": "celsius"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "The user wants the weather in Paris in Celsius.",
  "tool_calls": [
    {
      "arguments": {
        "city": "Paris",
        "unit": "celsius"
      },
      "name": "get_weather"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-single-call", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "The user wants the weather in Paris in Celsius.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{\"city\": \"Paris\", \"unit\": \"celsius\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [1008, 2742, 11333, 276, 10666, 306, 17374, 306, 110964, 13, 163607, 163595, 163597, 41937, 1150, 21055, 2800, 25, 15, 163598, 8264, 37666, 1289, 414, 113476, 665, 414, 8175, 1289, 414, 78841, 14211, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "The user wants the weather in Paris in Celsius.", "tool_calls": [{"name": "get_weather", "arguments": {"city": "Paris", "unit": "celsius"}}]}, "tags": ["single-call", "reasoning", "x-id-encodes-name", "x-think-no-open-tag", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-string-escapes expected_match
Checks that did not pass for kimi/k26-string-escapes
CheckStrategyResultDetail
expected_matchnonstream soft passreasoning_content (whitespace only): expected 'Save the note verbatim.', got ' Save the note verbatim.'
expected_matchone soft passreasoning_content (whitespace only): expected 'Save the note verbatim.', got ' Save the note verbatim.'
expected_matchspecial soft passreasoning_content (whitespace only): expected 'Save the note verbatim.', got ' Save the note verbatim.'
expected_matchtoken soft passreasoning_content (whitespace only): expected 'Save the note verbatim.', got ' Save the note verbatim.'
expected_matchrand:1:8 soft passreasoning_content (whitespace only): expected 'Save the note verbatim.', got ' Save the note verbatim.'
expected_matchrand:2:8 soft passreasoning_content (whitespace only): expected 'Save the note verbatim.', got ' Save the note verbatim.'
expected_matchrand:3:8 soft passreasoning_content (whitespace only): expected 'Save the note verbatim.', got ' Save the note verbatim.'
expected_matchrand:4:8 soft passreasoning_content (whitespace only): expected 'Save the note verbatim.', got ' Save the note verbatim.'
expected_matchrand:5:8 soft passreasoning_content (whitespace only): expected 'Save the note verbatim.', got ' Save the note verbatim.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-string-escapes --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 9 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
   "content": null,
-  "reasoning_content": "Save the note verbatim.",
+  "reasoning_content": " Save the note verbatim.",
   "tool_calls": [
     {

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: single-call, string-escapes, reasoning, x-think-no-open-tag, x-kimi-k2.

Raw output

Save the note verbatim.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.write_file:0<|tool_call_argument_begin|>{"path": "C:\\Users\\ana\\notes.txt", "content": "line 1\n\tline 2 \"quoted\" \\ end"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "Save the note verbatim.",
  "tool_calls": [
    {
      "arguments": {
        "content": "line 1\n\tline 2 \"quoted\" \\ end",
        "path": "C:\\Users\\ana\\notes.txt"
      },
      "name": "write_file"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-string-escapes", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Save the note verbatim.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.write_file:0<|tool_call_argument_begin|>{\"path\": \"C:\\\\Users\\\\ana\\\\notes.txt\", \"content\": \"line 1\\n\\tline 2 \\\"quoted\\\" \\\\ end\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [13744, 276, 7234, 157023, 13, 163607, 163595, 163597, 41937, 9189, 6101, 25, 15, 163598, 8264, 4953, 1289, 414, 34, 20920, 12984, 2946, 5060, 2946, 39685, 8842, 665, 414, 4204, 1289, 414, 1611, 220, 16, 2423, 9146, 1611, 220, 17, 10083, 79530, 3378, 20502, 1565, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Save the note verbatim.", "tool_calls": [{"name": "write_file", "arguments": {"path": "C:\\Users\\ana\\notes.txt", "content": "line 1\n\tline 2 \"quoted\" \\ end"}}]}, "tags": ["single-call", "string-escapes", "reasoning", "x-think-no-open-tag", "x-kimi-k2"], "notes": "K2 carries JSON (escaped); K3 carries string values raw."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-truncated-in-reasoning expected_match
Checks that did not pass for kimi/k26-truncated-in-reasoning
CheckStrategyResultDetail
expected_matchnonstream soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris', got ' The user wants the weather in Paris'
expected_matchone soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris', got ' The user wants the weather in Paris'
expected_matchspecial soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris', got ' The user wants the weather in Paris'
expected_matchtoken soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris', got ' The user wants the weather in Paris'
expected_matchrand:1:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris', got ' The user wants the weather in Paris'
expected_matchrand:2:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris', got ' The user wants the weather in Paris'
expected_matchrand:3:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris', got ' The user wants the weather in Paris'
expected_matchrand:4:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris', got ' The user wants the weather in Paris'
expected_matchrand:5:8 soft passreasoning_content (whitespace only): expected 'The user wants the weather in Paris', got ' The user wants the weather in Paris'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/truncated.jsonl --id kimi/k26-truncated-in-reasoning --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 3 of fixtures/kimi/truncated.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
   "content": null,
-  "reasoning_content": "The user wants the weather in Paris",
+  "reasoning_content": " The user wants the weather in Paris",
   "tool_calls": []
 }

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: truncated, reasoning, x-think-no-open-tag, x-kimi-k2.

Raw output

The user wants the weather in Paris

Expected parse

{
  "content": null,
  "reasoning_content": "The user wants the weather in Paris",
  "tool_calls": []
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-truncated-in-reasoning", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "The user wants the weather in Paris", "output_token_ids": [1008, 2742, 11333, 276, 10666, 306, 17374], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "The user wants the weather in Paris", "tool_calls": []}, "tags": ["truncated", "reasoning", "x-think-no-open-tag", "x-kimi-k2"], "notes": "Token prefix of kimi/k26-single-call. The generation prompt opened the think channel, so the unterminated text is reasoning (see https://github.com/vllm-project/vllm/issues/57353 for K3)."}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k26-unicode-emoji expected_match
Checks that did not pass for kimi/k26-unicode-emoji
CheckStrategyResultDetail
expected_matchnonstream soft passreasoning_content (whitespace only): expected 'Search with the exact wording.', got ' Search with the exact wording.'
expected_matchone soft passreasoning_content (whitespace only): expected 'Search with the exact wording.', got ' Search with the exact wording.'
expected_matchspecial soft passreasoning_content (whitespace only): expected 'Search with the exact wording.', got ' Search with the exact wording.'
expected_matchtoken soft passreasoning_content (whitespace only): expected 'Search with the exact wording.', got ' Search with the exact wording.'
expected_matchrand:1:8 soft passreasoning_content (whitespace only): expected 'Search with the exact wording.', got ' Search with the exact wording.'
expected_matchrand:2:8 soft passreasoning_content (whitespace only): expected 'Search with the exact wording.', got ' Search with the exact wording.'
expected_matchrand:3:8 soft passreasoning_content (whitespace only): expected 'Search with the exact wording.', got ' Search with the exact wording.'
expected_matchrand:4:8 soft passreasoning_content (whitespace only): expected 'Search with the exact wording.', got ' Search with the exact wording.'
expected_matchrand:5:8 soft passreasoning_content (whitespace only): expected 'Search with the exact wording.', got ' Search with the exact wording.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k26-render.jsonl --id kimi/k26-unicode-emoji --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 7 of fixtures/kimi/k26-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,5 +1,5 @@
 {
   "content": null,
-  "reasoning_content": "Search with the exact wording.",
+  "reasoning_content": " Search with the exact wording.",
   "tool_calls": [
     {

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja. Tags: single-call, unicode, reasoning, x-think-no-open-tag, x-kimi-k2.

Raw output

Search with the exact wording.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.search_web:0<|tool_call_argument_begin|>{"query": "Zürich café ☕ 東京の天気 🌸"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": null,
  "reasoning_content": "Search with the exact wording.",
  "tool_calls": [
    {
      "arguments": {
        "query": "Zürich café ☕ 東京の天気 🌸"
      },
      "name": "search_web"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k26-unicode-emoji", "family": "kimi", "models": ["moonshotai/Kimi-K2.6"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2.6/blob/7eb5002f6aadc958aed6a9177b7ed26bb94011bb/chat_template.jinja", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Search with the exact wording.</think><|tool_calls_section_begin|><|tool_call_begin|>functions.search_web:0<|tool_call_argument_begin|>{\"query\": \"Zürich café ☕ 東京の天気 🌸\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [8583, 472, 276, 5801, 98763, 13, 163607, 163595, 163597, 41937, 20329, 41998, 25, 15, 163598, 8264, 4964, 1289, 414, 57, 14541, 969, 70591, 96150, 243, 220, 138442, 4663, 679, 87959, 17137, 234, 116, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2.6", "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb", "mode": "hf"}, "thinking": true, "expected": {"content": null, "reasoning_content": "Search with the exact wording.", "tool_calls": [{"name": "search_web", "arguments": {"query": "Zürich café ☕ 東京の天気 🌸"}}]}, "tags": ["single-call", "unicode", "reasoning", "x-think-no-open-tag", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {
    "enable_thinking": true,
    "thinking": true
  },
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|><think>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2.6",
  "model_rule": "Kimi-K2",
  "model_type": "kimi_k25",
  "parser_source": "docs/formats/kimi.md (vLLM v0.30.0 row; thinking K2.x)",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": ">Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|><think>",
  "reasoning_parser": "kimi_k2",
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "8bf859698fd4781c0e1e1c63ce74422aab27e53ccc5f47116317c64cda06132f",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2.6",
    "requested_mode": "auto",
    "resolved_revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "revision": "7eb5002f6aadc958aed6a9177b7ed26bb94011bb",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_dot_6.7eb5002f6aadc958aed6a9177b7ed26bb94011bb.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k2i-content-before-call expected_match
Checks that did not pass for kimi/k2i-content-before-call
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you.'
expected_matchone soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you.'
expected_matchspecial soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you.'
expected_matchtoken soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you.'
expected_matchrand:1:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you.'
expected_matchrand:2:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you.'
expected_matchrand:3:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you.'
expected_matchrand:4:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you.'
expected_matchrand:5:8 soft passcontent (whitespace only): expected 'Let me check that for you.', got ' Let me check that for you.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k2i-render.jsonl --id kimi/k2i-content-before-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 2 of fixtures/kimi/k2i-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,4 +1,4 @@
 {
-  "content": "Let me check that for you.",
+  "content": " Let me check that for you.",
   "reasoning_content": null,
   "tool_calls": [

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2-Instruct-0905/blob/ac6c49f04883bd0a0598b790693a72061c676629/chat_template.jinja. Tags: single-call, text-before-call, x-kimi-k2.

Raw output

Let me check that for you.<|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{"city": "Berlin"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": "Let me check that for you.",
  "reasoning_content": null,
  "tool_calls": [
    {
      "arguments": {
        "city": "Berlin"
      },
      "name": "get_weather"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k2i-content-before-call", "family": "kimi", "models": ["moonshotai/Kimi-K2-Instruct-0905", "moonshotai/Kimi-K2-Instruct"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2-Instruct-0905/blob/ac6c49f04883bd0a0598b790693a72061c676629/chat_template.jinja", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Let me check that for you.<|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0<|tool_call_argument_begin|>{\"city\": \"Berlin\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [9413, 1019, 2598, 473, 395, 398, 13, 163595, 163597, 41937, 1150, 21055, 2800, 25, 15, 163598, 8264, 37666, 1289, 414, 67347, 4797, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2-Instruct-0905", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "mode": "hf"}, "expected": {"content": "Let me check that for you.", "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Berlin"}}]}, "tags": ["single-call", "text-before-call", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {},
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2-Instruct-0905",
  "model_rule": "Kimi-K2-Instruct",
  "model_type": "kimi_k2",
  "parser_source": "Kimi-K2-Instruct model card: non-thinking; --tool-call-parser kimi_k2",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "middle|>Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|>",
  "reasoning_parser": null,
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2-Instruct-0905",
    "requested_mode": "auto",
    "resolved_revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_hyphen_Instruct_hyphen_0905.ac6c49f04883bd0a0598b790693a72061c676629.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k2i-no-call expected_match
Checks that did not pass for kimi/k2i-no-call
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'
expected_matchone soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'
expected_matchspecial soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'
expected_matchtoken soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'
expected_matchrand:1:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'
expected_matchrand:2:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'
expected_matchrand:3:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'
expected_matchrand:4:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'
expected_matchrand:5:8 soft passcontent (whitespace only): expected 'Paris is the capital of France.', got ' Paris is the capital of France.'

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/k2i-render.jsonl --id kimi/k2i-no-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 3 of fixtures/kimi/k2i-render.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,4 +1,4 @@
 {
-  "content": "Paris is the capital of France.",
+  "content": " Paris is the capital of France.",
   "reasoning_content": null,
   "tool_calls": []

Fixture

Provenance: template_render, https://huggingface.co/moonshotai/Kimi-K2-Instruct-0905/blob/ac6c49f04883bd0a0598b790693a72061c676629/chat_template.jinja. Tags: no-call, x-kimi-k2.

Raw output

Paris is the capital of France.

Expected parse

{
  "content": "Paris is the capital of France.",
  "reasoning_content": null,
  "tool_calls": []
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k2i-no-call", "family": "kimi", "models": ["moonshotai/Kimi-K2-Instruct-0905", "moonshotai/Kimi-K2-Instruct"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/moonshotai/Kimi-K2-Instruct-0905/blob/ac6c49f04883bd0a0598b790693a72061c676629/chat_template.jinja", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "license": "LicenseRef-modified-mit", "generator": "scripts/fixtures/kimi/build.py", "template_sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search_web", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object", "properties": {"site": {"type": "string"}, "max_results": {"type": "integer"}, "tags": {"type": "array", "items": {"type": "string"}}}}}, "required": ["query"]}}}, {"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time.", "parameters": {"type": "object", "properties": {}}}}, {"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}, {"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "attendees": {"type": "array", "items": {"type": "string"}}, "duration_minutes": {"type": "integer"}, "all_day": {"type": "boolean"}, "reminder_minutes": {"type": ["integer", "null"]}, "location": {"type": "object"}}, "required": ["title"]}}}, {"type": "function", "function": {"name": "convert_units", "description": "Convert a value between units.", "parameters": {"type": "object", "properties": {"value": {"type": "number"}, "from_unit": {"type": "string"}, "to_unit": {"type": "string"}}, "required": ["value", "from_unit", "to_unit"]}}}], "raw_output": "Paris is the capital of France.", "output_token_ids": [113476, 387, 276, 10484, 318, 15383, 13], "tokenizer": {"repo": "moonshotai/Kimi-K2-Instruct-0905", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "mode": "hf"}, "expected": {"content": "Paris is the capital of France.", "reasoning_content": null, "tool_calls": []}, "tags": ["no-call", "x-kimi-k2"]}
Parser configuration
{
  "chat_template_kwargs": {},
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2-Instruct-0905",
  "model_rule": "Kimi-K2-Instruct",
  "model_type": "kimi_k2",
  "parser_source": "Kimi-K2-Instruct model card: non-thinking; --tool-call-parser kimi_k2",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "middle|>Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|>",
  "reasoning_parser": null,
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2-Instruct-0905",
    "requested_mode": "auto",
    "resolved_revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_hyphen_Instruct_hyphen_0905.ac6c49f04883bd0a0598b790693a72061c676629.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k2i-vllm-empty-tool-section expected_match
Checks that did not pass for kimi/k2i-vllm-empty-tool-section
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchone soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchspecial soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchtoken soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:1:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:2:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:3:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:4:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:5:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/imported.jsonl --id kimi/k2i-vllm-empty-tool-section --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 6 of fixtures/kimi/imported.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,4 +1,4 @@
 {
-  "content": "Reasoning. ",
+  "content": " Reasoning. ",
   "reasoning_content": null,
   "tool_calls": []

Fixture

Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L388-L393. Tags: no-call, x-empty-section, x-kimi-k2.

Raw output

Reasoning. <|tool_calls_section_begin|><|tool_calls_section_end|>

Expected parse

{
  "content": "Reasoning. ",
  "reasoning_content": null,
  "tool_calls": []
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k2i-vllm-empty-tool-section", "family": "kimi", "models": ["moonshotai/Kimi-K2-Instruct-0905"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L388-L393", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "generator": "scripts/fixtures/kimi/imported.py", "attribution": "Copyright contributors to the vLLM project (Apache-2.0)"}, "tools": [{"type": "function", "function": {"name": "test", "parameters": {"type": "object", "properties": {"k": {"type": "string"}}}}}], "raw_output": "Reasoning. <|tool_calls_section_begin|><|tool_calls_section_end|>", "output_token_ids": [24977, 288, 13, 220, 163595, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2-Instruct-0905", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "mode": "hf"}, "expected": {"content": "Reasoning. ", "reasoning_content": null, "tool_calls": []}, "tags": ["no-call", "x-empty-section", "x-kimi-k2"], "notes": "The vLLM test exercises the parser without a tools list; the tool schemas here are minimal stand-ins. An empty tool-calls section yields no calls and no marker text in content."}
Parser configuration
{
  "chat_template_kwargs": {},
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2-Instruct-0905",
  "model_rule": "Kimi-K2-Instruct",
  "model_type": "kimi_k2",
  "parser_source": "Kimi-K2-Instruct model card: non-thinking; --tool-call-parser kimi_k2",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "middle|>Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|>",
  "reasoning_parser": null,
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2-Instruct-0905",
    "requested_mode": "auto",
    "resolved_revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_hyphen_Instruct_hyphen_0905.ac6c49f04883bd0a0598b790693a72061c676629.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k2i-vllm-id-without-functions-prefix expected_match
Checks that did not pass for kimi/k2i-vllm-id-without-functions-prefix
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected 'No prefix. ', got ' No prefix. '
expected_matchone soft passcontent (whitespace only): expected 'No prefix. ', got ' No prefix. '
expected_matchspecial soft passcontent (whitespace only): expected 'No prefix. ', got ' No prefix. '
expected_matchtoken soft passcontent (whitespace only): expected 'No prefix. ', got ' No prefix. '
expected_matchrand:1:8 soft passcontent (whitespace only): expected 'No prefix. ', got ' No prefix. '
expected_matchrand:2:8 soft passcontent (whitespace only): expected 'No prefix. ', got ' No prefix. '
expected_matchrand:3:8 soft passcontent (whitespace only): expected 'No prefix. ', got ' No prefix. '
expected_matchrand:4:8 soft passcontent (whitespace only): expected 'No prefix. ', got ' No prefix. '
expected_matchrand:5:8 soft passcontent (whitespace only): expected 'No prefix. ', got ' No prefix. '

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/imported.jsonl --id kimi/k2i-vllm-id-without-functions-prefix --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 4 of fixtures/kimi/imported.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,4 +1,4 @@
 {
-  "content": "No prefix. ",
+  "content": " No prefix. ",
   "reasoning_content": null,
   "tool_calls": [

Fixture

Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L120-L126. Tags: single-call, text-before-call, x-non-kimi-call-id, x-kimi-k2.

Raw output

No prefix. <|tool_calls_section_begin|><|tool_call_begin|>get_weather:0 <|tool_call_argument_begin|>{"city": "Tokyo"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": "No prefix. ",
  "reasoning_content": null,
  "tool_calls": [
    {
      "arguments": {
        "city": "Tokyo"
      },
      "name": "get_weather"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k2i-vllm-id-without-functions-prefix", "family": "kimi", "models": ["moonshotai/Kimi-K2-Instruct-0905"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L120-L126", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "generator": "scripts/fixtures/kimi/imported.py", "attribution": "Copyright contributors to the vLLM project (Apache-2.0)"}, "tools": [{"type": "function", "function": {"name": "get_weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}}}}], "raw_output": "No prefix. <|tool_calls_section_begin|><|tool_call_begin|>get_weather:0 <|tool_call_argument_begin|>{\"city\": \"Tokyo\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [4729, 14280, 13, 220, 163595, 163597, 618, 21055, 2800, 25, 15, 220, 163598, 8264, 37666, 1289, 414, 39818, 18009, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2-Instruct-0905", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "mode": "hf"}, "expected": {"content": "No prefix. ", "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Tokyo"}}]}, "tags": ["single-call", "text-before-call", "x-non-kimi-call-id", "x-kimi-k2"], "notes": "The vLLM test exercises the parser without a tools list; the tool schemas here are minimal stand-ins. The id lacks the 'functions.' prefix; the name is still recoverable from '{name}:{idx}'."}
Parser configuration
{
  "chat_template_kwargs": {},
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2-Instruct-0905",
  "model_rule": "Kimi-K2-Instruct",
  "model_type": "kimi_k2",
  "parser_source": "Kimi-K2-Instruct model card: non-thinking; --tool-call-parser kimi_k2",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "middle|>Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|>",
  "reasoning_parser": null,
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2-Instruct-0905",
    "requested_mode": "auto",
    "resolved_revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_hyphen_Instruct_hyphen_0905.ac6c49f04883bd0a0598b790693a72061c676629.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k2i-vllm-multiline-json expected_match
Checks that did not pass for kimi/k2i-vllm-multiline-json
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected 'Formatted. ', got ' Formatted. '
expected_matchone soft passcontent (whitespace only): expected 'Formatted. ', got ' Formatted. '
expected_matchspecial soft passcontent (whitespace only): expected 'Formatted. ', got ' Formatted. '
expected_matchtoken soft passcontent (whitespace only): expected 'Formatted. ', got ' Formatted. '
expected_matchrand:1:8 soft passcontent (whitespace only): expected 'Formatted. ', got ' Formatted. '
expected_matchrand:2:8 soft passcontent (whitespace only): expected 'Formatted. ', got ' Formatted. '
expected_matchrand:3:8 soft passcontent (whitespace only): expected 'Formatted. ', got ' Formatted. '
expected_matchrand:4:8 soft passcontent (whitespace only): expected 'Formatted. ', got ' Formatted. '
expected_matchrand:5:8 soft passcontent (whitespace only): expected 'Formatted. ', got ' Formatted. '

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/imported.jsonl --id kimi/k2i-vllm-multiline-json --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 3 of fixtures/kimi/imported.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,4 +1,4 @@
 {
-  "content": "Formatted. ",
+  "content": " Formatted. ",
   "reasoning_content": null,
   "tool_calls": [

Fixture

Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L107-L119. Tags: single-call, text-before-call, numeric-arguments, x-kimi-k2.

Raw output

Formatted. <|tool_calls_section_begin|><|tool_call_begin|>functions.process_data:0 <|tool_call_argument_begin|>{
  "name": "test",
  "value": 123
}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": "Formatted. ",
  "reasoning_content": null,
  "tool_calls": [
    {
      "arguments": {
        "name": "test",
        "value": 123
      },
      "name": "process_data"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k2i-vllm-multiline-json", "family": "kimi", "models": ["moonshotai/Kimi-K2-Instruct-0905"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L107-L119", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "generator": "scripts/fixtures/kimi/imported.py", "attribution": "Copyright contributors to the vLLM project (Apache-2.0)"}, "tools": [{"type": "function", "function": {"name": "process_data", "parameters": {"type": "object", "properties": {"name": {"type": "string"}, "value": {"type": "integer"}}}}}], "raw_output": "Formatted. <|tool_calls_section_begin|><|tool_call_begin|>functions.process_data:0 <|tool_call_argument_begin|>{\n  \"name\": \"test\",\n  \"value\": 123\n}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [68615, 13, 220, 163595, 163597, 41937, 28866, 3419, 25, 15, 220, 163598, 1028, 220, 414, 1152, 1289, 414, 3078, 1137, 220, 414, 2035, 1289, 220, 6694, 198, 92, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2-Instruct-0905", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "mode": "hf"}, "expected": {"content": "Formatted. ", "reasoning_content": null, "tool_calls": [{"name": "process_data", "arguments": {"name": "test", "value": 123}}]}, "tags": ["single-call", "text-before-call", "numeric-arguments", "x-kimi-k2"], "notes": "The vLLM test exercises the parser without a tools list; the tool schemas here are minimal stand-ins."}
Parser configuration
{
  "chat_template_kwargs": {},
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2-Instruct-0905",
  "model_rule": "Kimi-K2-Instruct",
  "model_type": "kimi_k2",
  "parser_source": "Kimi-K2-Instruct model card: non-thinking; --tool-call-parser kimi_k2",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "middle|>Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|>",
  "reasoning_parser": null,
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2-Instruct-0905",
    "requested_mode": "auto",
    "resolved_revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_hyphen_Instruct_hyphen_0905.ac6c49f04883bd0a0598b790693a72061c676629.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k2i-vllm-noise-between-markers expected_match
Checks that did not pass for kimi/k2i-vllm-noise-between-markers
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchone soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchspecial soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchtoken soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:1:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:2:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:3:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:4:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '
expected_matchrand:5:8 soft passcontent (whitespace only): expected 'Reasoning. ', got ' Reasoning. '

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/imported.jsonl --id kimi/k2i-vllm-noise-between-markers --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 5 of fixtures/kimi/imported.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,4 +1,4 @@
 {
-  "content": "Reasoning. ",
+  "content": " Reasoning. ",
   "reasoning_content": null,
   "tool_calls": [

Fixture

Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L370-L386. Tags: single-call, text-before-call, malformed, x-kimi-k2.

Raw output

Reasoning. <|tool_calls_section_begin|> spurious noise <|tool_call_begin|>functions.test:0 <|tool_call_argument_begin|>{"k": "v"} <|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": "Reasoning. ",
  "reasoning_content": null,
  "tool_calls": [
    {
      "arguments": {
        "k": "v"
      },
      "name": "test"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k2i-vllm-noise-between-markers", "family": "kimi", "models": ["moonshotai/Kimi-K2-Instruct-0905"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L370-L386", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "generator": "scripts/fixtures/kimi/imported.py", "attribution": "Copyright contributors to the vLLM project (Apache-2.0)"}, "tools": [{"type": "function", "function": {"name": "test", "parameters": {"type": "object", "properties": {"k": {"type": "string"}}}}}], "raw_output": "Reasoning. <|tool_calls_section_begin|> spurious noise <|tool_call_begin|>functions.test:0 <|tool_call_argument_begin|>{\"k\": \"v\"} <|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [24977, 288, 13, 220, 163595, 1284, 26163, 18226, 220, 163597, 41937, 9478, 25, 15, 220, 163598, 8264, 74, 1289, 414, 85, 16934, 220, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2-Instruct-0905", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "mode": "hf"}, "expected": {"content": "Reasoning. ", "reasoning_content": null, "tool_calls": [{"name": "test", "arguments": {"k": "v"}}]}, "tags": ["single-call", "text-before-call", "malformed", "x-kimi-k2"], "notes": "The vLLM test exercises the parser without a tools list; the tool schemas here are minimal stand-ins. The deltas of the streaming test, concatenated. Text inside the section but outside a call is not content (vLLM asserts it does not leak)."}
Parser configuration
{
  "chat_template_kwargs": {},
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2-Instruct-0905",
  "model_rule": "Kimi-K2-Instruct",
  "model_type": "kimi_k2",
  "parser_source": "Kimi-K2-Instruct model card: non-thinking; --tool-call-parser kimi_k2",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "middle|>Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|>",
  "reasoning_parser": null,
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2-Instruct-0905",
    "requested_mode": "auto",
    "resolved_revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_hyphen_Instruct_hyphen_0905.ac6c49f04883bd0a0598b790693a72061c676629.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k2i-vllm-single-call-content-before expected_match
Checks that did not pass for kimi/k2i-vllm-single-call-content-before
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected "I'll check. ", got " I'll check. "
expected_matchone soft passcontent (whitespace only): expected "I'll check. ", got " I'll check. "
expected_matchspecial soft passcontent (whitespace only): expected "I'll check. ", got " I'll check. "
expected_matchtoken soft passcontent (whitespace only): expected "I'll check. ", got " I'll check. "
expected_matchrand:1:8 soft passcontent (whitespace only): expected "I'll check. ", got " I'll check. "
expected_matchrand:2:8 soft passcontent (whitespace only): expected "I'll check. ", got " I'll check. "
expected_matchrand:3:8 soft passcontent (whitespace only): expected "I'll check. ", got " I'll check. "
expected_matchrand:4:8 soft passcontent (whitespace only): expected "I'll check. ", got " I'll check. "
expected_matchrand:5:8 soft passcontent (whitespace only): expected "I'll check. ", got " I'll check. "

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/imported.jsonl --id kimi/k2i-vllm-single-call-content-before --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 1 of fixtures/kimi/imported.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,4 +1,4 @@
 {
-  "content": "I'll check. ",
+  "content": " I'll check. ",
   "reasoning_content": null,
   "tool_calls": [

Fixture

Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L59-L66. Tags: single-call, text-before-call, x-id-encodes-name, x-kimi-k2.

Raw output

I'll check. <|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0 <|tool_call_argument_begin|>{"city": "Beijing"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": "I'll check. ",
  "reasoning_content": null,
  "tool_calls": [
    {
      "arguments": {
        "city": "Beijing"
      },
      "name": "get_weather"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k2i-vllm-single-call-content-before", "family": "kimi", "models": ["moonshotai/Kimi-K2-Instruct-0905"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L59-L66", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "generator": "scripts/fixtures/kimi/imported.py", "attribution": "Copyright contributors to the vLLM project (Apache-2.0)"}, "tools": [{"type": "function", "function": {"name": "get_weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}}}}], "raw_output": "I'll check. <|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0 <|tool_call_argument_begin|>{\"city\": \"Beijing\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [65447, 2598, 13, 220, 163595, 163597, 41937, 1150, 21055, 2800, 25, 15, 220, 163598, 8264, 37666, 1289, 414, 4396, 39556, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2-Instruct-0905", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "mode": "hf"}, "expected": {"content": "I'll check. ", "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Beijing"}}]}, "tags": ["single-call", "text-before-call", "x-id-encodes-name", "x-kimi-k2"], "notes": "The vLLM test exercises the parser without a tools list; the tool schemas here are minimal stand-ins. vLLM's test helper puts a space between the call id and <|tool_call_argument_begin|>."}
Parser configuration
{
  "chat_template_kwargs": {},
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2-Instruct-0905",
  "model_rule": "Kimi-K2-Instruct",
  "model_type": "kimi_k2",
  "parser_source": "Kimi-K2-Instruct model card: non-thinking; --tool-call-parser kimi_k2",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "middle|>Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|>",
  "reasoning_parser": null,
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2-Instruct-0905",
    "requested_mode": "auto",
    "resolved_revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_hyphen_Instruct_hyphen_0905.ac6c49f04883bd0a0598b790693a72061c676629.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}
soft pass kimi/k2i-vllm-three-tool-calls expected_match
Checks that did not pass for kimi/k2i-vllm-three-tool-calls
CheckStrategyResultDetail
expected_matchnonstream soft passcontent (whitespace only): expected 'Multiple tasks. ', got ' Multiple tasks. '
expected_matchone soft passcontent (whitespace only): expected 'Multiple tasks. ', got ' Multiple tasks. '
expected_matchspecial soft passcontent (whitespace only): expected 'Multiple tasks. ', got ' Multiple tasks. '
expected_matchtoken soft passcontent (whitespace only): expected 'Multiple tasks. ', got ' Multiple tasks. '
expected_matchrand:1:8 soft passcontent (whitespace only): expected 'Multiple tasks. ', got ' Multiple tasks. '
expected_matchrand:2:8 soft passcontent (whitespace only): expected 'Multiple tasks. ', got ' Multiple tasks. '
expected_matchrand:3:8 soft passcontent (whitespace only): expected 'Multiple tasks. ', got ' Multiple tasks. '
expected_matchrand:4:8 soft passcontent (whitespace only): expected 'Multiple tasks. ', got ' Multiple tasks. '
expected_matchrand:5:8 soft passcontent (whitespace only): expected 'Multiple tasks. ', got ' Multiple tasks. '

Minimal repro

uv run canitoolcall run --engine vllm --fixtures fixtures/kimi/imported.jsonl --id kimi/k2i-vllm-three-tool-calls --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all

Set up the engine first with scripts/engines/vllm.sh; this run used vllm 0.30.0. The fixture is line 2 of fixtures/kimi/imported.jsonl.

Observed vs expected

Identical parses are grouped. Empty strings are shown as null, as in strict comparison.

Strategies: nonstream, one, special, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8

--- expected
+++ observed
@@ -1,4 +1,4 @@
 {
-  "content": "Multiple tasks. ",
+  "content": " Multiple tasks. ",
   "reasoning_content": null,
   "tool_calls": [

Fixture

Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L78-L96. Tags: parallel-calls, text-before-call, x-global-idx, x-kimi-k2.

Raw output

Multiple tasks. <|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0 <|tool_call_argument_begin|>{"city": "New York"}<|tool_call_end|><|tool_call_begin|>functions.get_news:1 <|tool_call_argument_begin|>{"topic": "technology"}<|tool_call_end|><|tool_call_begin|>functions.send_email:2 <|tool_call_argument_begin|>{"to": "user@example.com", "subject": "Daily Update"}<|tool_call_end|><|tool_calls_section_end|>

Expected parse

{
  "content": "Multiple tasks. ",
  "reasoning_content": null,
  "tool_calls": [
    {
      "arguments": {
        "city": "New York"
      },
      "name": "get_weather"
    },
    {
      "arguments": {
        "topic": "technology"
      },
      "name": "get_news"
    },
    {
      "arguments": {
        "subject": "Daily Update",
        "to": "user@example.com"
      },
      "name": "send_email"
    }
  ]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "kimi/k2i-vllm-three-tool-calls", "family": "kimi", "models": ["moonshotai/Kimi-K2-Instruct-0905"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_kimi_k2_tool_parser.py#L78-L96", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "generator": "scripts/fixtures/kimi/imported.py", "attribution": "Copyright contributors to the vLLM project (Apache-2.0)"}, "tools": [{"type": "function", "function": {"name": "get_weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}}}}, {"type": "function", "function": {"name": "get_news", "parameters": {"type": "object", "properties": {"topic": {"type": "string"}}}}}, {"type": "function", "function": {"name": "send_email", "parameters": {"type": "object", "properties": {"to": {"type": "string"}, "subject": {"type": "string"}}}}}], "raw_output": "Multiple tasks. <|tool_calls_section_begin|><|tool_call_begin|>functions.get_weather:0 <|tool_call_argument_begin|>{\"city\": \"New York\"}<|tool_call_end|><|tool_call_begin|>functions.get_news:1 <|tool_call_argument_begin|>{\"topic\": \"technology\"}<|tool_call_end|><|tool_call_begin|>functions.send_email:2 <|tool_call_argument_begin|>{\"to\": \"user@example.com\", \"subject\": \"Daily Update\"}<|tool_call_end|><|tool_calls_section_end|>", "output_token_ids": [33251, 12757, 13, 220, 163595, 163597, 41937, 1150, 21055, 2800, 25, 15, 220, 163598, 8264, 37666, 1289, 414, 5632, 7282, 16934, 163599, 163597, 41937, 1150, 126818, 25, 16, 220, 163598, 8264, 30547, 1289, 414, 65785, 16934, 163599, 163597, 41937, 14131, 28599, 25, 17, 220, 163598, 8264, 1753, 1289, 414, 2482, 31, 17480, 1304, 665, 414, 37407, 1289, 414, 62156, 10829, 16934, 163599, 163596], "tokenizer": {"repo": "moonshotai/Kimi-K2-Instruct-0905", "revision": "ac6c49f04883bd0a0598b790693a72061c676629", "mode": "hf"}, "expected": {"content": "Multiple tasks. ", "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "New York"}}, {"name": "get_news", "arguments": {"topic": "technology"}}, {"name": "send_email", "arguments": {"to": "user@example.com", "subject": "Daily Update"}}]}, "tags": ["parallel-calls", "text-before-call", "x-global-idx", "x-kimi-k2"], "notes": "The vLLM test exercises the parser without a tools list; the tool schemas here are minimal stand-ins."}
Parser configuration
{
  "chat_template_kwargs": {},
  "detokenizer": "vllm.v1.engine.detokenizer.IncrementalDetokenizer.from_new_request",
  "detokenizer_class": "vllm.v1.engine.detokenizer.SlowIncrementalDetokenizer",
  "enable_auto_tools": true,
  "engine": "vllm",
  "entrypoint": "vllm.parser.parser_manager.ParserManager.get_parser",
  "generation_prompt": "<|im_assistant|>assistant<|im_middle|>",
  "generation_prompt_match": true,
  "is_harmony": false,
  "model": "moonshotai/Kimi-K2-Instruct-0905",
  "model_rule": "Kimi-K2-Instruct",
  "model_type": "kimi_k2",
  "parser_source": "Kimi-K2-Instruct model card: non-thinking; --tool-call-parser kimi_k2",
  "pinned_version": "0.30.0",
  "prompt_messages": [
    {
      "content": "Use the tools to answer.",
      "role": "user"
    }
  ],
  "prompt_tail": "middle|>Use the tools to answer.<|im_end|><|im_assistant|>assistant<|im_middle|>",
  "reasoning_parser": null,
  "stop_token_in_final_delta": false,
  "template": {
    "sha256": "00938c355ca7195fd4f9c923e93af063846d4d5005e06999274f8db57b65bb0b",
    "source": "tokenizer chat template (HF repo)"
  },
  "tokenizer": {
    "mode": "hf",
    "repo": "moonshotai/Kimi-K2-Instruct-0905",
    "requested_mode": "auto",
    "resolved_revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "revision": "ac6c49f04883bd0a0598b790693a72061c676629",
    "tokenizer_class": "transformers_modules.moonshotai.Kimi_hyphen_K2_hyphen_Instruct_hyphen_0905.ac6c49f04883bd0a0598b790693a72061c676629.tokenization_kimi.TikTokenTokenizer"
  },
  "tool_choice": "auto (tools and tool_choice omitted when the fixture offers no tools)",
  "tool_parser": "kimi_k2",
  "units_source": "fixture.output_token_ids"
}