lemma.trace() and record its LLM calls and tools as typed children.
One agent execution = one trace. In Raindrop you often emit one event per interaction and group by
convoId; in Lemma you emit one trace per execution and group multi-turn conversations by threadId. See the trace contract.How the two models differ
Raindrop starts from the event — a single tracked AI interaction created withtrackAi() (single-shot) or begin() / finish() (the interaction API) — and layers tracing spans, signals, and feedback onto it. Conversations are formed by sharing a convoId across events.
Lemma starts from the trace — one end-to-end execution — and requires its structure to be explicit:
- One root trace per agent execution carrying the current user input and the final output or error.
- Typed children — generations, tools, and generic spans, not undifferentiated records.
- Per-generation message history — the full ordered message list sent to each LLM call.
Concept mapping
The structural intuition transfers cleanly. What changes is that Lemma needs its children typed and its root complete.type is a discriminator. Setting a model on an untyped span does not make it a generation — you must set type: "generation". The SDK typed helpers (recordGeneration / recordTool / recordSpan and their Python equivalents) do this for you.metadata.
Migration path
1
Install the Lemma SDK
Install the SDK and set
LEMMA_API_KEY and LEMMA_PROJECT_ID. See Setup.- TypeScript
- Python
2
Wrap each execution in a trace
Replace the Raindrop
begin() / finish() (or trackAi()) that bracketed one interaction with a single lemma.trace() around the whole execution. Put the current user turn on input and let the callback return the final answer.3
Record generations and tools as typed children
Emit each LLM call with
recordGeneration / record_generation and each tool call with recordTool / record_tool. This is the Lemma equivalent of Raindrop’s auto-instrumented LLM spans, withTool, and trackTool.4
Add thread and user context
Map
convoId to threadId / thread_id and userId to userId / user_id on the trace so multi-turn conversations group correctly. See Threads & context.5
Confirm the shape
Turn on debug mode (
LEMMA_DEBUG=1) and check the sending trace log’s spanCount (span_count in Python) to confirm your generations and tools were recorded. Cross-check fields against the trace contract.Re-instrumenting an interaction
The example below is the Lemma equivalent of a Raindropbegin() → tool tracking → finish() flow: one trace, a typed tool, and a generation carrying the full message list. Install and configure the SDK first — see Setup.
- TypeScript
- Python
input and llmInputMessages / llm_input_messages. The root trace input is only the current user turn. For live handles that measure real duration, error recording, and nesting a tool under a measured parent span, see Generations and Tool calls.
If your run spans streaming callbacks or helpers rather than one function, use a TypeScript trace handle and end it from the terminal callback. See Traces.
Pitfalls
Related pages
Setup
Install the SDK and point it at Lemma.
Trace contract
The exact shape and fields Lemma reads.
Building high-quality traces
Bad → better → best examples for the ideal path.
Instrument an agent
Build a complete Lemma trace one piece at a time.