Pemecahan masalahPanduan
400 setelah tool call: kirim kembali reasoning_content
Mengapa permintaan kedua dari loop tool-call mengembalikan 400 pada model thinking, perbaikan Python yang menambahkan pesan lengkap, dan kapan Anda bisa melewatinya.

Di halaman ini
Loop agen Anda berfungsi pada permintaan pertama dan gagal pada permintaan kedua dengan 400. Pada model thinking, salah satu penyebab yang terdokumentasi adalah field yang hilang: pesan assistant yang Anda kirim kembali telah kehilangan reasoning_-nya. Jika itu penyebabnya, menambahkan seluruh pesan persis seperti yang dikembalikan API akan memperbaikinya.
Panduan mode thinking DeepSeek (docs, diperiksa 8 November 2026) merangkum aturannya dalam satu kalimat: ketika permintaan memiliki parameter tools, reasoning_ harus dikirim kembali secara utuh di semua permintaan berikutnya, termasuk giliran tanpa tool call. Jika tidak, API mengembalikan 400. Halaman yang sama menyebut thinking aktif secara default, dengan effort high. Jadi loop yang Anda tulis untuk model non-thinking bisa rusak tanpa satu baris pun berubah.
Apa yang terjadi antara permintaan satu dan permintaan dua#
Dalam mode thinking, chain of thought dikembalikan dalam reasoning_, field pada level yang sama dengan content. Bayangkan loop-nya:
- Anda mengirim pertanyaan dan daftar
tools. - Model menjawab dengan
tool_calls(danreasoning_di sampingnya).content - Anda menjalankan tool dan mengirim semuanya kembali: riwayat, pesan assistant, dan pesan
tooldengan hasilnya.
400 muncul pada permintaan di langkah 3 jika pesan assistant di dalamnya tidak memiliki reasoning_.

Halaman DeepSeek mendokumentasikan 400 hanya untuk kasus tool-call ini dan tidak mengutip teks error, jadi perhatikan status HTTP, bukan pesan spesifik, saat Anda memeriksa apakah Anda memiliki masalah ini.
Perbaikannya: tambahkan pesan sebagaimana dikembalikan#
Langkah teraman adalah tidak membangun ulang pesan assistant sama sekali. Ambil dari respons dan tambahkan utuh. Berikut adalah loop lengkap dengan OpenAI Python SDK yang diarahkan ke CheapTokens. Tool cuaca adalah stub, jadi Anda bisa menjalankannya apa adanya.
import json, os
from openai import OpenAI
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
MODEL = "deepseek-ai/DeepSeek-V4-Flash-0731"
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
def get_weather(city):
return {"city": city, "temp_c": 7} # stub
messages = [{"role": "user", "content": "Do I need a jacket in Oslo today?"}]
for _ in range(5): # hard step limit
resp = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
msg = resp.choices[0].message
messages.append(msg.model_dump(exclude_none=True)) # the whole message
if not msg.tool_calls:
print(msg.content)
break
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(get_weather(**args)),
})Satu baris yang penting adalah messages.. SDK menyimpan field yang tidak dikenalnya, jadi apa pun yang API letakkan pada pesan, termasuk reasoning_, ikut terkirim kembali. Jawaban akhir juga ditambahkan, sesuai aturan: setelah tool call pertama, setiap permintaan berikutnya membawa reasoning dari giliran assistant sebelumnya.
Mekanisme tool-call itu sendiri (schema, tool_call_id, parsing argumen) ada di Function calling in Python with an OpenAI-compatible API. Base URL, key, dan model id ada di halaman docs CheapTokens; model yang digunakan di sini dijelaskan di halaman DeepSeek: konteks 380K dan hingga 32.768 token output per jawaban, yang menyisakan ruang untuk thinking panjang plus jawaban.
Tersangka umum: pesan yang dibangun ulang secara manual#
Cara umum kehilangan field ini adalah kode yang tidak menambahkan objek respons tetapi membangun dict baru. Terlihat tidak berbahaya: role, content, tool calls. Framework dan wrapper melakukan hal yang sama ketika menyimpan riwayat dalam format mereka sendiri. Satu field yang tidak pernah mereka kenal adalah yang hilang.

Bandingkan
Dibangun ulang manual vs ditambahkan utuh
Dibangun ulang manual (rusak)
messages.append({
"role": "assistant",
"content": msg.content,
"tool_calls": [c.model_dump() for c in msg.tool_calls],
})Ditambahkan utuh (berfungsi)
messages.append(msg.model_dump(exclude_none=True))Jika Anda menggunakan framework dan tidak bisa menyentuh baris itu, periksa bagaimana ia menyimpan giliran assistant. Riwayat yang melewati serializer yang hanya menyimpan content dan tool_calls memiliki bug yang sama, hanya satu lapisan lebih rendah.
Kapan Anda tidak memerlukan ini#
Tidak setiap panggilan model thinking memerlukan perhatian ekstra. Untuk chat multi-turn tanpa tool, panduan DeepSeek menyebut reasoning_ tidak harus dikirim kembali; jika Anda tetap mengirimnya, ia diabaikan dan reasoning sebelumnya tidak ditambahkan ke konteks. Jadi chat biasa bisa terus membuangnya dan tidak ada yang rusak.
Pilih kasus Anda
Kasus mana milik Anda?
Pilih opsi untuk melihat jawabannya
Permintaan memiliki tools, model sedang thinking
Tambahkan seluruh pesan assistant setiap giliran, baik giliran tool maupun jawaban akhir.
Chat biasa, tanpa parameter tools
Tidak perlu perbaikan. Anda boleh membuang reasoning_ dari riwayat, atau mengirimnya; ia diabaikan.
Framework membangun riwayat untuk Anda
Temukan tempat ia menyerialisasi pesan assistant dan pastikan reasoning_ bertahan. Jika tidak bisa, panggil API dengan loop Anda sendiri untuk bagian tool.
Efek samping yang perlu diingat: riwayat yang Anda kirim ulang adalah input pada setiap permintaan, jadi reasoning panjang dalam loop panjang akan terakumulasi. Cara token thinking dihitung dibahas di Reasoning effort and thinking tokens, dan apa yang harus dilakukan ketika permintaan melebihi batas model ada di Request too long: 400 vs 413.
Jika masih mengembalikan 400#
Periksa secara berurutan:
- Cetak
messagestepat sebelum panggilan yang gagal. Apakah setiap pesan assistant yang berasal dari model memilikireasoning_, jika respons memilikinya?content - Apakah Anda membangun ulang pesan di suatu tempat: helper, kelas riwayat,
json.dumpsdan kembali dengan daftar key tetap? - Apakah pesan
tooluntuk setiaptool_call_idada, dengan id yang sama? - Apakah benar-benar masalah panjang? Permintaan yang melebihi batas konteks adalah 400 yang berbeda, dijelaskan di artikel di atas.
Cek cepat
Apa yang Anda tambahkan setelah model meminta tool?
Tampilkan jawaban
Jawaban: Seluruh pesan assistant sebagaimana dikembalikan, termasuk reasoning_content
tool_calls adalah yang dijawab oleh pesan tool Anda, dan dengan tool dalam permintaan, reasoning harus ikut bersama mereka.
Itulah seluruh perbaikannya: satu append, tanpa membangun ulang. Tambahkan batas langkah dari contoh ke setiap loop yang Anda rilis, agar giliran yang buruk memakan lima permintaan, bukan lima ratus.



