Sometimes you have some context prior to running a function and you want to tag it at
creation time. For example, you may want to tag a span with the model provider
endpoint that you use, or the test dataset that you used to run the request.
Note that tags are not the same as metadata. Metadata is additional information about a trace
in a form of key-value pairs. Tags are used to categorize and filter spans, and they must
be created in the Laminar UI in advance. See metadata for a more detailed
comparison.
Note that for adding span tags to work, you must call it inside
a span context. This is why we use observe here.
Copy
import { Laminar, observe } from '@lmnr-ai/lmnr';async function foo(message: string) { if (message.length > 100) { // ✅ Correct usage. We are inside an `observe`d function, Laminar.addSpanTags(["long_input"]); }}// ❌ Incorrect usage. We are not inside any span context. This will not work.// Laminar.addSpanTags(["my_tag", "another_tag"])await observe( { name: "foo", }, foo, "a".repeat(200))
Copy
import { Laminar, observe } from '@lmnr-ai/lmnr';async function foo(message: string) { if (message.length > 100) { // ✅ Correct usage. We are inside an `observe`d function, Laminar.addSpanTags(["long_input"]); }}// ❌ Incorrect usage. We are not inside any span context. This will not work.// Laminar.addSpanTags(["my_tag", "another_tag"])await observe( { name: "foo", }, foo, "a".repeat(200))
Copy
from lmnr import Laminar, observe@observe()def foo(user_input: str): if len(user_input) > 100: # ✅ Correct usage. We are inside an `observe`d function, Laminar.add_span_tags(["long_input"])# ❌ Incorrect usage. We are not inside any span context. This will not work.# Laminar.add_span_tags(["my_tag", "another_tag"])foo("a" * 200)
You can also add tags to a span in the Laminar SDK. You will need to save
the trace ID and then add tags to the root span of that trace using
LaminarClient.tags.tag.
Copy
import { Laminar, LaminarClient, observe } from '@lmnr-ai/lmnr';const laminarClient = new LaminarClient();// Take note of the traceId.const { traceId, responseText } = await observe( { name: "chat_completion", }, async (message: string) => { const response = await openaiClient.chat.completions.create({ model: "gpt-4.1-nano", messages: [{ role: "user", content: message }], }); const responseText = response.choices[0].message.content; return { // ✅ Correct usage. We are inside an `observe`d function, // so `getTraceId` returns a string UUID. traceId: Laminar.getTraceId(), responseText, } }, "Hello, world!")// Call this function later, when you get user feedback.const userFeedbackHandler = ( traceId: string, userFeedback: "good" | "bad") => laminarClient.tags.tag(traceId, userFeedback);
Make sure to call Laminar.getTraceId inside a span context, e.g.
inside an observed function. Otherwise, it will return null.
Copy
import { Laminar, LaminarClient, observe } from '@lmnr-ai/lmnr';const laminarClient = new LaminarClient();// Take note of the traceId.const { traceId, responseText } = await observe( { name: "chat_completion", }, async (message: string) => { const response = await openaiClient.chat.completions.create({ model: "gpt-4.1-nano", messages: [{ role: "user", content: message }], }); const responseText = response.choices[0].message.content; return { // ✅ Correct usage. We are inside an `observe`d function, // so `getTraceId` returns a string UUID. traceId: Laminar.getTraceId(), responseText, } }, "Hello, world!")// Call this function later, when you get user feedback.const userFeedbackHandler = ( traceId: string, userFeedback: "good" | "bad") => laminarClient.tags.tag(traceId, userFeedback);
Make sure to call Laminar.getTraceId inside a span context, e.g.
inside an observed function. Otherwise, it will return null.
Copy
from lmnr import Laminar, LaminarClient, observeimport uuidlaminar_client = LaminarClient()@observe()def chat_completion(user_input: str): response = openai_client.chat.completions.create( model="gpt-4.1-nano", messages=[{"role": "user", "content": user_input}] ) response = response.choices[0].message.content # ✅ Correct usage. We are inside an `observe`d function, # so `get_trace_id` returns a UUID. trace_id = Laminar.get_trace_id() return { "trace_id": trace_id, "response": response }# Take note of the trace_id.trace_id = response["trace_id"]response = response["response"]# Call this function later, when you get user feedback.def user_feedback_handler( trace_id: uuid.UUID, user_feedback: Literal["good", "bad"]): laminar_client.tags.tag(trace_id, user_feedback)
Make sure to call Laminar.get_trace_id inside a span context, e.g.
inside an observed function. Otherwise, it will return None.