Mensagens de sistema e alterações de ferramentas no meio da conversa
Altere instruções de sistema ou a disponibilidade de ferramentas no meio de uma conversa sem invalidar o prefixo em cache que veio antes delas.
As instruções de sistema normalmente ficam no campo system de nível superior, antes de todas as mensagens da conversa. Essa posição é ótima para o prompt caching (cache de prompt): o prompt do sistema faz parte do prefixo estável, então os turnos subsequentes acertam o cache. É uma posição ruim para instruções que você só descobre que precisa no meio de uma sessão, porque editar o campo system de nível superior altera o início do prompt e invalida o cache de tudo o que vem depois.
As mensagens de sistema no meio da conversa fecham essa lacuna. Você anexa uma mensagem {"role": "system"} no ponto da conversa em que a nova instrução se torna relevante, em vez de editar o campo system de nível superior. O prefixo em cache permanece o mesmo, então a próxima requisição ainda o lê do cache, e a nova instrução ainda é aplicada como uma instrução de sistema, e não como texto comum do usuário.
Alterações de ferramentas no meio da conversa
O array tools fica ainda mais cedo no prefixo da requisição com hash do que o campo system de nível superior, então editá-lo invalida o cache de prompt de toda a conversa. As alterações de ferramentas no meio da conversa são a contraparte, para ferramentas, das mensagens de sistema no meio da conversa. Em vez de fixar a lista de ferramentas por toda a vida da conversa, você altera quais ferramentas são oferecidas ao modelo entre os turnos: declare o conjunto completo de ferramentas em tools antecipadamente e, em seguida, use blocos tool_addition e tool_removal para oferecer uma ferramenta ao modelo, ou retirá-la, a partir de um ponto específico da conversa em diante. O array tools em si nunca muda, então o prefixo em cache permanece intacto.
tool_addition e tool_removal são blocos de conteúdo no array content de uma mensagem role: "system", e podem ser misturados com blocos text na mesma mensagem. A mensagem segue as mesmas regras de posicionamento de qualquer mensagem de sistema no meio da conversa (consulte Limitações), e a alteração se aplica daquele ponto da conversa em diante. O campo tool de cada bloco referencia uma ferramenta em vez de defini-la: {"type": "tool_reference", "name": "..."} nomeia uma ferramenta declarada no array tools da requisição, e as ferramentas do conector MCP podem ser referenciadas individualmente com mcp_tool_reference (server_name e name) ou como um conjunto de ferramentas inteiro com mcp_toolset_reference (server_name). Referenciar um nome que não está declarado em tools retorna um erro 400.
Toda ferramenta declarada em tools é oferecida ao modelo desde o início da conversa, a menos que seja declarada com defer_loading: true, o que a mantém retida até que um bloco tool_addition a exponha. tool_addition também volta a oferecer uma ferramenta que um tool_removal anterior retirou.
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=1024,
betas=["mid-conversation-tool-changes-2026-07-01"],
# O conjunto completo de ferramentas é declarado de antemão e nunca muda, então o
# prefixo em cache permanece intacto.
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a location.",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "City name"},
},
"required": ["location"],
},
},
],
messages=[
{
"role": "user",
"content": "Say OK.",
},
# Retira get_weather deste ponto em diante. O bloco referencia
# a ferramenta pelo nome em vez de editar `tools`, então os turnos anteriores ficam
# idênticos byte a byte e o cache ainda acerta.
{
"role": "system",
"content": [
{
"type": "tool_removal",
"tool": {"type": "tool_reference", "name": "get_weather"},
},
],
},
],
)
for block in response.content:
if block.type == "text":
print(block.text)As alterações de ferramentas no meio da conversa estão em beta. Para usá-las, inclua o cabeçalho beta mid-conversation-tool-changes-2026-07-01 em suas requisições.
Quando usar uma mensagem de sistema no meio da conversa
O cache de prompt calcula o hash do prefixo da requisição em ordem: tools, depois system, depois messages. Um acerto de cache exige que o prefixo corresponda exatamente a uma requisição recente, byte a byte, até o ponto de interrupção do cache.
Essa ordenação significa que o campo system de nível superior fica perto do início do prefixo com hash. Qualquer alteração nele, mesmo anexar uma frase, produz um hash diferente, e a requisição perde o cache do prompt do sistema e de todas as mensagens em cache depois dele.
As mensagens de sistema no meio da conversa permitem que você adicione a instrução no final do histórico de mensagens. Tudo antes da nova instrução permanece inalterado, então a entrada de cache existente ainda corresponde, e apenas a nova mensagem é processada como entrada nova.
Algumas situações em que isso importa:
- Mudanças de política ou persona no meio da sessão. Uma longa sessão agêntica precisa de uma nova restrição ("de agora em diante, escreva todo SQL como consultas parametrizadas") após dezenas de turnos em cache. Adicioná-la ao campo
systemde nível superior reprocessaria todo o histórico. - Contexto por turno que precisa ser autoritativo. Você quer injetar uma nota de atualidade, um prazo de sessão ou uma mudança de disponibilidade de ferramentas com peso de nível de sistema, e isso muda com frequência demais para ficar no prefixo em cache.
- Lembretes por turno que não devem se acumular. Um harness dá um toque no modelo após cada lote de resultados de ferramentas ("solicite leituras independentes juntas", "o usuário não recebe notícias suas há algum tempo") e quer que o modelo veja apenas a cópia mais recente. Uma mensagem de sistema com escopo de turno é renderizada por um turno e depois não custa nada, sem excluir nada do histórico.
- Mudanças de estado que sua aplicação observa. Sua aplicação percebe algo que Claude deve tratar como um fato de nível de operador: arquivos mudaram no disco, o usuário alternou uma configuração de aprovação automática, as ferramentas disponíveis mudaram ou o orçamento de tokens restante caiu abaixo de um limite.
- Entrada do usuário que não deve interromper um loop agêntico. Um usuário digita uma continuação enquanto Claude ainda está executando ferramentas para a requisição anterior. Repassá-la como uma mensagem de sistema após o próximo resultado de ferramenta permite que Claude incorpore a nova entrada ao trabalho que já está fazendo, em vez de tratá-la como uma nova requisição para a qual deve mudar. Consulte Posicionamento após resultados de ferramentas.
- Mudanças de modo que concedem permissões permanentes. Um modo de nível de sessão pode usar uma mensagem de sistema no meio da conversa para conceder consentimento permanente a uma capacidade cara, como iniciar automaticamente fluxos de trabalho multiagente, com um breve lembrete a cada vários turnos e um aviso de saída quando o modo é desativado. Para um exemplo completo, consulte Construir um modo de orquestração.
Em todos esses casos, você poderia colocar a instrução em uma mensagem user comum, e Claude segue instruções que chegam em turnos de usuário. A diferença é a prioridade: uma mensagem user é tratada como vinda do usuário final, enquanto uma mensagem system é tratada como vinda de você, o operador da aplicação. Quando as duas entram em conflito, as instruções de sistema têm precedência, então use o papel system para fatos e restrições de nível de operador que devem valer mesmo que o usuário final peça algo diferente. Uma mensagem de sistema no meio da conversa mantém essa prioridade de nível de operador sem pagar o custo de perda de cache de editar o campo system de nível superior.
Como funciona
Adicione uma mensagem com "role": "system" ao array messages. Use uma string simples ou blocos de conteúdo para content, da mesma forma que em um turno user ou assistant. A instrução se aplica daquele ponto da conversa em diante. Quando as instruções entram em conflito, mensagens de sistema posteriores têm precedência sobre as anteriores, e mensagens de sistema no meio da conversa têm precedência sobre o campo system de nível superior para os turnos que as seguem.
Você ainda pode definir o campo system de nível superior para instruções que devem se aplicar a toda a conversa. Reserve as mensagens de sistema no meio da conversa para instruções que só se tornam relevantes mais tarde, ou que você deseja adicionar sem invalidar o prefixo em cache.
Uma mensagem role: "system" também pode carregar output_config.effort para alterar o nível de esforço a partir do próximo turno user. Isso está em beta no Claude Fable 5.1, Claude Mythos 5.1 e Claude Opus 5 na Claude API e exige o cabeçalho beta mid-conversation-output-config-2026-07-01. Consulte Esforço por mensagem.
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
# Cache de prompt automático: cada requisição armazena em cache a conversa até o momento,
# e a próxima requisição lê do cache o prefixo inalterado.
cache_control={"type": "ephemeral"},
system="You are a code review assistant. Be concise.",
messages=[
{
"role": "user",
"content": "Review process() in utils.py for performance issues.",
},
{
"role": "assistant",
"content": "The list comprehension is fine for small inputs. For large inputs, consider a generator to avoid materializing the full list.",
},
{
"role": "user",
"content": "Now review the calling code that invokes process().",
},
# O revisor percebe no meio da sessão que todas as sugestões devem
# também passar pela política de tipagem estrita da equipe. Anexar a
# instrução aqui mantém os turnos anteriores idênticos byte a byte, então o
# prefixo armazenado em cache pela requisição anterior ainda é lido do cache.
{
"role": "system",
"content": "From now on, every suggestion must include explicit type annotations.",
},
],
)
for block in response.content:
if block.type == "text":
print(block.text)Este exemplo habilita o cache automático com o campo cache_control de nível superior. O cache de prompt é opcional: se uma requisição não tiver um campo cache_control (automático ou um ponto de interrupção explícito), nada é armazenado em cache e toda requisição paga o preço normal de tokens de entrada pela conversa completa. Com o cache habilitado, anexar a mensagem de sistema deixa os turnos já em cache inalterados, então a requisição que carrega a nova instrução ainda os lê do cache em vez de processá-los novamente. O cache também exige que a conversa atinja o comprimento mínimo de prompt armazenável em cache; um exemplo tão curto quanto este fica abaixo dele, então cache_creation_input_tokens e cache_read_input_tokens permanecem em 0 até que a conversa cresça.
Uma mensagem de sistema no meio da conversa deve seguir imediatamente um turno user (ou um turno assistant que termine em um resultado de ferramenta de servidor), e deve ser a última entrada em messages ou ser imediatamente seguida por um turno assistant. Uma mensagem user que carrega blocos tool_result conta: em um loop agêntico, você pode colocar a mensagem de sistema logo após os resultados de ferramentas, antes do próximo turno de Claude. Qualquer outra posição, incluindo entre um bloco tool_use de assistant e o tool_result que o responde, retorna um erro 400.
Posicionamento após resultados de ferramentas
Em um loop agêntico, a mensagem de sistema vai depois da mensagem user que entrega os resultados de ferramentas. É também aqui que sua aplicação pode repassar a entrada que o usuário digitou enquanto Claude estava trabalhando, para que o novo contexto seja absorvido sem reiniciar o turno:
[
{ "role": "user", "content": "Run the test suite and fix any failures." },
{
"role": "assistant",
"content": [{ "type": "tool_use", "id": "toolu_01", "name": "run_tests", "input": {} }]
},
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "12 passed, 0 failed" }
]
},
{
"role": "system",
"content": "The user sent the following message while you were working: also update the changelog before you finish."
}
]Formule o conteúdo de sistema como contexto, e não como um comando que sobrepõe o usuário. Declare o fato ("nova entrada chegou do usuário: X", "o orçamento de tokens restante agora é Y") e deixe Claude agir com base nele. Claude é treinado para resistir a instruções que parecem agir contra o usuário, e essa proteção ainda se aplica ao papel de sistema, então linguagem como "ignore o que o usuário disse" é menos eficaz do que declarar o que mudou.
Esse padrão serve para repassar entrada do próprio usuário final da conversa. Não o use para passar saída de ferramentas, documentos recuperados ou outro conteúdo de terceiros; mantenha esse conteúdo em blocos tool_result (consulte Limitações).
Mensagens de sistema com escopo de turno
Para limitar uma mensagem role: "system" ao turno atual, defina seu campo clear_at. Ele aceita um de dois valores:
"never"(o padrão): a mensagem é renderizada em sua posição em toda requisição que a inclui. Omitir o campo é idêntico."next_user_message": a mensagem tem escopo de turno. Seu texto é renderizado apenas enquanto nenhuma mensagemrole: "user"vier depois dela emmessages. Uma mensagem de usuário que carrega apenas blocostool_resultconta como mensagem de usuário aqui. Uma vez que exista uma mensagem de usuário posterior, a mensagem é limpa: ela permanece no array, mas não renderiza nada e não custa tokens de entrada, naquela requisição e em todas as posteriores.
As mensagens de sistema com escopo de turno estão em beta. Inclua o cabeçalho beta mid-conversation-system-clear-at-2026-08-21. Sem ele, clear_at é rejeitado como um campo desconhecido.
{
"role": "system",
"clear_at": "next_user_message",
"content": "First privately list what you need next; then request every item that doesn't depend on another's result in this one response."
}O principal uso é um lembrete por turno em um loop de ferramentas. Anexe o lembrete após a mensagem tool_result cada vez que quiser que o modelo o veja, e deixe todas as cópias anteriores onde estão. O modelo vê apenas as cópias que vêm depois da última mensagem de usuário, então o lembrete nunca se acumula. Nada anterior em messages muda, então o cache de prompt continua correspondendo. No Claude Fable 5.1, isso também mantém os blocos de pensamento posteriores válidos: excluir um lembrete anterior alteraria a conversa antes desses blocos e falharia na verificação de conversa, enquanto uma mensagem limpa permanece no array e deixa essa conversa inalterada.
A requisição a seguir é uma etapa posterior de um loop de agente. messages[3] foi renderizada na requisição anterior, quando era a última mensagem do array. Uma vez que messages[5] (uma mensagem de usuário posterior) existe, messages[3] é limpa: a mensagem limpa permanece no array, então a conversa antes do bloco de pensamento em messages[4] fica inalterada, mas o modelo não vê mais seu texto. messages[6] e messages[7] são ambas renderizadas, em ordem.
{
"model": "claude-fable-5-1",
"max_tokens": 16000,
"messages": [
{ "role": "user", "content": "Fix the failing test." },
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "", "signature": "..." },
{
"type": "tool_use",
"id": "toolu_01",
"name": "read_file",
"input": { "path": "test_auth.py" }
}
]
},
{
"role": "user",
"content": [{ "type": "tool_result", "tool_use_id": "toolu_01", "content": "..." }]
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "Request independent reads in one turn."
},
{
"role": "assistant",
"content": [
{ "type": "thinking", "thinking": "", "signature": "..." },
{
"type": "tool_use",
"id": "toolu_02",
"name": "read_file",
"input": { "path": "auth.py" }
},
{
"type": "tool_use",
"id": "toolu_03",
"name": "read_file",
"input": { "path": "tokens.py" }
}
]
},
{
"role": "user",
"content": [
{ "type": "tool_result", "tool_use_id": "toolu_02", "content": "..." },
{
"type": "tool_result",
"tool_use_id": "toolu_03",
"content": "...",
"cache_control": { "type": "ephemeral" }
}
]
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "Request independent reads in one turn."
},
{
"role": "system",
"clear_at": "next_user_message",
"content": "The shell exited with status 137."
}
]
}Regras para mensagens com escopo de turno:
- Reenvie mensagens limpas literalmente. Uma mensagem limpa ainda faz parte do histórico da conversa. Reconstruí-la a partir do estado atual (uma nova contagem de tokens, um timestamp), descartá-la como redundante ou alterar seu valor de
clear_até uma edição em uma mensagem anterior. O cache de prompt falha a partir daquele ponto e, no Claude Fable 5.1, todo bloco de pensamento produzido depois dela falha na verificação de conversa. - Somente texto.
contenté um ou mais blocostext(ou uma string). Blocostool_additionetool_removalretornam um erro 400 em uma mensagem com escopo de turno, assim comooutput_config. Use uma mensagemrole: "system"separada semclear_atpara esses casos. - Sem
cache_controlem seus blocos. Uma mensagem limpa nunca faz parte de uma chave de cache, então um ponto de interrupção nela nunca poderia corresponder. Coloque o ponto de interrupção no último bloco do turno de usuário anterior, como o exemplo faz. O campo de cache automático de nível superior ignora mensagens com escopo de turno ao escolher um ponto de interrupção. Na requisição que limpa uma mensagem, o prefixo em cache reutilizável termina no turno de usuário antes dela, então apenas o único turno de assistente entre essa mensagem e a nova mensagem de usuário é reprocessado. - As regras de posicionamento ainda se aplicam, limpa ou não. Uma mensagem com escopo de turno deve seguir um turno
user(ou um turnoassistantque termine em um resultado de ferramenta de servidor) e preceder um turnoassistantou encerrar o array, como qualquer mensagem de sistema no meio da conversa. Uma que encerra o array sempre é renderizada. Uma seguida diretamente por outra mensagemuseré um erro 400, não uma mensagem limpa: coloque todos os resultados de uma rodada de ferramentas em uma única mensagem de usuário e os lembretes depois dela. - Turnos de assistente não a limpam. Um turno de assistente pré-preenchido ou pausado após a mensagem, ou um loop de ferramentas do lado do servidor, não adiciona nenhuma mensagem de usuário, então a mensagem ainda é renderizada nessa continuação. Para manter um lembrete visível ao longo de um loop de ferramentas do lado do cliente, anexe-o novamente após cada mensagem
tool_result. - A contagem de tokens segue o que é renderizado. Uma mensagem limpa não adiciona nada a
usage.input_tokensnem a uma contagem de tokens. - Histórico importado. Em uma transcrição que você constrói em uma única etapa (exemplos few-shot, uma conversa migrada), uma mensagem com escopo de turno que já tem um turno de assistente e uma mensagem de usuário depois dela é limpa desde a primeira requisição e nunca é renderizada. Esse é o estado correto para um lembrete por turno que você está transferindo. Deixe
clear_atsem definir apenas em uma mensagem que o modelo deve ver em toda requisição.
Os erros de validação são:
messages.3.clear_at: Extra inputs are not permitted
messages.3.clear_at: clear_at is only permitted on role 'system' messages
messages.3.clear_at: Input should be 'next_user_message' or 'never'
messages.3: a turn-scoped system message supports text blocks only (clear_at: 'next_user_message')
messages.3: output_config is not permitted on a turn-scoped system message (clear_at: 'next_user_message')
messages.3.content.0: cache_control is not permitted on a turn-scoped system message (clear_at: 'next_user_message')O primeiro é o erro retornado sem o cabeçalho beta. No Amazon Bedrock e no Google Cloud, passe o valor beta conforme descrito em Cabeçalhos beta.
Pelos SDKs, defina clear_at na entrada role: "system" em messages e envie o cabeçalho beta. O exemplo a seguir anexa um lembrete com escopo de turno após o turno de usuário; na próxima requisição, uma vez que exista uma mensagem de usuário posterior, o lembrete permanece no array, mas não é mais renderizado:
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Draft a short status update on the database migration for the team channel.",
},
# Lembrete com escopo de turno: renderiza neste turno e é limpo quando existir uma mensagem de usuário posterior.
{
"role": "system",
"clear_at": "next_user_message",
"content": "The reader is on call: keep this reply under 50 words.",
},
],
betas=["mid-conversation-system-clear-at-2026-08-21"],
)
for block in response.content:
if block.type == "text":
print(block.text)Combinando com cache de prompt
As mensagens de sistema no meio da conversa e o cache de prompt foram projetados para serem usados juntos:
- Habilite o cache explicitamente. O cache só acontece quando a requisição inclui
cache_control, seja o campo de cache automático de nível superior ou um ponto de interrupção explícito em um bloco de conteúdo. Uma mensagem de sistema no meio da conversa não cria uma entrada de cache por si só, e sem o cache habilitado não há economia a preservar. - Armazene em cache o prefixo estável como de costume. Coloque
cache_controlno último bloco que permanece o mesmo entre requisições, seja o final do camposystemde nível superior, o final das suas definições de ferramentas ou um ponto estável no histórico de mensagens. - Anexe a mensagem de sistema após o ponto de interrupção. Como ela vem depois do prefixo em cache, não altera o hash do prefixo e o cache ainda acerta.
- Uma mensagem de sistema no meio da conversa é ela própria armazenável em cache. Uma vez que está na conversa, ela se torna parte do histórico estável. No próximo turno, você pode mover seu ponto de interrupção de cache para depois dela (ou contar com o cache automático para fazer isso) e a mensagem de sistema é lida do cache como qualquer outro turno.
Evite editar ou remover uma mensagem de sistema no meio da conversa que já foi enviada. Como qualquer outra alteração em mensagens anteriores, isso invalida o cache daquele ponto em diante. No Claude Fable 5.1, isso também invalida os blocos de pensamento em todos os turnos de assistente posteriores. Para orientações que devem se aplicar a apenas um turno, use uma mensagem de sistema com escopo de turno e deixe-a no lugar. Se a instrução precisar evoluir, anexe uma nova mensagem de sistema em vez de reescrever a antiga. Mensagens de sistema consecutivas são aceitas e tratadas como uma única seção de sistema, que segue a mesma regra de posicionamento como um todo.
Limitações
- Não para a primeira mensagem. Uma mensagem
systemque carrega conteúdo não pode ser a primeira entrada emmessages. Use o camposystemde nível superior para instruções que se aplicam desde o início. - O posicionamento é restrito. Uma mensagem
systemque carrega conteúdo (blocostext,tool_additionoutool_removal) deve seguir imediatamente um turnouser(incluindo um turnouserque carrega blocostool_result) ou um turnoassistantque termine em um resultado de ferramenta de servidor, e deve preceder um turnoassistantou encerrar o array. Ela não pode ficar entre um blocotool_usee seutool_result. Colocá-la em outro lugar retorna um erro 400. Uma mensagem comcontentvazio que apenas defineoutput_config.effortnão renderiza nada em sua posição e é aceita em qualquer lugar emmessages, inclusive como primeira ou entre um turnoassistante um turnouser. Mensagenssystemconsecutivas são avaliadas juntas, então adicionar uma mensagem que carrega texto ao lado de uma que define apenas esforço faz com que o grupo inteiro siga a regra de conteúdo. - Mensagens com escopo de turno são somente texto e reenviadas literalmente. Uma mensagem
clear_at: "next_user_message"não carregatool_addition,tool_removal,output_confignemcache_control, e uma vez limpa deve permanecer emmessagesbyte a byte nas requisições posteriores. Consulte Mensagens de sistema com escopo de turno. - Não é lugar para conteúdo não confiável. Claude trata o conteúdo de sistema como instruções do operador e o segue. Não coloque texto de fora da conversa, como saída bruta de ferramentas, documentos recuperados ou conteúdo da web, diretamente em uma mensagem de sistema; fazer isso dá a esse texto autoridade de nível de operador. Mantenha esses dados em blocos
tool_resulte continue seguindo Mitigar jailbreaks e injeções de prompt.
Relacionado
Como o cache funciona, onde colocar pontos de interrupção e como ler os campos de uso de cache.
Descubra exatamente onde duas requisições divergiram quando um acerto de cache que você esperava não acontece.
Estrutura de mensagens, conversas de múltiplos turnos e o campo system.
Escrevendo prompts e instruções de sistema eficazes.
Como os blocos tool_use e tool_result são estruturados no array messages.
Was this page helpful?