← Vetro Attest · Free Art. 12/14 checker · Free EU AI Act tools

From Langfuse to signed audit evidence

Langfuse is a good place to debug an agent. It is not evidence: traces live in a project your team administers, can be deleted or edited, and nothing tells an auditor whether they were. EU AI Act Article 12 asks for logs that make the system's behaviour traceable over its lifetime, and "we can show you our dashboard" is weak proof of that.

You don't have to replace Langfuse or add an SDK. If your spans already travel over OpenTelemetry, you can keep a copy as an OTLP/JSON file and have that copy attested.

1. Check that your traces are OpenTelemetry

Langfuse accepts OTLP at https://cloud.langfuse.com/api/public/otel (or /api/public/otel on your self-hosted instance). If your app sends spans there, from OpenLLMetry, OpenLIT, the Vercel AI SDK's experimental_telemetry, Pydantic AI / Logfire or any other OTel instrumentation, you are ready. Spans that carry the GenAI semantic conventions (gen_ai.operation.name, gen_ai.request.model, gen_ai.usage.*) become model calls in the report. execute_tool spans become tool calls. Everything else is kept as a timestamped span.

2. Put an OpenTelemetry Collector in the middle

Run otelcol-contrib (the file exporter is in the contrib distribution) and point your app's OTEL_EXPORTER_OTLP_ENDPOINT at it instead of at Langfuse. The Collector forwards every span to Langfuse unchanged and writes the same spans to a file:

receivers:
  otlp:
    protocols:
      http: { endpoint: 0.0.0.0:4318 }
      grpc: { endpoint: 0.0.0.0:4317 }
exporters:
  otlphttp/langfuse:
    endpoint: https://cloud.langfuse.com/api/public/otel   # the exporter appends /v1/traces
    headers:
      Authorization: "Basic ${env:LANGFUSE_AUTH}"         # base64 of public_key:secret_key
  file/evidence:
    path: /var/otel/traces.json
    format: json
service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [otlphttp/langfuse, file/evidence]

Langfuse keeps working exactly as before. You now also have your spans on disk, in a file only you control.

3. Turn the file into one OTLP/JSON trace

The file exporter writes one JSON object per line. Merge the lines into a single document:

jq -cs '{resourceSpans: map(.resourceSpans[])}' /var/otel/traces.json > run.otlp.json

Each traceId becomes its own run, so one file can carry a whole release worth of agent runs.

4. Paste it and get the report

Open the verifier, paste run.otlp.json or drop the file, and you get the EU AI Act record-keeping report for those runs, with a third-party countersignature and an RFC 3161 timestamp. From then on, any edit to the file shows up at verification. Want to see the output first? Open the sample report.

What this does not do

It attests what your pipeline exported, from the moment you started keeping the file. Past Langfuse traces are not evidence retroactively. To capture prompts, responses and inline policy decisions at the call site, not just span metadata, use the SDK adapters described in Start in 1 minute. For the difference between tracing and evidence, see OpenTelemetry GenAI traces as evidence and Vetro vs Langfuse.

See a sample ledger verified in one click, check your own logs free or get the countersigned EU AI Act report.

Pricing