In the Langfuse UI, traces produced by this plugin only ever show input; they never show output. Conversely, the nested opencode.generation observations have output but no input. As a result, no single observation (trace or generation) has a paired input + output, which makes it impractical to build LLM-as-judge evaluators on these traces.
Here are some example of what that looks like:
Please note that this is my first time using Langfuse, but I would have expected a different behavior based on the short video in https://langfuse.com/docs/observability/get-started#see-your-trace-in-langfuse.
Reproduction
- Enable the plugin per the README:
{
"experimental": { "openTelemetry": true },
"plugin": ["@langfuse/opencode-observability-plugin@latest"]
}
- Run any prompt with
opencode run "say hello" (or via the TUI).
- Open the resulting trace in Langfuse.
Observed:
- The trace pane shows the user prompt as
input, but output is empty.
- Click into the trace to see observations:
opencode.turn (root, drives trace-level I/O) — has input, no output.
opencode.generation — has output, no input.
Expected: at least one of the observations should carry both the input and the output of the LLM call, so users can run trace-level or observation-level LLM judges without manually joining sibling spans.
Root cause (from reading the source)
In src/langfuse.ts:
traceUserMessage creates the opencode.turn root span and sets langfuse.observation.input to the formatted user message. It never sets langfuse.observation.output on this span — neither at creation nor later when the turn finishes.
traceGeneration / startActiveGenerationStep create the nested opencode.generation span and set langfuse.observation.output (assistant text), model.name, usage_details, cost_details. They never set langfuse.observation.input.
Since Langfuse derives trace-level input/output from the root observation's attributes, the missing output on opencode.turn is what surfaces in the UI as the empty trace output column.
Environment
- Plugin:
@langfuse/opencode-observability-plugin (latest as of filing)
- OpenCode: 1.17.9
- Configuration:
experimental.openTelemetry: true, plugin loaded from opencode.json
In the Langfuse UI, traces produced by this plugin only ever show
input; they never showoutput. Conversely, the nestedopencode.generationobservations haveoutputbut noinput. As a result, no single observation (trace or generation) has a paired input + output, which makes it impractical to build LLM-as-judge evaluators on these traces.Here are some example of what that looks like:
Please note that this is my first time using Langfuse, but I would have expected a different behavior based on the short video in https://langfuse.com/docs/observability/get-started#see-your-trace-in-langfuse.
Reproduction
{ "experimental": { "openTelemetry": true }, "plugin": ["@langfuse/opencode-observability-plugin@latest"] }opencode run "say hello"(or via the TUI).Observed:
input, butoutputis empty.opencode.turn(root, drives trace-level I/O) — hasinput, nooutput.opencode.generation— hasoutput, noinput.Expected: at least one of the observations should carry both the input and the output of the LLM call, so users can run trace-level or observation-level LLM judges without manually joining sibling spans.
Root cause (from reading the source)
In
src/langfuse.ts:traceUserMessagecreates theopencode.turnroot span and setslangfuse.observation.inputto the formatted user message. It never setslangfuse.observation.outputon this span — neither at creation nor later when the turn finishes.traceGeneration/startActiveGenerationStepcreate the nestedopencode.generationspan and setlangfuse.observation.output(assistant text),model.name,usage_details,cost_details. They never setlangfuse.observation.input.Since Langfuse derives trace-level
input/outputfrom the root observation's attributes, the missingoutputonopencode.turnis what surfaces in the UI as the empty trace output column.Environment
@langfuse/opencode-observability-plugin(latest as of filing)experimental.openTelemetry: true, plugin loaded fromopencode.json