Há dois problemas diferentes nessa tabela. O índice de memória e o card do grafo não mudam durante a sessão — eram reenviados a cada turno e nunca cacheados. Os corpos de skill já estavam na conversa — as mesmas skills casavam de novo e de novo, mandando o texto completo toda vez.
A curadoria resolve os dois sob uma regra única:
O que o modelo continua recebendo
Nada sai do alcance do modelo. O que muda é onde cada bloco fica e quando ele é pago.- Prefixo cacheado
- Sufixo por turno
- A um pull de distância
Estável pela conversa inteira, então o provider serve como leitura quente de cache (~0,1x input) em vez de preço cheio a cada turno:
- banner de modo e diretiva de idioma
- a metade do workspace que não depende da pergunta — arquivos de bootstrap (
SOUL.md,USER.md,AGENTS.md…), índice de memória, card do grafo de conhecimento - anexos de
/context, skills fixadas - catálogo de tools MCP, listado por nome
Como o modelo sabe quando puxar
Ele nunca fica adivinhando. Todo adiamento no prompt cita a chamada exata que o recupera:- um corpo de skill que já está antes na conversa vira “Body already provided earlier in this conversation — follow that copy; it has not changed. If it is no longer visible above, call context_pull with kind=skill and this skill’s name.”
- um corpo deixado de fora pelo orçamento de injeção vira “Before applying this skill, call context_pull with kind=skill…”
- o bloco MCP diz quantas tools existem e que
context_pullcomkind=mcp_toolslê o que cada uma faz
context_pull — a terceira exceção sancionada do chat
O chat é tool-less por design. context_pull entra junto de ask_user, knowledge, @graphview e memória como exceção sancionada — e é a mais estreita delas: não executa nada, não escreve nada e não alcança nada fora do processo. Ela relê material que o próprio ChatCLI curou para fora do turno atual.
{"cmd":"skill","skill":"x"} e {"kind":"skill","args":{"name":"x"}} funcionam igual, porque parsing estrito só ensina o modelo a repetir a chamada ao custo de um round trip.
CHATCLI_CHAT_CONTEXT_PULL=false.
A de-duplicação de skills é verificada contra o histórico vivo
Um corpo de skill vira “você já tem isso” apenas enquanto a cópia anterior está genuinamente na conversa. Isso é verificado contra o histórico vivo a cada turno, e não rastreado pelos lugares que podem descartar uma mensagem — então compactação,/clear, /rewind, restauração de checkpoint e carga de sessão fazem o corpo voltar a ser embutido automaticamente. Os corpos têm fingerprint, então editar a skill em disco também força o re-embutido.
O TTL do prompt cache é escolhido por evidência
A entrada de cache de 1 hora da Anthropic custa 2x a escrita, em vez de 1,25x. Escolher isso de antemão é uma aposta: perda pura numa sessão que nunca pausa, ganho grande numa que pausa. O ChatCLI agora espera pela resposta. Quando a sessão vê o próprio prefixo expirar numa pausa que a hora teria coberto, ele pede a hora — uma vez, sem volta, nunca por cima de umCHATCLI_PROMPT_CACHE_TTL explícito e nunca num modelo que não suporta. Uma execução one-shot jamais chega à segunda observação, então permanece no TTL curto.
O /cost mostra o TTL em vigor na linha de cache.
Como enxergar
O/context status quebra o prompt atual seção por seção, marca quais seções ficam no prefixo cacheado e mostra o que o provider realmente contou na última chamada ao lado da projeção local — dá para ver a estimativa derivando, em vez de descobrir quando a compactação dispara cedo demais.
Agent e coder
Os mesmos dois movimentos valem lá, adaptados ao que aqueles loops já tinham. O split do workspace é idêntico. ObuildAgentSystemMessage tinha o bloco de workspace inteiro do lado volátil, então a metade que não depende do turno era reenviada a preço cheio a cada turno do run. Agora ela carrega breakpoint de cache, colocada por último na região cacheada para que o prefixo core/tools/orchestrator continue byte a byte idêntico e siga acertando. Runs de agent têm muitos turnos, então a economia compõe mais que no chat.
A de-duplicação de skills lá é entre runs. O re-scan mid-loop já garante que uma skill dispara no máximo uma vez por run (dedup set próprio, orçamento de bytes por run e skill aging que colapsa blocos antigos). O que ele não enxergava era o run anterior: uma sessão com vários /coder reconstruía o bloco inicial de skills do zero e reenviava corpos que a conversa já carregava. A verificação é a mesma do histórico vivo que o chat usa; a forma adiada aponta para o source path da skill, que agent e coder simplesmente leem — então ela arma incondicionalmente, sem depender do context_pull.
O catálogo MCP não muda lá: agent e coder recebem definições de tool reais, não um catálogo em prosa.