Skip to main content
Third-party models

Kimi

Call the Kimi K3 and Kimi K2.7 Code models through the OpenAI-compatible API or DashScope SDK on QwenCloud.

This guide shows how to call the Kimi K3 and Kimi K2.7 Code models via the OpenAI-compatible API or DashScope SDK.

Quick start

kimi-k3 is Kimi's most capable flagship model to date. It always reasons and uses preserved thinking (thinking-only mode). Supports text and image input (video input is not supported), conversation and agent tasks, and dynamic tool loading. kimi-k2.7-code is the most capable Kimi model for coding. It follows long-context instructions more reliably and achieves higher success rates on programming tasks. Supports text, image, and video input, thinking mode, conversation, and agent tasks. kimi-k3 and kimi-k2.7-code are thinking-only models: thinking mode is always enabled (enable_thinking defaults to true and cannot be disabled), and preserve_thinking defaults to true.
kimi-k3 does not support the thinking_budget parameter, and does not yet support the OpenAI-compatible Responses API. Use the OpenAI-compatible Chat Completions API instead.
The examples below use kimi-k2.7-code. To call kimi-k3, replace the model name with kimi-k3. Before you begin, get an API key and set it as an environment variable. If you call the model through an SDK, install the OpenAI or DashScope SDK.
  • OpenAI compatible
  • DashScope
  • Anthropic compatible
The enable_thinking parameter is not part of the standard OpenAI API. In the OpenAI Python SDK, pass it through extra_body. In the Node.js SDK, pass it as a top-level parameter.
  • Python
  • Node.js
  • curl
import os
from openai import OpenAI

client = OpenAI(
  api_key=os.getenv("DASHSCOPE_API_KEY"),
  base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
)

completion = client.chat.completions.create(
  model="kimi-k2.7-code",
  messages=[{"role": "user", "content": "Who are you?"}],
  stream=True,
)

reasoning_content = ""
answer_content = ""
is_answering = False
print("\n" + "=" * 20 + "Thinking Process" + "=" * 20 + "\n")

for chunk in completion:
  if chunk.choices:
    delta = chunk.choices[0].delta
    if hasattr(delta, "reasoning_content") and delta.reasoning_content is not None:
      if not is_answering:
        print(delta.reasoning_content, end="", flush=True)
      reasoning_content += delta.reasoning_content
    if hasattr(delta, "content") and delta.content:
      if not is_answering:
        print("\n" + "=" * 20 + "Complete Response" + "=" * 20 + "\n")
        is_answering = True
      print(delta.content, end="", flush=True)
      answer_content += delta.content

Dynamically loaded tools

When an application needs to mount a large number of tools, putting every tool declaration into the request's top-level tools field at once leads to tool definition bloat: every request must carry the description and parameter schema of all tools, driving up token consumption, and the more candidate tools there are, the more likely the model is to pick the wrong tool and construct incorrect call arguments. Dynamically loaded tools let you inject tools on demand during a conversation: mount only a few core tools first, and when the conversation reaches a point where a specific tool is needed, dynamically insert it into messages, reducing token consumption and improving tool-selection accuracy.
Dynamically loaded tools are currently supported only by kimi-k3. Requesting them on other models returns a tokenization failed error.

Inject tool declarations in messages

Insert a message with role set to system into messages, and declare the tools to load through that message's tools field. The format is identical to the request's top-level tools field, and you must provide the complete tool information (name, description, parameters).
  • A system message carrying tools has the same status as an ordinary message: the tools become visible to the model starting from the position where that message appears in the messages list.
  • Dynamically loaded tools coexist with the global tools declared in the request's top-level tools field; the model can see both kinds of tools at the same time.
  • A dynamically injected tool declaration must be a complete tool definition; you cannot pass only a tool name or reference a globally declared tool.
  • A system message carrying tools must not also carry a content field, or the request fails with a 400 error. When using the OpenAI SDK, you can pass the tools field through directly in messages.
  • Python
  • curl
import os
from openai import OpenAI

client = OpenAI(
  api_key=os.getenv("DASHSCOPE_API_KEY"),
  base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
)

completion = client.chat.completions.create(
  model="kimi-k3",
  messages=[
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Please calculate 23 * 47 for me."},
    # Dynamically load a tool: insert a system message carrying a tools field into the conversation
    {
      "role": "system",
      "tools": [
        {
          "type": "function",
          "function": {
            "name": "Calculator",
            "description": "Calculator; evaluates a single arithmetic expression only",
            "parameters": {
              "type": "object",
              "properties": {
                "expr": {
                  "type": "string",
                  "description": "Arithmetic expression supporting basic operations, exponentiation, logarithms, and trigonometric functions, in JavaScript syntax",
                }
              },
              "required": ["expr"],
            },
          },
        }
      ],
    },
  ],
)
print(completion.choices[0].message.tool_calls)

On-demand loading combined with a search tool

There is no dedicated tool-search API. When there are many tools, you can combine a custom search tool with dynamically loaded tools to load tools on demand:
  1. At the start of the session, declare in the top-level tools only a search_tools tool implemented by your application backend (it returns matching tool names and summaries by keyword), plus a few core tools that may be used every turn.
  2. Declare the searchable keywords (such as a tool catalog or domain tags) in the system prompt to guide the model to call search_tools first when it needs a tool. You can set tool_choice: "required" on the first request to force the model to search before answering, then restore tool_choice to "auto" after the search. Changing tool_choice does not break the prefix cache.
  3. Based on the results returned by search_tools, the application dynamically inserts the complete declarations of the corresponding tools into messages through a system message carrying tools.
  4. The model can then call these newly loaded tools directly in subsequent generation.
This way, no matter how large the total number of tools is, only a few tool declarations are actually present in each request, keeping the context window and the model's selection pressure under control.

Notes

  • Dynamic tool declarations take effect per request and are not remembered by the server. Whether to keep carrying them in the next request is up to the integrator: keep carrying them and the tools remain available (which also helps hit the prefix cache); stop carrying them and the declaration expires — if the tool is not declared elsewhere, the model cannot call it, and the prefix cache after the change point may miss.
  • Appending a dynamic tool declaration at the end of messages does not affect the cache of the existing prefix; deleting or modifying earlier tool declarations may affect cache hits after the change point. Declaring global tools in the request's top-level tools field also does not affect cache hits.
  • A system message carrying tools also consumes context length, so inject only the tools truly needed by the current conversation.
  • Dynamic tool declarations use exactly the same format as global tools declarations, so integrators do not need to maintain two schemas.

Supported features

Featurekimi-k3kimi-k2.7-code
Multi-turn conversation
Deep thinking✓ (always on)✓ (always on)
Function calling
Structured output
Web search
Context cache

Parameter defaults

Parameterkimi-k3kimi-k2.7-code
enable_thinkingtrue (thinking mode only)true (thinking mode only)
temperature1.01.0
top_p0.950.95
presence_penalty0.00.0

Models and billing

The Kimi series are large language models from Moonshot AI.
  • kimi-k3: Kimi's most capable flagship model to date. It always reasons and uses preserved thinking (thinking-only mode). Supports text and image input (video input is not supported), conversation and agent tasks, and dynamic tool loading.
  • kimi-k2.7-code: The most capable Kimi model for coding. It follows long-context instructions more reliably and achieves higher success rates on programming tasks. Supports text, image, and video input, thinking mode, conversation, and agent tasks.
For pricing and context window details, see the Model Marketplace. Billing is based on input and output token counts.
In thinking mode, the chain of thought counts as output tokens.

Error codes

If a model call fails and returns an error message, see Error codes.