# Playbook: FinOps de GenAI — cortar o custo de um agente sem perder qualidade

Agentes de GenAI em produção acumulam custo em lugares que os dashboards padrão não mostram: tokens de entrada inflados, loops sem critério de parada, retries silenciosos e modelos caros em tarefas triviais. Este playbook apresenta as seis alavancas de otimização — com ordem de execução, tabela de impacto e os anti-padrões que transformam economia em regressão de qualidade.

- URL: https://fernando.moretes.com/studies/playbook-finops-de-genai-cortar-custo-de-agente

- Markdown: https://fernando.moretes.com/studies/playbook-finops-de-genai-cortar-custo-de-agente/study.md?lang=pt

- Type: Playbook

- Domain: IA / FinOps

- Date: 2026-03-25

- Tags: finops, genai, bedrock, agents, cost-optimization, llm, prompt-engineering, aws

- Reading time: 10 min

---

O CFO entrou na conversa. Seu agente de GenAI funciona — mas a fatura do Bedrock cresceu mais rápido do que o uso justifica, e ninguém sabe exatamente por quê. O problema raramente é o modelo: é o design ao redor dele. Este playbook te dá as alavancas certas, na ordem certa, sem sacrificar qualidade.

## O que você vai conseguir decidir depois deste playbook

- Onde instrumentar antes de qualquer otimização (tokens por rota, por modelo, por iteração de loop)
- Qual alavanca atacar primeiro com base no perfil de custo do seu agente
- Como rotear tarefas simples para modelos baratos sem regressão de qualidade
- Quando usar cache de prompt e quando ele não ajuda
- Por que retry silencioso é o custo escondido mais perigoso em agentes
- Como structured output e stop rules cortam custo sem tocar no modelo

## Contexto do Playbook

- **Tipo:** Playbook genérico — aplicável a qualquer agente em Amazon Bedrock
- **Domínio:** FinOps de GenAI / Otimização de custo de LLM
- **Stack de referência:** Amazon Bedrock (Agents, Prompt Caching, Batch Inference), CloudWatch, Cost Explorer
- **Modelos cobertos:** Claude 3 Haiku / Sonnet / Opus, Titan, Llama 3 — qualquer modelo com preço por token de entrada/saída
- **Premissa crítica:** Você não corta custo que não mede. Instrumentação vem antes de otimização.
- **Números de economia:** Todos os percentuais citados são [exemplo ilustrativo] — não dados de caso real

## O modelo mental que desbloqueia tudo: você paga por cada token que entra no loop

A maioria dos engenheiros pensa no custo de um agente como `(tokens de entrada + tokens de saída) × preço/token`. Isso está certo para uma chamada única. Mas um agente não faz uma chamada — ele faz um **loop**: planeja, chama ferramenta, observa resultado, replana, chama ferramenta de novo, gera resposta final. Cada iteração desse loop recebe como entrada o histórico acumulado de todas as iterações anteriores. O contexto cresce. O custo cresce quadraticamente com o número de iterações se você não controlar o que entra.

Soma-se a isso o **retry silencioso**: quando o modelo retorna JSON malformado, quando um tool call falha, quando o parsing quebra — o orquestrador tenta de novo. Sem observabilidade, cada retry aparece como uma chamada normal no billing. Em agentes com loops longos e ferramentas instáveis, retries podem representar 20–40% do custo total [exemplo ilustrativo].

O segundo ponto cego é o **modelo uniforme**: times que sobem um agente usam Claude Sonnet (ou equivalente mid-tier) em todas as etapas porque é o que funciona no protótipo. Em produção, 60–70% das chamadas são classificação de intenção, extração de campo, roteamento — tarefas que um modelo de classe Haiku resolve com qualidade equivalente a uma fração do custo [exemplo ilustrativo]. Usar o mesmo modelo para raciocínio complexo e para 'qual é o sentimento desta frase?' é desperdício estrutural.

A premissa deste playbook é simples: **qualidade quase nunca mora no modelo mais caro — mora no design**. Contexto bem construído, saída estruturada, critério de parada explícito e roteamento por complexidade entregam mais resultado por dólar do que trocar Haiku por Opus em tudo.

## Instrumentação: o pré-requisito inegociável

Antes de tocar em qualquer alavanca de otimização, você precisa saber **onde o dinheiro está indo**. O Amazon Bedrock expõe métricas de token via CloudWatch (`InputTokenCount`, `OutputTokenCount` por model ID), mas por padrão elas não têm dimensão de rota ou de iteração de loop. Você precisa adicionar isso.

