> ## 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.

# SDK overview

> The foglamp() collector and its integration methods.

The `foglamp` package has **two entry points**, one per AI SDK generation. Both
batch spans and flush them to your ingest endpoint, and both share the same
trace-context fields, `fog.run()`, [configuration](/sdk/configuration), and
[flushing](/sdk/runtimes) — they differ only in how they attach to your calls.

<CardGroup cols={2}>
  <Card title="wrap() — AI SDK v4–v6" icon="package" href="/sdk/wrap">
    Wraps the `ai` module for the stable v4, v5, and v6 lines.
  </Card>

  <Card title="foglamp() — AI SDK v7" icon="bolt" href="#foglampconfig">
    The native telemetry-integrations collector. Documented below.
  </Card>
</CardGroup>

This page documents the v7 `foglamp()` collector; the v4–v6 `wrap()` API has its
own [reference](/sdk/wrap). `foglamp()` returns a **collector** that batches
spans and produces telemetry integrations you attach to AI SDK v7 calls.

```ts theme={null}
import { foglamp } from "foglamp";

const fog = foglamp();
```

<Note>
  Whichever entry point you use, the SDK carries a single small runtime
  dependency (`uuidv7`) and never forces a particular version of `zod` on your
  project — the wire types are a hand-written, zod-free mirror of the contract,
  so `ai` is the only required peer dependency
  (`ai@^4 || ^5 || ^6 || ^7.0.0-beta.1`).
</Note>

## `foglamp(config?)`

Creates a collector. All configuration is optional; sensible defaults apply and
missing credentials disable the collector silently. See
[Configuration](/sdk/configuration) for the full option table.

```ts theme={null}
const fog = foglamp({
  apiKey: process.env.FOGLAMP_API_KEY,
  endpoint: process.env.FOGLAMP_INGEST_URL,
  flushIntervalMs: 5000,
});
```

If `apiKey` is unset (and not in the environment), the collector is **disabled**:
integrations become no-ops, nothing is sent, and nothing is thrown.

## Collector methods

### `fog.integration(context)`

Returns a telemetry integration to pass into a call's
`telemetry.integrations` array (AI SDK v7 also accepts the legacy
`experimental_telemetry` alias). The context — a **required** argument —
labels every span the call produces; calling it without a `traceName` or
`agentName` throws immediately (at setup, not inside the call).

```ts theme={null}
fog.integration({
  agentName: "summarizer",
  workflowName: "deploy-digest",
  workflowRunId: run.id,
  sessionId: user.threadId,
  customer: { id: account.id, name: account.name, imageUrl: account.logoUrl },
  metadata: { environment: "production", region: "us-east-1" },
});

// A one-off call that isn't an agent — name it instead:
fog.integration({ traceName: "classify-email" });
```

| Context field   | Type                                               | Notes                                                                              |
| --------------- | -------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `traceName`     | string                                             | label for a one-off call; required if `agentName` is absent                        |
| `agentName`     | string                                             | the actor responsible for the call; required if `traceName` is absent              |
| `workflowName`  | string                                             | the named process; pass with `workflowRunId`                                       |
| `workflowRunId` | string                                             | groups traces into one run; pass with `workflowName`                               |
| `sessionId`     | string                                             | ties traces to one conversation                                                    |
| `customer`      | `{ id: string; name?: string; imageUrl?: string }` | the end-customer this call serves; powers per-customer cost. Only `id` is required |
| `metadata`      | `Record<string, string \| number \| boolean>`      | free-form labels; values are coerced to strings on the wire                        |

<Note>
  `traceName` **or** `agentName` is required (both is fine — the display label is
  `traceName ?? agentName`). `workflowName` and `workflowRunId` must be passed
  together. Both rules are enforced at compile time and rechecked at ingest.
</Note>

### `fog.flush()`

Sends any buffered spans immediately and resolves when the request completes.
Call this before a serverless function returns. Safe to call when the
collector is disabled (resolves immediately).

```ts theme={null}
await fog.flush();
```

### `fog.shutdown()`

Stops the flush timer and drains everything, including traces enqueued while a
flush was already in flight. Use on graceful process shutdown in long-running
servers.

```ts theme={null}
process.on("SIGTERM", async () => {
  await fog.shutdown();
});
```

<Note>
  **`flush()` vs `shutdown()`** — `flush()` is a per-request drain: the
  background timer keeps running and the collector stays usable. `shutdown()`
  is terminal: it stops the timer and loops until the queue is truly empty.
  Use `flush()` at the end of a serverless handler; use `shutdown()` exactly
  once when the process exits — calling only `flush()` there can strand traces
  enqueued mid-flush.
</Note>

## Registration paths

<CardGroup cols={2}>
  <Card title="Per-call" icon="crosshairs">
    Pass `fog.integration(...)` into a single call's telemetry. Fully typed, and
    wins over any global registration.
  </Card>

  <Card title="Global" icon="globe">
    `registerTelemetry(foglamp())` instruments every call. Reads `functionId`
    as `agentName` and reserved keys from `telemetry.metadata`.
  </Card>
</CardGroup>

## Nested calls inside tools

When a tool's `execute` function makes its own AI SDK call (a model call inside a
tool — e.g. a sub-agent), the v7 collector **automatically propagates the parent
call's grouping context** (`workflowName`, `workflowRunId`, `sessionId`,
`customer`, `metadata`) into that nested call. So the inner call lands in the
same workflow run as the outer one with no plumbing — you don't have to thread a
`fog.run()` through your tool bodies.

```ts theme={null}
const fog = foglamp();

await generateText({
  model,
  tools: { researchAgent },          // its execute() calls generateText again
  telemetry: {
    integrations: [
      fog.integration({
        agentName: "planner",
        workflowName: "deep-research",
        workflowRunId: run.id,        // ← the nested call inherits this…
      }),
    ],
  },
});
// …so the sub-agent's trace joins workflow run `run.id` automatically.
```

Only **grouping** context propagates — the inner call's **identity**
(`agentName` / `traceName`) is not inherited, so a nested call keeps its own
name. The nested call is still its own trace (a sibling in the run), not a child
span of the tool. A more specific inner `fog.run()` or `fog.integration()` still
wins. This is a v7-collector feature; on v4–v6 use [`fog.run()`](/sdk/wrap) to
share context across nested calls.

Next: tune batching and capture in [Configuration](/sdk/configuration), and make
sure spans actually leave serverless functions in
[Runtimes & flushing](/sdk/runtimes).
