Kimi K3 Quickstart
This guide summarises the official
Kimi K3 quickstart
so you can get kimi-k3 running fast. The API is OpenAI-compatible — if you already use the
OpenAI SDK, you only need to change the base URL, key and model name. All credit for the underlying
content goes to the official Kimi documentation; see the references at the end.
1. Get started
Grab an API key from the Kimi platform
(there is also a hosted playground if you want to try the model without code). The examples require
Python 3.9+ and the OpenAI SDK. Install the SDK and initialise the client once — later examples reuse
client.
python3 -m pip install --upgrade 'openai>=1.0'
Initialise the client
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.ai/v1",
)
2. Basic call
Pythoncompletion = client.chat.completions.create(
model="kimi-k3",
messages=[{"role": "user", "content": "Introduce Kimi K3 in one sentence."}],
)
print(completion.choices[0].message.content)
cURL
curl https://api.moonshot.ai/v1/chat/completions \
--header "Authorization: Bearer $MOONSHOT_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "kimi-k3",
"messages": [{"role": "user", "content": "Introduce Kimi K3 in one sentence."}]
}'
3. Thinking effort
K3 always has thinking mode enabled, and you configure it with the top-level
reasoning_effort field. Do not use the K2.x thinking parameter.
Thinking effort currently supports only the max level (the default); more levels are coming.
completion = client.chat.completions.create(
model="kimi-k3",
reasoning_effort="max",
messages=[{"role": "user", "content": "Prove that the square root of 2 is irrational."}],
)
print(completion.choices[0].message.content)
content.
4. Streaming
Streaming responses provide separate reasoning_content and final-answer
content deltas.
stream = client.chat.completions.create(
model="kimi-k3",
messages=[{"role": "user", "content": "Explain why the sky is blue."}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta
reasoning = getattr(delta, "reasoning_content", None)
if reasoning:
print(reasoning, end="", flush=True)
if delta.content:
print(delta.content, end="", flush=True)
5. Vision input
For vision messages, content must be an array of objects, not a serialized string.
Public image URLs are not supported — use base64 or an ms://<file-id> upload.
import base64
from pathlib import Path
image_data: str = base64.b64encode(Path("image.png").read_bytes()).decode()
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_data}"},
},
{"type": "text", "text": "Describe this image."},
],
}
],
)
print(completion.choices[0].message.content)
Video file
from pathlib import Path
video = client.files.create(file=Path("video.mp4"), purpose="video")
try:
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{
"role": "user",
"content": [
{
"type": "video_url",
"video_url": {"url": f"ms://{video.id}"},
},
{"type": "text", "text": "Summarize this video."},
],
}
],
)
print(completion.choices[0].message.content)
finally:
client.files.delete(video.id)
6. Structured output
Use json_schema with strict: true to constrain the final
message.content. Parse only that field — not reasoning_content.
import json
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "Lin is 28 years old. Extract the name and age."}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
"required": ["name", "age"],
"additionalProperties": False,
},
},
},
)
person: dict[str, object] = json.loads(
completion.choices[0].message.content or "{}"
)
print(person)
7. Partial mode
Add an assistant message with partial=True at the end of messages to continue
from a text prefix. Prepend that prefix when displaying the final result.
prefix: str = "Conclusion: "
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "In one sentence, explain why API compatibility matters."},
{"role": "assistant", "content": prefix, "partial": True},
],
)
print(prefix + (completion.choices[0].message.content or ""))
8. Custom tools and tool_choice
Use tool_choice="required" on the first turn to require at least one tool call. After
executing every call, return the complete assistant message and append one tool result with the matching
tool_call_id for each call.
import json
from typing import Any
tools: list[dict[str, Any]] = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}
]
messages: list[Any] = [
{"role": "user", "content": "What is the weather in San Francisco today?"}
]
first = client.chat.completions.create(
model="kimi-k3",
messages=messages,
tools=tools,
tool_choice="required",
)
assistant_message = first.choices[0].message
messages.append(assistant_message)
for tool_call in assistant_message.tool_calls or []:
arguments: dict[str, str] = json.loads(tool_call.function.arguments)
result: str = json.dumps(
{"city": arguments["city"], "weather": "sunny", "temperature_c": 24}
)
messages.append(
{"role": "tool", "tool_call_id": tool_call.id, "content": result}
)
final = client.chat.completions.create(
model="kimi-k3",
messages=messages,
tools=tools,
)
print(final.choices[0].message.content)
9. Dynamic tool loading
Place a complete tool definition in a system message without content. The tool
becomes available from that message onward.
from typing import Any
dynamic_messages: list[dict[str, Any]] = [
{"role": "user", "content": "Calculate 23 times 47."},
{
"role": "system",
"tools": [
{
"type": "function",
"function": {
"name": "calculate",
"description": "Evaluate an arithmetic expression",
"parameters": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "The arithmetic expression to evaluate",
}
},
"required": ["expression"],
},
},
}
],
},
]
completion = client.chat.completions.create(
model="kimi-k3",
messages=dynamic_messages,
)
print(completion.choices[0].message.tool_calls)
- Include the complete
name,descriptionandparametersdefinition. - The declaration takes effect at its position in
messages. - Keep this message in later request history; the server does not retain it.
10. 1M context and automatic caching
Context caching is automatic for regular model requests — no cache ID, TTL or extra parameter is required. Keep the long prefix unchanged so later requests can automatically attempt a cache hit.
from pathlib import Path
knowledge: str = Path("knowledge-base.md").read_text(encoding="utf-8")
for question in ["Summarize the key conclusions.", "List three implementation risks."]:
completion = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "system", "content": knowledge},
{"role": "user", "content": question},
],
)
print(completion.choices[0].message.content)
11. Official tools
Official tools are integrated through Formula:
- Fetch tool definitions from the Formula
/toolsendpoint. - Add those definitions to the Chat Completions
toolsfield. - When the model returns
tool_calls, submit each function name and arguments to the Formula/fibersendpoint. - Add the complete assistant message and Fiber output as the corresponding tool message.
- Call Chat Completions again until the model returns a final answer.
12. Important limits
reasoning_effortcurrently supports onlymax; K3 always has thinking mode enabled.max_completion_tokensdefaults to131072and can be set up to1048576.temperature=1.0,top_p=0.95,n=1,presence_penalty=0andfrequency_penalty=0are fixed; omit them from requests.- Return the complete assistant message unchanged in multi-turn conversations and tool calls.
- Vision input does not support public image URLs — use base64 or
ms://<file-id>, and makecontentan array of objects. - Web search is being updated and is not recommended for production workflows in the near term.
13. FAQ and pricing
How is Kimi K3 billed?
Kimi K3 offers a 1M-token context and uses flat pay-as-you-go pricing — there is no tiering by context length. Input (with separate rates for cache hits and misses) and output are billed at uniform per-token prices. See the Kimi K3 pricing page for current rates.
References
-
Kimi API Platform — Kimi K3 Quickstart (primary source for this page):
https://platform.kimi.ai/docs/guide/kimi-k3-quickstart
Retrieved 17 July 2026. Code examples reproduced for educational purposes with attribution.
- Kimi API Platform — playground and API keys: https://platform.kimi.ai/
- Kimi API Platform — model pricing: https://platform.kimi.ai/docs/pricing