**O que instrumentar, no mínimo:**

1. **Tokens por rota de negócio** — não apenas 'quanto o agente consumiu', mas 'quanto a rota de suporte ao cliente consumiu vs. a rota de análise de documento'. Isso revela qual fluxo está fora de controle.

2. **Tokens por iteração de loop** — log estruturado com `step_index`, `model_id`, `input_tokens`, `output_tokens`, `tool_called`, `is_retry`. Sem isso, você não distingue custo legítimo de custo de retry.

3. **Tokens de contexto acumulado** — o tamanho do contexto na entrada de cada chamada. Se esse número cresce monotonicamente ao longo do loop, você tem um problema de janela de contexto que vai explodir em produção.

4. **Taxa de retry por ferramenta** — quantas vezes cada tool call falhou e foi reexecutada. Ferramentas com alta taxa de falha são multiplicadores de custo.

**Onde emitir:** CloudWatch Embedded Metric Format (EMF) é a opção mais simples no ecossistema AWS — você emite JSON estruturado do Lambda/ECS e ele vira métrica e log simultaneamente, sem agente extra. Para análise ad-hoc, jogue os mesmos eventos no S3 + Athena.

Só depois de ter esse baseline por 5–7 dias de tráfego real você tem dados suficientes para priorizar as alavancas abaixo. Otimizar sem medir é trocar um problema por outro.

## As 6 alavancas de otimização — em ordem de execução recomendada

1. **Alavanca 1 — Instrumentação (pré-requisito)** — Emita tokens por rota, por iteração, por modelo via CloudWatch EMF. Adicione `is_retry: true` em toda chamada que é consequência de falha de parsing ou tool error. Crie um dashboard com: (a) custo por rota/dia, (b) média de iterações por sessão, (c) taxa de retry por ferramenta. Só avance para as próximas alavancas depois de 5–7 dias de baseline. **Testável:** você consegue responder 'qual rota custou mais ontem e quantas iterações ela teve em média?'

2. **Alavanca 2 — Roteamento por modelo (maior ROI, maior risco se mal feito)** — Classifique cada step do loop por complexidade: (a) classificação/extração/roteamento → modelo leve (ex: Claude 3 Haiku, Titan Lite); (b) raciocínio multi-step, síntese longa, geração de código complexo → modelo mid/high (ex: Claude 3 Sonnet/Opus). Implemente um roteador simples: antes de cada chamada, um classificador leve (pode ser o próprio modelo barato) decide qual modelo usar. **Regra prática:** se a tarefa tem resposta esperada com menos de 50 tokens e não requer raciocínio encadeado, use o modelo barato. **Risco:** não teste apenas no happy path — teste com inputs ambíguos, multilíngues, com erros de digitação. Regressão de qualidade em casos de borda é o principal problema do roteamento mal calibrado.

3. **Alavanca 3 — Cache de prompt** — O Bedrock Prompt Caching permite marcar prefixos de prompt (system prompt, documentos de contexto, exemplos few-shot) para reutilização entre chamadas. Tokens em cache custam menos por leitura do que tokens processados normalmente. **Quando usar:** system prompts longos (>1000 tokens) que se repetem em muitas requisições; documentos de referência fixos (manuais, políticas) injetados em todo contexto; exemplos few-shot estáticos. **Quando NÃO usar:** contextos altamente dinâmicos onde o prefixo muda a cada chamada (o cache nunca é hit); sessões de baixo volume onde o overhead de gerenciar TTL não compensa. **Implementação:** marque o prefixo estável com `cachePoint` na API do Bedrock.

4. **Alavanca 4 — Contexto enxuto (você paga token de entrada — não empurre o histórico inteiro)** — Em agentes com múltiplas iterações, o histórico de conversa é injetado como contexto em cada chamada. Se você injeta o histórico completo, o custo de entrada cresce O(n²) com o número de turnos. **Estratégias:** (a) **Truncamento por relevância:** mantenha apenas os N turnos mais recentes + o plano atual; (b) **Sumarização progressiva:** a cada K iterações, chame o modelo barato para sumarizar o histórico e substitua os K turnos pelo resumo; (c) **Tool results compactos:** quando uma ferramenta retorna um JSON grande, extraia apenas os campos relevantes antes de injetar no contexto — não injete o payload bruto. **Atenção:** truncamento ingênuo (cortar os primeiros N tokens) pode remover contexto crítico.

5. **Alavanca 5 — Stop rules e menos iterações** — Agentes sem critério explícito de parada 'pensam demais': o modelo continua planejando e chamando ferramentas mesmo quando já tem informação suficiente para responder. Isso é custo puro. **Implemente:** (a) `max_iterations` hardcoded por tipo de tarefa (não um valor global — uma tarefa de extração de campo tem max 3 iterações; uma tarefa de pesquisa profunda pode ter 10); (b) **Stop condition por confiança:** se o modelo retornar um campo `confidence` no structured output > threshold, interrompa o loop imediatamente; (c) **Early exit por tool result:** se uma ferramenta retornar um resultado definitivo (ex: registro encontrado no banco), não continue o loop — responda diretamente.

6. **Alavanca 6 — Structured output + batch/assíncrono** — **Structured output:** quando o agente precisa retornar dados estruturados (JSON, lista de campos), force o schema via `response_format` ou via instrução explícita no prompt. Saída não estruturada que falha no parsing vira retry — e retry é custo duplicado. Use JSON Schema quando o modelo suportar natively (Bedrock Converse API); caso contrário, inclua o schema no system prompt com exemplo. **Batch inference:** para workloads assíncronos (relatórios noturnos, processamento de documentos em fila, análise em lote), use Bedrock Batch Inference — o custo por token é significativamente menor do que on-demand [verifique pricing atual em aws.amazon.com/bedrock/pricing]. O trade-off é latência: batch tem SLA de horas, não segundos.

## Antes vs. Depois por alavanca — impacto, risco de qualidade, esforço
| Critério | Alavanca | Onde corta custo | Economia potencial [exemplo] | Risco de qualidade | Esforço de implementação |
| --- | --- | --- | --- | --- | --- |
| Instrumentação | Visibilidade — não corta diretamente | — | Nenhum | Baixo (1–3 dias) | Nenhum |
| Roteamento por modelo | Custo por chamada nas tarefas simples | 30–60% nas rotas roteadas [exemplo] | Alto se mal calibrado — teste edge cases | Médio (1–2 semanas + testes) | Baseline de qualidade por rota |
| Cache de prompt | Tokens de entrada repetidos (system prompt, docs) | 20–50% nos tokens de prefixo [exemplo] | Baixo — não altera lógica | Baixo (horas) | System prompt estável, volume suficiente |
| Contexto enxuto | Tokens de entrada por iteração de loop | 20–40% no custo de entrada em loops longos [exemplo] | Médio — truncamento errado perde contexto crítico | Médio (1 semana) | Mapa de quais campos do histórico são essenciais |
| Stop rules | Iterações desnecessárias no loop | 10–30% em agentes com loops longos [exemplo] | Baixo se max_iterations por tipo de tarefa | Baixo (dias) | Distribuição de iterações por tipo de tarefa |
| Structured output | Retries por parsing failure | Elimina custo de retry de parsing [pode ser 5–20% do total, exemplo] | Baixo — melhora consistência | Baixo (horas–dias) | Schema definido pelo produto |
| Batch/assíncrono | Custo por token em workloads sem SLA de tempo real | Desconto significativo vs. on-demand [verifique pricing atual] | Nenhum — mesma qualidade de modelo | Médio (arquitetura assíncrona) | Workload sem SLA de latência |

## O custo escondido: retry silencioso e por que ele é o mais perigoso

Em agentes de produção, o retry silencioso é o multiplicador de custo que ninguém vê até olhar os logs com atenção. Ele acontece em três formas principais:

**1. Retry por parsing failure:** o modelo retorna texto livre quando você esperava JSON, ou retorna JSON com campos faltando. O orquestrador detecta o erro, monta um novo prompt pedindo para o modelo 'tentar de novo no formato correto', e faz outra chamada completa. Cada retry desse tipo custa o mesmo que uma chamada original — e você paga duas vezes pelo mesmo resultado (quando funciona na segunda tentativa).

**2. Retry por tool error:** uma ferramenta externa (API, banco de dados, serviço interno) falha com timeout ou erro 5xx. O agente tenta de novo, às vezes com o mesmo input, às vezes com uma variação. Se a ferramenta é instável, isso vira um loop de retries que consome tokens sem produzir valor.

**3. Retry por ambiguidade de instrução:** o modelo interpreta a instrução de forma diferente do esperado, produz um resultado que o código downstream rejeita, e o orquestrador re-injeta a instrução com mais contexto. Esse é o mais caro porque o prompt de retry é maior do que o original.

