Conteúdo da trilha
Fundamento

Observabilidade para IA

Observability for AI

Observabilidade para IA (Observability for AI) é um fundamento de engenharia de IA para quem trabalha com LLMs. Traces, spans e logs que deixam você responder: por que o agente fez isso?

Elemento
13/13
Nível
Iniciante
Leitura
5 min
Atualizado
Nesta página 5
  1. 01A situação
  2. 02O conceito
  3. 03Experimente
  4. 04O que isso muda
  5. 05Teste seu entendimento
  6. ··Perguntas rápidas

A situação

Às 3h da manhã, o agente de incidentes recebeu um alerta de latência no serviço de pagamentos. Ele leu logs, consultou métricas e reiniciou o serviço de catálogo. O alerta continuou. O plantonista acordou com dois problemas em vez de um.

Na reunião do dia seguinte, a pergunta era uma só: por que o agente fez aquilo? O log da aplicação mostrava “restart solicitado pelo agente” e nada mais. Não dava para saber o que o modelo leu, qual ferramenta retornou o quê, nem qual versão do prompt estava rodando.

Em software comum, um stack trace conta a história do erro. Num sistema com IA, a decisão nasce do que o modelo viu no contexto. Se você não guardou o que ele viu, a decisão não tem explicação. E sem explicação, a única correção possível é chute: trocar o prompt, trocar o modelo, torcer.

O conceito

Observabilidade para IA é registrar cada execução de forma que você consiga responder, depois: o que entrou, o que o modelo decidiu, o que as ferramentas fizeram, quanto custou e quanto demorou. A unidade básica é o trace (o registro de uma execução inteira), dividido em spans (os trechos dessa execução).

flowchart TD
  T(["1. Trace: uma tarefa"]):::io --> S1(["2. Span: chamada ao modelo"]):::llm
  S1 --> S2["3. Span: ferramenta"]:::tool
  T --> S3(["2. Span: nova chamada ao modelo"]):::llm
  S1 --> A["4. Atributos: prompt, versão, tokens, custo"]:::tool
  S2 --> B["4. Atributos: argumentos, resultado, erro"]:::tool
  T --> D[("5. Armazenamento de traces")]:::store
  D --> Q{"6. Busca e análise"}
  1. Um trace cobre uma tarefa do começo ao fim: uma mensagem respondida, um documento processado, uma investigação.
  2. Cada chamada ao modelo vira um span, com início, fim e pai.
  3. Cada execução de ferramenta vira outro span, filho da chamada que pediu a ferramenta.
  4. Os atributos guardam o que importa para explicar a decisão.
  5. Os traces vão para um armazenamento que permite busca por usuário, por erro, por custo.
  6. Com isso você encontra a execução ruim, abre e lê o que aconteceu, passo a passo.

O mesmo incidente, com trace

Volte às 3h da manhã. Suponha que o agente tivesse trace. Abrindo a execução, você veria algo assim (exemplo ilustrativo):

trace incident-7f3a                          total 48s   custo US$ 0,21
├─ llm   decidir_proximo_passo   prompt=sre@12   in=3.104  out=88
│  └─ tool buscar_logs   args={"servico": "pagamentos", "limite": 50}
│        resultado: 50 linhas, todas "timeout ao chamar catalogo:8080"
├─ llm   decidir_proximo_passo   prompt=sre@12   in=6.877  out=41
│  └─ tool reiniciar_servico   args={"servico": "catalogo"}   resultado: ok
└─ llm   resposta_final   "Reiniciei o catálogo, causa provável dos timeouts."

Agora a decisão tem explicação. A ferramenta de logs devolveu só as 50 últimas linhas, e todas falavam do catálogo. O modelo fez uma inferência razoável com o que viu. O defeito não está no modelo: está no limite de 50 linhas e no fato de reiniciar_servico rodar sem aprovação. Você sai da reunião com duas correções concretas, em vez de “melhorar o prompt”.

Checagem +20 XP de primeiraNo trace de um agente, o span da ferramenta buscar_logs aparece solto, direto embaixo do trace, e não embaixo da chamada ao modelo que pediu a busca. Que informação você perde?

O que guardar em cada span

Span Atributos mínimos
Chamada ao modelo modelo, versão do prompt, mensagens de entrada, saída, tokens de entrada e saída, tokens de cache, latência, motivo de parada
Ferramenta nome, argumentos, resultado (ou resumo), erro, latência
Decisão em código rota escolhida, confiança, limite atingido
Humano quem aprovou ou recusou, quando, o que foi mostrado

O motivo de parada parece detalhe e não é. Uma resposta cortada por limite de tokens (max_tokens) e uma resposta completa podem parecer iguais no log da aplicação. No span, a diferença está escrita.

Logs, métricas e traces

  • Métricas respondem “está tudo bem?”: custo por hora, taxa de erro, latência p95.
  • Traces respondem “o que aconteceu nesta execução?”.
  • Logs guardam eventos soltos. Em sistemas com IA, quase tudo que importa cabe melhor como atributo de span.

Os três se completam. A métrica de custo por hora dispara o alerta. O filtro “traces com custo acima de US$ 1” mostra quais execuções puxaram a média. Abrir uma delas mostra o porquê.

