SSD Nodes Learn 🎉 VPS от $4.99/мес
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-07

Как развернуть Langfuse на собственном VPS

Пошаговое руководство по self-hosted установке Langfuse. Разбираем настройку ClickHouse для предотвращения переполнения диска, использование фиксированных тегов образов и TLS.

Зачем вообще отслеживать работу AI-агента

Вы разворачиваете Langfuse на собственном сервере, чтобы видеть, что именно делал ваш агент во время выполнения. Langfuse — это инструмент с открытым исходным кодом для обеспечения наблюдаемости LLM (больших языковых моделей). Он записывает каждый промпт, каждый ответ модели, каждый вызов инструмента и каждый токен, а затем группирует их в единую трассировку (trace), которую можно открыть и изучить. Запуск на собственном VPS означает, что эти промпты никогда не покидают сервер, который вы контролируете.

Причина, по которой стоит этим заниматься, очевидна. Вы не можете исправить проблему с затратами или качеством, если не видите её источник. Счет от провайдера говорит вам, что во вторник расходы были в четыре раза выше, чем в понедельник. Трассировка показывает, какой именно запуск агента стал причиной, какой промпт вырос до 40,000 токенов и какой цикл повторных попыток сработал девять раз, прежде чем завершиться неудачей. Счет дает вам цифру. Трассировка дает вам код, который её породил.

В этом руководстве используются три термина. Трассировка (trace) — это один полный цикл работы вашего агента от начала до конца. Наблюдение (observation) — это один шаг внутри этого цикла: span для обычного кода, generation для вызова модели. Оценка (score) — это число, присвоенное трассировке на основе проверки человеком или автоматическим оценщиком. Langfuse поддерживает OpenTelemetry (OTel) — независимый от вендора стандарт распределенной трассировки, поэтому уже имеющиеся у вас средства инструментирования могут быть направлены на него.

Что на самом деле запускается при self-hosting Langfuse

Langfuse v4 — это не один контейнер. Это два контейнера приложения и четыре сервиса хранения данных. На одном VPS все шесть компонентов работают на вашей машине.

  • langfuse-web обслуживает веб-интерфейс и API для приема данных.
  • langfuse-worker обрабатывает очередь в фоновом режиме. Он разбирает пакеты входящих данных, рассчитывает стоимость и выполняет ночные задачи по очистке данных.
  • Postgres хранит транзакционные данные, такие как пользователи, организации, проекты, API keys и промпты.
  • ClickHouse хранит сами данные трассировки, то есть наблюдения и оценки. Это колоночная база данных, созданная для аналитических запросов, поэтому дашборд по сотням миллионов строк работает быстро.
  • Redis выступает в роли очереди и кэша между веб-интерфейсом и воркером.
  • MinIO предоставляет S3-совместимое объектное хранилище на сервере. В нем хранятся все входящие события в исходном виде и любые прикрепленные медиафайлы.

Langfuse публикует минимальные требования к ресурсам для трех компонентов, выполняющих основную работу.

ChartLangfuse published minimum resources per component
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 требуется 8 GiB оперативной памяти. Веб-контейнер и воркер требуют по 4 GiB каждый. Это минимальные заявленные требования для 3 компонентов, которые учитывает Langfuse, при этом Postgres, Redis и MinIO также требуют дополнительной памяти. Официальное руководство по Docker Compose рекомендует машину с 4 ядрами, 16 GiB оперативной памяти и около 100 GiB дискового пространства, что соответствует этим расчетам без избыточного запаса.

Не пытайтесь запускать это на тарифе с 2 GiB памяти. ClickHouse запустится, некоторое время будет принимать записи, а затем упадет во время фонового слияния, так как слияние загружает большие части таблицы в оперативную память. Вы увидите, как docker compose ps сообщает о статусе контейнера clickhouse как restarting, dmesg содержит строку вида Out of memory: Killed process 1234 (clickhouse-serv), а все дашборды Langfuse возвращают ошибку 500. При меньшей нагрузке ClickHouse просто отклонит запрос и запишет в лог DB::Exception: Memory limit (total) exceeded. Восемь GiB достаточно для одного разработчика, отправляющего несколько тысяч трассировок в день. Планируйте использование 16 GiB.

