{"id":769,"date":"2026-10-09T18:35:03","date_gmt":"2026-10-09T21:35:03","guid":{"rendered":"https:\/\/yellowkode.com\/blog\/asana-reducao-custo-agente-navegador-prompt-caching\/"},"modified":"2026-10-09T18:35:03","modified_gmt":"2026-10-09T21:35:03","slug":"asana-reducao-custo-agente-navegador-prompt-caching","status":"publish","type":"post","link":"https:\/\/yellowkode.com\/blog\/asana-reducao-custo-agente-navegador-prompt-caching\/","title":{"rendered":"Como a Asana cortou 76x o custo de um agente de navegador: a mec\u00e2nica do prompt caching"},"content":{"rendered":"<p>Em 8 de outubro de 2026, a Asana publicou um estudo de 144 execu\u00e7\u00f5es mostrando que conseguiu reduzir em 76 vezes o custo e em 5 vezes o tempo do seu agente de navegador. No dia seguinte, a OpenAI publicou o case no pr\u00f3prio blog. O n\u00famero \u00e9 real, mas a leitura r\u00e1pida engana: o ganho n\u00e3o veio de um modelo novo milagroso, veio de arrumar como o agente usava o cache do prompt. A mesma otimiza\u00e7\u00e3o, rodada no modelo que a Asana j\u00e1 tinha em produ\u00e7\u00e3o (chamado Model B), cortou o custo em 29x sozinha. GPT-6.1 Sol forneceu os 2,6x restantes.<\/p>\n<p>Este artigo \u00e9 sobre a parte que transfere para qualquer agente que voc\u00ea rode em qualquer modelo: a mec\u00e2nica de prefixo de cache e por que a maneira como voc\u00ea monta o hist\u00f3rico destr\u00f3i ou preserva esse desconto.<\/p>\n<h2>Como funciona o prompt caching em um agente de navegador<\/h2>\n<p>Um agente de navegador \u00e9 um loop. A cada passo ele manda para o modelo tr\u00eas coisas: as instru\u00e7\u00f5es fixas (system prompt), as defini\u00e7\u00f5es das ferramentas que pode chamar (clicar, digitar, tirar screenshot, ler texto) e o hist\u00f3rico do que j\u00e1 aconteceu at\u00e9 agora (texto das p\u00e1ginas visitadas e screenshots). O modelo responde com a pr\u00f3xima a\u00e7\u00e3o, o navegador executa, e o hist\u00f3rico cresce. Repete.<\/p>\n<p>A cada chamada o agente reenvia tools, system prompt e esse hist\u00f3rico crescente de texto e screenshots. Isso \u00e9 caro porque o hist\u00f3rico \u00e9 a parte que mais cresce e \u00e9 a maior parte do input.<\/p>\n<p>A ideia do prompt caching \u00e9 cobrar barato por aquilo que o provedor j\u00e1 viu na requisi\u00e7\u00e3o anterior. Nos modelos testados pela Asana, leitura de cache custa entre 0,05x e 0,1x do pre\u00e7o normal de input. Ou seja, se o seu prefixo bater, voc\u00ea paga de 5% a 10% do que pagaria sem cache naquela parte.<\/p>\n<p>O detalhe que decide tudo: o cache s\u00f3 reusa o maior prefixo inalterado da requisi\u00e7\u00e3o. N\u00e3o \u00e9 um cache por peda\u00e7o, n\u00e3o \u00e9 um cache por chave. \u00c9 prefixo. Se qualquer byte no meio mudar, do ponto de mudan\u00e7a em diante o desconto some.<\/p>\n<h3>Uma analogia que carrega a mec\u00e2nica<\/h3>\n<p>Pense numa pilha de livros em cima de uma mesa. O desconto \u00e9 por quantos livros, de baixo para cima, est\u00e3o exatamente iguais aos da pilha anterior. Se voc\u00ea mant\u00e9m os de baixo intactos e s\u00f3 coloca livros novos no topo, conta todos de baixo como &#8220;iguais&#8221;. Se voc\u00ea tira um livro do meio para reorganizar, do ponto em que voc\u00ea mexeu para cima nada conta mais, mesmo que l\u00e1 em cima tudo esteja id\u00eantico. A analogia quebra num ponto: o cache tem janela de tempo e tamanho m\u00e1ximo, enquanto a pilha de livros n\u00e3o evapora sozinha. Fora isso, a mec\u00e2nica \u00e9 essa.<\/p>\n<h3>Os dois erros que compunham<\/h3>\n<p>A Asana descobriu, usando o GPT-6 Astra dentro do Codex para auditar o c\u00f3digo, dois problemas que se amplificavam:<\/p>\n<p>O agente em produ\u00e7\u00e3o fazia cache das instru\u00e7\u00f5es fixas e das defini\u00e7\u00f5es de ferramentas mas n\u00e3o do hist\u00f3rico de navega\u00e7\u00e3o. E editava esse hist\u00f3rico quase a cada passo: largava o screenshot anterior toda vez e cortava texto antigo para caber num budget de hist\u00f3rico. Cada edi\u00e7\u00e3o invalidava o prefixo, ent\u00e3o o cache seria quase in\u00fatil mesmo que estivesse ligado.<\/p>\n<p>Os dois erros se multiplicavam. Sem cache no hist\u00f3rico, voc\u00ea j\u00e1 paga caro pelo peda\u00e7o que mais cresce. E, por editar no meio, mesmo que ligasse o cache ele estouraria toda chamada.<\/p>\n<h2>A corre\u00e7\u00e3o: hist\u00f3rico append-only e batch pruning<\/h2>\n<p>A solu\u00e7\u00e3o tem duas partes:<\/p>\n<p>Primeiro, fazer cache do hist\u00f3rico tamb\u00e9m, com um marcador de cache no \u00faltimo resultado de ferramenta. Segundo, parar de editar o hist\u00f3rico a cada chamada. O batch pruning mant\u00e9m screenshots e os remove em lotes: na propor\u00e7\u00e3o 20:1, o agente guarda at\u00e9 20 e ent\u00e3o corta de volta para 1, de modo que cerca de 19 chamadas consecutivas reusam o hist\u00f3rico em cache.<\/p>\n<p>Em vez de remover o screenshot anterior toda chamada (edi\u00e7\u00e3o no meio, prefixo quebra), voc\u00ea deixa acumular at\u00e9 20 e s\u00f3 ent\u00e3o faz uma poda. Entre podas, voc\u00ea s\u00f3 anexa. Append-only no hist\u00f3rico significa que o prefixo cresce sem mudar o que j\u00e1 est\u00e1 l\u00e1, e o cache bate em quase tudo.<\/p>\n<p>A Asana tamb\u00e9m fez uma mudan\u00e7a n\u00e3o \u00f3bvia: aumentou o budget de hist\u00f3rico de 120.000 para 480.000 caracteres. Contraintuitivo se voc\u00ea acha que menos tokens \u00e9 sempre melhor, mas faz sentido na mec\u00e2nica de cache: se o budget \u00e9 apertado e voc\u00ea corta texto antigo para caber, voc\u00ea est\u00e1 editando o prefixo. Com budget maior, voc\u00ea raramente precisa cortar, e cada caractere adicional entra no desconto de cache em vez do pre\u00e7o cheio.<\/p>\n<h2>O que isso significa na pr\u00e1tica<\/h2>\n<p>O n\u00famero que explica o resultado:<\/p>\n<p>No GPT-6.1 Sol com o budget maior, a nova pol\u00edtica de cache e screenshots reduziu o custo em 4x, de 1,97 para 0,47 d\u00f3lares por execu\u00e7\u00e3o. Cada chamada ficou cerca de 3x mais barata, porque 89% do input vinha do cache a 5% do pre\u00e7o n\u00e3o cacheado.<\/p>\n<p>Guarde esse 89%. \u00c9 a m\u00e9trica que voc\u00ea mesmo precisa medir no seu agente: qual fra\u00e7\u00e3o do input de cada chamada \u00e9 cache read. Se est\u00e1 baixa, n\u00e3o adianta trocar de modelo, adianta arrumar o prefixo.<\/p>\n<p>Um pseudoc\u00f3digo do loop corrigido, para ancorar:<\/p>\n<pre><code>historico = []\nscreenshots = []\nMAX_SCREENSHOTS = 20\n\nwhile not terminou:\n # append-only: so adiciona no fim\n historico.append(nova_observacao_texto)\n screenshots.append(novo_screenshot)\n\n # poda em lote: so quando estourar, e de uma vez so\n if len(screenshots) > MAX_SCREENSHOTS:\n screenshots = [screenshots[-1]] # corta para 1\n\n requisicao = montar(\n system_prompt, # fixo, cacheado\n tools, # fixo, cacheado\n historico, # cresce, agora cacheado\n screenshots, # muda em lotes, cacheavel entre podas\n cache_marker_no_ultimo_tool_result=True,\n )\n acao = modelo.chamar(requisicao)\n executar(acao)\n<\/code><\/pre>\n<p>O que o c\u00f3digo antigo fazia de errado estava escondido num detalhe banal: dentro de <code>montar()<\/code>, o agente dropava o screenshot anterior antes de concatenar. Opera\u00e7\u00e3o de uma linha, consequ\u00eancia de ordem de grandeza no custo.<\/p>\n<p>Esse padr\u00e3o aparece fora de agentes de navegador tamb\u00e9m. Numa extens\u00e3o de navegador que constru\u00ed para escrever direto num CRM, a decis\u00e3o de validar o payload antes de executar a escrita custa lat\u00eancia extra justamente porque obriga uma chamada de modelo adicional, e cada chamada paga de novo o custo do contexto. Quando o contexto \u00e9 grande, a diferen\u00e7a entre cache read e input cru decide se validar antes \u00e9 vi\u00e1vel ou n\u00e3o. Chamada bem sucedida de API n\u00e3o diz nada sobre o payload fazer sentido, ent\u00e3o validar vale a pena, mas s\u00f3 porque d\u00e1 para fazer o cache absorver quase todo o input.<\/p>\n<h2>Onde quebra<\/h2>\n<p>Nem tudo transfere igual, e o pr\u00f3prio estudo mostra onde:<\/p>\n<p>A Asana rodou um follow-up perguntando se \u00e9 preciso podar. Em certos casos manter todos os screenshots custou 1,2x menos por chamada que a melhor condi\u00e7\u00e3o de poda no Model B e no GPT-6.1 Sol, e cerca de 5% menos no Model C. Poda ainda importa para tarefas longas, janelas de contexto pequenas e leituras de cache mais caras.<\/p>\n<p>Ou seja, o 20:1 n\u00e3o \u00e9 uma receita universal. Depende de qu\u00e3o caro \u00e9 cache read no seu modelo, de qu\u00e3o grande \u00e9 a janela e de quanto dura a tarefa. Se seus screenshots forem pesados e o modelo tiver janela pequena, n\u00e3o podar vai estourar contexto antes do fim. Se cache read for barato o suficiente, segurar tudo pode ser mais barato que a l\u00f3gica de poda.<\/p>\n<p>Outros limites reais:<\/p>\n<ul>\n<li>O desconto s\u00f3 existe se o provedor que voc\u00ea usa oferece prompt caching e se voc\u00ea est\u00e1 montando a requisi\u00e7\u00e3o de um jeito que ele reconhece. Em alguns provedores voc\u00ea precisa marcar explicitamente o ponto de corte do cache, em outros \u00e9 autom\u00e1tico pelo prefixo. Confira a documenta\u00e7\u00e3o do seu antes de supor.<\/li>\n<li>Cache tem TTL. Se seu agente faz pausas longas entre chamadas, o cache expira e voc\u00ea paga o pre\u00e7o cheio no pr\u00f3ximo passo. A economia depende de cad\u00eancia.<\/li>\n<li>Aumentar o budget de hist\u00f3rico para 480k caracteres s\u00f3 \u00e9 barato porque quase tudo entra no cache. Se o cache n\u00e3o bater, voc\u00ea est\u00e1 pagando input cheio em um prompt gigante, pior que antes.<\/li>\n<li>O 76x \u00e9 um n\u00famero de teste, n\u00e3o de produ\u00e7\u00e3o est\u00e1vel. Rodaram tr\u00eas vezes cada condi\u00e7\u00e3o, n\u00e3o durante semanas em usu\u00e1rios reais. O ganho esperado em produ\u00e7\u00e3o depende da vari\u00e2ncia de tarefas que voc\u00ea n\u00e3o controla.<\/li>\n<\/ul>\n<h2>O que n\u00e3o d\u00e1 para afirmar ainda<\/h2>\n<p>O material p\u00fablico \u00e9 um resumo com n\u00fameros principais e um post t\u00e9cnico do time do StackAI, mas v\u00e1rias pe\u00e7as ficaram de fora:<\/p>\n<ul>\n<li>Qual \u00e9 o Model B exatamente. O estudo chama de A, B e C os tr\u00eas modelos de fronteira n\u00e3o-OpenAI, sem nomear. Ent\u00e3o n\u00e3o d\u00e1 para dizer se seu caso de uso em outro provedor se comporta como esse Model B.<\/li>\n<li>Qual era o conjunto de tarefas do benchmark. O estudo diz que os custos foram calculados pelos pr\u00f3prios contadores de token de cada provedor e que cada resposta foi avaliada contra uma refer\u00eancia preparada de forma independente, mas o detalhe das tarefas e dos crit\u00e9rios de qualidade n\u00e3o est\u00e1 no resumo p\u00fablico.<\/li>\n<li>O impacto em qualidade da resposta nas condi\u00e7\u00f5es otimizadas. O post diz que o objetivo era baratear sem reduzir qualidade, mas o resumo n\u00e3o mostra os n\u00fameros de qualidade por condi\u00e7\u00e3o.<\/li>\n<li>Como o cache marker \u00e9 implementado em cada provedor. A ideia \u00e9 port\u00e1vel, a API de cada um n\u00e3o \u00e9.<\/li>\n<\/ul>\n<p>Nada disso invalida o resultado. S\u00f3 delimita o que voc\u00ea pode copiar com confian\u00e7a (a mec\u00e2nica de prefixo, append-only, poda em lote) e o que voc\u00ea precisa medir no seu pr\u00f3prio contexto (n\u00fameros absolutos, limiar ideal de poda, qualidade final).<\/p>\n<h2>Como testar isso voc\u00ea mesmo<\/h2>\n<p>Um caminho pequeno, que cabe numa tarde:<\/p>\n<ol>\n<li>Escolha um agente simples que voc\u00ea j\u00e1 tenha, de prefer\u00eancia um que fa\u00e7a v\u00e1rias chamadas numa tarefa. Pode ser um agente de pesquisa, um de preenchimento de formul\u00e1rio, qualquer loop com hist\u00f3rico crescente.<\/li>\n<li>Instrumente cada chamada ao modelo e salve, do retorno da API, dois n\u00fameros: tokens de input totais e tokens de input lidos do cache. Quase todo provedor exp\u00f5e isso. Divida um pelo outro: essa \u00e9 sua taxa de cache hit.<\/li>\n<li>Rode a tarefa com o c\u00f3digo atual. Anote a taxa de cache hit por chamada. Se estiver abaixo de 50% a partir da terceira chamada, h\u00e1 prefixo quebrando no meio.<\/li>\n<li>Audite onde voc\u00ea edita o hist\u00f3rico. Qualquer <code>remove<\/code>, <code>pop<\/code>, <code>slice<\/code>, truncate ou substitui\u00e7\u00e3o de item antigo \u00e9 suspeito. Transforme em append-only.<\/li>\n<li>Se precisar podar (contexto apertado), implemente poda em lote. Comece com um limiar de 10 ou 20 e me\u00e7a. O n\u00famero 20:1 da Asana foi o que performou melhor no caso deles, n\u00e3o uma constante universal.<\/li>\n<li>Rode a mesma tarefa de novo. Compare taxa de cache hit, custo total e tempo. Se cache hit subiu e custo caiu sem queda de qualidade, voc\u00ea reproduziu o mecanismo.<\/li>\n<\/ol>\n<p>O ponto a levar deste caso n\u00e3o \u00e9 que exista um modelo m\u00e1gico. \u00c9 que a maior parte do ganho veio de parar de editar o meio do prompt. Isso \u00e9 uma decis\u00e3o de arquitetura do seu loop, n\u00e3o do fornecedor do modelo.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Entenda como a Asana reduziu 76x o custo e 5x o tempo de um agente de navegador reorganizando o prompt caching, com batch pruning e hist\u00f3rico append-only.<\/p>\n","protected":false},"author":2,"featured_media":768,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-769","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts\/769","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/comments?post=769"}],"version-history":[{"count":0,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/posts\/769\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/media\/768"}],"wp:attachment":[{"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/media?parent=769"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/categories?post=769"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yellowkode.com\/blog\/wp-json\/wp\/v2\/tags?post=769"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}