你的 messages 数组以 assistant turn 结尾,而 Claude 4.6 及更高版本会将其视为预填充并拒绝请求。请让对话以 user message 结尾,然后将预填充原本要实现的功能——强制输出 JSON、跳过前导语、保持角色设定或继续被截断的回答——改用 Anthropic 为这些场景记录的替代方式。
错误
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "This model does not support assistant message prefill. The conversation must end with a user message."
},
"request_id": "req_..."
}原因和解决方法一览
| 原因 | 解决方法 |
|---|---|
| messages 中的最后一项具有 role: "assistant" | 这就是预填充,Claude 4.6 及更高版本会拒绝它。请以 user message 结尾。 |
| 某个框架最后留下了一条空的 assistant 消息 | 发送前删除末尾没有内容的 assistant 消息。 |
| 你预填充了“{”以强制输出 JSON | 改用结构化输出(output_config.format)。 |
| 你使用预填充来跳过前导语、保持角色设定或继续被截断的回答 | 改用 system prompt 指令、在 system prompt 中设定角色,或使用 user turn 继续。 |
| 记忆管理器、agent 循环或交接流程最后留下了一个 assistant turn | 在请求发出前统一规范化末尾消息,而不是在每条代码路径中分别处理。 |
哪些 Claude 模型拒绝预填充(截至 2026 年 9 月)
Anthropic 的错误参考说明得很直接:Claude 4.6 及更高版本不支持预填充最后一条 assistant 消息,执行此操作的请求会准确返回此 400 错误(https://platform.claude.com/docs/en/api/errors#prefill-not-supported)。具体包括 Claude Opus 4.6 及之后的所有 Opus(包括 Claude Opus 5.5)(https://platform.claude.com/docs/en/models/opus-5-5/migration-guide);Claude Sonnet 4.6 和 Claude Sonnet 5(https://platform.claude.com/docs/en/models/sonnet-5/migration-guide);以及 Claude Fable 5 和 Fable 5.1(https://platform.claude.com/docs/en/models/fable-5-1/migration-guide)。Claude Haiku 4.5 仍接受预填充,Claude Sonnet 4.5 和 Claude Opus 4.5 也一样——因此这个错误通常是由模型 ID 变更引起,而不是代码变更。对话中更早的 assistant 消息(包括 few-shot 示例)不受影响。
以 user turn 结尾——包括一行修复方案
很多时候,没人有意写入预填充:技术栈中的某个组件把 assistant 消息放在了最后。公开报告将问题追溯到会追加一条 assistant 消息的记忆管理器(Strands issue #1694)、在错误认为某个回合未完成后重新发起请求的智能体循环(opencode issue #46415)、连续回复和智能体交接(LiveKit issue #4907),以及末尾遗留的空 assistant 消息(AutoGen PR #7931)。如果末尾消息为空,删除它——这就是一行修复。如果其中包含你希望续写的文本,请按照 Anthropic 迁移指南中关于续写的说明:将续写请求放入一条 user 消息,并引用答案停止的位置。有一个已记录的例外应保持不变:来自网页搜索等服务器工具的 pause_turn,应通过原样发回暂停的 assistant 内容来继续(https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools)。
from openai import OpenAI
client = OpenAI(base_url="https://api.kunavo.com/v1", api_key="sk-kn-...")
def end_on_user(messages: list[dict]) -> list[dict]:
"""Claude 4.6 and later reject a conversation whose last turn is the assistant's."""
last = messages[-1] if messages else None
if not last or last["role"] != "assistant" or last.get("tool_calls"):
return messages # tool_calls are owed tool results instead
content = last.get("content")
if not content or (isinstance(content, str) and not content.strip()):
return messages[:-1] # the one line: drop an empty tail
tail = content[-200:] if isinstance(content, str) else "..."
return messages + [{
"role": "user",
"content": f"Your previous response was interrupted and ended with {tail!r}. "
"Continue from where you left off.",
}]
messages = [
{"role": "user", "content": "Explain HTTP caching in three bullets."},
{"role": "assistant", "content": ""}, # the empty tail a framework left behind
]
resp = client.chat.completions.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=end_on_user(messages),
)
print(resp.choices[0].message.content)替代预填充原本要实现的功能
Anthropic 的提示工程指南将预填充的每种旧用法都映射到了替代方案(https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#migrating-away-from-prefilled-responses)。强制输出 JSON:使用结构化输出,将响应限制为符合你的模式;Claude Haiku 4.5、Sonnet 4.5、Opus 4.5 以及之后的每个模型均支持该功能(https://platform.claude.com/docs/en/build-with-claude/structured-outputs)。对于 YAML 或其他格式,指南建议请求指定结构,并在格式不符合时重试。分类:使用带有有效标签枚举的工具,或使用结构化输出。跳过前导语:使用系统提示词指令,例如“直接回答,不要添加前导语。”保持角色设定:在系统提示词中设定角色(https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#give-claude-a-role),并在用户回合中定期提醒,而不是在预填充的 assistant 回合中提醒。被截断的回答:使用上面所述的用户回合续写方式。强制工具调用并非在所有场景下都可直接替代——Claude Fable 5.1 和 Claude Opus 5.5 会拒绝 tool_choice 的 any 和 tool 值,并返回相应的 400 错误(https://platform.claude.com/docs/en/api/errors#forced-tool-use-not-supported)。
# Before: messages ended with {"role": "assistant", "content": "{"}
# Kunavo forwards output_config as sent; the reply is constrained to the schema.
curl https://api.kunavo.com/v1/messages \
-H "x-api-key: sk-kn-..." \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Extract the name and email: John Smith <john@example.com>"}
],
"output_config": {
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
},
"required": ["name", "email"],
"additionalProperties": false
}
}
}
}'如果你通过 Kunavo 调用
Kunavo 会转发末尾的 assistant 回合,不会修复它。/v1/messages 会将你的 messages 数组原样交给上游;对于 /v1/chat/completions,转换器会将最后一条 role: "assistant" 消息作为 Claude 请求中的最终 assistant 回合传递过去——包括空消息,因此请自行删除空消息。除 claude-haiku-4-5 外,我们提供的每个 claude-* 模型都会被 Anthropic 拒绝预填充最终回合;该 400 错误会返回给你,错误消息文本保持原样,其后附上上游请求 ID:/v1/messages 使用 Anthropic 格式,错误类型与 Anthropic API 一样为 invalid_request_error(2026 年 9 月 24 日之前为 api_error);/v1/chat/completions 使用 OpenAI 格式(type 为 upstream_error,code 为 upstream_400)。400 错误不会在其他通道上重试,失败调用的费用记录为零。对于 JSON,请发送模式,而不是预填充:/v1/messages 会按你发送的内容转发 output_config;在 /v1/chat/completions 中,type 为 json_schema 的 response_format 会被转换为 output_config.format。在 2026-09-24,该字段会将我们提供的每个 claude-* 模型的回复限制为符合模式。json_object 类型的 response_format 没有对应的 Claude 功能,不会被强制执行;将模式与预填充的最终回合一起发送也会返回相应的 400 错误,claude-haiku-4-5 也不例外:“使用输出格式时,不支持预填充 `assistant` 响应。” 原生端点及其透传的请求格式记录于 Messages API 文档.
常见问题
哪些 Claude 模型不支持 assistant 消息预填充?
根据 Anthropic 截至 2026 年 9 月的文档,所有 4.6 及更高版本的 Claude 模型都不支持:Claude Opus 4.6 及之后的所有 Opus、Claude Sonnet 4.6 和 Sonnet 5、Claude Fable 5 和 5.1,以及 Mythos 模型。Claude Haiku 4.5、Sonnet 4.5 和 Opus 4.5 仍然接受预填充。
如何在不使用预填充的情况下强制 Claude 输出 JSON?
使用结构化输出:在 output_config.format 中传入 JSON schema,响应会被限制在该 schema 内。通过 OpenAI 兼容端点时,以 type 为 json_schema 的 response_format 发送;Kunavo 会将其转换为 output_config.format。Anthropic 列出消息预填充与 JSON 输出在任何情况下都不兼容。
为什么我从未使用预填充,却收到此错误?
你的调用栈中的某个组件将 assistant 消息留在了最后——可能是记忆或会话管理器、在某个 turn 后重新请求的 agent 循环、agent 交接,或无人删除的空 assistant 消息。请准确记录实际发送的 messages 数组;它的最后一个元素会具有 role: "assistant"。
我仍然可以在对话中包含 assistant 消息吗?
可以。只有最后一个 turn 受到限制;更早的 assistant 消息(包括 few-shot 示例)不受影响。
为什么通过 OpenAI 兼容端点也会发生这种情况?
因为网关会将你最后一条 role: "assistant" 消息作为最终的 Claude assistant turn 传递过去——也就是经过重塑的同一个预填充。Kunavo 的聊天转换器正是如此处理,其他 OpenAI 兼容网关也报告过相同消息(opencode issue #13768)。修复方法相同:以 user message 结尾。