ADR-0024: Langfuse sessions tagged with each other¶
Status: Accepted, amended by ADR-0026 and lattice ADR-0022
Date: 2026-10-12
Deciders: Alex Nodeland
Amends: ADR-0013: relayr's langfuse extra needs evalr
Context¶
In Langfuse, a thread is artifactr's session, and a causal chain is reflexr's (ADR-0004). D4 joins them with tags: a run that starts from a thread event is tagged thread:<id>, and a turn relayr starts is tagged chain:<correlation id> and rule:<name>. The Langfuse user of a run started from a bridged event is the event's author, not relayr's source. Each library takes a context entered around every turn or run, and offers its Langfuse attributes as turn_attributes(session) and run_attributes(reaction).
Decision¶
relayr.langfuse.bridged_runis a reflexrRunContext, given to the reactor in place oflangfuse_run. It propagates reflexr's run attributes, addsthread:<id>for each thread of the bridged events that made the rule fire, and sets the user to the person who acted in artifactr, when a person did.relayr.langfuse.bridged_turns(ledger)returns an artifactrTurnContext, given to theRunnerin place oflangfuse_turn. It propagates artifactr's turn attributes. For a turn that acts for a rule's actor, it addsrule:<name>, andchain:<correlation id>for the run behind the rule's message that the turn carries out.- The turn's chain is found the way the follower finds it (ADR-0021): by reading the thread back to the rule's last message, whose run the outbound adapter recorded before it sent it.
relayr.outbound.turn_causeis that one function, which both use. The turn's context is entered as the turn starts, before the follower has traced it, and before the turn'srun_startedis in the log, so it reads back from the head. That finds the right message nearly always. If the rule sends another message after the turn starts and before its context reads back, the read finds that one, and the turn is tagged with the chain of the run that sent it. - Both are behind the
langfuseextra, which installs the libraries' own[langfuse]extras, and so evalr. relayr namesevalr[langfuse]in it and takes evalr from the workspace, as the libraries do, so its wheel is built and installed with relayr's; ADR-0013's "relayr requires no extra that needs evalr" no longer holds. - LiteLLM's metadata doesn't carry the tags yet. The libraries' gateways build it from their own fields and fixed tags. lattice #86 asks them to take the propagated tags, which would need nothing from relayr.
Options considered¶
| Option | For | Against |
|---|---|---|
| Wrap the libraries' attributes (chosen) | Their sessions, users and metadata stay theirs; relayr adds only what joins them | The application gives relayr's contexts in place of the libraries' |
| One Langfuse session for a thread and its chains | One view | D4 ruled it out |
Consequences¶
- Easier: from a thread's session, Langfuse finds the chains it started by tag, and from a chain, the turns it started.
- Harder: the turn context reads the thread back once per turn that acts for a rule.