Skip to main content
wrapAgent wraps your agent function with OpenTelemetry tracing, creating a top-level span that captures the full execution — timing, errors, 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 signal the run is done, 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
optionsobjectOptional configuration (see below)
Options
FieldTypeDefaultDescription
isExperimentbooleanfalseTag this run as an experiment
autoEndRootbooleantrueIf true (the default), the top-level span is automatically ended when the wrapped function returns or throws. Set to false to manage the span lifetime manually via onComplete.
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)Signals the run is complete. When autoEndRoot is true (the default), this is a no-op — the span ends automatically when the function returns. When autoEndRoot is false, this ends the root span and returns true.
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
By default (autoEndRoot: true), the root span ends automatically when the wrapped function returns or throws — no manual onComplete call needed. Set autoEndRoot: false to manage span lifetime yourself via onComplete.

Next Steps