Skip to main content
wrapAgent wraps your agent function with OpenTelemetry tracing, creating a top-level span that captures the full execution — inputs, outputs, timing, and any nested operations that happen inside it.

Basic Usage

import { wrapAgent } from "@uselemma/tracing";

export const callAgent = async (userMessage: string) => {
  const wrappedFn = wrapAgent(
    "my-agent",
    async ({ onComplete }, input) => {
      const result = await doWork(input.userMessage);
      onComplete(result);
      return result;
    }
  );

  const { result, runId } = await wrappedFn({ userMessage });
  return { result, runId };
};

Streaming

For streaming responses, set autoEndRoot: true so the RunBatchSpanProcessor automatically ends the root span when all direct child spans have finished. Call onComplete to record the output once the stream finishes, and recordError if something goes wrong.
import { wrapAgent } from "@uselemma/tracing";

export const callAgent = async (userMessage: string) => {
  const wrappedFn = wrapAgent(
    "my-agent",
    async ({ onComplete, recordError }, input) => {
      try {
        const stream = await streamResponse(input.userMessage);
        let fullResponse = "";

        for await (const chunk of stream) {
          fullResponse += chunk;
          // stream to your client here
        }

        onComplete({ text: fullResponse });
        return { text: fullResponse };
      } catch (error) {
        recordError(error);
        throw error;
      }
    },
    { autoEndRoot: true }
  );

  const { result, runId } = await wrappedFn({ userMessage });
  return { result, runId };
};

API Reference

Parameters

wrapAgent(name, agentFn, options?)
ParameterTypeDescription
namestringAgent identifier for filtering and grouping in the dashboard
agentFn(ctx: TraceContext, input: Input) => anyYour agent logic. Receives the call-time input as its second argument, which is recorded as the trace input
optionsobjectOptional configuration (see below)
Options
FieldTypeDefaultDescription
isExperimentbooleanfalseTag this run as an experiment
autoEndRootbooleanfalseIf true, the RunBatchSpanProcessor automatically ends the root span when all direct child spans have ended. Useful for streaming where child spans outlive the wrapped function.
Return Value
FieldTypeDescription
resultanyYour agent function’s return value
runIdstringUnique identifier for this trace
spanSpanThe underlying OpenTelemetry span

TraceContext

Your agent function always receives a TraceContext object as its first argument:
FieldDescription
onComplete(result) / on_complete(result)Records the agent’s output on the span. When autoEndRoot is false (the default), this also ends the root span and returns true. When autoEndRoot is true, this only records the output and returns false — the span is ended automatically by the processor when all direct children finish.
recordError(error) / record_error(error)Records the exception and marks the span as errored
spanThe underlying OpenTelemetry span for custom attributes or child spans
runId / run_idThe unique run identifier
When autoEndRoot is false (the default), you must call onComplete(result) to record the output and end the root span. When autoEndRoot is true, onComplete(result) only records the output — the RunBatchSpanProcessor ends the root span automatically once all direct child spans have ended.