A solução para (1) é structured output com schema explícito. A solução para (2) é circuit breaker nas ferramentas externas + retry com backoff no nível da ferramenta, não no nível do loop do agente. A solução para (3) é prompt engineering mais preciso + testes de instrução antes de ir para produção.

O que torna o retry silencioso perigoso não é apenas o custo — é que ele mascara problemas de qualidade. Se seu agente tem 15% de taxa de retry e você não sabe, você está pagando 15% a mais e acreditando que o sistema é mais confiável do que é.

## Fluxo de custo do agente — onde cada alavanca corta

Diagrama mostra o loop interno de um agente Bedrock com os pontos de custo e onde cada alavanca de otimização atua. Tokens de entrada crescem com o histórico acumulado; retries duplicam chamadas; iterações desnecessárias multiplicam tudo.

### 👤 Entrada do usuário

- Usuário User request (user)

### 🔀 Roteador / Router

- Roteador de Modelo [Alavanca 2] Model Router (compute)

### 🧠 Loop do Agente / Agent Loop

- Orquestrador Orchestrator (compute)
- Context Builder [Alavanca 4: contexto enxuto] [Lever 4: lean context] (compute)
- Chamada ao Modelo Model Call 💰 INPUT TOKENS 💰 OUTPUT TOKENS (ai)
- Stop Rule Check [Alavanca 5] max_iterations / confidence (compute)
- Output Parser [Alavanca 6: structured output] JSON Schema validation (compute)

### 🔧 Ferramentas / Tools

- Tool Executor API / DB / Service (external)
- Circuit Breaker (evita retry de tool) (prevents tool retry) (compute)

### 💾 Cache / Cache

- Prompt Cache [Alavanca 3] Bedrock cachePoint 💰 cache read < input token (storage)

### 📦 Batch / Async

- Fila Assíncrona Async Queue [Alavanca 6: batch] SQS / EventBridge (messaging)
- Bedrock Batch Inference 💰 menor custo/token 💰 lower cost/token (ai)

### 📊 Observabilidade / Observability

- CloudWatch EMF [Alavanca 1] tokens/rota, tokens/iteração is_retry flag (data)
- Dashboard Custo/rota, P95 iterações taxa de retry (data)

### Fluxos

- user -> router: request
- router -> orchestrator: modelo selecionado
- orchestrator -> context_builder: histórico + plano
- context_builder -> prompt_cache: prefixo estático
- context_builder -> model_call: contexto enxuto
- model_call -> stop_check: resposta + confiança
- stop_check -> output_parser: continua
- stop_check -> user: early exit
- output_parser -> tool_exec: tool call
- output_parser -> orchestrator: retry (parsing fail) ⚠️
- tool_exec -> circuit_breaker: resultado / erro
- circuit_breaker -> orchestrator: tool result
- circuit_breaker -> orchestrator: retry tool ⚠️
- model_call -> emf: tokens + is_retry
- emf -> dashboard
- batch_queue -> batch_inference: workload assíncrono

> **Anti-padrões que vão te morder em produção:** **1. Otimizar sem medir primeiro.** Trocar o modelo sem baseline de qualidade é o caminho mais rápido para uma regressão silenciosa. Você vai cortar custo, o CFO vai ficar feliz, e três semanas depois alguém vai perceber que a taxa de resolução caiu. Meça antes, meça depois, compare com rigor.

**2. Trocar por modelo pior em tarefas que parecem simples mas não são.** 'Classificação de intenção' parece trivial até você descobrir que seu domínio tem 40 intenções, algumas com sobreposição semântica alta, e o modelo barato confunde 8% dos casos — e esses 8% são justamente os casos de alto valor. Teste com dados reais do seu domínio, não com benchmarks genéricos.

**3. Cache de prompt em contexto dinâmico.** Se o seu system prompt muda por usuário, por sessão, ou por feature flag, o cache nunca vai ser hit e você vai pagar o overhead de escrita sem nenhum benefício. Cache só funciona quando o prefixo é verdadeiramente estático e o volume é alto o suficiente para amortizar a escrita.

**4. `max_iterations` global alto como 'segurança'.** Um valor como `max_iterations=20` em produção não é segurança — é um cheque em branco para loops patológicos. Defina por tipo de tarefa, com valores conservadores, e monitore a distribuição de iterações ativamente.

