Domínio 5 — Context Management & Reliability · Lição 5 de 5

Observabilidade, evals e proveniência

Objetivos de aprendizagem

Observabilidade: logue o usage de cada resposta

Cada resposta da Messages API traz um objeto usage com os contadores da chamada:

Logando esses números por chamada você responde perguntas de produção: quanto custa cada fluxo? O cache está funcionando (cache hit rate)? Qual agente do pipeline consome mais? Uma mudança de prompt invalidou silenciosamente o cache (hit rate despencou)? Sem esses logs, otimização de custo é chute.

Exemplo: logging de usage e cache hit rate

import anthropic

client = anthropic.Anthropic()

metrics = {"calls": 0, "input": 0, "output": 0, "cache_read": 0, "cache_write": 0}

def tracked_call(**kwargs):
    """Wrapper que loga usage por chamada e acumula metricas do pipeline."""
    response = client.messages.create(**kwargs)
    u = response.usage
    metrics["calls"] += 1
    metrics["input"] += u.input_tokens
    metrics["output"] += u.output_tokens
    metrics["cache_read"] += u.cache_read_input_tokens or 0
    metrics["cache_write"] += u.cache_creation_input_tokens or 0
    print(f"req={response._request_id} in={u.input_tokens} out={u.output_tokens} "
          f"cache_read={u.cache_read_input_tokens} cache_write={u.cache_creation_input_tokens}")
    return response

def cache_hit_rate() -> float:
    total_input = metrics["input"] + metrics["cache_read"] + metrics["cache_write"]
    return metrics["cache_read"] / total_input if total_input else 0.0

response = tracked_call(
    model="claude-opus-5",
    max_tokens=1024,
    system=[{"type": "text", "text": "Voce e um analista de pesquisa.",
             "cache_control": {"type": "ephemeral"}}],
    messages=[{"role": "user", "content": "Liste 3 riscos de sintese multi-fonte."}],
)
print(f"cache hit rate acumulado: {cache_hit_rate():.1%}")

Evals: avalie antes de otimizar

"Melhorar o prompt" sem uma suíte de avaliação é andar no escuro: você não sabe se a mudança melhorou, piorou ou só mudou os erros de lugar. O ciclo maduro:

  1. Defina critérios de sucesso mensuráveis (acurácia por segmento, taxa de escalação correta, custo por caso);
  2. Monte um conjunto de casos de teste representativo — incluindo os casos raros e os segmentos fracos;
  3. Rode a eval como baseline, mude uma coisa, rode de novo e compare;
  4. Em produção, monitore as mesmas métricas para detectar regressões e padrões novos de erro.

Evals conectam os domínios: os thresholds de confiança da lição 3 só são confiáveis porque foram medidos contra validation set; o custo da lição 2 só cai de verdade quando o cache hit rate é observado.

Proveniência: claim-source mappings (TS 5.6)

Em síntese multi-fonte, a atribuição de fonte se perde no ponto em que achados são comprimidos sem preservar o mapeamento claim → fonte. Depois de dois níveis de resumo, "o mercado cresceu 12%" não tem mais dono — e não pode ser verificado.

O padrão correto: exigir que subagentes emitam saída estruturada em que cada claim carrega sua fonte (URL ou nome do documento, trecho relevante/excerpt, data de publicação) e que os agentes downstream preservem e mesclem esses mapeamentos ao combinar achados — a síntese nunca "achata" o claim descartando a origem.

# Schema de finding com proveniencia que os subagentes devem emitir
# e que a sintese e obrigada a preservar ao mesclar:
finding = {
    "claim": "O mercado de X cresceu 12% em 2025",
    "source_name": "Relatorio Setorial Alfa 2025",
    "source_url": "https://exemplo.com/relatorio-alfa",
    "excerpt": "...crescimento de 12% no exercicio de 2025...",
    "publication_date": "2026-01-15",
    "methodology_note": "amostra de 400 empresas; exclui informais",
}
assert all(finding.get(k) for k in ("claim", "source_name", "publication_date"))

Conflitos entre fontes críveis

Formato segue o conteúdo. Na síntese final, renderize cada tipo de conteúdo adequadamente — dados financeiros como tabelas, notícias como prosa, achados técnicos como listas estruturadas — em vez de converter tudo para um formato uniforme que degrada a legibilidade.

Pegadinhas da prova

Resumo em 5 linhas

  1. Logue usage por chamada (input, output, cache read/write) para custo por fluxo e cache hit rate — sem isso, otimização é chute.
  2. Evals antes de otimizar: baseline mensurável, mudar uma coisa por vez, monitorar as mesmas métricas em produção.
  3. Cada claim carrega sua fonte (nome/URL, excerpt, data) em saída estruturada; a síntese preserva e mescla os mapeamentos.
  4. Conflito entre fontes críveis: incluir ambos os valores anotados com atribuição — nunca escolher arbitrariamente; datas evitam falsas contradições temporais.
  5. Relatórios separam "bem estabelecido" de "contestado", trazem coverage annotations e renderizam cada tipo de conteúdo no formato adequado.

Documentação oficial

Questões de fixação

1. Dois subagentes retornam estatísticas conflitantes de fontes igualmente críveis: crescimento de 12% e de 15%. O que o agente de análise deve entregar ao coordenador?

2. Após dois níveis de sumarização em um pipeline de pesquisa, o relatório final afirma "a adoção dobrou" sem que ninguém consiga dizer de qual fonte isso veio. Qual mudança estrutural previne o problema?

3. Um relatório sintetizado marca como "contradição entre fontes" dois números de market share: um de um censo de 2024 e outro de uma pesquisa de 2026. Que requisito de structured output teria evitado o falso conflito?

4. Quais duas práticas de observabilidade permitem detectar que uma mudança de prompt invalidou silenciosamente o prompt cache e disparou o custo? (escolha duas)