Skip to main content
Every event accepts the same metadata object, whether it comes from an SDK wrapper, a wrapped tool, or manual capture:
type CarbonMetadata = {
  traceId?: string;
  context?: {
    threadId?: string;
    agentId?: string;
    agentGroupId?: string;
    userId?: string;
  };
  additionalProperties?: Record<string, string | number>;
};

Traces

A trace groups the events of one logical operation — an agent run, a request, a job. Create a trace ID once and pass it to every call that belongs together:
const traceId = carbon.createTraceId();

const plan = await openai.chat.completions.create({
  model: "gpt-5.4-nano",
  messages: [{ role: "user", content: "Plan the trip." }],
  carbon: { traceId },
});

const booking = await bookFlight({ destination: "Tokyo" }, { traceId });
createTraceId returns a UUID and stores no state — the SDK never infers trace membership, so correlation is always explicit.
Wrappers that run multi-step loops (Vercel AI SDK tools, OpenAI runTools) put every step of a call on the same trace automatically. Pass your own traceId when a trace spans multiple top-level calls.

Context

Context fields are the identifiers the dashboard aggregates by. All are optional strings with meaning defined by your application:
FieldWhat it identifiesPowers
userIdThe end user behind the callUsers analytics
agentIdThe agent instance or roleAgents analytics
agentGroupIdA group of related agentsAgent group filters
threadIdA conversation or sessionThreads analytics
carbon: {
  context: {
    userId: "user-481",
    agentId: "support-agent",
    threadId: "thread-92",
  },
}
Set the fields that match your product’s shape — a chat product benefits from threadId and userId; a multi-agent system from agentId and agentGroupId.

Custom properties

additionalProperties holds your own dimensions as string or number values — release tags, environment names, experiment arms:
carbon: {
  additionalProperties: {
    release: "2026-06",
    experiment: "prompt-v2",
    region: "eu-west-1",
  },
}

Where metadata goes

Pass a carbon field in the call arguments. The wrapper strips it before the request reaches the provider.
await openai.chat.completions.create({
  model: "gpt-5.4-nano",
  messages,
  carbon: { traceId, context: { userId: "user-481" } },
});