Um agente que trabalha às três da manhã sem ninguém olhando vale tanto quanto a sua capacidade de reconstruir depois o que ele fez. «Queimou US$ 38 em tokens durante a noite» é uma manhã ruim. «Queimou US$ 38 porque uma ferramenta de busca devolveu uma página vazia e o planejador tentou de novo 400 vezes» é um bug que você corrige antes do almoço. A segunda frase exige traces.
O Langfuse registra cada chamada ao LLM, cada prompt, passo de ferramenta, contagem de tokens e latência como uma árvore em que dá para clicar. Hospedado por você, esses prompts e respostas — que muitas vezes trazem dados de clientes, saídas de API e algum segredo perdido — ficam num servidor que você controla, e não no painel de outra pessoa.
Quanto custa manter no ar
O Langfuse v4 não é um binário pequeno, e sim seis contêineres: o app web, um worker em segundo plano, Postgres, ClickHouse para os eventos, Redis e MinIO para os arquivos. Instalamos num servidor de teste e medimos cerca de 3,5 GB de RAM em uso com um projeto vazio. Quem cresce é o ClickHouse, porque é lá que vai parar cada span que você envia.
| Carga | Plano |
|---|---|
| Alguns agentes, semanas de traces | Medium-IP: 6 vCPU, 6 GB, 45 GB ($20/mês) |
| Uma frota de agentes, meses de histórico | Planos Pro, a partir de 32 GB de RAM — sob consulta |
Em planos menores ele instala e depois sofre assim que o ClickHouse e o worker querem memória ao mesmo tempo. Eu não ficaria abaixo de 6 GB.
Onde vivem os agentes? Se rodam em outras máquinas, escolha um plano com IPv4 próprio: eles precisam de um endpoint HTTPS, e num plano NAT o endereço de saída não é seu e de fora só se chega à porta SSH. Se os agentes rodam neste mesmo servidor, o Langfuse nunca precisa encarar a internet: para um teste basta o Medium com NAT ($12/mês). São duas localizações, Alemanha e Finlândia; a disponibilidade aparece na hora do pedido. Escolha a mais próxima dos agentes, não de você. Os servidores são pagos em cripto, sem KYC.
Instalação
Num servidor Ubuntu 24.04 ou Debian 12 recém-criado, como root. Primeiro o Docker:
curl -fsSL https://get.docker.com | sh
Depois o Langfuse, com segredos de verdade no lugar dos valores padrão do arquivo compose:
git clone --depth 1 https://github.com/langfuse/langfuse.git
cd langfuse
PG=$(openssl rand -hex 16); MINIO=$(openssl rand -hex 16)
cat > .env <<EOF
NEXTAUTH_URL=https://langfuse.example.com
NEXTAUTH_SECRET=$(openssl rand -hex 32)
SALT=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$PG
DATABASE_URL=postgresql://postgres:$PG@postgres:5432/postgres
CLICKHOUSE_PASSWORD=$(openssl rand -hex 16)
MINIO_ROOT_PASSWORD=$MINIO
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=$MINIO
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY=$MINIO
LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY=$MINIO
REDIS_AUTH=$(openssl rand -hex 16)
TELEMETRY_ENABLED=false
EOF
chmod 600 .env
Duas dessas senhas andam em par: a do Postgres também fica dentro de DATABASE_URL, e a do MinIO precisa bater com as três linhas S3_..._SECRET_ACCESS_KEY. Por isso cada uma vem de uma única variável.
Agora a armadilha. O arquivo compose publica o app web na porta 3000 e o MinIO na 9090 em todas as interfaces, e portas publicadas pelo Docker passam por cima do ufw. Prenda as duas ao localhost para que o proxy reverso seja a única entrada:
sed -i 's/- 3000:3000/- 127.0.0.1:3000:3000/; s/- 9090:9000/- 127.0.0.1:9090:9000/' docker-compose.yml
docker compose up -d
curl -s http://127.0.0.1:3000/api/public/health
O último comando deve mostrar {"status":"OK", ...}. A primeira inicialização roda as migrações do banco; no nosso teste, o health check passou uns 15 segundos depois que os contêineres subiram.
HTTPS na frente
Aponte langfuse.example.com para o IP do servidor e então:
apt install -y caddy
cat > /etc/caddy/Caddyfile <<'EOF'
langfuse.example.com {
reverse_proxy 127.0.0.1:3000
}
EOF
systemctl reload caddy
ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw enable
O Caddy obtém o certificado sozinho. Abra o site, crie sua conta (ela vira a primeira organização), adicione um projeto e copie as chaves pública e secreta dele.
Depois, feche a porta ao sair. O Langfuse entende AUTH_DISABLE_SIGNUP, mas o arquivo compose padrão não a repassa ao contêiner web, então é preciso uma linha a mais sob langfuse-web:
sed -i 's|^ NEXTAUTH_SECRET: \(.*\)$| NEXTAUTH_SECRET: \1\n AUTH_DISABLE_SIGNUP: ${AUTH_DISABLE_SIGNUP:-false}|' docker-compose.yml
echo "AUTH_DISABLE_SIGNUP=true" >> .env
docker compose up -d
A partir daí, uma tentativa de cadastro recebe «Sign up is disabled». Colegas você adiciona de dentro do projeto.
Enviando traces de um agente
O SDK Python envolve suas funções, e chamadas aninhadas viram spans aninhados:
python3 -m venv venv && . venv/bin/activate
pip install langfuse
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...
export LANGFUSE_BASE_URL=https://langfuse.example.com
from langfuse import get_client, observe
langfuse = get_client() # lê as variáveis LANGFUSE_*
@observe(name="fetch-prices")
def fetch_prices(pair: str) -> dict:
return {"pair": pair, "bid": 64210.5}
@observe(name="nightly-agent-run")
def run() -> str:
data = fetch_prices("BTC/USDT")
return f"done: {data['pair']}"
print(run())
langfuse.flush() # scripts curtos terminam antes de o envio em segundo plano acabar
Não pule LANGFUSE_BASE_URL. Sem ela, o SDK manda tudo em silêncio para a nuvem do Langfuse, suas chaves não existem lá e você fica olhando para um painel vazio.
Para conferir pelo terminal que os spans chegaram:
curl -s -u "$LANGFUSE_PUBLIC_KEY:$LANGFUSE_SECRET_KEY" \
"$LANGFUSE_BASE_URL/api/public/v2/observations?limit=5"
No v4, o antigo endpoint /api/public/traces responde com um erro sobre o modo events-only. Isso é esperado, não uma instalação quebrada. Num agente de verdade você envolve do mesmo jeito a chamada ao LLM e cada ferramenta; além disso, o Langfuse tem integrações para os SDKs de LLM e frameworks de agentes mais comuns, então muitas vezes basta trocar um import em vez de espalhar decoradores por tudo.
O que acompanhar
- Disco. O ClickHouse e o MinIO guardam tudo o que você envia.
docker system df -vmostra para onde foi o espaço. Se você rastreia prompts e respostas longos, os 45 GB do Medium-IP enchem em semanas, não em anos. Confira uma vez por mês; quando ficar apertado, um plano Pro com 400 GB ou mais está sob consulta. - Atualizações. O arquivo compose fixa a versão major (
:4).docker compose pull && docker compose up -dtraz as correções dentro dela. Leia o changelog antes de trocar de versão major: foi justamente na v4 que o endpoint de traces sumiu. - Backups. O que importa vive em volumes do Docker: o Postgres guarda usuários, projetos e chaves; o ClickHouse e o MinIO, os traces. Copie-os para fora do servidor de forma agendada.
Vale $20 por mês? Se os seus agentes gastam mais do que isso em tokens — e a maioria dos agentes sem supervisão gasta —, saber para onde foram os tokens se paga na primeira vez que um loop sai do controle. Um agente pequeno que roda uma vez por dia não precisa de nada disso: um arquivo de log e um contador de tokens bastam.
Relacionados
- VPS para agentes de IA: onde os próprios agentes rodam
- VPS para sistemas multiagente: dimensionar uma frota inteira
- VPS para um proxy LiteLLM: um gateway para todas as chaves de modelos, com limites de gasto
- Planos Pro sob consulta: de 32 a 80 GB de RAM para uma frota de agentes
- Como configurar um firewall ufw
Comentários
Nenhum comentário ainda. Seja o primeiro.