No primeiro post, contei como levei ao Startup Summit, em agosto, a palestra “Preço por token não é preço”, criada pelo Bruno Vilardi Bueno. Ao estudar o material e rodar as demos na minha conta, encontrei uma diferença de consumo entre versões da mesma família que ainda não estava no deck.
Em outubro, apresentei a palestra novamente no Oktobertech, em Blumenau. Entre as duas apresentações, o catálogo mudou de novo. O Sonnet 5.5 ainda não estava disponível em agosto e já estava em outubro. A pergunta da palestra continuava a mesma, mas a comparação tinha mais um modelo para considerar.
Ficou faltando abrir essa conta técnica por aqui. Parto de duas demos para discutir o consumo no Amazon Bedrock, a execução no Bedrock AgentCore e as decisões de arquitetura que uma tabela de preços não resolve sozinha.
A primeira demo compara uma chamada simples por modelo, usando a mesma frase em português. O consumo reportado foi de 32 tokens de entrada no Claude Sonnet 4.6, 40 no Sonnet 5 e 42 no Sonnet 5.5. Nos modelos OpenAI comparados, do GPT-5.4 ao GPT-6.1 Sol, a mesma frase ficou em 26 tokens.
Uma chamada isolada, porém, conta só parte da história. Na segunda demo, um agente recebeu uma tarefa de FinOps, consultou ferramentas e usou os resultados para continuar a execução. O que começou como um único pedido gerou cinco chamadas ao modelo e acumulou 16.223 tokens de entrada.
A partir desses dois exemplos, podemos olhar para o custo de uma tarefa considerando tanto o consumo de cada chamada quanto o contexto que se acumula ao longo da execução.
Trocar de versão também muda o consumo
A primeira demo usa chamadas simples ao Bedrock, sem ferramentas nem loop de agente, com o seguinte pedido.
Explique em 3 bullets curtos o que é RAG (Retrieval-Augmented Generation).
No primeiro texto, contei que, ao preparar a apresentação de agosto, encontrei 32 tokens de entrada no Sonnet 4.6 e 40 no Sonnet 5 para a mesma frase. Os registros reunidos aqui incluem também o Sonnet 5.5, com 42 tokens. É mais uma versão para conferir antes de reaproveitar os números da apresentação anterior. A frase continuou igual, mas a entrada reportada não.
| Modelos exibidos na demo | Tokens de entrada para a mesma frase |
|---|---|
| Claude Sonnet 4.6 | 32 |
| Claude Sonnet 5 | 40 |
| Claude Sonnet 5.5 | 42 |
| GPT-5.4, GPT-5.6 Luna, GPT-6 Luna e GPT-6.1 Sol | 26 em cada um |
Essas diferenças importam porque, mesmo que a tarifa de entrada fosse mantida, uma quantidade maior de tokens elevaria o custo dessa parte da chamada. A pergunta continuou igual, sem ferramentas novas nem aumento no volume de requisições. O que mudou no registro foi a quantidade reportada por chamada.
Nos modelos OpenAI desse recorte, as chamadas via Converse mantiveram 26 tokens de entrada. Essa estabilidade vale para a frase e para as versões observadas. Ela não permite concluir que qualquer texto terá o mesmo consumo, assim como as diferenças entre os modelos Claude não dizem, sozinhas, quanto custou a resposta completa.
Também é preciso cuidado ao atribuir uma causa à variação. A documentação do Sonnet 5.5 informa que ele usa o mesmo tokenizer do Sonnet 5. Portanto, a diferença de 40 para 42 tokens nos registros não demonstra uma mudança de tokenizer. O registro mostra o uso reportado pela chamada, sem isolar toda a representação interna do prompt. A causa dessa diferença permanece sem explicação neste recorte.
A API CountTokens ajuda a estimar a entrada nos modelos e formatos suportados. As fichas do GPT-5.4 e do GPT-6.1 Sol indicam que o recurso não está disponível para esses modelos. Por isso, a API não oferece um caminho para reproduzir integralmente a tabela.
Em uma nova avaliação, eu verificaria primeiro o suporte de cada modelo à API escolhida, manteria o payload e a configuração comparáveis e registraria os IDs, o endpoint, a entrada, a saída e as tarifas aplicáveis. Também verificaria o roteamento. A configuração exibida como us-east-1 não comprova a região efetiva de execução da inferência quando há roteamento cross-region, como nos perfis descritos na documentação do GPT-6.1 Sol. Esse cuidado precisa acompanhar as atualizações do modelo. No agente, ele também precisa acompanhar cada etapa da execução.
Como uma tarefa vira um loop de agente
Na chamada simples, envio uma pergunta e recebo uma resposta. No agente, dou um objetivo e disponibilizo ferramentas. O modelo avalia o contexto e escolhe o próximo passo, o código executa a ferramenta escolhida e o resultado volta como contexto para uma nova chamada. O ciclo continua até a resposta final ou até um limite de execução.
Na tarefa de FinOps, o objetivo era encontrar o serviço AWS mais caro do mês anterior, detalhar seu custo diário nas duas semanas anteriores, analisar a tendência, gerar um forecast desse serviço, consultar budgets e concluir em até cinco linhas.
Para fazer isso, o agente primeiro precisa descobrir qual serviço lidera o gasto. A ferramenta consulta os dados e devolve o resultado. Com essa informação, o modelo pode escolher o serviço e montar a consulta diária. O código executa a consulta, seu resultado volta ao contexto e uma nova chamada ao modelo define como continuar. A resposta final depende do que essas etapas conseguem apurar.
Aqui usamos o Strands Agents, SDK open source lançado pela AWS. Nesse framework, o Agent organiza o loop, funções expostas como tools executam operações e o BedrockModel permite configurar o acesso aos modelos do Bedrock. Na demo, o Bedrock AgentCore Runtime hospeda a aplicação. Strands coordena a execução, Bedrock fornece a inferência e Runtime mantém o código rodando.
O registro expandido da demo, identificado como GPT-6.1 Sol, com ID us.openai.gpt-6.1-sol, permite acompanhar esse percurso.
| Ciclo | Operação visível | Entrada | Saída |
|---|---|---|---|
| 1 | Consulta de custo agregado por serviço | 1.332 | 53 |
| 2 | Consulta de custo diário | 2.284 | 163 |
| 3 | Consulta de forecast | 3.745 | 441 |
| 4 | Consulta de budgets | 4.309 | 178 |
| 5 | Resposta final | 4.553 | 255 |
| Tarefa completa | Cinco chamadas ao modelo | 16.223 | 1.090 |
O primeiro ciclo recebeu 1.332 tokens de entrada. O último recebeu 4.553. Entre eles, entraram respostas do modelo, chamadas de ferramentas e seus resultados. O contexto cresceu ao longo da execução, e a entrada reportada acumulada chegou a 16.223 tokens, embora o usuário tivesse feito um único pedido.
Contar só o primeiro prompt deixaria de fora boa parte desse consumo. Multiplicar o total por cinco cometeria o erro contrário, porque os ciclos já estão somados na última linha. Para transformar os números em custo, ainda é preciso entender como a API e a interface apresentam o uso de cache.
A saída também não se resume à conclusão entregue ao usuário. O agente produz conteúdo para operar as ferramentas antes de escrever a resposta final. Pedir uma conclusão curta não limita, por si só, tudo que acontece até chegar nela.
O retorno da ferramenta merece uma revisão
Ao acompanhar o crescimento da entrada, o retorno das ferramentas se torna um ponto concreto de revisão. Campos enviados em uma etapa podem continuar no contexto das chamadas seguintes. Antes de trocar de modelo, eu olharia para esse conteúdo.
Depois da consulta agregada, quais campos são necessários para decidir a próxima chamada? Depois do detalhamento diário, quais informações precisam continuar no contexto? Se a ferramenta devolve uma estrutura inteira e o agente a carrega pelas próximas etapas, esse desenho aparece no consumo acumulado.
As próprias definições das ferramentas ocupam espaço, incluindo descrições e schemas. A documentação de tool use para Claude no Bedrock descreve esses componentes da entrada. O overhead depende da família de modelos, então não convém transportar uma estimativa de uma para outra sem conferir.
Minha primeira hipótese de otimização seria fazer a ferramenta retornar só o necessário para a próxima decisão, mantendo o resultado completo disponível fora do prompt para auditoria. Outra seria calcular agregações determinísticas em código, em vez de pedir ao modelo que reconstrua tudo a cada ciclo.
Essas são hipóteses para outra rodada, não economias já demonstradas. Remover campos pode tirar a informação que permitiria detectar um problema. Eu compararia o fluxo completo antes e depois, com os mesmos critérios de acerto. E, para interpretar a diferença de custo, verificaria também quanto do contexto repetido foi efetivamente reaproveitado pelo cache.
Cache precisa aparecer na conta sem entrar duas vezes
Parte do contexto se repete entre as chamadas, o que pode permitir reaproveitamento. A repetição, porém, não garante que aquele conteúdo seja elegível para cache nem que tenha ocorrido um cache hit.
No Bedrock, o suporte e as condições de prompt caching variam por modelo e API. Leituras têm tarifa própria, gravações podem custar mais que a entrada comum e o reaproveitamento depende das condições do cache. Os campos de uso permitem conferir se ele aconteceu e como foi contabilizado. Habilitar o recurso, por si só, não confirma o desconto.
Antes de aplicar as tarifas, é preciso conferir como a interface apresenta esses campos. Se o valor mostrado como “do cache” já estiver incluído na entrada exibida, somá-lo novamente inflará o consumo. Sem confirmar esse mapeamento nos dados da API e no código da interface, não dá para assumir a convenção usada pela demo.
Na inferência textual, eu separaria a entrada sem cache, a leitura de cache, a escrita de cache e a saída, usando categorias mutuamente exclusivas e compatíveis com a API. Cada quantidade recebe sua tarifa, na unidade indicada pela tabela de preços. Depois, somo os custos de todas as chamadas da tarefa.
Essa separação evita cobrar duas vezes o mesmo consumo na estimativa. Ainda assim, ela cobre apenas a inferência. O código que organiza o agente e executa suas ferramentas também precisa rodar em algum lugar.
O que o AgentCore Runtime acrescenta
Para acompanhar esse loop no AgentCore Runtime, a aplicação emite eventos de ciclo, ferramentas, tokens e recursos, repassados por SSE até a interface. O Runtime não precisa interpretar o significado desses eventos. A instrumentação permite enxergar o que aconteceu dentro da invocação, em vez de medir só o pedido e a resposta final.
Hospedar o agente no Runtime não substitui a cobrança de inferência no Bedrock. A aplicação continua fazendo chamadas ao modelo e, ao mesmo tempo, consome recursos para executar seu código.
Na modalidade microVM v1 considerada na demo, CPU e memória precisam ser tratadas separadamente. A documentação de custos e observabilidade explica que CPU é consumo efetivo, enquanto memória é contabilizada ao longo do tempo. Esperar a resposta do modelo ou de uma ferramenta não implica consumir CPU durante toda a espera, se nenhum processo estiver usando CPU. A memória ocupada pode continuar faturável.
Por isso, a duração de uma invocação não equivale automaticamente ao mesmo tempo de uma vCPU consumida. E terminar a resposta não significa necessariamente encerrar a sessão naquele instante.
Na calculadora da demo, a estimativa de Runtime combinava os recursos reportados com premissas sobre a sessão. Entre elas estavam 900 segundos de tempo ocioso, footprint aproximado de 1 GB e CPU em idle estimada em 1% de vCPU. Eram premissas da estimativa, não uma medição reconciliada com a fatura. A tabela de preços do AgentCore precisa ser consultada para a modalidade e a região aplicáveis antes de transformar esse uso em custo.
O tempo ocioso chama atenção porque a sessão continuava entrando na estimativa depois de a resposta estar pronta. Reduzir o timeout pode diminuir a memória acumulada nesse intervalo, mas aumenta a chance de precisar iniciar outra sessão. Se várias interações reutilizam a mesma sessão, a atribuição do custo por tarefa também muda.
Serviços adicionais, como AgentCore Gateway e Memory, entram na conta se forem usados. O loop com ferramentas e histórico, por si só, não depende de incluir esses componentes. Para comparar arquiteturas, precisamos identificar os recursos que cada uma realmente usa e verificar se elas chegam a resultados equivalentes.
A comparação que eu faria antes de escolher
A comparação começa por uma definição de sucesso. No registro de FinOps, o forecast retornou uma janela diferente da solicitada e a consulta de budgets veio vazia. A resposta final reconheceu essas limitações. Esse comportamento precisa entrar na avaliação. Detectar a diferença de período e informar a ausência de dados pode ser mais importante que economizar tokens na conclusão.
Não houve uma nova execução para este texto nem uma avaliação de qualidade equivalente entre os modelos. Uma execução por modelo não sustenta um ranking de qualidade. Para decidir, eu montaria um conjunto representativo de tarefas, incluindo dados vazios, períodos divergentes, falhas de ferramenta e retries. Avaliaria as respostas contra critérios explícitos e mediria o tempo do fluxo inteiro.
Com esses critérios, compararia alternativas mudando uma coisa por vez. As mudanças poderiam envolver o contrato das ferramentas, o contexto carregado, a divisão entre modelo e código determinístico, o modelo escolhido ou os limites de execução. Assim consigo separar o efeito de cada decisão sobre custo, qualidade e latência.
A modalidade de inferência também precisa combinar com o trabalho. Batch pode servir a análises offline que aceitam espera, mas não substitui diretamente cada etapa dependente de resposta desse fluxo interativo. Os service tiers oferecem outros compromissos entre processamento e preço, conforme o modelo.
Depois de definir o que conta como sucesso, posso reunir as inferências de todos os ciclos, a execução no Runtime, os serviços chamados pelas ferramentas, a observabilidade e os demais recursos usados. Esse é o custo do fluxo que será comparado, não apenas o valor da última resposta.
O custo por tarefa resolvida
Para comparar alternativas, eu dividiria o custo total da avaliação pela quantidade de tarefas resolvidas segundo o critério definido. O custo total precisa incluir também as tentativas que falharam. Excluir os erros faria a solução parecer mais barata sem melhorar sua capacidade de resolver o trabalho.
Junto desse resultado, eu mostraria a taxa de resolução e a latência, porque o mesmo custo pode esconder comportamentos muito diferentes. A telemetria ajuda a explicar as chamadas, enquanto o Cost Explorer e o relatório de custos ajudam a reconciliar a cobrança. Um contador de tokens ou uma estimativa de Runtime não substitui essa conferência.
A comparação entre modelos começa pela tarifa, mas precisa acompanhar o que a aplicação faz com cada um deles. Na chamada simples, a mesma frase teve contagens diferentes nos registros. No agente, os resultados das ferramentas passaram a compor as chamadas seguintes. No Runtime, a sessão continuava entrando na estimativa depois de a resposta estar pronta. Cada parte aponta para uma decisão que vale examinar antes de atribuir todo o custo ao modelo escolhido.
Isso também muda a forma de procurar economia. Um retorno menor de uma ferramenta pode reduzir a entrada das chamadas seguintes, desde que preserve a informação necessária. Um tempo ocioso menor pode reduzir o custo da sessão, dependendo de como ela será reutilizada. Para saber se o ajuste compensa, precisamos olhar para o fluxo completo, incluindo a qualidade da resposta e o tempo até a conclusão.
A palestra nasceu com o Bruno, ganhou uma nova comparação quando a preparei para o Summit e voltou ao público em outubro, no Oktobertech. A cada retomada, os números precisam ser conferidos outra vez. Novos modelos entram no catálogo, as ferramentas podem devolver outros dados e a tarefa pode exigir mais etapas do que o primeiro teste mostrou. É a relação entre consumo, execução e resultado que dá sentido ao preço por token.




Top comments (1)
Task cost is most actionable when it is tied to an outcome rather than averaged across all requests.
Tracking tokens, tool calls, retries, and human review time per completed task makes routing decisions much clearer: a cheaper run that needs two manual corrections is not actually cheaper.