Развертывание Langfuse с помощью Docker Compose

Клонируйте репозиторий. Стек, связи между компонентами и параметры окружения по умолчанию находятся в файле docker-compose.yml.

git clone https://github.com/langfuse/langfuse.git
cd langfuse

Все значения, которые необходимо изменить, отмечены в этом файле как # CHANGEME. Сначала сгенерируйте три секрета приложения.

openssl rand -base64 32   # NEXTAUTH_SECRET
openssl rand -base64 32   # SALT
openssl rand -hex 32      # ENCRYPTION_KEY

Значение ENCRYPTION_KEY должно представлять собой 256 бит, записанных как 64 шестнадцатеричных символа; именно это выводит команда openssl rand -hex 32. Этот ключ шифрует конфиденциальные данные в состоянии покоя, включая ключи провайдеров LLM, которые вы храните в экземпляре. Изменение ключа после появления данных приведет к невозможности их расшифровки, поэтому считайте его постоянным с момента первого запуска. Значение SALT используется для хеширования ваших API-ключей Langfuse, поэтому его изменение сделает недействительными все ключи, которые уже используют ваши агенты.

Затем установите POSTGRES_PASSWORD, CLICKHOUSE_PASSWORD, REDIS_AUTH и MINIO_ROOT_PASSWORD. Пароль MinIO указывается в четырех местах: один раз как MINIO_ROOT_PASSWORD, а затем как LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY, LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY и LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY. Если пропустить хотя бы одно, MinIO отклонит клиент с ошибкой SignatureDoesNotMatch, которая попадет в лог воркера, в то время как веб-интерфейс будет выглядеть работоспособным. Хранение этих значений в файле окружения, а не в отслеживаемом файле compose — это стандартная практика, описанная в файлах окружения и секретах Docker Compose.

Зафиксируйте теги образов перед запуском

Поставляемый файл использует langfuse/langfuse:4 и langfuse/langfuse-worker:4. Эти теги могут меняться. Langfuse автоматически выполняет миграции Postgres и ClickHouse при запуске, поэтому обычная команда docker compose pull через несколько месяцев может привести к незапланированной миграции схемы базы данных, которую вы не успели забэкапить утром. Зафиксируйте обе версии в файле docker-compose.override.yml, который Compose объединит с основным файлом, чтобы последующая команда git pull не конфликтовала с вашими правками.

services:
  langfuse-web:
    image: docker.io/langfuse/langfuse:4.3.1
  langfuse-worker:
    image: docker.io/langfuse/langfuse-worker:4.3.1

Версия 4.3.1 была актуальным релизом 4.3 по состоянию на август 2026 года (с тех пор вышел 4.4.0). Проверьте страницу релизов проекта на GitHub, зафиксируйте версию, актуальную на день развертывания, и обновляйте её осознанно. Образы хранилищ в поставляемом файле уже зафиксированы по мажорным версиям: postgres:17, clickhouse-server:25.12 и redis:7, и они требуют такого же подхода.

Запустите стек.

docker compose up -d
docker compose ps
docker compose logs -f langfuse-worker

При первом запуске выполняются миграции, поэтому подождите минуту или две, прежде чем ожидать ответа. Команда docker compose ps должна показать шесть сервисов в состоянии running. Если воркер перезапускается в цикле, причина указана в его логе: CLICKHOUSE_MIGRATION_URL использует нативный протокол ClickHouse на порту 9000, а не HTTP-порт 8123. Указание порта 8123 приведет к ошибке, хотя веб-контейнер будет выглядеть исправным.

Проверьте работоспособность с самого сервера.

curl -s "http://localhost:3000/api/public/health?failIfDatabaseUnavailable=true"
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/public/ready

