Skip to content

Set the Langfuse user per session from session metadata - #48

Closed
geoff-ux wants to merge 1 commit into
langfuse:mainfrom
geoff-ux:per-session-user
Closed

geoff-ux wants to merge 1 commit into
langfuse:mainfrom
geoff-ux:per-session-user

Conversation

@geoff-ux

@geoff-ux geoff-ux commented Oct 1, 2026

Copy link
Copy Markdown

What

A session's Langfuse user can now come from the session itself. When an OpenCode session's metadata.userId is a non-empty string, it is set as langfuse.user.id on every span of that session.

Idea and discussion: https://github.com/orgs/langfuse/discussions/18148

Why

LANGFUSE_USER_ID is applied to every span the process exports. Under opencode serve, one process hosts sessions for several people, so every trace is filed under one user, or under none.

Behaviour

  • Precedence: the session's user outranks the process-wide user. Sessions without metadata.userId keep using LANGFUSE_USER_ID, so existing setups are unchanged and there is no new configuration.
  • Child agent sessions inherit their parent's user, since their spans join the parent's trace. OpenCode 1 creates them without the parent's metadata.
  • Invalid values (anything but a non-empty string) are ignored.
  • Sessions the plugin has not seen an event for, such as one continued after OpenCode restarts, are read from OpenCode once before their first span starts. If that read fails, the turn is traced with the process-wide user, a warning is logged, and the read is repeated on the session's next turn.
  • Cleanup: the user is kept across turns and dropped when the session is deleted.

How

  • src/langfuse.ts: a span processor, registered after the process-wide one, sets langfuse.user.id from the span's session, walking up to parent sessions. The trace state keeps one entry per known session.
  • src/v1.ts, src/v2.ts: remember the user from session events, and read a session not yet seen before tracing its first span.
  • src/schema.ts: the pinned @opencode-ai/plugin Session type omits metadata, which OpenCode includes in its session events, so it is decoded with a small schema.
  • README.md: a "Per-Session User" section.

Testing

  • pnpm run format:check, build, lint, knip and test:integration pass (49 tests, 14 of them new).
  • Checked by hand against a real opencode serve 1.18.32 with two sessions created with different metadata.userId: every exported span carried its own session's user.
  • Not checked against a real OpenCode 2 server. That path is covered by the integration tests only.

Notes for review

馃 Generated with Claude Code

LANGFUSE_USER_ID attributes every trace of an OpenCode process to one
user, which is wrong when a single `opencode serve` hosts sessions for
several people.

Read `userId` from the session metadata. A non-empty string is set as
`langfuse.user.id` on every span of that session and takes precedence
over the process-wide user, which still applies to sessions without it.
Child agent sessions inherit their parent's user.

The metadata comes from OpenCode's session events. A session the plugin
has not seen an event for, such as one continued after a restart, is read
from OpenCode before its first span starts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@geoff-ux
geoff-ux marked this pull request as draft October 1, 2026 23:32
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@geoff-ux

geoff-ux commented Oct 2, 2026

Copy link
Copy Markdown
Author

Closing this for now. Our own review found that the patch reads the session from OpenCode inside hooks that OpenCode waits on, which is not something telemetry should do, and we'd rather rework it than ask for your time on this version. The request itself stands in https://github.com/orgs/langfuse/discussions/18148.

@geoff-ux geoff-ux closed this Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants