Claude Code + n8n + Langfuse Hands-On
When Claude Code calls a local Ollama model, Token usage goes dark, latency spikes have no root cause, and error rates can't be attributed — problems that get worse once you leave the cloud and self-host everything. This article builds a Claude Code + n8n + Langfuse stack that uses Langfuse's OTEL traces to cover the full链路 from Prompt input to workflow execution, so every Claude Code call leaves a trace.
Architecture Overview
Three-piece data flow:
Claude Code (Prompt input)
↓ HTTP (OpenAI-compatible API)
Ollama (local LLM)
↓ OTEL Trace
Langfuse (self-hosted, port 3000)
↓ Trigger
n8n (listening to Langfuse Webhook)
↓ Action
Workflow execution (Slack notification / Notion log / CI trigger)
- **Claude Code**: connects to Ollama via `OLLAMA_BASE_URL=http://localhost:11434/v1` + `OPENAI_API_KEY=anything`
- **n8n**: receives Langfuse webhook callbacks and triggers downstream actions
- **Langfuse**: records Token usage, latency, and error rate for every LLM call; supports self-hosting
Prerequisites
- **OS**: Ubuntu 22.04 LTS, 16GB+ RAM
- **Software**: Docker 26.x, Docker Compose v2, Ollama 0.5.x
- **Model**: Default Ollama model (e.g., llama3.2:3b)
- **Verify**: `docker --version && ollama --version && curl -s http://localhost:3000/api/public/health`
Step 1: Deploy Langfuse Self-Hosted
Langfuse's official Docker Compose template is more controllable than Vercel deployment (no data leaving your server).
mkdir -p ~/langfuse && cd ~/langfuse
# Download official template
curl -fsSL https://langfuse.com/self-hosting/docker -o docker-compose.yml
# Set environment variables
export SECRET_KEY=local-dev-secret-change-in-prod
export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/langfuse
export NEXTAUTH_SECRET=local-auth-secret
# Start
docker compose up -d
# Verify
curl -s http://localhost:3000/api/public/health | python3 -m json.tool
Output example:
{"status":"ok","version":"3.14.2"}
Langfuse dashboard: http://your-server:3000. The first registered user becomes admin.
Step 2: Configure Claude Code to Connect to Ollama
Claude Code talks to Ollama via the OpenAI-compatible API — no plugins needed.
# Set environment variables (add to ~/.bashrc)
export OLLAMA_BASE_URL=http://localhost:11434/v1
export OPENAI_API_KEY=local-dev
export MODEL=llama3.2:3b
# Test in Claude Code
claude "What is 2+2?" --output-format stream
If you see Connection refused, verify Ollama is listening:
curl http://localhost:11434/api/tags
Step 3: Inject Langfuse Python SDK Traces
Instrument your Claude Code call scripts with the Langfuse SDK:
# my_script.py
from langfuse import Langfuse
import os
langfuse = Langfuse(
public_key=os.environ["LANGFuse_PUBLIC_KEY"],
secret_key=os.environ["LANGFUSE_SECRET_KEY"],
host="http://your-langfuse-server:3000"
)
def call_llm(prompt):
with langfuse.start_span(name="ollama-call") as span:
span.input = prompt
# Actually call Ollama (via OpenAI SDK)
response = openai.ChatCompletion.create(
model=os.environ["MODEL"],
messages=[{"role":"user","content":prompt}],
api_base=os.environ["OLLAMA_BASE_URL"],
api_key=os.environ["OPENAI_API_KEY"]
)
span.output = response["choices"][0]["message"]["content"]
return response["choices"][0]["message"]["content"]
Step 4: n8n Listens to Langfuse Webhooks
Langfuse supports webhook callbacks; n8n receives them and triggers downstream actions (Slack alerts, Notion logs, CI pipelines).
# n8n self-hosted (continued from 6/15 n8n + Langfuse hands-on)
mkdir -p ~/n8n && cd ~/n8n
curl -fsSL https://raw.githubusercontent.com/n8n-io/n8n/master/docker-compose.yml -o docker-compose.yml
# Add Langfuse Webhook Node
# n8n dashboard → Workflows → New → Webhook (langfuse-events)
# Trigger URL: https://your-langfuse.com/api/public/ingestion
n8n workflow example: when Langfuse records an LLM call with latency > 5000ms, send a Slack alert:
[Webhook Trigger] → [IF: trace.latency > 5000] → [Slack Node: @here High Latency Alert]
💣 Pitfall Survival Guide
Pitfall 1: Ollama Port 11434 Not Listening on All Interfaces
**Error**: ECONNREFUSED 127.0.0.1:11434
**Cause**: Ollama binds to 127.0.0.1 by default — Docker containers on the host can't reach it.
**Fix**: Set OLLAMA_HOST=0.0.0.0:
# Edit systemd service
sudo systemctl edit ollama
# Add:
[Service]
Environment="OLLAMA_HOST=0.0.0.0"
# Reload
sudo systemctl daemon-reload && sudo systemctl restart ollama
Pitfall 2: Langfuse Port 3000 Conflict with Docker Default
**Error**: port is already allocated
Cause: Some Docker images default to port 3000 (Flask/Remnia etc.).
Fix:
# Method 1: Remap Langfuse ports
# In docker-compose.yml:
services:
langfuse:
ports:
- "3000:3000"
- "3001:3001"
# Update DATABASE_URL to use 5432 (PostgreSQL default)
# Method 2: Find the conflicting process
sudo lsof -i :3000
Pitfall 3: Langfuse Python SDK Model Name Mismatch with Ollama
**Symptom**: Trace shows in Langfuse dashboard, but model name shows as unknown.
**Cause**: Ollama returns model names in format llama3.2:3b, which Langfuse SDK doesn't auto-detect.
Fix: Explicitly pass model in span metadata:
with langfuse.start_span(
name="ollama-call",
metadata={"model": os.environ["MODEL"]}
) as span:
...
Pitfall 4: n8n Webhook Timeout (Langfuse Default 30s)
**Error**: RequestTimeoutError: Webhook request timeout
Cause: Langfuse webhook default timeout is 30s, but complex n8n workflows often exceed this.
Fix: Either increase timeout in Langfuse dashboard → Settings → Webhooks, or switch to async trigger:
[Webhook] → [Node: Delay 0] → [Node: HTTP Request (Langfuse ACK)]
Pitfall 5: Langfuse PostgreSQL Connection Pool Exhaustion (High-Frequency Calls)
**Error**: remaining connection slots are reserved
**Cause**: Langfuse self-hosted defaults to max_connections=20. High-frequency Claude Code calls (100+/min) burn through this fast.
Fix:
# In docker-compose.yml PostgreSQL section, add:
environment:
POSTGRES_MAX_CONNECTIONS: 100
# Or directly:
ALTER SYSTEM SET max_connections = 100;
sudo systemctl restart postgresql
Before vs After Comparison
| Dimension | Without Langfuse | With Langfuse |
|---|---|---|
| Token usage transparency | Black box | Full trace per call |
| Latency analysis | Gut feeling | P50/P95/P99 auto-calculated |
| Error rate tracking | Log searching | Dashboard real-time alerts |
| n8n automation trigger | Custom monitoring | Webhook native integration |
| Cost attribution | Rough estimate | Trace-level precision |
Summary
The Claude Code + n8n + Langfuse three-piece stack turns the local LLM call black box transparent: Langfuse records every call, n8n triggers downstream workflows based on trace results, forming a complete closed loop of "LLM call → observability tracing → automated response."
If you're running models locally, start with Langfuse self-hosted (30 minutes to up and running), then gradually integrate n8n for alerting and workflow automation.
Related Reading:
👉 Join MiniMax Token Plan: AI coding acceleration for businesses
👉 Join Zhipu Coding Plan: GLM-4.6/GLM-5 coding packages, China-stable, pay-per-token unlimited
👉 Join Aliyun AI: Top AI products with exclusive coupons for business innovation
📌 This article was AI-assisted generated and human-reviewed | TechPassive — An AI-driven content testing site focused on real tool reviews
🔗 Recommended Tools
These are carefully selected tools. Using our affiliate links supports us to keep producing quality content: