distil

Otimização de contexto para agentes de LLM: registro de ferramentas, mascaramento de resultados, orçamento e compactação.

Documentação

distil

npm MCP Registry Smithery license

Install in Cursor Install in VS Code

claude mcp add distil -- npx -y @munhq/distil

Sem conta, sem chave de API, nada para configurar. O pacote é um pequeno wrapper que busca o binário para a sua plataforma e o verifica contra os checksums publicados; install.sh e um binário pré-compilado permanecem para quem não tem Node.


Gravações de cache são 2% dos seus tokens e 28% da sua conta

Isso não é uma afirmação, é uma medição: 13.814 sessões reais de agente, 410.742 turnos de assistente, reexecutados em 29/08/2026. Cada token único nelas foi cobrado 550 vezes, porque uma requisição reenvia todo o histórico.

O que significa que a jogada óbvia — comprimir o histórico — geralmente é a errada. Editar o histórico invalida o prefixo em cache a partir da edição e converte leituras a 0,1x em gravações a 1,25x ou 2,0x. Você não consegue comprimir para sair do custo de contexto. Você só pode recusar admitir tokens.

Where an agent session's tokens go: tool results 59.9%, tool calls 17.9%, user text 14.0%, assistant text 7.2%, thinking 1.0% How much a rewrite must delete just to break even: 8% with one turn left, 46% with ten, 90% with a hundred

Toda ferramenta nesse espaço publica uma porcentagem de economia medida em seus próprios fixtures. O que nenhuma publica é o denominador: qual parcela de uma sessão real ela pode tocar, e quanto essa parcela custa quando o preço de prompt cache é aplicado. distil mede ambos em transcrições que um agente realmente escreveu.

O que é estado da arte, e o que não é. A aritmética de cache abaixo não é uma descoberta. Os https://platform.claude.com/docs/en/build-with-claude/context-editing da Anthropic afirmam que limpar resultados de ferramentas invalida o prefixo em cache, e enviam clear_at_least para que uma limpeza só dispare quando for grande o suficiente para pagar por isso. A regra de ponto de equilíbrio também é publicada: em um cache de 5 minutos, tokens limpos vezes requisições-antes-da-próxima-limpeza devem exceder 11,5 vezes os tokens que você mantém. A tabela neste README reproduz essa regra exatamente — foi derivada de forma independente, o que é uma verificação da aritmética, não uma contribuição.

A lacuna é empírica. Toda fonte diz para calibrar contra sua própria carga de trabalho, e nenhuma entrega uma forma de fazer isso ou publica quais são os valores. É para isso que este crate serve: medir os números que você precisa para escolher clear_at_least, ou para decidir não limpar nada.

A medição completa

Medido em 29/08/2026 em 13.814 transcrições locais do Claude Code — 410.742 turnos de assistente, 212,7M de tokens de texto único. Reproduza no seu próprio corpus com distil-bench ~/.claude/projects; um corpus cresce, então a data importa mais do que as casas decimais.

tokensparcela
resultados de ferramentas127.371.43059,9%
chamadas de ferramentas38.065.12117,9%
texto do usuário29.818.53614,0%
texto do assistente15.402.0777,2%
raciocínio2.076.7161,0%

Esses 212,7M de tokens únicos foram cobrados como 116,9 bilhões de tokens de entrada — cada token pago 550 vezes, porque uma requisição reenvia todo o histórico.

Precifique isso com multiplicadores de cache reais (leitura 0,1x, gravação 1,25x para o TTL de 5 minutos e 2,0x para o de 1 hora):

parcela de tokensparcela do custo
leitura de cache97,9%71,8%
gravações de cache2,0%27,6%

Gravações de cache são 2% dos tokens e 28% da conta. Editar o histórico invalida o prefixo em cache a partir da edição, convertendo leituras a 0,1x em gravações a 1,25x ou 2,0x. Então uma reescrita deve encolher o que invalida abaixo de:

turnos restantesTTL 5mTTL 1h
18,0%5,0%
1046,5%34,5%
2063,5%51,3%
10089,7%84,0%

Essa tabela é a regra de ponto de equilíbrio publicada em outra forma: em cada linha, cleared x turns / kept é igual a 11,5 para o nível de 5 minutos. Use-a para escolher um valor de clear_at_least, e use distil-bench para encontrar a contagem de turnos e o tamanho da cauda para colocar nele — essas são propriedades da carga de trabalho, e são a parte que ninguém publica.

Por unidade de histórico, com 10 turnos restantes: mantê-lo custa 1,00, comprimi-lo custa 2,15, e nunca admiti-lo custa 0. Você não consegue comprimir para sair do custo de contexto. Você só pode recusar admitir tokens.

O que isso significa para usar este crate

Camadas que não tocam o histórico estão do lado certo dessa aritmética: CacheAlignLayer (ordena o conteúdo para que o prefixo estável permaneça em cache) e ScratchpadLayer (mantém o estado de trabalho fora da janela).

Camadas que reescrevem o histórico — MaskingLayer, SummarizationLayer, CompactionLayer — custam mais do que economizam no caso comum. Recorra a elas em apenas um limite: estouro de contexto, onde a alternativa é uma requisição falha e o preço do cache deixa de ser a comparação. BudgetLayer existe para exatamente esse momento.

