Skip to main content
agent() automatically captures ai.agent.input, ai.agent.output, and timing. To filter runs by user, session, or environment in the Lemma dashboard, attach custom attributes on the run span inside the wrapped function.

Setting attributes on the run span

Use ctx.span.setAttribute() / ctx.span.set_attribute() to set attributes at any point inside the wrapped function:
const myAgent = agent("support-agent", async (input, ctx) => {
  ctx.span.setAttribute("lemma.user_id", input.userId);
  ctx.span.setAttribute("lemma.session_id", input.sessionId);
  ctx.span.setAttribute("lemma.environment", "production");
  ctx.span.setAttribute("lemma.feature", "support_chat");

  return await handleRequest(input.message);
});

KeyDescription
lemma.user_idUnique identifier for the end user
lemma.session_idSession or conversation identifier
lemma.environmentDeployment environment, e.g. "production", "staging"
lemma.featureFeature area, e.g. "support_chat", "onboarding"
These keys are indexed by Lemma and available as filters in the dashboard. You can use any key — the lemma.* prefix is just a convention for attributes you intend to filter on.

Python context manager

In context manager mode, access the span through the yielded run object:
async with agent("support-agent", input=input_data) as run:
    run.span.set_attribute("lemma.user_id", input_data["user_id"])
    run.span.set_attribute("lemma.environment", "production")
    result = await handle_request(input_data["message"])
    run.complete(result)

Attributes on child spans

Child spans (tool calls, LLM steps) can also carry custom attributes. Set them via the OTel span API directly inside the helper function:
const lookup = tool("lookup-order", async (orderId: string) => {
  const span = trace.getActiveSpan();
  span?.setAttribute("order.id", orderId);
  return db.orders.findById(orderId);
});

Next Steps