Seu array messages termina com um turno do assistant, e os modelos Claude 4.6 e posteriores interpretam isso como prefill e recusam a solicitação. Termine a conversa com uma mensagem do usuário e mova o que o prefill fazia — forçar JSON, pular um preâmbulo, manter uma persona ou retomar uma resposta interrompida — para o substituto documentado pela Anthropic.
O erro
{
"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_..."
}Causas e soluções em resumo
| Causa | Solução |
|---|---|
| A última entrada em messages tem role: "assistant" | Isso é um prefill, e os modelos Claude 4.6 e posteriores o rejeitam. Termine com uma mensagem do usuário. |
| Um framework deixou uma mensagem vazia do assistant por último | Remova a mensagem final do assistant que não tem conteúdo antes de enviar. |
| Você usou “{” como prefill para forçar JSON | Use saídas estruturadas (output_config.format) no lugar. |
| Você usou prefill para pular um preâmbulo, manter uma persona ou retomar uma resposta interrompida | Uma instrução no system prompt, uma função no system prompt ou uma continuação em um turno do usuário. |
| Um gerenciador de memória, loop de agente ou handoff deixou um turno do assistant por último | Normalize o final uma vez, imediatamente antes da solicitação, em vez de fazer isso em cada caminho do código. |
Quais modelos Claude rejeitam prefill (em setembro de 2026)
A referência de erros da Anthropic é direta: os modelos Claude 4.6 e posteriores não aceitam o preenchimento da última mensagem do assistant, e uma solicitação que faz isso retorna exatamente este 400 (https://platform.claude.com/docs/en/api/errors#prefill-not-supported). Pelo nome, isso inclui Claude Opus 4.6 e todos os Opus posteriores, incluindo Claude Opus 5.5 (https://platform.claude.com/docs/en/models/opus-5-5/migration-guide); Claude Sonnet 4.6 e Claude Sonnet 5 (https://platform.claude.com/docs/en/models/sonnet-5/migration-guide); e Claude Fable 5 e Fable 5.1 (https://platform.claude.com/docs/en/models/fable-5-1/migration-guide). Claude Haiku 4.5 ainda aceita prefill, assim como Claude Sonnet 4.5 e Claude Opus 4.5 — por isso esse erro costuma surgir com uma mudança de model-ID, e não de código. Mensagens do assistant anteriores na conversa, incluindo exemplos few-shot, não são afetadas.
Termine com um turno do usuário — incluindo a correção de uma linha
Muitas vezes ninguém escreveu um prefill de propósito: algo na pilha colocou uma mensagem do assistant por último. Relatos públicos atribuem isso a um gerenciador de memória que adiciona uma mensagem (Strands issue #1694), a um loop de agente que faz uma nova solicitação depois de um turno que considera incorretamente inacabado (opencode issue #46415), a respostas consecutivas e handoffs de agentes (LiveKit issue #4907) e a uma mensagem vazia do assistant deixada no final (AutoGen PR #7931). Se a mensagem final estiver vazia, remova-a — essa é a correção de uma linha. Se ela contiver texto que você quer continuar, siga a orientação de migração da Anthropic para continuações: coloque a continuação em uma mensagem do usuário que cite onde a resposta parou. Uma exceção documentada que deve ser mantida: um pause_turn de ferramentas do servidor, como pesquisa na web, deve ser continuado reenviando o conteúdo pausado do assistant sem alterações (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)Substitua a função que o prefill desempenhava
O guia de prompting da Anthropic mapeia cada uso antigo de prefill para um substituto (https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#migrating-away-from-prefilled-responses). Para forçar JSON: use saídas estruturadas, que restringem a resposta ao seu schema e estão disponíveis no Claude Haiku 4.5, Sonnet 4.5, Opus 4.5 e em todos os modelos posteriores (https://platform.claude.com/docs/en/build-with-claude/structured-outputs); para YAML ou outro formato, o guia recomenda solicitar a estrutura e tentar novamente quando ela não for respeitada. Para classificação: use uma ferramenta com um enum dos rótulos válidos ou saídas estruturadas. Para pular um preâmbulo: uma instrução no system prompt, como “Responda diretamente, sem preâmbulo.” Para manter uma persona: defina a função no system prompt (https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#give-claude-a-role) e coloque lembretes periódicos no turno do usuário, em vez de usar um assistant predefinido. Para uma resposta interrompida: use a continuação no turno do usuário descrita acima. Forçar uma chamada de ferramenta não é um substituto direto em todos os casos — Claude Fable 5.1 e Claude Opus 5.5 rejeitam tool_choice any e tool com um 400 próprio (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
}
}
}
}'Se você estiver chamando pela Kunavo
A Kunavo encaminha um turno final do assistant; ela não o corrige. /v1/messages envia seu array messages ao upstream sem alterações, e em /v1/chat/completions o tradutor transporta uma mensagem final com role: "assistant" como um turno final do assistant na solicitação ao Claude — inclusive quando vazia, portanto remova as mensagens vazias por conta própria. A Anthropic rejeita um turno final predefinido em todos os modelos claude-* que servimos, exceto claude-haiku-4-5, e esse 400 chega até você com o texto da mensagem intacto, seguido pelo request id do upstream: no formato da Anthropic em /v1/messages, com tipo invalid_request_error como na API da Anthropic (até 24 de setembro de 2026, era api_error), e no formato da OpenAI em /v1/chat/completions (type upstream_error, code upstream_400). Um 400 nunca é repetido em outro canal, e a chamada com falha é registrada com custo zero. Para JSON, envie um schema em vez de um prefill: /v1/messages encaminha output_config como você o enviou, e em /v1/chat/completions um response_format do tipo json_schema é traduzido para output_config.format. Em 2026-09-24, esse campo restringia a resposta ao schema em todos os modelos claude-* que servimos. Um response_format json_object não tem equivalente no Claude e não é aplicado, e um schema enviado junto com um turno final predefinido gera seu próprio 400, inclusive em claude-haiku-4-5: "When using output format, pre-filling the `assistant` response is not supported." O endpoint nativo e o formato de solicitação que ele encaminha estão documentados em na documentação da API Messages.
Perguntas frequentes
Quais modelos Claude não aceitam prefill de mensagem do assistant?
Segundo a documentação da Anthropic em setembro de 2026, todos os modelos Claude a partir do 4.6: Claude Opus 4.6 e todos os Opus posteriores, Claude Sonnet 4.6 e Sonnet 5, Claude Fable 5 e 5.1, e os modelos Mythos. Claude Haiku 4.5, Sonnet 4.5 e Opus 4.5 ainda aceitam prefill.
Como forçar uma saída JSON do Claude sem prefill?
Use saídas estruturadas: passe um schema JSON em output_config.format e a resposta ficará restrita a ele. Por meio de um endpoint compatível com OpenAI, envie-o como response_format com type json_schema; a Kunavo traduz isso para output_config.format. A Anthropic informa que o preenchimento de mensagens é incompatível com saídas JSON em qualquer caso.
Por que recebo esse erro se nunca usei prefill?
Algo na sua pilha deixou uma mensagem do assistant por último — um gerenciador de memória ou sessão, um loop de agente que faz uma nova solicitação após um turno, um handoff de agente ou uma mensagem vazia que ninguém removeu. Registre o array messages exatamente como é enviado; seu último elemento terá role: "assistant".
Ainda posso incluir mensagens do assistant na conversa?
Sim. Apenas o turno final é restrito; mensagens anteriores do assistant, incluindo exemplos few-shot, não são afetadas.
Por que isso também acontece por meio de um endpoint compatível com OpenAI?
Porque o gateway transporta sua mensagem final com role: "assistant" como um turno final do assistant no Claude — o mesmo prefill, apenas remodelado. O tradutor de chat da Kunavo faz exatamente isso, e a mesma mensagem já foi relatada por outros gateways compatíveis com OpenAI (opencode issue #13768). A correção é a mesma: termine com uma mensagem do usuário.
Guias relacionados
- Claude API 400 “tool_use ids foram encontrados sem blocos tool_result” — a regra de ordenação
- “`temperature` e `top_p` não podem ser especificados simultaneamente para este modelo” — envie um deles e, nos modelos Claude mais recentes, nenhum
- “Unsupported parameter: 'max_tokens' is not supported with this model” — use max_completion_tokens
- API do Claude — o guia completo para chamar o Claude no Kunavo
Mais detalhes sobre o significado dos erros estão em referência de erros; obter uma chave leva um minuto por meio de cadastro e da guia de autenticação.