Langfuse Cloud chosen as OTEL observability backend for Claude Code + OpenCode
Langfuse observability — 2026-07-06
Decision
Adopt Langfuse Cloud Hobby tier as the OTEL sink for both Claude Code and OpenCode. Wired via two OpenTelemetry standard env vars per agent; values resolve through the existing .env → user env → process.env sync chain, so secrets never appear in repo.
Why Langfuse (vs LangSmith vs others)
- Free Hobby tier = 50k traces / mo, 30-day retention, 2 users, no card. LangSmith free = 5k traces, 14-day retention, 1 user, card pushed for higher tiers. ≥10× headroom per
never-hit-quotas. - OpenTelemetry native, not vendor-Lockin. CC and OpenCode both speak OTEL — no LangChain compile-time coupling.
- Open-source ethos aligns with workspace posture per
okf-ecosystem-first-mover+community-packages-first. - Direct OTEL endpoint, no LiteLLM proxy hop. Two env vars = one config line per agent. Matches user's "one-line, two-line replacement" ask exactly.
How it works
.env (encrypted) # LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_OTEL_HEADERS
↓ scripts/sync-env-to-system-env.ps1 # Windows Scheduled Task, logon + 09:00 daily
user-scope Windows env vars
↓ inherited by every new process
Claude Code → reads OTEL_EXPORTER_OTLP_ENDPOINT + OTEL_EXPORTER_OTLP_HEADERS → POSTs traces
OpenCode → reads OTEL_EXPORTER_OTLP_ENDPOINT + OTEL_EXPORTER_OTLP_HEADERS → POSTs traces
↓
Langfuse Cloud Hobby project
Three config layers, additive only:
repos/private/agent-configs/agents/claude/settings.json— env block adds:OTEL_EXPORTER_OTLP_ENDPOINT: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}— same env-expansion pattern used forANTHROPIC_AUTH_TOKENon the canonical line 14; the actual URL is in user env, derived by sync-env per region.OTEL_EXPORTER_OTLP_HEADERS: ${env:OTEL_EXPORTER_OTLP_HEADERS}— secret via env expansion; no manual base64.
repos/private/agent-configs/agents/opencode/opencode.json— NO explicit env block added. OpenCode inheritsOTEL_EXPORTER_OTLP_*from the launching shell (Windows env propagation), so the same user-env values land there too..env.example— new "Langfuse" section at the tail:LANGFUSE_HOST=(user sets their region:https://us.cloud.langfuse.comorhttps://eu.cloud.langfuse.com)LANGFUSE_PUBLIC_KEY=LANGFUSE_SECRET_KEY=LANGFUSE_BASE_URLis also accepted as an alias forLANGFUSE_HOST(matches Langfuse SDK docs naming).
Region handling (added 2026-07-06 after first activation)
Langfuse region-routes accounts since 2025. The regional direct host (us.cloud.langfuse.com or eu.cloud.langfuse.com) is the documented production endpoint per https://langfuse.com/docs; using the regional host removes any cross-region redirect from the OTEL path and is faster. Avoid hardcoding the generic https://cloud.langfuse.com because it redirects at the gateway layer and adds an avoidable hop.
scripts/sync-env-to-system-env.ps1 automatically appends /api/public/otel to LANGFUSE_HOST (or LANGFUSE_BASE_URL) and exports OTEL_EXPORTER_OTLP_ENDPOINT to user env. Both CC and OpenCode pick it up via shell env inheritance (CC additionally has ${env:...} expansion in its env block; OpenCode relies on default shell propagation), so a single .env change lights up the entire fleet.
Verification
scripts/verify-langfuse-otel.ps1 posts a minimal OTLP-shaped trace to https://cloud.langfuse.com/api/public/otel/v1/traces using creds from user env, prints HTTP status + trace ID, exits non-zero on failure. Run after signup to confirm the chain is wired.
Known gaps (out of scope this commit)
- Leaked secrets in agent-configs submodule that should be rotated + env-backed in a separate commit:
agents/claude/settings.jsonline containing"HELICONE_API_KEY": "sk-helicone-rl-vu42yey-yfyekoa-so3po7q-px3tbnq"agents/opencode/opencode.jsonprovideromniroute.options.apiKeycontaining"sk-6ebcf766fc4fe062-1fc03a-7eb89a28"- Fix requires rotating the keys at the source services (paid side-effect on Helicone + OmniRoute provisioning) — outside this commit's standing-auth envelope. Flag for follow-up.
- OmniRoute-level traces are NOT captured. The agents above emit CC- and OpenCode-internal spans (tool selections, prompts, responses). The actual upstream model request/response (which OmniRoute forwards) is invisible until OmniRoute itself gains a Langfuse exporter. Tracked as a follow-up.
- Kilo Code, Cline, Antigravity, Freebuff, Qwen are NOT configured this turn. Decision applies to CC + OpenCode per the user's literal ask; extend fleet parity when the leak cleanup commit lands.
Activation checklist (user-side)
scripts/sync-env-to-system-env.ps1 (extended 2026-07-06) auto-derives BOTH OTEL_EXPORTER_OTLP_HEADERS (from LANGFUSE_PUBLIC_KEY:LANGFUSE_SECRET_KEY base64) AND OTEL_EXPORTER_OTLP_ENDPOINT (from LANGFUSE_HOST or LANGFUSE_BASE_URL + /api/public/otel). The user does NOT pre-compute anything.
- Sign up at https://langfuse.com (free, no card). Email or GitHub OAuth. Note the regional host Langfuse returns (e.g.
https://us.cloud.langfuse.comorhttps://eu.cloud.langfuse.com). - Create a project (e.g. "chirag127-fleet").
- Settings → API Keys → Create new key pair → copy both
pk-lf-…andsk-lf-…. - Paste three values into local
.env(gitignored, encrypted to.env.encvia sops):LANGFUSE_HOST=https://<us|eu>.cloud.langfuse.com(the regional host, NOT the genericcloud.langfuse.com)LANGFUSE_PUBLIC_KEY=pk-lf-…LANGFUSE_SECRET_KEY=sk-lf-…
pwsh C:\d\ws\scripts\sync-env-to-system-env.ps1 -Verbose— propagates LANGFUSE_* to user env AND auto-derives both OTEL_* user-scope env vars.pwsh C:\d\ws\scripts\verify-langfuse-otel.ps1 -Verbose— confirms HTTP 200 with traceId.- Run Claude Code / OpenCode as usual — traces appear in the Langfuse dashboard at the regional host, under the project.
Cross-refs
- Langfuse docs cited: https://langfuse.com/docs (in particular
/integrations/native/opentelemetryand/self-hosting). - Claude Code monitoring: https://code.claude.com/docs/en/monitoring-usage
- The existing
.env → user envchain:knowledge/rules/agent/env-to-system-env-daily.md