Se você usa agentes de IA para programar, provavelmente já tentou economizar usando um modelo mais barato, escrevendo prompts menores ou simplesmente reduzindo o número total de tokens. Tudo isso pode ajudar, mas nenhuma dessas métricas, sozinha, diz quanto uma tarefa realmente vai custar.
Uma requisição com 100 mil tokens pode custar menos que outra com 20 mil. Um modelo mais caro por token pode terminar uma tarefa gastando menos dinheiro. E uma Rule que adiciona tokens em todas as requisições pode, no fim das contas, reduzir seu custo total.
Parece contraditório, mas o motivo é simples: tokens não têm todos o mesmo custo, e o número total de tokens não conta a história inteira.
A composição da requisição importa. Contexto que pode ser reutilizado, informação nova que precisa ser processada e conteúdo gerado pelo modelo têm impactos diferentes no custo. Por isso, duas execuções com a mesma quantidade total de tokens podem terminar com custos completamente diferentes.
E existe outra variável ainda mais importante: quantas execuções foram necessárias para chegar ao resultado.
Um modelo mais barato que erra e precisa de várias tentativas pode custar mais que um modelo caro que resolve o problema de primeira. Da mesma forma, adicionar contexto pode aumentar o custo de uma chamada, mas reduzir o custo total se aquele contexto evitar retrabalho.
Então a estratégia não é simplesmente usar menos tokens, colocar tudo em cache ou escolher sempre o modelo mais barato.
O objetivo é:
Reutilizar barato o que é estável, controlar o que entra novo e evitar trabalho que não aproxima o agente da solução.
Neste post, vou passar por sete estratégias que uso para pensar nisso:
- Proteger o que pode ser reutilizado.
- Controlar o que entra no contexto.
- Usar a ferramenta mais seletiva para buscar informação.
- Carregar conhecimento sob demanda com Rules e Skills.
- Controlar o que o modelo gera.
- Ajustar o esforço e escolher o modelo pelo custo de errar.
- Medir custo por tarefa concluída, não apenas tokens.
No final, todas elas tentam responder à mesma pergunta:
Quanto custou para concluir a tarefa corretamente?
Porque usar menos tokens e precisar de três tentativas não é economia. É só uma execução ruim com uma métrica bonita.
1. Proteja o que pode ser reutilizado
Prompt caching funciona em cima de prefixos. Se uma parte inicial do contexto continua igual entre chamadas, ela pode ser reutilizada em vez de ser processada novamente como conteúdo novo.
Na implementação da Anthropic, a hierarquia do prefixo segue:
tools → system → messages
Alterações em uma parte anterior podem afetar o reaproveitamento das seguintes. A regra é simples:
Estável na frente, volátil no fim.
Quanto maior a parte estável que continua idêntica entre chamadas, maior a possibilidade de reaproveitamento. Pense em instruções de sistema, definições de ferramentas e outras informações que permanecem iguais durante a tarefa.
Evite mexer nas instruções estáveis durante uma tarefa longa
Rules são instruções persistentes para o agente. Se você altera uma instrução que faz parte da porção estável enviada ao modelo, pode acabar modificando um conteúdo que vinha sendo reaproveitado.
Não dá para afirmar que toda Rule do Cursor ocupa uma posição específica no prompt ou que editar uma sempre invalida todo o cache, porque essa implementação interna não é documentada dessa forma. Ainda assim, quanto menos você modifica as instruções estáveis durante uma execução longa, mais previsível tende a ser o reaproveitamento do contexto.
Na prática, prefiro ajustar Rules estruturais entre tarefas ou sessões, não enquanto um fluxo grande já está em andamento.
Sessão fria pode sair mais cara, mas sessão infinita também não é solução
No cache padrão da Anthropic, o TTL é de cinco minutos, com opção de extensão para uma hora. Em uma configuração usando o TTL padrão, interações frequentes conseguem continuar reaproveitando conteúdo já cacheado. Depois de uma pausa longa, a próxima chamada pode precisar processar novamente partes daquele contexto. Modelos da OpenAI também utilizam mecanismos de reutilização de contexto e otimizações internas que favorecem interações contínuas, embora não exponham TTL de cache da mesma forma. Já no Cursor, o reaproveitamento depende da continuidade da sessão e da forma como o contexto é mantido e atualizado ao longo das interações.
Isso não significa que você deve manter uma conversa infinita só para proteger o cache. Sessões longas acumulam histórico, e chega um momento em que boa parte dele deixa de ser relevante para a tarefa atual.
Esse acúmulo não impacta apenas o custo. Ele também pode afetar o desempenho do agente.
Quando o contexto contém muita informação irrelevante, o modelo precisa separar o que importa do que pode ser ignorado. Isso significa mais informação para processar, mais ambiguidade e mais chances de o agente considerar detalhes que não ajudam a resolver o problema.
Na prática, ele pode acabar levando em conta arquivos antigos, interpretações já descartadas ou instruções que não se aplicam mais à tarefa atual.
Existe um trade off:
Sessão longa: maior possibilidade de reaproveitamento, mas mais contexto acumulado e potencialmente mais ruído.
Sessão nova: contexto menor e mais limpo, mas possivelmente um novo cold start para informações que antes estavam cacheadas.
Para tarefas completamente independentes, prefiro sessões separadas. Não porque uma sessão nova seja universalmente mais barata, mas porque carregar contexto irrelevante indefinidamente também não faz sentido, tanto do ponto de vista de custo quanto da qualidade das decisões do agente.
O objetivo é:
Não faça o modelo processar informação que não ajuda a resolver a tarefa atual.
2. Controle o que entra no contexto
O agente precisa procurar código, abrir arquivos, ler resultados de testes e investigar dependências. O problema não é fazer isso. O problema é deixar que grandes volumes de informação irrelevante entrem no contexto sem necessidade.
Isso acontece mais do que parece. Você cola um log inteiro quando só algumas linhas explicam a falha. Pede para o agente analisar um projeto inteiro quando a mudança está restrita a um módulo. Entrega a saída completa de uma pipeline quando o erro já aponta para um único teste. Ou inclui arquivos gerados, mocks enormes e documentação que não têm relação direta com a tarefa.
Tudo isso aumenta a quantidade de informação que o modelo precisa processar antes mesmo de começar a raciocinar sobre o problema.
Por isso, uma das otimizações mais simples é reduzir o escopo antes de aumentar o contexto.
Se uma pipeline falhou em um teste específico, comece por esse teste e pelo erro associado, não pelo log inteiro da execução. Se a tarefa é alterar o fluxo de criação de usuários, direcione o agente para esse domínio antes de deixá-lo explorar o repositório inteiro. Se uma saída gerada por uma ferramenta é enorme, permita que o agente investigue primeiro o que falhou e aprofunde apenas quando precisar.
A ideia não é esconder informação do modelo. É disponibilizá-la progressivamente.
Comece com o menor contexto suficiente para investigar o problema e expanda conforme surgirem novas perguntas.
Isso também vale para o resultado das ferramentas usadas pelo próprio agente. Um comando que retorna milhares de linhas pode gerar muito contexto sem necessariamente gerar mais informação útil. Sempre que possível, vale preferir execuções mais direcionadas, como rodar apenas o teste que falhou, consultar os logs do serviço envolvido ou restringir uma busca ao domínio em que o problema acontece.
O ganho não vem simplesmente de "mandar menos tokens". Vem de evitar que o modelo precise separar sinal de ruído antes de começar a trabalhar.
Em agentes, mais contexto nem sempre significa mais inteligência.
Às vezes significa apenas mais coisa para ignorar.
3. Use a ferramenta mais seletiva para buscar informação
Coding agents têm diferentes formas de encontrar informação, e cada uma funciona melhor para um tipo de pergunta. O Cursor, por exemplo, consegue fazer buscas literais, semânticas e explorar o codebase de forma agentic. O objetivo não deveria ser escolher uma ferramenta favorita, mas evitar buscas mais amplas do que o problema exige.
Se eu quero encontrar todas as ocorrências de UserRepository no código, estou procurando algo exato. Uma busca literal provavelmente resolve rápido.
Mas imagine que a pergunta seja:
"Em que ponto do fluxo de checkout o valor do frete é recalculado após a aplicação de cupons?"
Talvez você não saiba o nome da função, da classe ou sequer o termo usado na implementação. Nesse caso, tentar adivinhar palavras para buscar pode ser menos eficiente do que deixar o agente usar uma busca semântica para localizar o comportamento.
A diferença está no tipo de pergunta.
Se você sabe o que está procurando, procure diretamente.
Se você sabe o comportamento, mas não sabe onde ele está implementado, procure semanticamente.
Se precisa entender como várias partes se conectam, deixe o agente explorar o fluxo.
O princípio é:
Use a busca com o menor alcance capaz de responder à pergunta atual.
Isso evita dois extremos. De um lado, abrir arquivos demais para responder algo simples. Do outro, limitar tanto a busca que o agente precisa fazer várias tentativas até encontrar o que realmente importa.
A otimização não está em escolher uma ferramenta específica.
Está em não transformar toda pergunta sobre o código em uma exploração completa do repositório.
Tire o discovery do modelo mais caro
Quando o agente precisa entender um projeto antes de começar uma tarefa, existe outro desperdício possível: usar o mesmo modelo caro que vai resolver o problema para fazer todo o trabalho de descoberta.
Nem toda etapa exige o mesmo nível de inteligência.
A parte puramente estrutural do discovery pode ser feita de forma determinística. Um script simples pode percorrer o repositório, identificar diretórios relevantes, arquivos de configuração conhecidos, workspaces, módulos e possíveis entrypoints e devolver um mapa compacto da estrutura.
A partir daí, se ainda for necessário interpretar essas informações, um modelo mais barato pode transformar esse mapa em um resumo arquitetural antes de entregar o resultado ao modelo principal.
O fluxo fica mais ou menos assim:
coleta determinística
↓
mapa estrutural
↓
modelo mais barato
↓
resumo do projeto
↓
modelo principal
↓
execução da tarefa
A ideia é separar coleta, síntese e raciocínio.
Um script continua sendo uma boa ferramenta para extrair diretamente a estrutura do projeto, como módulos existentes, arquivos de configuração e organização de diretórios.
Já perguntas como "qual parece ser a arquitetura deste sistema?", "quais são os principais domínios?" ou "como esses módulos se relacionam?" exigem interpretação. Para isso, pode fazer sentido usar um modelo mais barato para produzir um resumo antes de envolver o modelo principal.
Nesse caso, uma Skill poderia orquestrar o processo:
---
name: project-discovery
description: "Mapeia e resume a arquitetura do projeto antes de tarefas que exigem contexto amplo."
allowed-tools: ["Bash"]
---
1. Execute o script de discovery para gerar o mapa estrutural do repositório.
2. Use o mapa como base para produzir um resumo compacto da arquitetura.
3. Retorne apenas o resumo relevante para a tarefa atual.
4. Aprofunde a leitura apenas nos módulos necessários.
O script não tem custo zero de contexto e o modelo barato também tem custo. O ponto é que você não está usando sua capacidade mais cara para executar todas as etapas do processo.
Faça com código o que é determinístico, use modelos baratos para síntese e reserve os modelos mais fortes para decisões em que errar custa caro.
Essa é a mesma lógica de roteamento por etapa aplicada ao contexto.
O modelo principal recebe um mapa já interpretado e decide onde aprofundar, em vez de gastar parte da sua execução descobrindo do zero como o projeto está organizado.
Isso vai além de economia de tokens. É arquitetura de agente.
Sempre que um modelo caro estiver gastando raciocínio para fazer uma tarefa que código ou um modelo mais barato conseguiriam executar com confiabilidade suficiente, vale perguntar se aquela etapa realmente deveria continuar pertencendo a ele.
4. Carregue conhecimento sob demanda com Rules e Skills
Existe uma diferença importante entre algo que o agente precisa saber sempre e algo que ele só precisa saber em situações específicas.
Uma Rule contém algo que deve influenciar o comportamento do agente de forma recorrente. Uma Skill pode conter um procedimento inteiro que só interessa quando determinada situação acontece.
Agent Skills seguem uma lógica de carregamento progressivo. Inicialmente, informações básicas como nome e descrição permitem que o agente descubra que aquela capacidade existe. Quando a Skill é relevante, suas instruções podem ser carregadas, junto de scripts e referências adicionais conforme a necessidade.
Isso cria uma regra de arquitetura útil:
Rule para conhecimento curto, estável e recorrente.
Skill para conhecimento longo, procedural e situacional.
Imagine um conjunto de instruções como convenções de nomenclatura, padrões de commit ou regras de validação específicas do projeto. Algumas dessas orientações, como convenções de nomenclatura, fazem sentido como Rules globais, já que influenciam praticamente qualquer alteração no código. Outras, como padrões de commit, podem ser mais situacionais e não precisam estar presentes em todas as tarefas. Você pode colocar tudo isso em uma Rule global, fazendo com que qualquer tarefa, até mesmo corrigir um typo, carregue esse conteúdo. Ou pode organizar essas orientações em uma Skill, que só é utilizada quando realmente fazem diferença para a tarefa em questão.
Uma Skill boa não deixa de pesar. Ela pesa pouco enquanto está inativa e só ocupa mais contexto quando realmente tem valor para a tarefa.
Isso economiza contexto, mas também reduz ruído. Contexto irrelevante não tem apenas custo financeiro. Ele também compete pela atenção do modelo.
5. Controle o que o modelo gera
Até agora falamos sobre o que o agente recebe. O outro lado da equação é o que ele produz.
Gerar conteúdo tem custo, e uma das formas mais caras de geração é aquela que você simplesmente joga fora. Isso inclui respostas excessivamente longas, código que será descartado e, principalmente, implementações erradas que obrigam o agente a repetir todo o ciclo.
Previna o erro com uma Rule
Um dos maiores desperdícios não é uma resposta longa. É gerar a resposta errada.
O modelo implementa, você percebe o erro, explica o problema, ele investiga novamente, abre mais arquivos, roda mais testes e gera outra implementação.
Agora você não pagou apenas duas vezes pelo código. Teve mais contexto processado, mais geração, mais tool calls, mais resultados de ferramentas e mais uma rodada inteira de raciocínio.
Se existe um comportamento recorrente do agente que costuma gerar retrabalho, uma Rule curta pode ser muito mais barata que corrigir o mesmo problema repetidamente.
Um exemplo comum é o agente criar uma nova função, helper, serviço ou abstração sem perceber que o projeto já possui algo equivalente:
Antes de criar uma nova função, helper, serviço ou abstração,
procure por implementações existentes que resolvam o mesmo problema.
Prefira reutilizar ou estender padrões já existentes no projeto
antes de introduzir uma nova solução.
Essa é uma instrução que pode fazer diferença em praticamente qualquer tarefa de implementação. Sem ela, o agente pode criar um novo helper para algo que já existe, introduzir uma segunda abstração para o mesmo problema ou implementar novamente uma lógica que deveria ser compartilhada.
O resultado não é apenas mais código gerado. Depois alguém precisa identificar a duplicação, explicar o problema, pedir a correção e fazer o agente investigar o projeto novamente.
Essa Rule usa tokens. A pergunta não é se ela tem custo. A pergunta é:
Quanto custa manter essa instrução comparado ao custo dos erros que ela evita?
A conta conceitual é:
probabilidade do erro × custo do retrabalho
>
custo incremental da instrução
Não existe um número mágico para o ponto de equilíbrio. Ele depende do tamanho da instrução, da frequência com que ela é carregada, do custo do erro e de quanto retrabalho ela realmente evita.
Para comportamentos recorrentes e que afetam várias tarefas, esse ponto pode chegar rápido. E existe um custo que nem aparece no painel de tokens: o nosso tempo.
Diga o formato que você quer
Boa parte do conteúdo gerado nasce de uma instrução vaga.
Você pede:
"Revise essa implementação."
O modelo pode responder com uma introdução sobre a abordagem utilizada, explicar o que entendeu do código, elogiar partes da implementação, comentar decisões que não são relevantes e só depois chegar aos problemas que realmente precisam da sua atenção.
Mas talvez o que você queira seja simplesmente:
Revise essa implementação e retorne apenas:
1. Problemas encontrados, ordenados por severidade.
2. Arquivo e trecho afetado.
3. Impacto de cada problema.
4. Correção sugerida.
Se não encontrar problemas, diga apenas que a implementação está correta.
Não faça um resumo geral do código.
Agora a resposta tende a vir muito mais próxima do que você realmente precisa para tomar uma decisão:
1. Alta: possibilidade de race condition em processPayment()
Arquivo: payment.service.ts
Impacto: duas requisições simultâneas podem processar o mesmo pagamento.
Correção: garantir idempotência antes de chamar o provider.
2. Média: erro do provider está sendo capturado sem preservar a causa original.
Arquivo: payment.gateway.ts
Impacto: dificulta investigação em produção.
Correção: manter a exceção original como cause.
A diferença é que você não pediu apenas para o modelo ser breve. Você definiu qual informação tem valor e como ela deve ser entregue.
Isso funciona especialmente bem em tarefas recorrentes, como code review, análise de logs, investigação de bugs, planejamento e validação de implementações.
Quanto mais claro você é sobre o resultado que precisa, menos o modelo precisa gastar tokens decidindo o que colocar na resposta.
Às vezes, a melhor otimização não é pedir uma resposta menor. É eliminar da resposta tudo aquilo que você já sabe que não vai usar.
Corte explicação que não tem função
Nem toda tarefa precisa de uma aula. Se quero entender uma decisão arquitetural, quero explicação. Se mandei renomear uma variável em três arquivos, provavelmente não preciso de quatro parágrafos dizendo que a variável foi renomeada.
Para tarefas mecânicas, uma Rule simples pode ajudar:
Após alterações simples, responda apenas com:
1. o que foi alterado;
2. arquivos afetados;
3. resultado da validação.
Não explique decisões triviais.
O objetivo não é tornar o agente sempre lacônico.
É:
Pague por explicação quando a explicação tem valor.
6. Ajuste o esforço e escolha o modelo pelo custo de errar
Pedir "responda em duas linhas" controla principalmente o texto que você recebe. Mas um modelo ainda pode fazer muito raciocínio para chegar àquelas duas linhas.
Nos modelos que oferecem controles de esforço de raciocínio, essa é outra alavanca importante. Renomear uma propriedade não deveria exigir o mesmo nível de raciocínio usado para decidir como migrar uma arquitetura distribuída sem downtime.
Então:
Formato de resposta controla o que você recebe.
Effort controla quanto trabalho cognitivo você está pedindo.
Não faz sentido gastar raciocínio máximo para ajustar um import. Ao mesmo tempo, economizar esforço numa decisão arquitetural complexa pode produzir uma solução ruim e gerar três rodadas extras de retrabalho.
A regra é:
Use o nível de inteligência proporcional ao custo de errar.
O mesmo raciocínio vale para a escolha do modelo.
Uma das ciladas mais comuns é escolher o modelo apenas porque ele parece mais barato por unidade de uso e concluir que ele necessariamente reduzirá o custo da tarefa.
Só que a tarefa precisa terminar.
Um modelo mais barato pode interpretar o problema errado, abrir arquivos desnecessários, tentar uma solução, falhar, receber uma correção e só então resolver. Outro pode ter um custo maior por chamada e acertar o caminho logo na primeira execução.
Não dá para saber qual foi mais barato olhando apenas para o custo unitário do modelo.
Benchmarks de coding agents ajudam a mostrar isso porque medem não apenas qualidade, mas também custo total, quantidade de tokens e número de steps. No CursorBench, por exemplo, configurações diferentes apresentam relações distintas entre score e custo. O ranking de custo não é simplesmente uma cópia do ranking de preço do modelo.
Isso não significa que um modelo caro seja sempre mais econômico ou que exista um modelo universalmente melhor.
Significa apenas que:
O preço do modelo não é a métrica final.
Na prática, isso abre espaço para roteamento por etapa:
Modelo leve para trabalho mecânico.
Modelo intermediário para execução comum.
Modelo forte para problemas em que um erro provavelmente vai gerar muito retrabalho.
Essa mesma lógica apareceu anteriormente no discovery do projeto. Talvez um script resolva a coleta estrutural, um modelo barato faça a síntese e o modelo forte seja usado apenas quando a tarefa exigir decisões mais complexas.
A pergunta deixa de ser "qual é o modelo mais barato?" e passa a ser:
Qual é o recurso mais barato capaz de executar esta etapa com a confiabilidade que eu preciso?
Repare que agora a pergunta nem precisa estar limitada a modelos.
Às vezes a resposta é um script.
Às vezes é uma busca.
Às vezes é um modelo leve.
E, quando o custo de errar é alto, pode ser um modelo mais forte.
7. Meça custo por tarefa concluída, não apenas tokens
Depois de tudo isso, chegamos à métrica que considero mais importante:
custo total da execução
────────────────────────
tarefa concluída corretamente
Toda otimização de custo precisa preservar o resultado.
Se você reduz a quantidade de geração, mas o agente passa a errar duas vezes mais, provavelmente não economizou.
Se troca para um modelo mais barato, mas precisa de três rodadas adicionais, talvez não tenha economizado.
Se adiciona uma Rule que aumenta um pouco o contexto de todas as chamadas, mas elimina um erro recorrente que gerava horas de retrabalho, provavelmente economizou.
É por isso que gosto de pensar no custo de agentes como um problema de sistema, não como um problema de contagem de tokens.
Contexto ruim gera raciocínio ruim. Raciocínio ruim gera implementação ruim. Implementação ruim gera mais ferramentas, mais testes, mais mensagens e mais rodadas de processamento.
O custo se propaga.
Da mesma forma, uma boa decisão no início pode eliminar uma cadeia inteira de trabalho depois.
No fim, isso é engenharia de agentes
Otimizar o custo de um agente não é uma competição para ver quem usa menos tokens. É projetar melhor todo o sistema ao redor do modelo.
O contexto é uma parte disso, mas não é a única. Rules, Skills, ferramentas, scripts, estratégias de busca, escolha de modelos e a forma como cada etapa do fluxo é executada também fazem parte do harness que determina como o agente trabalha.
As sete estratégias deste post apontam para a mesma direção: reutilizar o que é estável, controlar o que entra no contexto, buscar informação de forma seletiva, carregar conhecimento apenas quando necessário, reduzir geração sem valor, delegar cada etapa ao recurso mais adequado e medir tudo pelo custo de chegar a uma solução correta.
No fim, não adianta ter o melhor modelo se o sistema ao redor dele faz com que ele leia contexto desnecessário, use a ferramenta errada, carregue instruções irrelevantes ou desperdice raciocínio em tarefas que poderiam ser resolvidas de forma mais simples.
O painel de uso continua sendo um ótimo termômetro.
Mas o número que realmente importa é:
Quanto custou para chegar a uma resposta correta?
A lógica é simples:
Não otimize tokens isolados. Otimize o sistema que leva o agente até a solução.
Top comments (0)