RegistryLayer e CodeModeLayer são anteriores à Tool Search Tool e à Programmatic Tool Calling da Anthropic, que fazem os mesmos trabalhos nativamente e melhor. Prefira os recursos nativos.

Para limpar resultados antigos de ferramentas, prefira a edição de contexto clear_tool_uses do provedor em vez de MaskingLayer: ela roda no lado do servidor, aceita clear_at_least, e é um parâmetro de API contra uma dependência. Recorra a uma camada aqui apenas quando precisar de um comportamento que a API não oferece.

Medição

cargo build --features bench --release

# Where tokens are, what they cost, and the break-even table
./target/release/distil-bench ~/.claude/projects --json baseline.json

# Sessions that called a given tool, against those that did not
./target/release/distil-bench ~/.claude/projects --split-by-tool mcp__codeindex__

# Export real traffic so other compressors run on the same input
./target/release/distil-bench ~/.claude/projects --export-sessions ./sessions --min-turns 40

Veja bench/README.md para a comparação com ferramentas externas, as regras de justiça, e os dois erros de harness que produziram números errados primeiro.

Retenção

Uma economia só é economia se o modelo ainda consegue responder o que o contexto original conseguia responder.

# No LLM judge: file paths checked against ground truth from the transcript
python bench/artifact_retention.py ./sessions 12

# LLM-graded probes (recall / artifact / continuation / decision)
cargo build --features probe --release
./target/release/distil-probe <session.jsonl> --probes 6 --model qwen2.5:3b

A taxonomia de sondas é da Factory.ai; o artigo deles a define e não envia harness. O juiz é um Completer, nunca um Summarizer — um sumarizador pode impor enquadramento de sumarização, o que reescreve tanto o formato da sonda quanto a instrução de avaliação.

Usando como biblioteca

use distil::{CacheAlignLayer, Ctx, EstimateCounter, Pipeline};

let pipeline = Pipeline::builder()
    .counter(EstimateCounter)
    .layer(CacheAlignLayer::generic())
    .build();

let mut ctx = Ctx::new(messages, tools, turn);
let result = pipeline.optimize(&mut ctx);
println!("{result}");

Este exemplo é mantido compilável como examples/readme_quickstart.rs — execute-o com cargo run --example readme_quickstart.

Cada camada implementa Layer e reporta tokens_before, tokens_after e uma linha de detalhe, para que cada uma possa ser medida por conta própria.

Recursos

recursoo que adiciona
corpuscarregador de transcrições (sem dependências extras)
benchdistil-bench, precisa de tiktoken
probedistil-probe, precisa de proxy para o juiz HTTP
tiktokencontagens BPE precisas em vez da estimativa chars/3,5
proxyservidor HTTP distil-proxy
mcpservidor MCP distil-mcp
metrics/metrics Prometheus

Instalação

./install.sh                       # binaries, the skill, and the MCP server
/plugin marketplace add munhq/distil
/plugin install distil             # Claude Code: skill and server in one step

install.sh instala ambos os binários, coloca a skill em cada home do Claude que encontrar, e registra o servidor MCP no escopo do usuário. Quando o plugin já está instalado, instala apenas o binário, já que o plugin declara o servidor e envia a skill por conta própria.

O plugin inicia o servidor com npx -y @munhq/distil, então precisa de Node. Não pode usar um caminho relativo ao plugin: o Claude Code expande ${CLAUDE_PLUGIN_ROOT} e nada mais faz isso, então um plugin que declara um entrega a todos os outros clientes um caminho literal que não existe. install.sh e os binários pré-compilados permanecem para quem não tem Node.

Suporte de plataforma

plataformabináriosscripts
Linux x86_64 / arm64lançados, testadossim
macOS x86_64 / arm64lançados, compilados no CIsim
Windows x86_64 / arm64lançados, compilados no CIprecisa de um shell: Git Bash, MSYS2 ou WSL

O lançamento publica seis alvos e plugin/test_platform.sh mantém tanto o instalador quanto o launcher do plugin nessa matriz, para que um nome de asset e o nome solicitado não possam divergir. install.sh e o launcher são scripts bash, então no Windows precisam de um shell — cmd e o PowerShell não conseguem executá-los. Os binários Linux são builds musl estáticos, então não precisam de um glibc correspondente.

Ressalvas

O corpus é a máquina de um desenvolvedor. As proporções são a descoberta; os totais absolutos são pessoais. As contagens usam cl100k_base, que aproxima o tokenizador do Claude dentro de alguns por cento. O modelo de ponto de equilíbrio assume um único ponto de interrupção de cache, então uma reescrita confinada à cauda custa menos do que a tabela mostra — isso a refina, não a reverte.

Contribuindo

Instruções de build e teste, as regras que uma mudança de benchmark deve seguir, e o que um pull request precisa antes da revisão: CONTRIBUTING.md. Reporte uma vulnerabilidade em particular — SECURITY.md.

Licença

Licenciado sob qualquer uma de

à sua escolha.

A menos que você declare explicitamente o contrário, qualquer contribuição que você enviar intencionalmente para inclusão neste trabalho, conforme definido na licença Apache-2.0, será duplamente licenciada como acima, sem termos ou condições adicionais.