Phase 13 - Lesson 20

OpenTelemetry GenAI — Rastreamento de Chamadas de Ferramentas de Ponta a Ponta

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

Um agente chama cinco ferramentas, três servidores MCP e dois subagentes. Você precisa de um único trace em tudo isso. As convenções semânticas do OpenTelemetry GenAI (atributos estáveis na v1.37 e superiores) são o padrão de 2026, suportadas nativamente por Datadog, Langfuse, Arize Phoenix, OpenLLMetry e AgentOps. Esta lição nomeia os atributos necessários, percorre a hierarquia de spans (agente → LLM → ferramenta) e entrega um emissor de span da stdlib que você pode plugar em qualquer exportador OTel.

Tipo: Build Linguagens: Python (stdlib, emissor de span OTel) Pré-requisitos: Fase 13 · 07 (servidor MCP), Fase 13 · 08 (cliente MCP) Tempo: ~75 minutos

Objetivos de Aprendizado

  • Nomear os atributos OTel GenAI necessários para um span de LLM e um span de execução de ferramenta.
  • Construir uma hierarquia de trace que cubra o loop do agente, a chamada de LLM, a chamada de ferramenta e o despacho do cliente MCP.
  • Decidir qual conteúdo capturar (opt-in) vs. redigir (padrão).
  • Emitir spans para um coletor local (Jaeger, Langfuse) sem reescrever o código da ferramenta.

O Problema

Um debug de fevereiro de 2026: o usuário relata "meu agente às vezes leva 30 segundos para responder; outras vezes 3 segundos". Nenhum trace. Os logs mostram a chamada de LLM, mas não o despacho da ferramenta, nem a ida e volta ao servidor MCP, nem o subagente. Você tenta adivinhar. Eventualmente, você descobre: um servidor MCP ocasionalmente trava em um cold-start.

Sem rastreamento de ponta a ponta, você não consegue encontrar isso. O OTel GenAI resolve esse problema.

As convenções se consolidaram in 2025-2026 sob o grupo de convenções semânticas do OpenTelemetry (semantic-conventions). Elas definem nomes de atributos estáveis para que Datadog, Langfuse, Phoenix, OpenLLMetry e AgentOps analisem os mesmos spans. Instrumente uma vez; envie para qualquer backend.

O Conceito

Hierarquia de spans

agent.invoke_agent  (top, INTERNAL span)
 ├── llm.chat       (CLIENT span)
 ├── tool.execute   (INTERNAL)
 │    └── mcp.call  (CLIENT span)
 ├── llm.chat       (CLIENT span)
 └── subagent.invoke (INTERNAL)

Tudo se aninha sob um único ID de trace. Os IDs de span vinculam as relações pai-filho.

Atributos obrigatórios

De acordo com as convenções semânticas (semconv) de 2025-2026:

  • gen_ai.operation.name"chat", "text_completion", "embeddings", "execute_tool", "invoke_agent".
  • gen_ai.provider.name"openai", "anthropic", "google", "azure_openai".
  • gen_ai.request.model — string do modelo solicitado (ex: "gpt-4o-2024-08-06").
  • gen_ai.response.model — o modelo realmente servido.
  • gen_ai.usage.input_tokens / gen_ai.usage.output_tokens.
  • gen_ai.response.id — ID de resposta do provedor para correlação.

Para spans de ferramentas:

  • gen_ai.tool.name — identificador da ferramenta.
  • gen_ai.tool.call.id — o ID de chamada específico.
  • gen_ai.tool.description — descrição da ferramenta (opcional).

Para spans de agentes:

  • gen_ai.agent.name / gen_ai.agent.id / gen_ai.agent.description.

Tipos de spans (Span kinds)

  • SpanKind.CLIENT para chamadas que cruzam uma fronteira de processo (provedor de LLM, servidor MCP).
  • SpanKind.INTERNAL para as etapas do próprio loop do agente e execução de ferramentas.

Captura de conteúdo opcional (Opt-in)

Por padrão, os spans carregam métricas e temporização — não prompts ou conclusões (completions). Grandes volumes de dados (payloads) e PII (informações pessoalmente identificáveis) ficam desativados por padrão. Defina OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental e variáveis de ambiente específicas de captura de conteúdo para incluir o conteúdo. Revise cuidadosamente antes de ativar em produção.

Eventos em spans

Eventos no nível de token podem ser adicionados como eventos de span:

  • gen_ai.content.prompt — mensagens de entrada.
  • gen_ai.content.completion — mensagens de saída.
  • gen_ai.content.tool_call — chamada de ferramenta conforme registrada.

