Skip to main content

HTTP tracing SDK for Lemma

Project description

uselemma-tracing

HTTP tracing SDK for AI agents. The primary API sends trace payloads directly to Lemma over HTTP.

Installation

pip install uselemma-tracing

Quick Start

from uselemma_tracing import Lemma

lemma = Lemma()

def run(trace):
    docs = search_docs(user_message)
    trace.record_tool(
        name="search_docs",
        input={"query": user_message},
        output=docs,
        tool_parameters={"query": "string"},
    )

    response = call_model(user_message, docs)
    trace.record_generation(
        name="draft-reply",
        input=response.messages,
        output=response.text,
        model="gpt-4o",
        llm_input_messages=[{"role": "user", "content": user_message}],
        llm_invocation_parameters={"temperature": 0.2},
    )

    return response.text

answer = lemma.trace(
    "support-agent",
    run,
    input=user_message,
    thread_id=conversation_id,
    user_id=user.id,
)

lemma.trace() measures the trace from callback start to completion. Use async_trace() for async callbacks.

Live Spans

def run(trace):
    span = trace.start_span(name="retrieve-context", input=query)
    try:
        docs = retrieve(query)
        span.end(output={"count": len(docs)})
        return docs
    except Exception as error:
        span.end(status="ERROR", error=error)
        raise

Live handles know their start time when created and their end time when .end() is called, so you usually do not pass duration_ms. Pass duration_ms only when replaying historical work or overriding the measured duration with a value from another timer.

For one-off records where you already measured the work, pass duration_ms on the record call:

trace.record_generation(
    name="answer",
    output=text,
    model="gpt-4o",
    duration_ms=measured_model_ms,
)

The same handle pattern is available for tool calls and generations:

tool = trace.start_tool(name="search_docs", input={"query": query})
docs = search_docs(query)
tool.end(output=docs)

generation = trace.start_generation(name="answer", input=messages)
response = call_model(messages)
generation.end(output=response.text)

Sending a Trace You Built Yourself

trace() assumes the client owns the trace lifecycle within a single process. When the producer lives elsewhere — a cross-process buffer, a queue worker, a batch backfill — build a TraceContext yourself and deliver it with ingest():

from uselemma_tracing import Lemma, TraceContext

lemma = Lemma()

context = TraceContext(
    id=turn_id,  # stable id ties batches to one trace
    name=prompt,
    input=prompt,
    thread_id=conversation_id,
)
context.record_tool(name="search_docs", input=query, output=docs, duration_ms=25)
context.record_generation(name="answer", model="gpt-4o", output=final_answer)
context.output(final_answer)

lemma.ingest(context, started_at=started_at)

ingest() is a single POST. Spans merge into the trace by id when replace is False (the default), so you can send a trace incrementally across several calls under one stable id and let the server reconcile them; pass replace=True to overwrite the trace wholesale. It raises on a non-2xx response and never mutates the trace's status, so a failed send can be retried as-is without fabricating an error.

OpenAI Agents SDK

Install the OpenAI Agents extra and register the Lemma processor:

pip install "uselemma-tracing[openai-agents]" openai-agents
from agents import Agent, Runner
from uselemma_tracing import instrument_openai_agents

instrument_openai_agents()

agent = Agent(
    name="support-agent",
    instructions="Answer customer questions clearly and concisely.",
)

async def call_agent(user_message: str):
    result = await Runner.run(agent, user_message)
    return result.final_output

The processor creates one Lemma trace for each OpenAI Agents trace. Generation spans become Lemma generations, function spans become Lemma tool spans, and parent IDs are preserved so tools stay nested under the generation or agent span that called them.

Enable debug mode to validate live span shape while developing:

from uselemma_tracing import enable_debug_mode

enable_debug_mode()

Use openai_agents(record_inputs=False, record_outputs=False) when you need a processor that avoids sending prompts, tool inputs, tool outputs, and generated text.

LangChain and LangGraph

Install the optional integration dependency and pass langchain() as a callback handler:

pip install "uselemma-tracing[langchain]" langchain-openai
from langchain_openai import ChatOpenAI
from uselemma_tracing import langchain

model = ChatOpenAI(
    model="gpt-4o",
    callbacks=[langchain(agent_name="support-agent")],
)

response = model.invoke(user_message)

LangGraph uses LangChain callbacks too:

pip install "uselemma-tracing[langgraph]"
from uselemma_tracing import langgraph

result = graph.invoke(
    {"input": user_message},
    {"callbacks": [langgraph(agent_name="support-graph")]},
)

The handler creates one Lemma trace for the root chain/graph run, records LLM calls as generations, tools as tool spans, retrievers as spans, and nested chains or graph nodes as child spans.

Use langchain(record_inputs=False, record_outputs=False) or langgraph(record_inputs=False, record_outputs=False) to avoid sending prompts, tool inputs, tool outputs, or generated text.

Supported Contract Fields

Use native SDK keyword arguments for OpenInference-style fields:

  • LLM: llm_model_name, llm_provider, llm_system, llm_invocation_parameters, llm_input_messages, llm_output_messages, llm_tools, token counts, and prompt template fields
  • tools: tool_description, tool_parameters
  • embeddings and rerankers: embedding_model_name, embedding_invocation_parameters, embedding_embeddings, reranker_model_name, reranker_input_documents, reranker_output_documents

Use attributes for raw attributes that do not yet have a native SDK keyword.

Configuration

Option Environment variable Default
api_key LEMMA_API_KEY Required
project_id LEMMA_PROJECT_ID Required
base_url none https://api.uselemma.ai

The SDK sends to {base_url}/traces/ingest.

You can pass configuration directly to the constructor instead of using environment variables:

lemma = Lemma(
    api_key="sk_...",
    project_id="proj_...",
    base_url="https://api.uselemma.ai",
)

Debug Mode

Debug mode logs trace starts, span starts, span completions, send attempts, and send results as they happen:

from uselemma_tracing import enable_debug_mode

enable_debug_mode()

You can also set LEMMA_DEBUG=true. Use this when validating that spans are created in the expected order and the SDK is sending to the intended URL.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uselemma_tracing-7.3.0.tar.gz (15.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

uselemma_tracing-7.3.0-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file uselemma_tracing-7.3.0.tar.gz.

File metadata

  • Download URL: uselemma_tracing-7.3.0.tar.gz
  • Upload date:
  • Size: 15.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for uselemma_tracing-7.3.0.tar.gz
Algorithm Hash digest
SHA256 7aa840acb6ecf365e50c9cb119d0ed625eeb8476fb1bbdd74586ca298503bcfe
MD5 669dbb5609e8bfa93627f8eda0dfce5b
BLAKE2b-256 b98df2a5dea7cdcbe9ab8ca45c32b48015cd7a931f59a96b620c1b28d289618a

See more details on using hashes here.

File details

Details for the file uselemma_tracing-7.3.0-py3-none-any.whl.

File metadata

  • Download URL: uselemma_tracing-7.3.0-py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for uselemma_tracing-7.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 baa894b3e614907a89733019839f8b21f84d960a4f3497b9d82eefb738441110
MD5 e0ba1bac18bab98e0308d225791c8a65
BLAKE2b-256 47e41a4925f4e80e6be66064d715466516838e050f58be5061d81279a4487853

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page