Observabilidade pra Agentes de AI em Produção: do Zero ao Avançado
Como monitorar, debuggar e entender o que seus agentes autônomos estão fazendo com OpenTelemetry, Langfuse e ferramentas open-source
Software tradicional quebra de formas previsíveis. Um timeout, um null pointer, um 500. Você olha o log, acha a linha, corrige. Agentes de AI quebram de formas criativas. Eles alucinam, chamam a ferramenta errada, entram em loop, gastam tokens sem parar, e o pior: às vezes parecem funcionar quando na verdade estão fazendo besteira.
Se você tá colocando agentes em produção sem observabilidade, você tá voando cego. Este artigo é o guia completo pra resolver isso.
O problema é diferente
Quando um microsserviço falha, o erro é binário: funcionou ou não. Com agentes de AI, o espectro é muito mais amplo:
- O agente respondeu, mas a resposta tá errada (alucinação)
- O agente chamou 15 ferramentas quando precisava de 2 (custo explodindo)
- O agente entrou em loop entre duas ferramentas e nunca convergiu
- A latência da resposta subiu de 2s pra 45s sem motivo aparente
- O prompt de sistema foi ignorado parcialmente
Nenhum desses problemas aparece num health check HTTP 200. Você precisa de traces, métricas e logs específicos pra GenAI.
Os três pilares aplicados a agentes
Observabilidade tem três pilares clássicos: traces, métricas e logs. Pra agentes de AI, cada um ganha um significado próprio.
Traces
Um trace de agente não é só "request → response". É uma árvore de decisões:
[Agent Run] ─── duração total: 12.3s
├── [LLM Call #1] ─── modelo: claude-sonnet-4-6, tokens: 1.2k in / 340 out
│ └── decisão: chamar ferramenta "buscar_pedido"
├── [Tool Call: buscar_pedido] ─── duração: 230ms
│ └── resultado: {pedido_id: 4521, status: "enviado"}
├── [LLM Call #2] ─── modelo: claude-sonnet-4-6, tokens: 1.8k in / 120 out
│ └── decisão: chamar ferramenta "rastrear_envio"
├── [Tool Call: rastrear_envio] ─── duração: 890ms
│ └── resultado: {codigo: "BR123456789", status: "em_transito"}
└── [LLM Call #3] ─── modelo: claude-sonnet-4-6, tokens: 2.1k in / 250 out
└── resposta final ao usuário
Cada nó dessa árvore é um span. O trace completo mostra o fluxo de execução do agente, passo a passo: chamadas ao modelo, uso de ferramentas, latência, tokens e resposta final. Isso vale independente do provider: OpenAI, Anthropic, Google, Mistral.
Métricas
As métricas que importam pra agentes são diferentes das tradicionais:
- Token usage (input + output, por chamada e por execução completa)
- Custo estimado (tokens × preço do modelo)
- Latência por etapa (LLM call vs tool call vs total)
- Número de steps por execução (agente convergiu rápido ou ficou rodando?)
- Taxa de fallback (quantas vezes o agente não conseguiu resolver)
- Tool call distribution (quais ferramentas são mais usadas)
Logs (eventos)
Logs estruturados capturam o conteúdo das interações:
- Prompt de sistema enviado
- Mensagens do usuário
- Respostas do modelo (incluindo tool calls)
- Argumentos e retornos de ferramentas
- Erros e exceções
Isso é sensível. Por padrão, a maioria das ferramentas não captura o conteúdo das mensagens. Você liga isso explicitamente quando precisa debuggar.
OpenTelemetry: a fundação
OpenTelemetry (OTel) é o padrão open-source pra instrumentação. É vendor-agnostic: você instrumenta uma vez e exporta pra Jaeger, Grafana, Datadog, Honeycomb, ou qualquer backend.
O OTel já tem semantic conventions específicas pra GenAI, cobrindo spans de inferência, métricas de token usage e eventos de input/output. Também existe uma seção separada para agent spans. Detalhe importante: em março de 2026, essas convenções ainda estão em status Development, o que significa que nomes de atributos e estruturas podem evoluir em versões futuras.
As convenções cobrem providers específicos com documentação dedicada: OpenAI, Anthropic, AWS Bedrock e Azure AI Inference.
Os atributos principais:
| Atributo | O que captura |
gen_ai.operation.name | Tipo de operação (chat, invoke_agent, execute_tool, etc.) |
gen_ai.request.model | Modelo solicitado (gpt-4.1, claude-sonnet-4-6, etc.) |
gen_ai.response.model | Modelo que respondeu (pode diferir do solicitado) |
gen_ai.usage.input_tokens | Tokens consumidos no input |
gen_ai.usage.output_tokens | Tokens consumidos no output |
gen_ai.provider.name | Provider (openai, anthropic, etc.) |
gen_ai.response.finish_reasons | Motivo do fim da geração (stop, length, tool_calls, end_turn) |
Pra fluxos agentic, o OTel documenta operações padronizadas como create_agent (criação do agente), invoke_agent (invocação) e execute_tool (execução de ferramenta), além dos spans tradicionais de inferência. Na prática, isso permite separar o trace do "agente como orquestrador" do trace das chamadas LLM e das ferramentas executadas.
Instrumentações disponíveis no ecossistema OTel
O ecossistema de instrumentação OTel pra GenAI cresceu rápido. Aqui tá o que existe e funciona:
Repositório oficial opentelemetry-python-contrib
Estas vivem no repositório oficial do OpenTelemetry (opentelemetry-python-contrib):
| Pacote | SDK suportado |
opentelemetry-instrumentation-openai-v2 | openai >= 1.26.0 |
opentelemetry-instrumentation-anthropic | anthropic >= 0.16.0 |
opentelemetry-instrumentation-google-genai | google-genai >= 1.32.0 |
opentelemetry-instrumentation-langchain | langchain >= 0.3.21 |
opentelemetry-instrumentation-vertexai | google-cloud-aiplatform >= 1.64 |
Os pacotes acima oferecem níveis diferentes de suporte a traces, eventos/logs e, em alguns casos, métricas. Como esse detalhe varia por pacote e versão, vale conferir a documentação do instrumentor exato antes de assumir cobertura completa.
Note também que pra o ecossistema Google existem pacotes distintos dependendo do SDK que você usa (google-genai vs google-cloud-aiplatform). Valide o nome do pacote contra o SDK exato do seu projeto.
OpenLLMetry (Traceloop)
Projeto open-source (Apache 2.0) que oferece instrumentação automática pra vários providers: OpenAI, Anthropic, Azure OpenAI, Google AI, Mistral, Cohere, Amazon Bedrock, além de vector DBs como Pinecone, Chroma e Weaviate. Disponível pra Python e Node.js/TypeScript.
A grande vantagem do OpenLLMetry: um init() e ele detecta e instrumenta automaticamente os SDKs compatíveis instalados.
Stack prática: montando do zero
Três opções, todas com exemplos multi-provider.
Opção 1: OpenTelemetry puro + Jaeger
Pra quem já usa OTel na infra ou quer controle total.
Setup base (compartilhado entre providers)
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
def setup_telemetry(endpoint: str = "localhost:4317") -> None:
provider = TracerProvider()
processor = BatchSpanProcessor(
OTLPSpanExporter(endpoint=endpoint, insecure=True)
)
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
O insecure=True é pra desenvolvimento local (sem TLS). Em produção, configure certificados.
Com OpenAI
pip install openai opentelemetry-api opentelemetry-sdk \
opentelemetry-exporter-otlp \
opentelemetry-instrumentation-openai-v2
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
import openai
setup_telemetry()
OpenAIInstrumentor().instrument()
client = openai.OpenAI()
response = client.chat.completions.create(
model="gpt-4.1",
messages=[{"role": "user", "content": "Qual a capital da França?"}]
)
Com Anthropic (Claude)
pip install anthropic opentelemetry-api opentelemetry-sdk \
opentelemetry-exporter-otlp \
opentelemetry-instrumentation-anthropic
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
import anthropic
setup_telemetry()
AnthropicInstrumentor().instrument()
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Qual a capital da França?"}]
)
O setup do OTel é idêntico. Só muda o instrumentor e o client. Os traces gerados seguem as mesmas semantic conventions, com gen_ai.provider.name setado pra "anthropic" ou "openai".
Múltiplos providers no mesmo projeto
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
setup_telemetry()
OpenAIInstrumentor().instrument()
AnthropicInstrumentor().instrument()
# A partir daqui, qualquer chamada a qualquer provider gera traces
Útil quando seu agente usa modelos diferentes pra tarefas diferentes (ex: Claude pra raciocínio complexo, GPT-4.1-nano pra classificação rápida).
Capturando conteúdo das mensagens
A captura de conteúdo varia por instrumentação. Nas instrumentações GenAI mais novas (como openai-v2 e google-genai), prompts e respostas normalmente não são capturados por padrão e precisam ser habilitados explicitamente.
O utilitário opentelemetry-util-genai define os seguintes modos via variável de ambiente:
# Não captura conteúdo (padrão)
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=NO_CONTENT
# Captura conteúdo apenas em atributos de span
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=SPAN_ONLY
# Captura conteúdo apenas como eventos/logs
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=EVENT_ONLY
# Captura em ambos (spans e eventos)
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=SPAN_AND_EVENT
Pra habilitar as features experimentais das semantic conventions, você também pode precisar de:
export OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental
Já alguns pacotes do ecossistema Traceloop, como a instrumentação do Anthropic via OpenLLMetry, podem capturar conteúdo por padrão e exigir disable explícito:
export TRACELOOP_TRACE_CONTENT=false # pra desabilitar
Sempre confira a documentação do pacote exato que você instalou. O comportamento padrão e os valores aceitos variam.
Subindo Jaeger local
docker run -d --name jaeger \
-p 16686:16686 \
-p 4317:4317 \
jaegertracing/jaeger:latest
Acesse http://localhost:16686 e você vai ver os traces de cada chamada LLM, independente do provider.
Opção 2: OpenLLMetry (Traceloop)
Pra quem quer instrumentação automática de múltiplos providers com o mínimo de código. O OpenLLMetry detecta os SDKs compatíveis instalados e instrumenta automaticamente.
Python
pip install traceloop-sdk openai anthropic
from traceloop.sdk import Traceloop
import openai
import anthropic
Traceloop.init(
app_name="meu-agente",
disable_batch=True # pra ver traces imediatamente em dev
)
# OpenAI
oai_client = openai.OpenAI()
oai_response = oai_client.chat.completions.create(
model="gpt-4.1",
messages=[{"role": "user", "content": "Explique observabilidade."}]
)
# Anthropic
claude_client = anthropic.Anthropic()
claude_response = claude_client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Explique observabilidade."}]
)
# Ambas as chamadas geram traces automaticamente
Node.js / TypeScript
npm install @traceloop/node-server-sdk openai @anthropic-ai/sdk
import * as traceloop from "@traceloop/node-server-sdk";
// IMPORTANTE: inicializar ANTES de importar os clients
traceloop.initialize({ disableBatch: true });
import OpenAI from "openai";
import Anthropic from "@anthropic-ai/sdk";
const openaiClient = new OpenAI();
const anthropicClient = new Anthropic();
// Ambos são instrumentados automaticamente
Pra exportar traces, configure TRACELOOP_BASE_URL e, quando necessário, TRACELOOP_HEADERS, apontando para um collector ou backend OTLP compatível.
Opção 3: Langfuse (plataforma completa)
Langfuse é uma plataforma open-source de LLM engineering. Diferente das opções anteriores que são "só" instrumentação, o Langfuse entrega UI pronta: dashboard de custos, visualização de traces em árvore, sessões multi-turno, avaliação de qualidade e prompt management.
Self-hosted com Docker Compose
git clone https://github.com/langfuse/langfuse.git
cd langfuse
docker compose up -d
Acesse http://localhost:3000, crie um projeto e pegue as chaves da API.
Integração via OpenTelemetry (recomendada)
O Langfuse aceita traces via protocolo OTLP no endpoint /api/public/otel.
Importante: o endpoint OTLP do Langfuse é HTTP, não gRPC. Se você estiver usando o exportador otlp/http, funciona direto. Se estiver usando o exportador gRPC (como no setup base com Jaeger), vai precisar trocar o exporter ou colocar um OTel Collector no meio fazendo a conversão.
Configuração via variáveis de ambiente:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:3000/api/public/otel
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic $(echo -n 'public_key:secret_key' | base64)"
Ou no código Python, usando o exportador HTTP:
import base64
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
credentials = base64.b64encode(b"public_key:secret_key").decode()
exporter = OTLPSpanExporter(
endpoint="http://localhost:3000/api/public/otel/v1/traces",
headers={"Authorization": f"Basic {credentials}"}
)
Pra usar o exportador HTTP, instale:
pip install opentelemetry-exporter-otlp-proto-http
Com isso, você pode usar o OpenLLMetry ou as instrumentações oficiais (OpenAI, Anthropic, Google) e enviar tudo pro Langfuse. Não importa qual provider.
Instrumentando um agente completo
As opções acima funcionam pra chamadas individuais. Mas um agente faz múltiplas chamadas em sequência, com decisões entre elas. Você precisa agrupar tudo num trace pai.
Vou usar a API da Anthropic neste exemplo pra mostrar que o padrão é o mesmo independente do provider.
Com OpenTelemetry manual + Claude
from opentelemetry import trace
import anthropic
import json
tracer = trace.get_tracer("meu-agente")
client = anthropic.Anthropic()
def executar_agente(pergunta: str):
with tracer.start_as_current_span(
"invoke_agent assistente-pedidos",
attributes={
"gen_ai.operation.name": "invoke_agent",
"gen_ai.agent.name": "assistente-pedidos",
"gen_ai.provider.name": "anthropic"
}
) as agent_span:
messages = [{"role": "user", "content": pergunta}]
system_prompt = "Você ajuda com pedidos. Use as ferramentas disponíveis."
tools = [
{
"name": "buscar_pedido",
"description": "Busca info de um pedido pelo ID",
"input_schema": {
"type": "object",
"properties": {
"pedido_id": {"type": "string"}
},
"required": ["pedido_id"]
}
}
]
max_steps = 10
for step in range(max_steps):
# Cada chamada LLM gera um span filho automaticamente
# via AnthropicInstrumentor
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=system_prompt,
messages=messages,
tools=tools
)
# Claude retorna stop_reason: "end_turn" ou "tool_use"
if response.stop_reason == "end_turn":
texto_final = next(
(b.text for b in response.content if b.type == "text"), ""
)
agent_span.set_attribute("agent.steps", step + 1)
return texto_final
if response.stop_reason == "tool_use":
# Adiciona a resposta do assistant ao histórico
# no formato esperado pela SDK/API da Anthropic
messages.append({
"role": "assistant",
"content": response.to_dict()["content"]
})
tool_results = []
for block in response.content:
if block.type == "tool_use":
with tracer.start_as_current_span(
f"execute_tool {block.name}",
attributes={
"gen_ai.operation.name": "execute_tool",
"tool.name": block.name,
"tool.arguments": json.dumps(block.input)
}
):
result = executar_ferramenta(
block.name, block.input
)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result
})
messages.append({"role": "user", "content": tool_results})
agent_span.set_attribute("agent.steps", max_steps)
agent_span.set_attribute("agent.converged", False)
return "Não consegui resolver."
def executar_ferramenta(nome: str, argumentos: dict) -> str:
if nome == "buscar_pedido":
return json.dumps({"status": "enviado", "previsao": "2025-03-15"})
return json.dumps({"error": "ferramenta desconhecida"})
Algumas diferenças importantes entre os SDKs da Anthropic e OpenAI que afetam a instrumentação:
- Stop reason: Anthropic usa
stop_reasoncom valores"end_turn"e"tool_use". OpenAI usafinish_reasoncom"stop"e"tool_calls". - Tool results: No Anthropic, tool results vão como conteúdo do role
"user"comtype: "tool_result". No OpenAI, vão como role"tool". - System prompt: No Anthropic, vai no parâmetro
systemseparado. No OpenAI, vai como primeira mensagem com role"system".
Mas nos traces OTel, ambos geram os mesmos atributos padronizados. Essa é a beleza: a observabilidade é normalizada.
Métricas que você precisa ter em dashboard
Com traces funcionando, é hora de extrair métricas.
1. Custo por execução
Preços de API mudam frequentemente. Não faça hardcode de valores no código. Uma abordagem melhor:
from dataclasses import dataclass
from pathlib import Path
import json
import os
@dataclass
class ModelPricing:
input_per_mtok: float # USD por 1M tokens de input
output_per_mtok: float # USD por 1M tokens de output
class CostCalculator:
"""Calcula custo de chamadas LLM a partir de um arquivo de config.
Preços mudam frequentemente. Mantenha o arquivo de config atualizado
consultando as páginas oficiais:
- OpenAI: https://openai.com/api/pricing
- Anthropic: https://docs.anthropic.com/en/docs/about-claude/pricing
"""
def __init__(self, config_path: str | None = None):
path = config_path or os.environ.get(
"LLM_PRICING_CONFIG", "pricing.json"
)
self._pricing: dict[str, ModelPricing] = {}
self._load(path)
def _load(self, path: str) -> None:
config_file = Path(path)
if not config_file.exists():
return
data = json.loads(config_file.read_text())
for model, prices in data.items():
self._pricing[model] = ModelPricing(
input_per_mtok=prices["input"],
output_per_mtok=prices["output"]
)
def calculate(
self, model: str, input_tokens: int, output_tokens: int
) -> float | None:
pricing = self._pricing.get(model)
if not pricing:
return None
return (
input_tokens * pricing.input_per_mtok
+ output_tokens * pricing.output_per_mtok
) / 1_000_000
Com um pricing.json separado:
{
"gpt-5.4": {"input": 2.50, "output": 15.00},
"gpt-5-mini": {"input": 0.25, "output": 2.00},
"gpt-4.1": {"input": 2.00, "output": 8.00},
"gpt-4.1-mini": {"input": 0.40, "output": 1.60},
"gpt-4.1-nano": {"input": 0.10, "output": 0.40},
"claude-opus-4-6": {"input": 5.00, "output": 25.00},
"claude-sonnet-4-6": {"input": 3.00, "output": 15.00},
"claude-haiku-4-5": {"input": 1.00, "output": 5.00}
}
Os valores acima são referência de março/2026. Consulte sempre as páginas oficiais (OpenAI, Anthropic) antes de usar.
Vantagens dessa abordagem: o arquivo de preços pode ser atualizado sem tocar no código, versionado separadamente, e até carregado de uma URL se quiser automatizar.
2. Token acumulado por conversa
A cada step do agente, o context window cresce. Se você não monitora, um agente de 5 steps pode estar mandando 50k tokens no último call porque acumula todo o histórico.
Capture gen_ai.usage.input_tokens em cada chamada e plote a progressão. Se o crescimento é linear, tudo certo. Se é exponencial, tem algo errado no gerenciamento de contexto.
Isso é especialmente relevante em modelos com janelas de contexto muito grandes (200k+ tokens). Só porque cabe, não significa que deveria estar lá.
3. Steps até convergência
Histograma de quantos passos o agente leva pra resolver uma tarefa. Se a maioria resolve em 2-3 steps mas tem um tail de 10+, investigue esses casos.
4. Taxa de uso de ferramentas
Qual ferramenta é mais chamada? Alguma nunca é usada? Alguma falha frequentemente? Isso mostra se o agente tá usando bem o que tem disponível.
5. Latência decomposta
Não basta saber que a execução total levou 15s. Decompor:
- Tempo em chamadas LLM (latência do provider)
- Tempo em tool calls (latência da sua infra)
- Tempo de processamento local
Se 80% do tempo tá em tool calls, o gargalo é a sua API, não o modelo.
Alertas que salvam
Configure alertas pra cenários críticos:
# Exemplo conceitual (adapte pro seu sistema de alertas)
alertas:
- nome: agente_em_loop
condição: agent.steps > 8
ação: matar execução + notificar
- nome: custo_alto
condição: custo_execucao > 0.50 # USD
ação: notificar
- nome: latencia_alta
condição: duracao_total > 30s
ação: notificar
- nome: token_explosion
condição: input_tokens_ultima_chamada > 100000
ação: matar execução + notificar
Na prática, implemente isso com métricas OTel + Prometheus + Alertmanager, ou use os alertas nativos do Grafana/Datadog/seu backend.
Grafana: visualizando tudo
Se você usa Grafana (e deveria, é grátis e open-source), aqui vai uma stack completa:
# docker-compose.yml
services:
jaeger:
image: jaegertracing/jaeger:latest
ports:
- "16686:16686" # UI
- "4317:4317" # OTLP gRPC
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana:latest
ports:
- "3001:3000"
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
Configurando o Prometheus pra coletar métricas OTel, você consegue dashboards com:
- Custo acumulado por hora/dia, segmentado por provider e modelo
- Latência P50/P95/P99 por modelo (compare Claude vs GPT lado a lado)
- Token usage ao longo do tempo
- Top ferramentas mais chamadas
- Execuções que excederam o limite de steps
Considerações de segurança
Capturar prompts e respostas em produção levanta questões sérias:
PII (dados pessoais): se o usuário manda dados pessoais pro agente e você loga tudo, agora você tem PII no seu sistema de observabilidade. Defina políticas de retenção e considere mascaramento.
Prompts de sistema: seu prompt de sistema é propriedade intelectual. Cuidado com quem tem acesso aos traces completos.
Retenção: traces de LLM são grandes (tokens de input/output). Defina TTL agressivo pra dados de conteúdo (7-30 dias) e mantenha métricas agregadas por mais tempo.
Ambiente: capture conteúdo de mensagens só em staging/debug. Em produção, capture apenas métricas e metadados.
Comparativo rápido
Pra fechar, quando usar o quê:
OTel puro + Jaeger/Grafana: você já tem infra de observabilidade OTel. Quer controle total. Escolhe o instrumentor específico do provider que usa.
OpenLLMetry: quer instrumentação automática de múltiplos providers e frameworks sem escrever código de instrumentação. Instala, inicializa, e tudo que passa pelo SDK é trackeado.
Langfuse: quer uma plataforma completa com UI pronta, dashboard de custos, prompt management e avaliação. Self-hosted ou cloud. Aceita dados via OTLP (HTTP), então combina com qualquer instrumentação.
As três opções não são excludentes. Você pode usar OpenLLMetry pra instrumentar tanto OpenAI quanto Anthropic e exportar pro Langfuse via OTLP. Ou usar instrumentações oficiais do OTel e mandar pro Jaeger + Grafana. Mix and match.
Conclusão
Agentes de AI em produção sem observabilidade é receita pra dor de cabeça. O ecossistema já tem ferramentas maduras o suficiente pra resolver isso, e todas suportam os principais providers.
Comece simples: instrumente suas chamadas LLM com o instrumentor do seu provider, exporte pra um Jaeger local, e veja os traces. Depois adicione métricas de custo e alertas. Quando sentir necessidade, suba pra uma plataforma como Langfuse.
O investimento é pequeno. A alternativa é descobrir que seu agente gastou $200 em tokens fazendo loop às 3 da manhã.