O padrão de mercado para isso é o OpenTelemetry, que tem convenções semânticas próprias para IA generativa (atributos gen_ai.*). Essas convenções ainda estão marcadas como em desenvolvimento, então nomes de atributos podem mudar entre versões. Várias ferramentas de observabilidade de LLM leem esse formato.

Checagem +20 XP de primeiraA fatura do provedor de LLM subiu 40% nesta semana. Qual é a ordem de investigação que usa cada ferramenta para o que ela faz melhor?

Erros comuns

  • Guardar só a resposta final. É o equivalente a guardar só a última linha do stack trace. O erro quase sempre está num passo do meio.
  • Amostrar 1% dos traces. Funciona para tráfego web, onde as requisições se parecem. Em agentes, a execução rara e cara é justamente a que você precisa. Guarde todas as execuções com erro, as que bateram em limite e as mais caras.
  • Esquecer a versão do prompt. Sem ela, você não sabe se a reclamação de ontem veio do prompt antigo ou do novo.
  • Truncar o resultado da ferramenta sem avisar. Se o span mostra um resumo, marque que é resumo. Senão, você vai investigar um dado que o modelo nunca viu daquele jeito.

Privacidade

Traces guardam o texto que o usuário mandou. Isso inclui dados pessoais: CPF, endereço, histórico de compras, às vezes dados de saúde. Defina quem pode abrir os traces, por quanto tempo eles ficam guardados e o que é mascarado antes de gravar.

Mascare antes de gravar, não depois. Um trace com CPF em texto puro, guardado por um ano e aberto por qualquer pessoa do time, é um problema de LGPD esperando para acontecer. Troque o dado por um marcador ([CPF]) ou por um hash quando você precisar correlacionar execuções do mesmo usuário.

Experimente

Este exemplo cria um trace mínimo com OpenTelemetry e imprime no terminal. Instale opentelemetry-sdk e anthropic.

import anthropic
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor

provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("ai-guru.demo")

client = anthropic.Anthropic()
MODEL = "claude-haiku-4-5"
PROMPT_VERSION = "classifier@3"

with tracer.start_as_current_span("handle_message") as root:
    root.set_attribute("user.id", "u-123")
    with tracer.start_as_current_span(f"chat {MODEL}") as span:
        reply = client.messages.create(
            model=MODEL, max_tokens=50,
            system="Classifique em: fatura, pedido ou outro.",
            messages=[{"role": "user", "content": "Fui cobrado duas vezes"}],
        )
        span.set_attribute("gen_ai.operation.name", "chat")
        span.set_attribute("gen_ai.request.model", MODEL)
        span.set_attribute("prompt.version", PROMPT_VERSION)
        span.set_attribute("gen_ai.usage.input_tokens", reply.usage.input_tokens)
        span.set_attribute("gen_ai.usage.output_tokens", reply.usage.output_tokens)
        span.set_attribute("gen_ai.response.finish_reasons", [reply.stop_reason])
        span.set_attribute("app.output", reply.content[0].text)

Rode e leia o JSON que aparece. Repare em três coisas:

  1. O span chat claude-haiku-4-5 tem um parent_id igual ao span_id de handle_message.
  2. Os dois spans compartilham o mesmo trace_id. É ele que junta todos os passos de uma tarefa.
  3. prompt.version está lá. Mude para classifier@4, rode de novo e veja como fica fácil separar as execuções por versão.

Agora imagine uma tarefa com 15 spans assim, e um trace aberto numa tela que mostra a árvore inteira. É isso que faltou na reunião do começo desta página. Em produção, troque o ConsoleSpanExporter por um exportador OTLP que envia para a sua ferramenta de observabilidade.

O que isso muda

  • Sem trace, nenhum smell deste catálogo pode ser diagnosticado com certeza. O smell de não ter traces é o Voo Cego, e a refatoração é Adicionar Trace.
  • Toda página de padrão tem a seção “Em produção”, com os spans que devem existir e os alertas sugeridos.
  • A versão do prompt precisa estar no span. Sem ela você não reproduz a resposta que gerou a reclamação. Veja Prompt Sem Versão.
  • Traces de produção são a melhor fonte de casos para eval. Uma execução ruim vira um caso no Dataset de Ouro.
  • Quando o sistema decide sobre dinheiro, dados ou pessoas, o trace vira prova. O padrão que cuida disso é a Trilha de Auditoria.

Teste seu entendimento

Checagem +20 XP de primeiraUm cliente reclama que o bot de atendimento deu uma resposta errada sobre prazo de entrega ontem às 14h. Seu sistema guarda trace de todas as execuções, mas sem a versão do prompt. O time trocou o prompt às 13h. O que você não consegue afirmar?

Checagem +20 XP de primeiraSeu time quer economizar armazenamento e propõe guardar só 1% dos traces, escolhidos ao acaso. Qual é o problema dessa proposta num sistema com agentes?

Checagem +20 XP de primeiraUm assistente financeiro guarda nos traces as mensagens completas dos clientes, com CPF e saldo, por tempo indeterminado e com acesso livre para todo o time de engenharia. O que você muda primeiro?

Perguntas rápidas

O que é Observabilidade para IA?

Observabilidade para IA (Observability for AI) é um fundamento de engenharia de IA para quem trabalha com LLMs. Traces, spans e logs que deixam você responder: por que o agente fez isso?

Para ir além

Relações

Buscar