Pular para o conteúdo

Workflow: Otimizar Custo

Playbook para reduzir custo de operação de um tenant ou tipo de agente sem comprometer qualidade.


Quando usar

  • “O cliente X está caro demais”
  • “Vamos otimizar o agent-suporte que tá pesado”
  • /otimizar-custo TENANT_ID
  • Quando alerta automático dispara: custo > 200% da média do tipo

Princípio

Otimização sempre na ordem do mais barato e seguro pro mais caro e arriscado:

  1. Prompt caching (custo baixo, risco zero)
  2. Reduzir top_k do RAG (custo baixo, risco baixo)
  3. Memory summarizer (custo médio, risco baixo)
  4. Tática híbrida (Haiku para sub-tarefas) (custo médio, risco médio)
  5. Trocar modelo principal (custo alto, risco alto)

Não pule etapas.


Passo 1: Diagnóstico de custo

Terminal window
# Pega métricas reais dos últimos 30 dias
python scripts/cost_analysis.py --tenant {tenant_id} --days 30

Saída esperada:

Tenant: {tenant_id}
Período: 30 dias
Conversas processadas: X.XXX
Custo total: $XX.XX
Custo médio/conv: $0.XXXX
Distribuição de tokens:
Input: XX% (XX% deveria ser cache)
Output: XX%
Distribuição de modelo:
Sonnet: XX%
Haiku: XX%
Distribuição de tarefas:
Conversa principal: XX%
Classificação: XX%
Extração: XX%
Outros: XX%

Passo 2: Comparar com baseline do tipo

Terminal window
python scripts/cost_compare.py --tenant {tenant_id}

Compara com média de outros tenants do mesmo tipo de agente.

Se está dentro de ±20% da média: provavelmente saudável, mas vale verificar oportunidades comuns.

Se está >20% acima da média: tem problema específico, investigue.


Passo 3: Verificar oportunidades em ordem

Oportunidade A: Prompt caching está ativo?

Terminal window
grep -r "cache_control" src/ tenants/{tenant_id}/

Se NÃO está usando cache em system prompts > 1024 tokens:

Implementação:

# Em src/agent.py
system_messages = [
{
"role": "system",
"content": [
{
"type": "text",
"text": rendered_system_prompt,
"cache_control": {"type": "ephemeral"}
}
]
}
]

Economia esperada: 30-60% no custo de input quando cache hit > 70%.

Oportunidade B: top_k do RAG

Terminal window
grep "top_k" tenants/{tenant_id}/config.yaml

Se top_k > 6, vale testar redução:

# Antes
rag:
top_k: 8
# Depois
rag:
top_k: 5

Validação: rodar eval golden + 10 queries comuns. Se score não cai, manter 5.

Economia esperada: 15-25% no custo de input.

Oportunidade C: Memory summarizer

Terminal window
grep -A 3 "memory:" tenants/{tenant_id}/config.yaml

Se conversas são longas (>15 turnos médios) e summarizer não está agressivo:

memory:
short_term_size: 5 # últimas 5 mensagens em formato original
summarize_after: 8 # comprimir a partir da 8ª mensagem
summary_max_tokens: 200 # resumo enxuto

Economia esperada: até 40% em conversas longas.

Oportunidade D: Tática híbrida (model router)

Terminal window
grep "model_router\|task_type" src/

Se NÃO está usando model router:

Identifique sub-tarefas estruturadas no flow:

  • Classificação de intenção → Haiku
  • Extração de campos do CRM → Haiku
  • Confirmação de dados → Haiku
  • Geração de mensagem de despedida → Haiku
  • Conversa principal continua em Sonnet

Implementação:

# Antes
response = await llm.ainvoke(messages)
# Depois
response = await model_router.invoke(
messages=messages,
task_type="conversation", # ou "classification", "extraction", etc
tenant_id=tenant_id,
)

Configurar no config.yaml:

