Skip to main content
bryel is agent-first. Three units structure everything you see.

Trace

One agent run (turn) — the root span plus all its model steps and tool calls.

Interaction

The turn itself — one user → agent exchange, summarized.

Session

A conversation — multiple turns grouped by sessionId.

Grouping keys

These telemetry keys connect runs into conversations and tie feedback back to a turn.
KeySet viaPurpose
sessionIdtelemetry metadata.sessionIdGroups turns into a conversation.
userIdtelemetry metadata.userIdThe end-user behind the run.
messageIdtelemetry metadata.messageIdA per-turn handle, stamped as bryel.interaction.id so feedback joins to the turn.

Span kinds

Every span carries an OpenInference span kind (openinference.span.kind) so bryel knows what it is. The adapters set this for you; a custom SpanMapper sets it from OpenInferenceSpanKind.
KindWhat it represents
LLMA model generation — generateText / streamText / a provider request.
TOOLA tool or function call inside a run.
CHAINA composite step that wraps other spans, such as an agent loop.
AGENTAn agent run.
RETRIEVER · EMBEDDING · RERANKERRetrieval-augmented steps.
GUARDRAIL · EVALUATORSafety checks and scoring steps.

Tokens and cost

Token counts live on the leaf model spans (the actual provider request); the outer operation span repeats them as a roll-up. bryel sums tokens and cost over the whole trace and prices them at ingest, so you see cost per turn, per session, and per project. Pricing is recorded as bryel.cost.usd with a bryel.cost.status (provider_reported, priced, unknown_model, or no_tokens), so you always know whether a number is exact, estimated, or unavailable.
Span kinds and the bryel.* attributes are defined in @bryel/semconv.