Skip to content

feat(examples): zero-install Langfuse replay + a demo memory worth searching - #374

Merged
dani1005 merged 2 commits into
mainfrom
feat/langfuse-trace-replay
Jul 29, 2026
Merged

feat(examples): zero-install Langfuse replay + a demo memory worth searching#374
dani1005 merged 2 commits into
mainfrom
feat/langfuse-trace-replay

Conversation

@dani1005

Copy link
Copy Markdown
Collaborator

Why

Native OTel moved span emission into the server, which cost the Langfuse example its try-before-install path: since 1.2.0, seeing anything at all requires a configured EverOS with an LLM behind it. The live cookbook page still tells readers to copy everos_langfuse.py, a file that no longer exists.

This restores a zero-install path without fabricating anything, and makes the demo produce traces that show behaviour rather than plumbing.

replay.py — no EverOS, no model keys

Pushes a recording of a real EverOS run into the reader's own Langfuse project. Span names, attributes, token usage, parent/child structure and durations are replayed verbatim; only three things are rewritten, and the README says so: ids are minted fresh, timestamps shift to now, and root spans carry a replay tag.

Two failure modes found while testing against real Langfuse, both fixed here:

  • the scores API rate-limits, and posting 47 scores in a tight loop lost 18 of them to 429. Now retries with backoff, honouring Retry-After, and paces sends. 47/47 land.
  • Langfuse keys are region-scoped, and a wrong LANGFUSE_HOST fails silently: the OTLP exporter only complains through SDK logging, so the script printed success into an empty project. A pre-flight credential check now names the other region. It only treats 401/403 as fatal, so it cannot become a host-validity gate.

record_trace.py — how the recording was made

Stands in for Langfuse's OTLP and scores endpoints on localhost. This works because EverOS derives both from langfuse_host, so one sink captures both signals straight from a real server run. Nothing in the fixture is synthesized.

demo.py — a memory worth searching

It used to ingest one conversation and search it, so recall had nothing to choose between.

Eleven short conversations now span ten weeks, each on its own topic. Two revisit the same subject five days apart, close enough for geometry clustering to group them, which finally gives reflection something to consolidate: the demo nudges reflect_episodes (a 0 2 * * 1 cron otherwise), waits for the merge to land, and the superseded memory is gone from search before the questions are asked. One question asks about something never discussed.

Recall on the resulting store, from the recorded run:

question HYBRID AGENTIC
the October trip and its revision 0.763 0.987
what the vet said about the cat 0.753 0.980
why the sourdough kept coming out flat 0.813 0.976
which foods to leave out of meal planning 0.743 0.906
something never discussed 0.168 0.004

Two sequencing bugs had to be fixed to get there, and both would bite anyone driving EverOS from a script:

  • a fixed sleep after flush searched a half-built index. Readiness is now polled per session. Polling is deliberately slack, because every probe is itself a traced search and a tight loop buried the real questions under readiness checks.
  • /ome/trigger returns once the OME engine is idle, but the merge reaches LanceDB through the cascade, and deprecating the old episodes is a separate write from indexing the merged one. Querying in between saw neither and scored 0.55 where the memory deserved 0.76. The demo now waits for both edges.

KEYWORD is no longer a demonstrated method: its top score is raw BM25, on a different scale from the calibrated ones, so showing the three side by side invited a comparison that means nothing. It still runs as the readiness probe.

The recording

recorded_trace.json, one demo.py run against 1.2.1: 237 spans over 60 traces, zero error spans, no secrets, no absolute paths, synthetic content throughout. Includes everos.reflect.consolidate under everos.ome.reflect_episodes.

Agent cases and skills are deliberately absent. Exercising them needs a tool-call trajectory, and that path has open issues (agent-case extraction requires >= 3 tool-call rounds; AGENTIC search over agent-owned memory 500s; the case-to-skill chain races the LanceDB sync). The span and score contract is identical when they appear, so a later re-record is a fixture swap.

Verification

Replayed into real Langfuse (60 traces, 47 scores, $0.07 of cost computed by Langfuse from our token attributes) and round-tripped through the recorder offline, asserting span count, name multiset, isomorphic parent/child edges, preserved durations and token usage, fresh non-colliding ids, every score remapped onto a replayed span, and the replay tag on roots only.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UyKinsWs1MgoARPoB9R4NW

dani1005 and others added 2 commits July 29, 2026 15:56
Native OTel moved span emission into the server, so the Langfuse example
lost its try-before-install path: seeing anything now required a
configured EverOS. Restore one without fabricating spans.

replay.py pushes a recording of a real EverOS run into the reader's own
Langfuse project. Names, attributes, token usage, structure and durations
are replayed verbatim; only ids, timestamps and a `replay` tag are
rewritten, so nothing in the trace is invented. It needs the OTel SDK and
Langfuse keys, nothing else.

record_trace.py is the maintainer tool that produced the recording. It
stands in for Langfuse's OTLP and scores endpoints on localhost, which
works because EverOS derives both from langfuse_host, so one sink captures
both signals straight from a real server run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UyKinsWs1MgoARPoB9R4NW
The demo ingested one conversation and searched it, so recall had nothing to
choose between and the traces showed plumbing rather than behaviour.

Eleven short conversations now span ten weeks, each on its own topic, so a
question has to find the right memory in a populated store. Two revisit the
same subject five days apart, close enough for geometry clustering to group
them, which finally gives reflection something to consolidate: the demo nudges
reflect_episodes (a `0 2 * * 1` cron otherwise), waits for the merge to land,
and the superseded memory is gone from search by the time the questions are
asked. One question asks about something never discussed, so a miss looks like
a miss.

KEYWORD is no longer a demonstrated method. Its top score is raw BM25, on a
different scale from the calibrated ones, so showing the three side by side
invited a comparison that means nothing.

Readiness is polled per session rather than slept through, since a fixed sleep
searched a half-built index and reported scores lower than the memory deserved.
Polling is deliberately slack: every probe is itself a traced search, and a
tight loop buried the real questions under a wall of readiness checks.

recorded_trace.json is that run against 1.2.1: 237 spans over 60 traces, no
errors, no secrets, synthetic content throughout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UyKinsWs1MgoARPoB9R4NW
@dani1005
dani1005 merged commit e723a4e into main Jul 29, 2026
8 of 9 checks passed
@dani1005
dani1005 deleted the feat/langfuse-trace-replay branch July 29, 2026 23:25
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