Os eventos são ordenados cronologicamente dentro de um span para reprodução detalhada.

Exportadores (Exporters)

Os spans do OTel são exportados para:

  • Jaeger / Tempo. OSS, on-prem.
  • Langfuse. Específico para observabilidade de LLM; visualiza o uso de tokens.
  • Arize Phoenix. Avaliações + tracing combinados.
  • Datadog. Comercial; analisa nativamente os atributos gen_ai.*.
  • Honeycomb. Orientado a colunas; amigável para consultas.

Todos utilizam o OTLP, o formato de transmissão de rede (wire format). Seu código não precisa se preocupar com isso.

Propagação via MCP

Quando um cliente MCP chama um servidor, injete o cabeçalho W3C traceparent na requisição. O HTTP transmitível (Streamable HTTP) suporta cabeçalhos padrão. O canal de entrada/saída padrão (stdio) não carrega cabeçalhos HTTP nativamente; o roadmap de 2026 da especificação discute a adição de um campo _meta.traceparent em chamadas JSON-RPC.

Até que isso seja lançado: inclua manualmente o traceparent no campo _meta de cada requisição. O servidor registra o ID de trace.

Métricas

Junto com os spans, as convenções semânticas do GenAI definem métricas:

  • gen_ai.client.token.usage — histograma.
  • gen_ai.client.operation.duration — histograma.
  • gen_ai.tool.execution.duration — histograma.

Use-as para painéis (dashboards) que não precisam de detalhes por chamada.

Camada do AgentOps

O AgentOps (fundado em 2024) é especializado em observabilidade de GenAI. Ele envelopa frameworks populares (LangGraph, Pydantic AI, CrewAI) para emitir spans do OTel automaticamente. Útil se sua pilha de tecnologia (stack) usa um framework suportado; caso contrário, use instrumentação manual.

Use-o

O arquivo code/main.py emite spans no formato OTel para a saída padrão (stdout) (em um formato semelhante a OTLP-JSON) para um agente que chama uma LLM, despacha duas ferramentas e faz uma viagem de ida e volta (round-trip) via MCP. Não há um exportador real — a lição se concentra no formato do span e no conjunto de atributos. Cole a saída em um visualizador compatível com OTLP ou apenas leia-a.

O que observar:

  • O ID de trace é compartilhado por todos os spans.
  • Os links pai-filho são codificados via parentSpanId.
  • Os atributos obrigatórios gen_ai.* são preenchidos.
  • A captura de conteúdo está desativada por padrão; um cenário a ativa por meio de variável de ambiente.

Envie

Esta lição produz outputs/skill-otel-genai-instrumentation.md. Dada uma base de código de agente, a skill produz um plano de instrumentação: onde adicionar spans, quais atributos preencher e quais exportadores visar.

Exercícios

  1. Execute code/main.py. Conte os spans e identifique quais são CLIENT vs. INTERNAL.

  2. Ative a captura de conteúdo (variável de ambiente) e confirme se os eventos gen_ai.content.prompt e gen_ai.content.completion aparecem. Observe as implicações para PII.

  3. Adicione a métrica de execução da ferramenta gen_ai.tool.execution.duration e emita-a como uma amostra de histograma por chamada.

  4. Propague um traceparent de um span pai de agente para o campo _meta.traceparent de uma requisição MCP. Verifique se o servidor MCP veria o mesmo ID de trace.

  5. Leia a especificação do OTel GenAI semconv. Identifique um atributo listado no semconv que o código desta lição NÃO emite. Adicione-o.

Termos-chave

Termo O que as pessoas dizem O que isso realmente significa
OTel "OpenTelemetry" Padrão aberto para traces, métricas e logs
GenAI semconv "Convenções semânticas do GenAI" Nomes de atributos estáveis para spans de LLM / ferramenta / agente
gen_ai.* "O namespace do atributo" Todos os atributos GenAI compartilham este prefixo
Span "Operação cronometrada" Uma unidade de trabalho com início, fim e atributos
Trace "Ancestralidade cruzada entre spans" Árvore de spans que compartilham um ID de trace
SpanKind "CLIENT / SERVER / INTERNAL" Dicas sobre a direção do span
OTLP "Protocolo de Linha do OpenTelemetry" Formato de transmissão (wire format) para exportadores
Opt-in content "Captura de prompt / completion" Desativado por padrão; variável de ambiente para ativar
traceparent "Cabeçalho W3C" Propaga o contexto de trace entre serviços
Exporter "Enviador específico do backend" Componente que envia spans para Jaeger / Datadog / etc.

Leitura Adicional

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).