Alojar Langfuse para rastrear agentes de IA
Instale Langfuse en su VPS con recursos mínimos reales, imágenes fijadas, TLS, retención de ClickHouse para no llenar el disco y copias de seguridad verificadas.
Por qué rastrear un agente de IA
Puede alojar Langfuse para ver qué hizo realmente su agente durante una ejecución. Langfuse es una herramienta de observabilidad de LLM (modelo de lenguaje grande) de código abierto. Registra cada prompt, cada respuesta del modelo, cada llamada a una herramienta y cada token. Después los agrupa en una única traza que puede abrir y leer. Si lo ejecuta en su propio VPS, esos prompts nunca salen de un servidor bajo su control.
El motivo es sencillo. No puede corregir un problema de costes ni un problema de calidad que no puede ver. La factura del proveedor le indica que el martes costó cuatro veces más que el lunes. Una traza le indica qué ejecución del agente lo provocó, qué prompt creció hasta 40,000 tokens y qué bucle de reintento se ejecutó nueve veces antes de detenerse. La factura proporciona la cifra. La traza muestra el código que la produjo.
En esta guía se utilizan tres términos. Una traza es una ejecución completa del agente, de principio a fin. Una observación es un paso dentro de esa ejecución: un span para el código normal y una generación para una llamada a un modelo. Un score es un número asociado a una traza, obtenido mediante una revisión humana o un evaluador automatizado. Langfuse utiliza OpenTelemetry (OTel), el estándar independiente del proveedor para el tracing distribuido. Por tanto, la instrumentación que ya tenga puede enviar datos a Langfuse.
Qué ejecuta realmente Langfuse en un entorno autogestionado
Langfuse v4 no es un solo contenedor. Está formado por dos contenedores de aplicación y cuatro servicios de almacenamiento. En un VPS único, los seis se ejecutan en el servidor.
langfuse-websirve la interfaz web y la API de ingestión.langfuse-workervacía la cola en segundo plano. Analiza los lotes de ingestión, calcula los costes y ejecuta el trabajo nocturno de retención.- Postgres almacena datos transaccionales como usuarios, organizaciones, proyectos, claves de API y prompts.
- ClickHouse almacena los datos de trazas, es decir, observaciones y puntuaciones. Es un almacén de columnas diseñado para consultas analíticas. Por eso un panel que consulta más de cien millones de filas sigue respondiendo con rapidez.
- Redis es la cola y la caché situadas entre web y worker.
- MinIO proporciona almacenamiento de objetos compatible con S3 en el propio servidor. Almacena todos los eventos entrantes sin procesar y cualquier contenido multimedia que adjunte.
Langfuse publica los recursos mínimos de los tres componentes que realizan el trabajo.
The data behind this chart
[
{
"label": "ClickHouse",
"cpu_cores": 2,
"memory_gib": 8
},
{
"label": "Langfuse web",
"cpu_cores": 2,
"memory_gib": 4
},
{
"label": "Langfuse worker",
"cpu_cores": 2,
"memory_gib": 4
}
]ClickHouse por sí solo necesita 8 GiB de memoria. El contenedor web y el worker necesitan 4 GiB cada uno. Esas son las cantidades mínimas publicadas para los 3 componentes que Langfuse dimensiona. Postgres, Redis y MinIO también necesitan memoria adicional. La propia guía de Docker Compose del proyecto recomienda una máquina con 4 núcleos, 16 GiB de memoria y unos 100 GiB de almacenamiento. Esa recomendación coincide con el cálculo anterior, sin añadir margen artificial.
No intente ejecutarlo en un plan de 2 GiB. ClickHouse arranca y acepta escrituras durante un tiempo, pero después termina durante una combinación en segundo plano, porque una combinación carga partes grandes de una tabla en memoria. Verá que docker compose ps informa de que el contenedor clickhouse está en estado restarting, que dmesg muestra una línea como Out of memory: Killed process 1234 (clickhouse-serv) y que todos los paneles de Langfuse devuelven 500. Con una carga menor, ClickHouse rechaza la consulta y registra DB::Exception: Memory limit (total) exceeded. Ocho GiB son suficientes para un desarrollador que envíe unos pocos miles de trazas al día. Planifique 16 GiB.
Implementar Langfuse con Docker Compose
Clone el repositorio. La pila, la configuración de servicios y el entorno predeterminado están en su docker-compose.yml.
git clone https://github.com/langfuse/langfuse.git
cd langfuseTodos los valores que debe cambiar están marcados como # CHANGEME en ese archivo. Genere primero los tres secretos de la aplicación.
openssl rand -base64 32 # NEXTAUTH_SECRET
openssl rand -base64 32 # SALT
openssl rand -hex 32 # ENCRYPTION_KEYENCRYPTION_KEY debe tener 256 bits, escritos como 64 caracteres hexadecimales. Eso es exactamente lo que muestra openssl rand -hex 32. Este valor cifra los datos confidenciales en reposo, incluidas las claves de proveedores de LLM que almacene en la instancia. Si lo cambia después de que existan datos, esas filas ya no se podrán descifrar. Trátelo como permanente desde el primer arranque. SALT se usa para aplicar hash a las claves de API de Langfuse. Si lo cambia, invalidará todas las claves que ya usan sus agentes.
Después, configure POSTGRES_PASSWORD, CLICKHOUSE_PASSWORD, REDIS_AUTH y MINIO_ROOT_PASSWORD. La contraseña de MinIO aparece en cuatro lugares: una vez como MINIO_ROOT_PASSWORD y después como LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY, LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY y LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY. Si omite una aparición, MinIO rechaza ese cliente con SignatureDoesNotMatch. El mensaje aparece en el registro del worker, aunque la interfaz web siga pareciendo correcta. Mantener estos valores en un archivo de entorno, en lugar de incluirlos en el archivo compose versionado, es el patrón descrito en archivos env y secretos de Docker Compose.
Fije las etiquetas de imagen antes de empezar
El archivo incluido usa langfuse/langfuse:4 y langfuse/langfuse-worker:4. Esas etiquetas cambian. Langfuse ejecuta automáticamente las migraciones de Postgres y ClickHouse al arrancar. Por tanto, un docker compose pull rutinario meses después se convierte en una migración de esquema no planificada sobre una base de datos de la que no hizo una copia de seguridad esa mañana. Fije ambas imágenes a una versión en un docker-compose.override.yml. Compose lo combina con el archivo incluido y aplica sus valores encima, de modo que un git pull posterior no sobrescriba sus cambios.
services:
langfuse-web:
image: docker.io/langfuse/langfuse:4.3.1
langfuse-worker:
image: docker.io/langfuse/langfuse-worker:4.3.1La versión 4.3.1 era la versión actual de la serie 4.3 en agosto de 2026 (desde entonces se publicó la 4.4.0). Consulte la página de versiones del proyecto en GitHub, fije la versión disponible el día del despliegue y cambie ese número de forma deliberada. Las imágenes de almacenamiento del archivo incluido ya están fijadas a versiones principales: postgres:17, clickhouse-server:25.12 y redis:7. También conviene fijarlas a versiones concretas.
Inicie la pila.
docker compose up -d
docker compose ps
docker compose logs -f langfuse-workerEl primer arranque ejecuta las migraciones, así que espere uno o dos minutos antes de comprobar los servicios. docker compose ps debería mostrar seis servicios en estado running. Si el worker se reinicia continuamente, el motivo estará en su registro: CLICKHOUSE_MIGRATION_URL usa el protocolo nativo de ClickHouse en el puerto 9000, no el puerto HTTP 8123. Si apunta al puerto 8123, fallará, aunque el contenedor web siga pareciendo correcto.
Compruebe el estado desde el propio servidor.
curl -s "http://localhost:3000/api/public/health?failIfDatabaseUnavailable=true"
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/public/readyUna llamada /api/public/health sencilla sólo demuestra que el proceso de API está activo. Omite deliberadamente la base de datos para que el servicio siga atendiendo peticiones mientras Postgres presenta interrupciones breves. La variante failIfDatabaseUnavailable=true es la adecuada para un monitor y devuelve 503 cuando no se puede acceder a la base de datos. /api/public/ready devuelve 200 cuando terminan las migraciones y el contenedor acepta tráfico. Ambas son comprobaciones HTTP normales, por lo que una página de estado de Uptime Kuma puede supervisarlas e indicar que la pila está caída antes de que lo detecten sus agentes.
Configura TLS delante y cierra los puertos adicionales
El archivo compose incluido publica 3000:3000 para el contenedor web y 9090:9000 para MinIO. Ambos escuchan en todas las interfaces. En una IP pública, cualquiera que escanee el puerto 3000 llega a la página de registro, y cualquiera que escanee el puerto 9090 se comunica con el bucket que contiene tus prompts sin procesar.
Una regla del firewall por sí sola no los cierra. Docker escribe sus propias reglas DNAT en la tabla nat, y estas se evalúan antes de que las reglas de filtrado de ufw vean el paquete. Por eso, ufw deny 3000 deja abierto el puerto publicado. Este problema es tan habitual que tiene su propia guía: por qué los puertos publicados por Docker omiten ufw. En su lugar, enlaza el puerto con loopback en tu archivo de override.
services:
langfuse-web:
ports:
- "127.0.0.1:3000:3000"
environment:
NEXTAUTH_URL: https://langfuse.example.com
minio:
ports:
- "127.0.0.1:9090:9000"
- "127.0.0.1:9091:9001"NEXTAUTH_URL debe ser la dirección pública exacta, incluido el esquema, porque el flujo de inicio de sesión construye la URL de callback a partir de ese valor. Si lo dejas como http://localhost:3000 detrás de un proxy HTTPS, el recorrido de inicio de sesión redirige el navegador a una dirección que no puede alcanzar.
Ahora apunta un reverse proxy a 127.0.0.1:3000 y deja que gestione el certificado. Traefik en el mismo proyecto de Compose suele ser la opción habitual, y las etiquetas de enrutamiento son las que se explican en ejecutar varias aplicaciones detrás de un reverse proxy Traefik. Caddy hace el mismo trabajo en dos líneas si Langfuse es el único servicio del servidor. Verifica con curl -sI https://langfuse.example.com/api/public/ready y, después, confirma desde otro equipo que curl http://YOUR_IP:3000 ahora agota el tiempo de espera.
Hay una consideración sobre MinIO. Langfuse sirve los archivos multimedia adjuntos al navegador mediante URLs prefirmadas que apuntan a ese endpoint S3. Por tanto, si usas trazas multimodales con imágenes o audio, un MinIO accesible sólo mediante loopback hará que esos archivos adjuntos no se carguen. Lee la página de configuración del almacenamiento de blobs antes de ponerlo detrás de un proxy, porque el endpoint escrito en la URL prefirmada debe coincidir con el que publicas. Las trazas de texto sin formato no se ven afectadas.
Crea tu cuenta durante la primera visita y conserva el control de la instancia. Establece LANGFUSE_ALLOWED_ORGANIZATION_CREATORS con tu propia dirección de correo electrónico para que un desconocido que llegue a la página no pueda crear una organización en tu servidor. Si ya ejecutas Authentik como tu propio proveedor de identidad, Langfuse admite una conexión OIDC estándar. Así, las cuentas se crean y eliminan junto con las demás aplicaciones, en lugar de mantenerse en una lista de contraseñas que sólo conoce este servidor.
Envía tu primera traza
Crea un proyecto en la interfaz web y copia sus claves pública y secreta desde la configuración del proyecto. El SDK de Python lee tres variables de entorno.
export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_SECRET_KEY="sk-lf-..."
export LANGFUSE_BASE_URL="https://langfuse.example.com"LANGFUSE_BASE_URL es el nombre de la variable en SDK v4, publicado en marzo de 2026. El código y las guías anteriores usan LANGFUSE_HOST. Si tus trazas llegan a Langfuse Cloud en lugar de a tu servidor, la causa es que la URL base no está definida, porque el valor predeterminado apunta a la instancia alojada.
pip install langfuse opentelemetry-instrumentation-anthropic anthropicimport os
from anthropic import Anthropic
from langfuse import get_client, observe
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
AnthropicInstrumentor().instrument()
langfuse = get_client()
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
@observe(as_type="tool")
def lookup_order(order_id: str) -> str:
return f"order {order_id}: shipped"
@observe()
def handle_request(question: str) -> str:
context = lookup_order("A-1042")
message = client.messages.create(
model="claude-haiku-4-5",
max_tokens=512,
messages=[{"role": "user", "content": f"{context}\n\n{question}"}],
)
return message.content[0].text
if __name__ == "__main__":
assert langfuse.auth_check()
print(handle_request("Where is my order?"))
langfuse.flush()El decorador @observe abre una observación alrededor de la función, captura sus argumentos y su valor de retorno, y la anida bajo cualquier observación que ya esté activa. AnthropicInstrumentor es la instrumentación de OpenTelemetry para el cliente de Anthropic y convierte cada llamada messages.create en una generación que incluye el nombre del modelo, el uso de tokens y la latencia, sin cambiar el punto de llamada.
Dos llamadas realizan las comprobaciones por ti. langfuse.auth_check() devuelve False si las claves no son válidas o la URL base es incorrecta. Esto es más rápido que preguntarse por qué el panel está vacío. langfuse.flush() bloquea la ejecución hasta que se envían los spans en cola. Los procesos de corta duración lo necesitan, porque el SDK agrupa los datos en segundo plano y un script que termina inmediatamente se lleva consigo el lote que no se haya enviado.
¿Por qué ClickHouse sigue creciendo?
Las trazas son los datos que más rápido crecen en la mayoría de las instalaciones autogestionadas. Cada ejecución de un agente escribe una fila por paso, y las entradas y salidas se almacenan completas. Por eso, un agente conversacional con prompts largos produce muchos más bytes al día que la aplicación que supervisa. Si se deja sin controlar, ClickHouse llena el disco, y un disco lleno detiene la ingesta en lugar de ralentizarla.
Aquí crecen dos elementos distintos, y cada uno requiere una solución diferente.
El primero son sus propios datos de trazas, y la solución es configurar la retención. Abra la configuración del proyecto en la interfaz web y establezca un periodo de retención de datos en días. Langfuse acepta un mínimo de 3 días. Después, un trabajo nocturno selecciona las trazas, observaciones, puntuaciones y recursos multimedia que superan ese periodo y los elimina de ClickHouse y del almacenamiento de blobs. El trabajo necesita permiso DeleteObject en el bucket, que las credenciales root de MinIO del archivo compose predeterminado ya tienen. La eliminación es permanente, así que configure primero una exportación al almacenamiento de blobs si necesita conservar el historial a largo plazo. No escriba manualmente cláusulas TTL en las tablas propias de Langfuse: el trabajo de retención mantiene sincronizados ClickHouse y el bucket, mientras que un TTL manual elimina los datos de un solo lado.
Elija el periodo según el uso real. La revisión de costes y calidad se realiza con datos de hace días, no de hace meses. Treinta días es un buen punto de partida para un equipo pequeño, y 14 días son suficientes si sólo abre una traza cuando algo falla.
El segundo elemento son las propias tablas de registros del sistema de ClickHouse. Esto sorprende a muchas personas porque el disco sigue creciendo después de configurar la retención. ClickHouse escribe trace_log, text_log, opentelemetry_span_log, metric_log y asynchronous_metric_log para sus propios diagnósticos. Estas tablas se distribuyen sin TTL y Langfuse nunca las lee. Averigüe primero dónde se ha utilizado realmente el disco.
SELECT table, formatReadableSize(size) AS size, rows FROM (
SELECT table, database, sum(bytes) AS size, sum(rows) AS rows
FROM system.parts
WHERE active
GROUP BY table, database
ORDER BY size DESC
)Ejecútelo con docker compose exec clickhouse clickhouse-client --password "$CLICKHOUSE_PASSWORD". Si las tablas del sistema aparecen cerca de los primeros puestos, desactívelas mediante una configuración adicional, porque ClickHouse combina todos los archivos de /etc/clickhouse-server/config.d/ con su configuración principal al iniciarse.
<clickhouse>
<trace_log remove="1"/>
<text_log remove="1"/>
<opentelemetry_span_log remove="1"/>
<asynchronous_metric_log remove="1"/>
<metric_log remove="1"/>
</clickhouse>Móntela y reinicie ClickHouse.
services:
clickhouse:
volumes:
- ./clickhouse-config.d/system-logs.xml:/etc/clickhouse-server/config.d/system-logs.xml:roEsto detiene las nuevas escrituras. Las filas que ya están en el disco permanecen allí, así que recupere el espacio explícitamente con DROP TABLE IF EXISTS system.trace_log y haga lo mismo con cada tabla que haya eliminado. Si prefiere conservar los diagnósticos, la alternativa es aplicar un TTL agresivo a cada tabla en lugar de remove="1", tal como se explica en la documentación de escalado de Langfuse.
Conviene conocer una tabla más. blob_storage_file_log registra los archivos de eventos subidos al bucket. Si también configura una política de ciclo de vida en el bucket, establezca un TTL equivalente para la tabla, de modo que ambos no se desincronicen.
ALTER TABLE blob_storage_file_log MODIFY TTL created_at + INTERVAL 30 DAY DELETE;Configure también una alerta sencilla de df -h en el disco de datos. Las trazas no crecen de forma uniforme. Crecen el día que publica un agente nuevo, y la primera señal de ello no debería ser que falle la ingesta.
Copia de seguridad de Postgres y ClickHouse
Una copia de seguridad de Langfuse tiene tres partes. Postgres almacena los usuarios, las organizaciones, los proyectos y las claves de API. ClickHouse almacena las trazas. MinIO almacena los eventos sin procesar. Si restaura sólo Postgres, tendrá un inicio de sesión funcional, pero sin historial. Si restaura sólo ClickHouse, tendrá un historial que nadie podrá consultar porque no podrá iniciar sesión.
Postgres es un pg_dump simple, que es lo que recomienda la documentación de copias de seguridad de Langfuse.
docker compose exec -T postgres pg_dump -U postgres postgres \
| gzip > langfuse-pg-$(date +%F).sql.gzClickHouse requiere más cuidado, porque copiar un directorio de datos activo mientras se ejecutan fusiones no produce una copia de seguridad coherente. En un solo servidor, el método sencillo consiste en detener el contenedor y archivar el volumen.
docker compose stop clickhouse
docker volume ls | grep clickhouse
docker run --rm -v langfuse_langfuse_clickhouse_data:/data -v "$PWD":/backup alpine \
tar czf /backup/langfuse-ch-$(date +%F).tar.gz -C /data .
docker compose start clickhouseUse el nombre del volumen que muestra docker volume ls, no el que aparece escrito en el archivo YAML. El archivo declara langfuse_clickhouse_data y Compose le añade como prefijo el nombre del proyecto, por lo que una copia en un directorio llamado langfuse produce langfuse_langfuse_clickhouse_data. Si se equivoca, docker run crea un volumen nuevo y vacío sin mostrar ningún error, y el archivo contiene una copia sin datos.
El contenedor web escribe cada evento entrante en el bucket antes de que el worker lo procese, por lo que una breve detención de ClickHouse normalmente sólo hace que el worker vuelva a intentarlo después. Hágalo durante una hora de poca actividad y mantenga la detención lo más corta posible. En una instancia con más actividad, la instrucción BACKUP DATABASE default TO S3(...) propia de ClickHouse escribe una copia de seguridad coherente sin detener el servidor. MinIO es la tercera pieza, y mc mirror o la replicación de MinIO a un bucket externo la cubren. Sea cual sea el método, saque la copia del servidor. Para eso sirven las copias de seguridad cifradas con restic en un VPS.
Redis no necesita copia de seguridad. Almacena la cola y la caché, por lo que perderlo sólo hace que se pierdan los eventos que estén en proceso en ese momento, pero no los anteriores.
La limitación de coherencia es real y conviene explicarla claramente. Postgres y ClickHouse se vuelcan en momentos distintos, por lo que una restauración puede dejar una fila de proyecto sin trazas, o trazas pertenecientes a un proyecto que ya no existe. Langfuse tolera esta situación, pero haga ambos volcados con poca diferencia de tiempo y durante un periodo de baja actividad. El bucket de eventos es la verdadera red de seguridad, porque Langfuse conserva allí cada evento entrante antes de procesarlo.
Restaure en una pila de prueba al menos una vez. Así descubrirá ahora un nombre de volumen incorrecto, en lugar de descubrirlo durante una interrupción del servicio.
Qué revisar primero
Cuatro aspectos justifican su atención durante la primera semana.
- Coste por traza. Langfuse calcula el coste a partir del nombre del modelo y del uso de tokens. Ordene las trazas por coste y lea de principio a fin la más cara. La causa suele ser un prompt que ha crecido: un documento completo pegado en el contexto o un historial de conversación que nadie recorta. Cuando pueda verlo, controlar cuánto le cuesta un agente de IA se convierte en una tarea de ingeniería y deja de ser una estimación.
- Uso de tokens separado entre entrada y salida. Los tokens de entrada son numerosos y baratos. Los tokens de salida son menos numerosos y caros. La entrada almacenada en caché es aún más barata. Este cálculo se explica con detalle en cómo se contabiliza el uso de tokens de Claude Code y se aplica a cualquier agente que escriba usted mismo.
- Percentiles de latencia. La mediana oculta el problema. Los valores p95 y p99 son donde aparecen los tiempos de espera agotados. Dentro del ciclo de un agente, una llamada lenta a una herramienta en p95 se multiplica por el número de iteraciones.
- Llamadas fallidas a herramientas. Filtre las observaciones por nivel
ERROR. Una herramienta que falla el 5% de las veces no se aprecia en una tasa de éxito agregada. En cambio, resulta evidente en las trazas, donde puede observar cómo el modelo reintenta y después consume tokens para eludir el fallo.
Establezca la ventana de retención y elija el panel que revisará semanalmente el mismo día en que haga el despliegue. Una herramienta de observabilidad que nadie abre es una base de datos que termina llenando un disco.
FAQ
¿Cuánta memoria necesita un Langfuse autohospedado?
Planifique 4 núcleos de CPU y 16 GiB de memoria, que es lo que recomienda la guía de Langfuse para Docker Compose para una sola máquina virtual, además de unos 100 GiB de almacenamiento. Los mínimos publicados para los componentes son 8 GiB para ClickHouse y 4 GiB para cada contenedor web y de worker. Postgres, Redis y MinIO también necesitan memoria adicional. Ocho GiB bastan para la instancia de un desarrollador. Dos GiB no bastan: el kernel termina el proceso de ClickHouse durante las fusiones en segundo plano, y dmesg muestra Out of memory: Killed process.
¿Por qué sigue llenándose el disco de ClickHouse después de configurar la retención de datos?
La configuración de retención sólo cubre los datos propios de Langfuse. ClickHouse escribe por separado sus tablas de diagnóstico trace_log, text_log, opentelemetry_span_log, metric_log y asynchronous_metric_log, y estas se crean sin TTL. Consulte system.parts agrupado por tabla para ver cuál ocupa más espacio. Después, deshabilite las tablas que no use mediante una entrada remove="1" en un archivo situado bajo /etc/clickhouse-server/config.d/, reinicie ClickHouse y elimine las tablas existentes para recuperar el espacio que ya ocupan.
¿Cuál es el período mínimo de retención de datos en Langfuse?
Tres días. La retención se configura por proyecto en los ajustes del proyecto o mediante la API de proyectos. Un trabajo nocturno elimina de ClickHouse y del almacenamiento de blobs las trazas, observaciones, puntuaciones y recursos multimedia que sean anteriores a ese período. La eliminación no se puede deshacer. Configure primero una exportación al almacenamiento de blobs si necesita conservar el historial más allá de ese período.
¿Tengo que hacer copias de seguridad de Postgres y ClickHouse?
Sí, porque almacenan datos diferentes. Postgres almacena los usuarios, las organizaciones, los proyectos y las claves de API. ClickHouse almacena los datos de las trazas. Una restauración de Postgres sin ClickHouse produce una instancia en la que puede iniciar sesión, pero que no contiene datos. Haga también una copia de seguridad del bucket de MinIO, ya que contiene los eventos sin procesar que Langfuse persiste al recibirlos. Es lo más cercano a una fuente de verdad en la pila.
¿Puedo dirigir una configuración existente de OpenTelemetry a un Langfuse autohospedado?
Sí. Langfuse v4 y sus SDK v4 se basan en OpenTelemetry, y las instrumentaciones OTel de Anthropic y OpenAI exportan los datos directamente a Langfuse. En Python, ejecute pip install langfuse opentelemetry-instrumentation-anthropic, llame a AnthropicInstrumentor().instrument() una vez durante el arranque y configure LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY y LANGFUSE_BASE_URL con su propio host. Confirme el funcionamiento con langfuse.auth_check() antes de investigar si falta un dashboard.