modelo:
principal: claude-sonnet-4-20250514 # conversa
estruturadas: claude-haiku-4-5-20251001 # sub-tarefas
routing:
classification: estruturadas
extraction: estruturadas
simple_response: estruturadas
confirmation: estruturadas
conversation: principal
creative: principal

Economia esperada: 30-50%. Risco: baixo se sub-tarefas são realmente estruturadas.

Oportunidade E: Trocar modelo principal

Última opção, maior risco.

Apenas considere se:

  • Outras 4 oportunidades já foram aplicadas
  • Custo ainda alto
  • Análise de traces sugere que tarefa não exige Sonnet

Sempre faça A/B test com 10% do tráfego por 7 dias antes de promover.


Passo 4: Simular impacto financeiro

Antes de aplicar, calcular projeção:

Terminal window
python scripts/cost_simulate.py \
--tenant {tenant_id} \
--apply prompt_caching,reduce_top_k,memory_summarizer,model_router \
--baseline-days 30

Saída:

Cenário atual (média 30 dias):
Custo/conv: $0.0XX
Custo/mês: R$ XXX
Cenário simulado:
Custo/conv: $0.0XX (-XX%)
Custo/mês: R$ XXX (economia de R$ XXX)
Risco estimado:
Prompt caching: Quase zero
top_k 8→5: Baixo (eval requerido)
Memory summarizer: Baixo
Model router: Médio (A/B test recomendado)

Passo 5: Aplicação faseada

Não aplique tudo de uma vez. Cada mudança pode ser medida isoladamente.

Cronograma sugerido:

  • Dia 1: Prompt caching (deploy direto)
  • Dia 2-3: Monitora cache hit rate
  • Dia 4: Reduzir top_k (deploy direto, monitora score)
  • Dia 5-7: Avaliar
  • Dia 8: Memory summarizer (deploy direto se conversas longas)
  • Dia 9-14: Avaliar
  • Dia 15: Model router em A/B com 10% (se necessário)
  • Dia 16-22: A/B running
  • Dia 23: Decidir promover ou descartar

Passo 6: Documentar resultado

Em .claude/reference/otimizacoes.md:

## YYYY-MM-DD — Tenant {tenant_id}
**Baseline**: $0.0XX/conv • R$ XXX/mês
**Pós-otimização**: $0.0XX/conv • R$ XXX/mês
**Economia**: R$ XXX/mês (-XX%)
**Aplicado**:
1. Prompt caching (impacto: -XX%)
2. top_k 8 → 5 (impacto: -XX%)
3. Memory summarizer (impacto: -XX%)
4. Model router para classificação e extração (impacto: -XX%)
**Não aplicado**:
- Trocar Sonnet por Haiku no flow principal
- Razão: A/B test mostrou queda de XX% na taxa de qualificação
**Aprendizado**: {generalizar para outros tenants}

Saída para o Alex

✓ Otimização concluída — {Cliente}
Resultado:
- Custo/conv: $0.0XX → $0.0XX (-XX%)
- Custo/mês: R$ XXX → R$ XXX (economia R$ XXX)
- Qualidade (CSAT/score): mantida em X.X
Aplicado:
1. {item}
2. {item}
3. {item}
Não aplicado:
- {item} — razão: {por que descartou}
Documentação: .claude/reference/otimizacoes.md (entrada nova)
Próximos candidatos a otimização (outros tenants):
- {tenant} — perfil similar, economia projetada R$ XXX
- {tenant} — perfil similar, economia projetada R$ XXX

Erros comuns a evitar

  1. Trocar modelo sem A/B — receita pra perder cliente
  2. Aplicar todas otimizações juntas — não consegue medir o que ajudou
  3. Não medir antes — sem baseline não tem como saber se otimizou
  4. Esquecer de documentar — perde aprendizado replicável
  5. Cortar muito o RAG — top_k abaixo de 3 quase sempre piora qualidade

Versão: 1.0 Relacionado: .claude/reference/decisoes.md, .claude/workflows/debug-producao.md