Skip to content

Add Langfuse trace.userId / trace.sessionId population (0064)#171

Merged
chris-colinsky merged 4 commits into
mainfrom
feature/0064-langfuse-session-user-promotion
Jun 19, 2026
Merged

Add Langfuse trace.userId / trace.sessionId population (0064)#171
chris-colinsky merged 4 commits into
mainfrom
feature/0064-langfuse-session-user-promotion

Conversation

@chris-colinsky

Copy link
Copy Markdown
Member

Summary

Implements proposal 0064 (spec v0.62.0): the Langfuse observer populates Langfuse's two cross-trace grouping fields, trace.userId and trace.sessionId, from data OpenArmature already carries. Pins the spec submodule v0.61.0 -> v0.62.0.

What changed

  • trace.userId (live). The observer recognizes a userId key in the caller-supplied invocation metadata and promotes it to the first-class trace.userId field, automatically and additively (the key also remains at trace.metadata.userId). An absent key leaves trace.userId unset.
  • trace.sessionId (dormant). Sourced from openarmature.session_id, which the sessions capability (proposal 0020) establishes. python does not implement 0020 yet, so the plumbing is wired end to end but the observer passes None (unset) until 0020 lands. An unset trace.sessionId is the correct "not session-bound" behavior in the interim.
  • Plumbing. LangfuseClient.trace() (the Protocol, the in-memory client, and the SDK adapter) gains session_id / user_id. The observer centralizes the promotion through a _client_trace wrapper so all five trace-open sites (main, lazy, detached) apply it uniformly.
  • Manifest / docs / changelog / example. conformance.toml records 0064 partial (scoped to the session half); the observability concepts page documents the promotion; the langfuse-observability example demonstrates the userId promotion.

Design notes

The split is principled and matches the proposal: session_id is a first-class OA concept (it loads and persists session state) and earns its source from the sessions capability, whereas a user id has no runtime semantics in OA, so it is promoted observer-side from caller metadata rather than introduced as an engine surface. Langfuse-only: OpenTelemetry has no trace-level session/user field, and the OTel side already carries openarmature.session_id plus the openarmature.user.* family as span attributes.

conformance.toml is partial because trace.sessionId cannot be conformance-tested until python produces openarmature.session_id: fixture 084's session-bound cases (1, 5) defer per-case until 0020, while cases 2/3/4 (not session-bound, plus the userId promotion) run now.

Testing

  • Conformance fixture 084 cases 2/3/4; unit tests for the client plumbing and the promotion helper.
  • Validated live against Langfuse Cloud: both trace.userId and trace.sessionId populate the real Trace and the Users dashboard (the integration test asserts both via the REST API; the end-to-end cloud test demonstrates the observer promotion).
  • Full suite green (1331 passed); pyright and mkdocs clean.

Notes

  • The 0.15.0 changelog date is tentative pending the release tag.
  • Follow-on (tracked, after this lands): the Langfuse SDK has deprecated trace-level set_trace_io (the proposal 0043 trace.input / trace.output path) in favor of propagate_attributes; migrating that path is out of scope here (0064 already uses propagate_attributes for session/user).

Advance the spec submodule pin v0.61.0 -> v0.62.0 to absorb accepted
proposal 0064 (Langfuse trace.sessionId / trace.userId population).
Updates __spec_version__, the pyproject spec_version, the smoke-test
version assertion, and regenerates the bundled AGENTS.md.

conformance.toml records 0064 as partial: the trace.userId half ships,
while trace.sessionId is dormant until the sessions capability (0020)
supplies openarmature.session_id.
Implement proposal 0064's Langfuse Trace-level grouping fields. The
observer recognizes a userId key in the caller-supplied invocation
metadata and promotes it to the first-class trace.userId, additively
(the key also stays in trace.metadata.userId). trace.sessionId sources
from openarmature.session_id; python has no source until the sessions
capability (0020), so that half is plumbed but dormant (passes None).