**5. Ignorar o custo de tokens de saída em modelos de raciocínio.** Modelos com 'thinking' ou 'extended reasoning' (ex: Claude com thinking habilitado) geram tokens de raciocínio interno que são cobrados. Para tarefas simples, desabilite o thinking — você está pagando por um processo de raciocínio que a tarefa não precisa.

> **Regra de bolso:** **Se você só puder fazer uma coisa: instrumente os tokens por rota e por iteração antes de qualquer otimização.** O custo de um agente quase nunca está onde você acha que está. Sem dados, você vai otimizar a parte errada e não vai saber se funcionou. Com dados, as alavancas certas ficam óbvias em 48 horas de análise.

> **Minha perspectiva — o que eu faço na prática:** Quando recebo um agente com problema de custo, a primeira coisa que faço é pedir os logs brutos das últimas 48 horas com `input_tokens`, `output_tokens`, `model_id`, `step_index` e `is_retry`. Em 80% dos casos, o problema é um desses três: (a) system prompt de 3000 tokens sendo injetado em cada iteração sem cache; (b) tool results brutos de 10k tokens sendo empurrados no contexto inteiro; ou (c) taxa de retry de parsing acima de 10% porque o prompt não especifica o schema de saída.

O roteamento por modelo é a alavanca de maior ROI, mas também a que mais vejo ser feita errada. Times fazem o roteamento baseado em 'esse step parece simples', sem testar com dados reais do domínio. Minha abordagem: antes de rotear qualquer step para o modelo barato, crio um conjunto de 100 casos representativos (incluindo edge cases do domínio), rodo nos dois modelos, e só roteo se a diferença de qualidade for < threshold definido pelo produto. Isso leva 2–3 dias, mas evita a regressão silenciosa que aparece 3 semanas depois.

Sobre cache de prompt: é a alavanca mais fácil de implementar e a mais subestimada. Se você tem um system prompt longo e estático, ativar o cache no Bedrock é literalmente adicionar um campo na API e monitorar o hit rate. O único cuidado é garantir que o prefixo marcado como cache realmente não muda entre requisições — se mudar, você paga write sem ganhar read.

Uma coisa que aprendi em sistemas financeiros: custo escondido é risco escondido. Retry silencioso não é só caro — é um sinal de que o sistema está falhando de formas que você não está vendo. Instrumentar o retry é instrumentar a confiabilidade.

## Alinhamento com AWS Well-Architected

- **security**: Ao truncar histórico e sumarizar contexto, certifique-se de que dados sensíveis não persistem em resumos além do necessário. Revise políticas de retenção de logs de tokens — eles podem conter dados de negócio.
- **reliability**: Circuit breaker em ferramentas externas e structured output reduzem tanto custo quanto falhas silenciosas. Stop rules com max_iterations por tipo de tarefa previnem loops infinitos em produção.
- **performance**: Contexto enxuto reduz latência além de custo — menos tokens de entrada = menor tempo de processamento. Cache de prompt reduz latência de primeiras iterações com system prompts longos.

## Referências

- [Amazon Bedrock — Pricing](https://aws.amazon.com/bedrock/pricing/)
- [Amazon Bedrock — Prompt Caching (User Guide)](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html)
- [Amazon Bedrock — Batch Inference (User Guide)](https://docs.aws.amazon.com/bedrock/latest/userguide/batch-inference.html)
- [AWS Well-Architected — Cost Optimization Pillar](https://docs.aws.amazon.com/wellarchitected/latest/cost-optimization-pillar/welcome.html)

## Veredicto

FinOps de GenAI não é sobre usar o modelo mais barato — é sobre não desperdiçar tokens em design ruim. O modelo certo para a tarefa certa, contexto cirúrgico, cache onde o prefixo é estável, stop rules que respeitam a complexidade da tarefa, e saída estruturada que elimina retry: essas seis alavancas, aplicadas com dados, entregam mais resultado por dólar do que qualquer troca de modelo feita às cegas. O custo escondido mais perigoso não é o token que você vê na fatura — é o retry silencioso que te diz que o sistema está falhando de formas que você ainda não mediu.

## Fontes do caso

- [Amazon Bedrock — Pricing](https://aws.amazon.com/bedrock/pricing/)
- [Amazon Bedrock — Prompt caching](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html)
- [Amazon Bedrock — Batch inference](https://docs.aws.amazon.com/bedrock/latest/userguide/batch-inference.html)
- [AWS — Cost Optimization Pillar (Well-Architected)](https://docs.aws.amazon.com/wellarchitected/latest/cost-optimization-pillar/welcome.html)
