Você não pode debugar o que não vê. Multi-agent + tool use + reasoning models + RAG geram cascatas de chamadas LLM com latências, custos e modos de falha que stack tradicional (APM, logs) não captura. Em 2026, observability LLM tem 4 jogadores principais: LangSmith (LangChain-native), Helicone (proxy agnóstico), Phoenix (OTel + RAG-focused), Langfuse (open-source full-stack). Este módulo compara cada um e mostra setups práticos.
O que precisa ser observado num agente
LangSmith — integrado ao LangChain
# Setup: variáveis de ambiente + uso automático
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "lsv2_..."
os.environ["LANGCHAIN_PROJECT"] = "ffv-agente-prod"
from langchain_anthropic import ChatAnthropic
from langgraph.graph import StateGraph
# Toda call LLM e nó LangGraph é tracked automaticamente
llm = ChatAnthropic(model="claude-sonnet-4-7")
response = llm.invoke("Olá")
# → aparece em smith.langchain.com com latência, tokens, custo, prompt, response
# Decorators para custom code
from langsmith import traceable
@traceable(name="custom-retrieval", run_type="retriever")
def my_retrieval(query: str) -> list[str]:
# Sua lógica de retrieval — vira span filho do trace pai
return search_db(query)
# Prompt versioning via Hub
from langchain import hub
prompt = hub.pull("my-team/research-agent:v3") # versão pinada
response = llm.invoke(prompt.format(question="..."))Helicone — proxy agnóstico
# Setup: muda base_url para Helicone — não exige callbacks/framework
import openai
import anthropic
# OpenAI via Helicone
openai_client = openai.OpenAI(
base_url="https://oai.helicone.ai/v1",
default_headers={
"Helicone-Auth": f"Bearer {os.environ['HELICONE_API_KEY']}",
"Helicone-User-Id": "user-42",
"Helicone-Property-Feature": "research", # custom properties
},
)
# Anthropic via Helicone
anthropic_client = anthropic.Anthropic(
base_url="https://anthropic.helicone.ai",
default_headers={
"Helicone-Auth": f"Bearer {os.environ['HELICONE_API_KEY']}",
"Helicone-Cache-Enabled": "true", # cache built-in
"Helicone-Rate-Limit-Policy": "1000;w=60", # 1000 req/min
},
)
# Toda call passa pelo proxy — captura automática + features extras:
# - Cache de responses repetidos
# - Rate limiting per user
# - Cost tracking per property
# - Prompt management via Helicone PromptsO fato de ser proxy traz feature exclusiva: cache de response (configurável por header). Identidade de prompt repetido = mesma resposta retornada sem chamar o provider. Reduz drasticamente custos em apps com prompts cacheáveis.
Phoenix (Arize) — OTel-native + RAG
# Phoenix self-host (Docker) + auto-instrumentation via openinference
import phoenix as px
from phoenix.otel import register
from openinference.instrumentation.openai import OpenAIInstrumentor
from openinference.instrumentation.langchain import LangChainInstrumentor
# Inicia UI local ou aponta para servidor remoto
px.launch_app() # http://localhost:6006
# Configura tracer OTel — exports para Phoenix ou qualquer OTel backend
tracer_provider = register(
project_name="ffv-agente",
endpoint="http://localhost:6006/v1/traces",
)
# Auto-instrument SDKs
OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)
LangChainInstrumentor().instrument(tracer_provider=tracer_provider)
# Specialty: embedding visualizations
# Phoenix mostra UMAP/t-SNE de embeddings, detecta drift entre prod/eval datasets
# Ideal para RAG observability — visualiza queries que retornam docs irrelevantesLangfuse — open-source full stack
from langfuse import Langfuse
from langfuse.decorators import observe
langfuse = Langfuse(
public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
secret_key=os.environ["LANGFUSE_SECRET_KEY"],
host="https://cloud.langfuse.com", # ou self-host
)
@observe()
def research_agent(query: str) -> str:
# Trace é criado automaticamente — child spans capturam calls LLM internas
prompt = langfuse.get_prompt("research-system", version=3)
messages = [{"role": "system", "content": prompt.compile()}]
messages.append({"role": "user", "content": query})
response = anthropic_client.messages.create(
model="claude-sonnet-4-7",
messages=messages,
max_tokens=2000,
)
# Captura score (eval feedback ou LLM-as-judge)
langfuse.score(
trace_id=langfuse.get_current_trace_id(),
name="relevance",
value=0.85,
comment="LLM-as-judge: relevância da resposta",
)
return response.content[0].textComparativo direto
| Feature | LangSmith | Helicone | Phoenix | Langfuse |
|---|---|---|---|---|
| Modelo | SDK callback | HTTP proxy | OTel SDK | SDK + decorators |
| Framework-agnostic | Limitado | ✅ Total | ✅ OTel | ✅ Total |
| Self-hostable | ⚠️ Enterprise | ⚠️ Enterprise | ✅ | ✅ |
| Open-source | ❌ | ⚠️ Parcial | ✅ | ✅ |
| Prompt versioning | ✅ (Hub) | ✅ | ⚠️ | ✅ |
| Dataset capture | ✅ | ✅ | ✅ | ✅ |
| LLM-as-judge | ✅ | ⚠️ | ✅ | ✅ |
| Cache built-in | ❌ | ✅ (proxy) | ❌ | ❌ |
| Sweet spot | LangChain stacks | Multi-framework, cache | OTel-native, RAG | OSS full-stack |
Arquitetura: como capturas hierárquicos funcionam
Decisão prática
📋 Time de 5 devs usa LangChain + LangGraph + Anthropic + alguns scripts Python diretos com OpenAI.
Time é LangChain-first: LangSmith integra zero-config nos casos centrais. Para os scripts ad-hoc com OpenAI direto, decorators @traceable capturam. Se time quer evitar lock-in ou self-host, Langfuse OSS cobre 90% das features com instrumentation similar.
Alt: Helicone —
Alt: Phoenix —
Alt: Langfuse OSS —
Timeline
Perguntas frequentes
❓ Posso usar 2 ferramentas ao mesmo tempo?
❓ LGPD/GDPR: como tratar PII em traces?
❓ Latência adicionada?
❓ Custo?