Обычный вызов /api/public/health лишь подтверждает, что процесс API запущен, так как он намеренно игнорирует базу данных, чтобы сервис продолжал работать при кратковременных сбоях Postgres. Формат failIfDatabaseUnavailable=true — это то, на что стоит настроить мониторинг; он возвращает 503, если база данных недоступна. /api/public/ready возвращает 200, как только миграции завершены и контейнер готов принимать трафик. Оба варианта — это обычные HTTP-проверки, поэтому страница статуса Uptime Kuma может отслеживать их и сообщить вам о неработоспособности стека раньше, чем это заметят ваши агенты.

Настройка TLS и закрытие лишних портов

В поставляемом файле compose порт 3000:3000 открыт для веб-контейнера, а 9090:9000 — для MinIO. Оба привязаны ко всем сетевым интерфейсам. На публичном IP это означает, что любой, кто просканирует порт 3000, попадет на вашу страницу регистрации, а любой, кто просканирует 9090, получит доступ к хранилищу с вашими исходными промптами.

Правила межсетевого экрана сами по себе не закрывают эти порты. Docker записывает собственные правила DNAT в таблицу nat, которые обрабатываются до того, как пакеты попадают в правила фильтрации ufw, поэтому ufw deny 3000 оставляет опубликованный порт открытым. Эта проблема встречается достаточно часто, чтобы для неё существовало отдельное руководство: почему опубликованные порты Docker обходят ufw. Вместо этого привяжите сервисы к loopback-интерфейсу в вашем файле переопределения.

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 должно в точности соответствовать публичному адресу, включая схему, так как процесс входа в систему формирует URL обратного вызова на основе этого параметра. Если оставить http://localhost:3000 при работе через HTTPS-прокси, цикл авторизации направит браузер туда, где сервис недоступен.

Теперь направьте обратный прокси на 127.0.0.1:3000 и поручите ему управление сертификатом. Traefik в том же проекте Compose — стандартный выбор, а метки маршрутизации описаны в запуск нескольких приложений за одним обратным прокси Traefik. Caddy выполняет ту же задачу в две строки, если Langfuse — единственный сервис на сервере. Проверьте конфигурацию с помощью curl -sI https://langfuse.example.com/api/public/ready, а затем убедитесь с другого компьютера, что соединение с curl http://YOUR_IP:3000 теперь завершается по таймауту.

Важное замечание по MinIO. Langfuse передает прикрепленные медиафайлы в браузер через подписанные URL, указывающие на этот S3-эндпоинт. Если вы используете мультимодальные трассировки с изображениями или аудио, привязка MinIO только к loopback приведет к тому, что эти вложения не будут загружаться. Ознакомьтесь со страницей настройки хранилища объектов перед тем, как проксировать его, так как эндпоинт, записанный в подписанном URL, должен совпадать с тем, который вы публикуете. На текстовые трассировки это не влияет.

Создайте свою учетную запись при первом посещении, а затем ограничьте доступ к инстансу. Установите LANGFUSE_ALLOWED_ORGANIZATION_CREATORS на свой адрес электронной почты, чтобы посторонний человек, попавший на страницу, не смог создать организацию на вашем сервере.

Отправка первой трассировки

Создайте проект в веб-интерфейсе и скопируйте публичный и секретный ключи из настроек проекта. Python SDK считывает три переменные окружения.

export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_SECRET_KEY="sk-lf-..."
export LANGFUSE_BASE_URL="https://langfuse.example.com"

LANGFUSE_BASE_URL — это имя переменной в SDK v4, выпущенном в марте 2026 года. В старом коде и руководствах используется LANGFUSE_HOST. Если ваши трассировки попадают в Langfuse Cloud вместо вашего сервера, значит, не задан базовый URL, так как по умолчанию используется облачный экземпляр.

pip install langfuse opentelemetry-instrumentation-anthropic anthropic
import 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()

