Bu bir araç hatası değil, mesaj sıralama hatasıdır. Claude, bir assistant dönüşündeki her tool_use bloğunun hemen sonraki user dönüşünde aynı kimliklere sahip bir tool_result bloğuyla yanıtlanmasını gerektirir — arada hiçbir şey olmamalıdır. Döngünüz birini düşürmüştür; genellikle bunun nedeni aracın hata vermesidir.
Hata
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "messages.1: tool_use ids were found without tool_result blocks immediately after: toolu_01A... Each tool_use block must have a corresponding tool_result block in the next message."
}
}Nedenler ve çözümler özeti
| Neden | Çözüm |
|---|---|
| Aracınız hata verdi, bu yüzden hiçbir şey eklenmedi | Yine de is_error: true ve hata metni içeren bir tool_result gönderin. |
| tool_result daha sonraki bir mesaja yerleştirildi | Tam olarak hemen sonraki mesaj olmalıdır — arada hiçbir assistant veya user dönüşü bulunamaz. |
| tool_use_id eşleşmiyor | tool_use bloğundaki kimliği aynen geri yansıtın; yeniden üretmeyin. |
| Geçmiş, gidiş-dönüşün ortasında kırpıldı | Kırpmayı her zaman tam araç gidiş-dönüşlerinde yapın; tek bir turun iki yarısı arasından asla kırpmayın. |
Değişmez kural, tek seferde
Bir asistan turundaki her tool_use bloğu, hemen sonraki kullanıcı mesajında aynı tool_use_id'yi taşıyan tam olarak bir tool_result bloğu gerektirir. Tek turdaki birden fazla tool_use bloğu, sonraki tek mesajda birden fazla tool_result bloğu gerektirir. Bu iki turun arasına hiçbir şey giremez.
Araç başarısız olsa bile her zaman yanıt verin
Model, başarısız bir aracı gayet iyi yönetebilir; eksik bir aracı yönetemez. Hatayı tool_result olarak döndürmek konuşmanın geçerliliğini korur ve genellikle 400 hatası yerine makul bir kurtarma sağlar.
results = []
for block in (b for b in resp.content if b.type == "tool_use"):
try:
out = run_tool(block.name, block.input)
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": str(out),
})
except Exception as e:
# A failed tool still owes the model an answer.
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": f"Tool failed: {e}",
"is_error": True,
})
messages.append({"role": "assistant", "content": resp.content})
messages.append({"role": "user", "content": results})Göndermeden önce son iki turu doğrulayın
Bir düzine satırlık assertion, bunu ağdan gelen bir 400 yerine çağrı noktasında yakalar — asistan turundaki tool_use kimliklerini dolaşın ve sonraki kullanıcı turunun tümünü yanıtladığını doğrulayın.
def check_pairs(messages):
for i, m in enumerate(messages):
if m["role"] != "assistant" or not isinstance(m.get("content"), list):
continue
ids = {b.get("id") for b in m["content"]
if isinstance(b, dict) and b.get("type") == "tool_use"}
if not ids:
continue
nxt = messages[i + 1] if i + 1 < len(messages) else None
answered = {b.get("tool_use_id") for b in (nxt or {}).get("content", [])
if isinstance(b, dict) and b.get("type") == "tool_result"}
missing = ids - answered
assert not missing, f"message {i}: unanswered tool_use {missing}"Geçmişi gidiş-dönüş sınırlarında kırpın
Mesaj sayısına göre yapılan bağlam penceresi kırpması, er ya da geç bir tool_use ile tool_result arasını kesecektir. Neyin atılacağına karar verirken çifti bölünemez tek birim olarak ele alın.
Kunavo üzerinden çağrı yapıyorsanız
Bu yük size aittir ve Kunavo bunu örtbas etmez: 400 yeniden denenemezler listesindedir; bu nedenle hatalı bir tool gidiş-dönüşü, aynı hataya ulaşmak için ikinci bir upstream gidiş-dönüş gecikmesi harcamadan bir kez başarısız olur ve reddedilen istek sıfır maliyetle kaydedilir. /v1/messages üzerinde doğrudan Messages protokolüyle konuştuğunuz için tools, tool_use ve tool_result blokları çevrilmeden iletilir. Burada 400, Anthropic API'sinde olduğu gibi typed invalid_request_error olarak geri döner; upstream'in mesaj metnini, ardından upstream'in kendi request id'sini içerir ve request_id alanı bulunmaz. 24 Eylül 2026'ya kadar tür api_error olarak okunuyordu; bu nedenle günlükleriniz daha eskiye gidiyorsa HTTP durumuna ve mesaj metnine göre dallanın.
Sık sorulan sorular
Yanıtlamak yerine tool_use turunu tamamen kaldırabilir miyim?
Evet, asistan turunun tamamını kaldırırsanız. Geçersiz olan, tool_use'u tutup tool_result'ı eksik bırakmaktır.
OpenAI uyumlu uç nokta da aynı kurala mı sahip?
Aynı eşleştirme gerekir, ancak farklı adlandırılır — asistan mesajında tool_calls, ardından her çağrı için tool_call_id taşıyan bir role: "tool" mesajı.
Reddedilen bir istek ücretlendirilir mi?
Kunavo'da hayır. Başarısız istekler sıfır maliyetle kaydedilir ve ücretlendirilen bir upstream çağrısına hiçbir zaman ulaşmaz.
İlgili kılavuzlar
- model_not_found / 404 — Claude, Gemini ve ağ geçitlerinde model adlandırması
- Claude API 429 rate_limit_error — nedenleri ve işe yarayan çözüm
Hata anlamlarına ilişkin daha fazla bilgi hata referansı bölümünde; anahtar almak kayıt ve kimlik doğrulama kılavuzu üzerinden bir dakika sürer.