LangfuseClient.trace() (the Protocol, the in-memory client, and the SDK
adapter) gains session_id / user_id; the observer centralizes the
promotion through a _client_trace wrapper so all five trace-open sites
apply it uniformly. Unit tests cover the client plumbing and the
promotion helper; the live integration test plus the extended
end-to-end cloud test assert both fields populate real Langfuse.
Activate observability fixture 084 (Langfuse session/user promotion):
cases 2/3/4 (not session-bound, userId present additively, userId
absent) run now; the session-bound cases 1/5 defer per-case until the
sessions capability (0020) supplies a session_id source.

Extend the fixture-parsing models for 084's shapes: ObservabilityExpected
gains langfuse_trace / langfuse_traces (and the matching discriminator
keys), and CaseSpec.invocations widens to int | list to carry case 5's
multi-invocation specs alongside the existing run-count usage.
Document the Langfuse trace.userId / trace.sessionId population in the
observability concepts page, add the 0.15.0 changelog entry (folding
0064 into the cycle's spec-pin bullet), and demonstrate the userId
promotion in the langfuse-observability example (a per-operator userId
that surfaces in the captured trace). sessionId is left out of the
example since it stays dormant until the sessions capability lands.
Copilot AI review requested due to automatic review settings June 19, 2026 19:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements spec proposal 0064 (spec v0.62.0) for Langfuse observability by populating Langfuse’s cross-trace grouping fields (trace.userId, trace.sessionId) from OpenArmature-carried data, and bumps the pinned spec version to v0.62.0.

Changes:

  • Add session_id / user_id plumbing to the Langfuse client protocol, in-memory client, and Langfuse SDK adapter; centralize trace creation in the observer to apply promotions uniformly.
  • Promote caller invocation metadata userId into Langfuse trace.userId (additive: remains in trace.metadata.userId); wire trace.sessionId end-to-end but leave observer source dormant (unset) pending sessions capability (0020).
  • Add/extend unit, conformance, and integration coverage for the new trace-level fields; update docs/examples/changelog and bump spec version markers.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/unit/test_observability_langfuse.py Adds unit tests for session/user id recording and userId promotion helper.
tests/unit/test_observability_langfuse_adapter.py Updates adapter cloud test invocation to include metadata={"userId": ...} and documents expected dashboard behavior.
tests/test_smoke.py Updates asserted __spec_version__ to 0.62.0.
tests/integration/test_langfuse_sdk_adapter.py Adds live Langfuse integration test asserting session_id / user_id land on the retrieved trace.
tests/conformance/test_observability.py Wires conformance fixture 084 runner and implements assertions for runnable cases (session-bound cases deferred).
tests/conformance/harness/fixtures.py Extends invocations typing to support list-shaped multi-invocation specs for fixture 084.
tests/conformance/harness/expectations.py Adds Langfuse trace-level expectation fields for fixture 084.
src/openarmature/observability/langfuse/observer.py Adds _promoted_user_id and routes all trace opens through _client_trace to set user_id and (currently) unset session_id.
src/openarmature/observability/langfuse/client.py Extends LangfuseTrace and LangfuseClient.trace() with session_id / user_id; stores them in the in-memory client.
src/openarmature/observability/langfuse/adapter.py Caches and propagates session_id / user_id via propagate_attributes for every observation under a trace.
src/openarmature/AGENTS.md Updates embedded spec version reference to v0.62.0.
src/openarmature/init.py Bumps __spec_version__ to 0.62.0.
pyproject.toml Bumps tool.openarmature.spec_version to 0.62.0.
examples/langfuse-observability/main.py Demonstrates passing metadata={"userId": ...} and prints promoted userId in captured trace output.
docs/concepts/observability.md Documents Langfuse trace.sessionId / trace.userId population behavior and current session-id dormancy.
conformance.toml Adds proposal 0064 status as partial with rationale and fixture coverage notes.
CHANGELOG.md Adds release-note entry for proposal 0064 and updates spec pin summary.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@chris-colinsky chris-colinsky merged commit 44cf643 into main Jun 19, 2026
7 checks passed
@chris-colinsky chris-colinsky deleted the feature/0064-langfuse-session-user-promotion branch June 19, 2026 19:17
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