Декоратор @observe открывает наблюдение вокруг функции, захватывает её аргументы и возвращаемое значение, а также вкладывает его в уже активное наблюдение. AnthropicInstrumentor — это инструментарий OpenTelemetry для клиента Anthropic; он превращает каждый вызов messages.create в генерацию, содержащую имя модели, использование токенов и задержку, без изменений в месте вызова.

Два вызова позволяют выполнить проверку. langfuse.auth_check() возвращает False при неверных ключах или некорректном базовом URL; это быстрее, чем выяснять, почему панель мониторинга пуста. langfuse.flush() блокирует выполнение до тех пор, пока не будут отправлены поставленные в очередь спаны. Это необходимо для кратковременных процессов, так как SDK выполняет пакетную обработку в фоновом режиме, и скрипт, который завершается немедленно, прерывает отправку пакета.

Почему ClickHouse продолжает расти?

Трассировки — это самый быстрорастущий тип данных, который пользователи обычно размещают на собственных серверах. Каждый запуск агента записывает по одной строке на каждый шаг, а входные и выходные данные сохраняются полностью. В результате «разговорчивый» агент с длинными промптами генерирует гораздо больше байтов в день, чем само приложение, за которым он наблюдает. Если оставить всё как есть, ClickHouse заполнит диск, а переполнение диска полностью останавливает прием данных, а не просто замедляет его.

Здесь растут два разных типа данных, и для них требуются два разных решения.

Первый тип — это ваши собственные данные трассировки, и решение заключается в настройке периода хранения. Откройте настройки проекта в веб-интерфейсе и укажите период хранения данных в днях. Langfuse принимает значение минимум 3 дня. Ночное задание выбирает трассировки, наблюдения, оценки и медиа-ресурсы, которые старше этого периода, и удаляет их из ClickHouse и из объектного хранилища. Заданию требуются права DeleteObject на бакет, которые уже есть у root-учетных данных MinIO в стандартном файле compose. Удаление является необратимым, поэтому сначала настройте экспорт в объектное хранилище, если вам нужна долгосрочная история. Не прописывайте TTL-условия вручную для таблиц Langfuse: задание по очистке синхронизирует ClickHouse и бакет, а ручной TTL удалит данные только в одном месте.

Выберите период, исходя из реальных потребностей. Анализ стоимости и качества проводится на данных за несколько дней, а не месяцев. 30 дней — разумный срок для небольшой команды, а 14 дней достаточно, если вы открываете трассировку только при возникновении проблем.

Второй тип — это системные таблицы логов самого ClickHouse. Это часто удивляет пользователей, так как диск продолжает расти даже после настройки периода хранения. ClickHouse записывает trace_log, text_log, opentelemetry_span_log, metric_log и asynchronous_metric_log для собственной диагностики; они поставляются без настроенного TTL, и Langfuse их никогда не читает. Сначала выясните, куда именно уходит место на диске.

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
)

Запустите его с помощью docker compose exec clickhouse clickhouse-client --password "$CLICKHOUSE_PASSWORD". Если системные таблицы занимают верхние строчки, отключите их через конфигурационный оверлей, так как ClickHouse при запуске объединяет каждый файл из /etc/clickhouse-server/config.d/ со своей основной конфигурацией.

<clickhouse>
    <trace_log remove="1"/>
    <text_log remove="1"/>
    <opentelemetry_span_log remove="1"/>
    <asynchronous_metric_log remove="1"/>
    <metric_log remove="1"/>
</clickhouse>

Примонтируйте его и перезапустите ClickHouse.

services:
  clickhouse:
    volumes:
      - ./clickhouse-config.d/system-logs.xml:/etc/clickhouse-server/config.d/system-logs.xml:ro

Это остановит новые записи. Строки, которые уже находятся на диске, останутся там, поэтому освободите место явно с помощью DROP TABLE IF EXISTS system.trace_log и повторите то же самое для каждой удаленной таблицы. Если вы хотите сохранить диагностику, альтернативой будет агрессивный TTL для каждой таблицы вместо remove="1", что подробно описано в документации Langfuse по масштабированию.

Стоит упомянуть еще одну таблицу. blob_storage_file_log отслеживает файлы событий, загруженные в ваш бакет. Если вы также установили политику жизненного цикла для бакета, задайте для этой таблицы соответствующий TTL, чтобы данные в них не разошлись.

ALTER TABLE blob_storage_file_log MODIFY TTL created_at + INTERVAL 30 DAY DELETE;

Также настройте простое оповещение df -h для диска с данными. Трассировки не растут равномерно. Они растут в тот день, когда вы выпускаете нового агента, и первым признаком этого не должен быть отказ в приеме данных.

Резервное копирование Postgres и ClickHouse

Резервная копия Langfuse состоит из трех частей. В Postgres хранятся ваши пользователи, организации, проекты и API-ключи. В ClickHouse хранятся трассировки. В MinIO хранятся необработанные события. Если восстановить только Postgres, вы получите работающую систему входа, но без истории. Если восстановить только ClickHouse, вы получите историю, которую никто не сможет просмотреть, так как не сможет войти в систему.

Postgres — это обычный pg_dump, что и рекомендует документация по резервному копированию Langfuse.

docker compose exec -T postgres pg_dump -U postgres postgres \
  | gzip > langfuse-pg-$(date +%F).sql.gz

С ClickHouse требуется больше внимания, так как каталог с данными, скопированный во время активных процессов слияния (merges), не является консистентной резервной копией. Простой подход для одного сервера — остановить контейнер и заархивировать том.

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 clickhouse

Используйте имя тома, которое выводит docker volume ls, а не то, что указано в YAML. В файле объявлено langfuse_clickhouse_data, но Compose добавляет к нему префикс с именем проекта, поэтому клон в каталоге с именем langfuse создаст langfuse_langfuse_clickhouse_data. Если ошибиться, docker run создаст новый пустой том без предупреждений, и ваш архив окажется пустым.

Контейнер web записывает каждое входящее событие в бакет до того, как его обработает worker, поэтому кратковременная остановка ClickHouse в основном означает, что worker просто повторит попытку позже. Выполняйте это в часы низкой нагрузки и старайтесь сократить время простоя. Для более нагруженных инстансов используйте встроенную инструкцию ClickHouse BACKUP DATABASE default TO S3(...), которая создает консистентную резервную копию без остановки сервера. MinIO — это третья часть, и для нее подойдет mc mirror или репликация MinIO на внешний бакет. Что бы вы ни создали, выносите это с сервера, для чего и предназначены зашифрованные резервные копии restic на VPS.

Redis не нуждается в резервном копировании. В нем хранятся очередь и кэш, поэтому его потеря приведет лишь к потере событий, находящихся в обработке в данный момент, но не более старых данных.

Предупреждение о консистентности реально, и его стоит проговорить прямо. Дампы Postgres и ClickHouse создаются в разное время, поэтому после восстановления может оказаться, что запись о проекте существует, а трассировок нет, или наоборот — есть трассировки, принадлежащие проекту, которого больше не существует. Langfuse допускает такие ситуации, но старайтесь делать оба дампа с минимальным интервалом и в период низкой активности. Бакет с событиями — это ваша основная страховка, так как Langfuse сохраняет там каждое входящее событие до начала его обработки.

Хотя бы раз выполните восстановление в тестовой среде. Это позволит вам обнаружить ошибку в имени тома сейчас, а не во время аварийной ситуации.

На что смотреть в первую очередь

