> ## Documentation Index
> Fetch the complete documentation index at: https://docs.foglamp.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Data model

> Traces, spans, workflows, runs, agents, sessions, and customers.

Foglamp's model maps directly onto how the Vercel AI SDK executes. Five
concepts cover everything you see in the dashboard.

## Trace

A **trace** is one top-level model call — a single `generateText`, `streamText`,
`generateObject`, or `streamObject` invocation. It carries the call's identity
(name, agent, workflow, run, session), free-form metadata, and a list of spans.

| Field           | Type    | Notes                                                                            |
| --------------- | ------- | -------------------------------------------------------------------------------- |
| `traceId`       | string  | 1–128 chars, unique per call                                                     |
| `traceName`     | string? | up to 256 chars — required if `agentName` is absent                              |
| `agentName`     | string? | up to 256 chars                                                                  |
| `workflowName`  | string? | up to 256 chars                                                                  |
| `workflowRunId` | string? | up to 128 chars — groups traces into one run                                     |
| `sessionId`     | string? | up to 128 chars                                                                  |
| `customer`      | object? | `{ id, name?, imageUrl? }` — the end-customer served (see [Customer](#customer)) |
| `metadata`      | map?    | string → string                                                                  |
| `spans`         | span\[] | 1–2000 spans                                                                     |

<Note>
  Two rules are enforced at compile time (SDK) and at ingest:

  * Every trace must set **`traceName` or `agentName`** (both is fine — see [Trace name](#trace-name)).
  * **`workflowName` and `workflowRunId` go together** — pass both or neither.
</Note>

## Span

A **span** is a unit of work inside a trace — a model step, a tool call, an
embedding, or anything else. Spans carry timing, status, model identity, token
usage, and optional input/output.

| Field                   | Type    | Notes                                        |
| ----------------------- | ------- | -------------------------------------------- |
| `spanId`                | string  | 1–128 chars                                  |
| `parentSpanId`          | string? | builds the waterfall                         |
| `spanType`              | enum    | `agent`, `llm`, `tool`, `embedding`, `other` |
| `name`                  | string  | up to 512 chars                              |
| `startTime` / `endTime` | int     | epoch milliseconds; `endTime ≥ startTime`    |
| `status`                | enum    | `ok` (default) or `error`                    |
| `errorMessage`          | string? | up to 8192 chars                             |
| `provider`              | string? | e.g. `openai`                                |
| `modelId`               | string? | e.g. `gpt-4o`                                |
| `usage`                 | object? | token dimensions, see below                  |
| `ttftMs`                | number? | time to first token (may be fractional)      |
| `input` / `output`      | string? | up to 1,000,000 chars each                   |
| `metadata`              | map?    | string → string                              |

### Usage

Every usage dimension is an optional non-negative integer. Each is priced
independently at ingest.

| Field                   | Meaning                         |
| ----------------------- | ------------------------------- |
| `inputTokens`           | prompt tokens                   |
| `outputTokens`          | completion tokens               |
| `totalTokens`           | total reported by the provider  |
| `reasoningTokens`       | reasoning/thinking tokens       |
| `cachedInputTokens`     | prompt tokens served from cache |
| `cacheWriteInputTokens` | tokens written to cache         |
| `imageCount`            | images generated                |
| `webSearchCount`        | web search calls                |
| `requestCount`          | provider requests               |

## Workflow & run

A **workflow** is a named, repeatable process (e.g. `deploy-digest`). A
**workflow run** is one execution of it, identified by `workflowRunId`. Every
trace sharing a `workflowRunId` belongs to the same run, and the dashboard
stitches them into a single timeline.

## Trace name

A **trace name** (`traceName`) is the call's human label. Use it for a one-off
call that isn't an agent — `fog.integration({ traceName: "classify-email" })` —
so it's identifiable and groupable in the dashboard instead of landing in an
unnamed bucket.

The effective label a trace displays as is `traceName ?? agentName`: if you set
only `agentName`, that's the label; if you set both, the call is attributed to
the agent and shows the `traceName`. Every trace must set one of the two.

## Agent

An **agent** is a named actor (`agentName`) responsible for a call. Agents give
you per-agent rollups — cost, latency, error rate — across every trace they
produced, independent of which workflow they ran in.

## Session

A **session** (`sessionId`) ties together traces that belong to one
conversation or user interaction, cutting across workflows and agents. Use it to
follow a single end-user thread end to end.

## Customer

A **customer** (`customer`) is the end-customer a call serves — the tenant or
user *your* app is acting on behalf of. It rolls cost up per customer (the
**Customers** card on the [Overview](/dashboard/overview)), so it's the building
block for usage-based pricing on top of Foglamp.

| Field      | Type    | Notes                                                                                                                                                        |
| ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`       | string  | **required** — 1–128 chars, the stable grouping key. Unlike names, this is a high-cardinality identifier (one per customer), so a dynamic id is correct here |
| `name`     | string? | up to 256 chars — display label; the latest value seen wins                                                                                                  |
| `imageUrl` | string? | up to 2048 chars — avatar URL; falls back to a generated icon                                                                                                |

`name` and `imageUrl` are display-only and may change over time (Foglamp keeps
the latest). Only `id` is denormalized onto spans for attribution; the name and
image live in a small dimension table. `customer` is optional and purely
additive — omitting it changes nothing.

## How it streams

```
generateText() ─────────────▶ trace
  ├─ step (model call) ──────▶ llm span   (tokens, cost, ttft)
  ├─ tool call ──────────────▶ tool span
  └─ step (model call) ──────▶ llm span
```

The SDK opens a span per step and tool execution, reads the SDK's own
performance metrics for TTFT, and closes the trace when the call ends.

<Note>
  **Embeddings aren't captured yet.** The wire contract reserves an `embedding`
  span type, but neither SDK path emits one today. Both paths instrument
  `generateText`, `streamText`, `generateObject`, and `streamObject` (plus the
  `ToolLoopAgent`/`Experimental_Agent` classes); `embed`/`embedMany` and `rerank`
  are not yet traced. Instrumenting an `embed` call today produces a trace with a
  root span but no token usage or cost. Embedding capture is planned — until
  then, treat the `embedding` span type as reserved.
</Note>