Четыре показателя заслуживают внимания в первую неделю работы.

  • Стоимость трассировки. Langfuse вычисляет стоимость на основе названия модели и количества использованных токенов. Отсортируйте трассировки по стоимости и изучите самую дорогую от начала до конца. Обычно причина кроется в разросшемся промпте: в контекст вставлен целый документ или история диалога, которую никто не обрезает. Как только вы увидите это, контроль расходов на AI-агента станет инженерной задачей, а не догадкой.
  • Распределение токенов на вход и выход. Входных токенов много, и они дешевы; выходных — мало, и они дороги; кэшированные входные данные стоят еще меньше. Тот же принцип учета описан в том, как считается использование токенов в Claude Code, и он применим к любому агенту, который вы создаете самостоятельно.
  • Перцентили задержки. Медиана скрывает проблему. Тайм-ауты живут в p95 и p99. Внутри цикла агента медленный вызов инструмента на уровне p95 умножается на количество итераций.
  • Неудачные вызовы инструментов. Отфильтруйте наблюдения по уровню ERROR. Инструмент, который дает сбой в 5% случаев, незаметен в общем показателе успешности, но хорошо виден в трассировках, где вы наблюдаете, как модель повторяет попытки и тратит токены на обходные пути.

Установите период хранения данных и выберите дашборд, который будете проверять еженедельно в день деплоя. Инструмент наблюдаемости, который никто не открывает, — это просто база данных, заполняющая диск.

FAQ

Сколько оперативной памяти требуется для self-hosted Langfuse?

Планируйте использование 4 ядер CPU и 16 GiB оперативной памяти — это рекомендуемые параметры для одной виртуальной машины согласно руководству Langfuse Docker Compose, плюс около 100 GiB дискового пространства. Опубликованные минимальные требования для компонентов составляют 8 GiB для ClickHouse и по 4 GiB для контейнеров web и worker; кроме того, память требуется для Postgres, Redis и MinIO. Восемь GiB достаточно для запуска экземпляра одного разработчика. Двух GiB недостаточно: ядро завершает процесс ClickHouse во время фонового слияния данных, а dmesg показывает Out of memory: Killed process.

Почему диск с ClickHouse продолжает заполняться после настройки хранения данных?

Настройка хранения (retention) распространяется только на собственные данные Langfuse. ClickHouse отдельно записывает данные в свои диагностические таблицы trace_log, text_log, opentelemetry_span_log, metric_log и asynchronous_metric_log, для которых по умолчанию не задан TTL. Выполните запрос system.parts с группировкой по таблицам, чтобы определить самую большую из них, затем отключите неиспользуемые таблицы с помощью записи remove="1" в файле в директории /etc/clickhouse-server/config.d/, перезапустите ClickHouse и удалите существующие таблицы, чтобы освободить занятое место.

Какой минимальный срок хранения данных в Langfuse?

Три дня. Срок хранения настраивается для каждого проекта в настройках проекта или через API проектов. Ежедневное задание удаляет трассировки (traces), наблюдения (observations), оценки (scores) и медиафайлы, которые старше указанного периода, как из ClickHouse, так и из объектного хранилища (blob storage). Удаление необратимо, поэтому сначала настройте экспорт в объектное хранилище, если вам нужна история за пределами этого периода.

Нужно ли делать резервные копии и Postgres, и ClickHouse?

Да, так как они хранят разные данные. В Postgres находятся пользователи, организации, проекты и API-ключи, а в ClickHouse — сами данные трассировок. Восстановление только из Postgres даст вам пустой экземпляр, в который можно войти, но в котором ничего нет. Также делайте резервную копию бакета MinIO, так как в нем хранятся необработанные события, которые Langfuse сохраняет при поступлении; это наиболее близкий аналог первоисточника данных в данном стеке.

Можно ли подключить существующую настройку OpenTelemetry к self-hosted Langfuse?

Да. Langfuse v4 и его SDK версии v4 построены на базе OpenTelemetry, а инструменты Anthropic и OpenAI OTel экспортируют данные напрямую в него. В Python выполните pip install langfuse opentelemetry-instrumentation-anthropic, вызовите AnthropicInstrumentor().instrument() один раз при запуске и установите LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY и LANGFUSE_BASE_URL на ваш хост. Проверьте результат с помощью langfuse.auth_check(), прежде чем искать причину отсутствия данных на дашборде.