Skip to main content
This page is written for an AI coding agent (Claude Code, Cursor, and so on) asked to add Foglamp tracing to a codebase. If you’re a human, the Quickstart is friendlier.
You are instrumenting a Vercel AI SDK app so its runs appear in Foglamp. Foglamp captures model, tool, and step boundaries from the AI SDK and renders them as traces with cost, tokens, and latency. Make the smallest safe change that gets one real run flowing, then enrich.

Rules

  • Check the AI SDK version first and pick the matching path (step 2): wrap() from foglamp/wrap on AI SDK v4 to v6, or fog.integration(...) on v7. Both capture identical traces. Never upgrade the app’s AI SDK just to instrument it. Steps 3 to 5 apply to both paths.
  • Never refactor working AI code to instrument it. wrap() covers generateText, streamText, generateObject, streamObject, and the ToolLoopAgent / Experimental_Agent classes. Wrap in place; do not rewrite agent classes into generateText calls or restructure pipelines.
  • Prefer the installed package’s types and README over memory. Don’t invent SDK APIs or hand-wire ingest endpoints; only use foglamp’s public API below.
  • The SDK does nothing without FOGLAMP_API_KEY, so it’s safe to add in every environment. Nothing throws and no spans are sent until the key is set.
  • Names are static string literals. agentName, workflowName, and traceName must be written as literal strings in the source, never template literals, concatenation, or variables. Anything dynamic (a slug, URL, id, date) goes in metadata, workflowRunId, or sessionId instead. See the mapping rules.
  • Instrument one real entry point first, verify a trace appears, then expand.

1. Install and configure

Install foglamp with the repo’s own package manager (check the lockfile; don’t introduce a second one):
.env

2. Wire up Foglamp for the installed version

Check the installed ai version first (read the lockfile or package.json), then follow the matching path. Every traced call needs a traceName or an agentName.

AI SDK v4, v5, or v6: wrap()

Wrap the ai module once, then bind a context with fog.with(...). The returned functions keep the AI SDK’s own, fully typed signatures. wrap() also covers generateObject, streamObject, and the agent classes; instrument them in place.
See AI SDK v4 to v6 (wrap) for fog.run(...) (ambient context) and the per-call foglamp: {...} option.

AI SDK v7: fog.integration()

Attach the integration to each generateText / streamText call via the telemetry option.

3. Map the codebase to Foglamp’s model

This is the step that makes the dashboard useful, so spend real effort here: read the codebase and decide what its agents, workflows, and sessions actually are before writing any context. The full context surface: Rules the SDK enforces, at the type level and at ingest:
  • Every call needs traceName or agentName (both is fine; the trace belongs to the agent and displays the traceName).
  • workflowName and workflowRunId go together; one without the other is an error. Calls sharing a workflowRunId are stitched into one run, so the id must be shared by every call in the run and unique per execution.
How to decide, concretely:
  • Find the agents. A class, module, or function that owns a system prompt and is invoked from more than one place is an agent: give it an agentName taken from what the code calls it.
  • Find the pipelines. A request handler or job that makes several model calls (or calls several agents) before producing its result is a workflow: put the same workflowName + workflowRunId on every call in it, including calls made by nested agents. Use fog.run(context, fn) at the handler or job entry point. It sets the context for everything inside, however deeply nested, so you don’t pass a trace parameter through every function signature:
    On AI SDK v7, calls a tool makes back into the model inherit the parent call’s workflow and session context automatically (see the SDK overview), so fog.run() is mainly for the entry point and for the v4 to v6 wrap path.
  • Find the threads. If the app has conversations (a chat, a support thread), pass its id as sessionId on every call serving that thread. A session is a conversation where a user goes back and forth. If no human is conversing, there is no session: a batch run, cron job, pipeline execution, billing period, or engagement cycle is not a session, even though its id would technically group traces. Group executions with workflowName + workflowRunId and put longer-lived business ids (campaign, cycle, tenant) in metadata. When in doubt, omit sessionId; it is optional.
  • Don’t overload the names. High-cardinality values (user ids, slugs, URLs, dates, ticket numbers) belong in workflowRunId, sessionId, or metadata, never in agentName, workflowName, or traceName, which should each have a small, stable set of values. The mechanical check: every name must be a string literal at the call site. If you catch yourself writing a template literal or passing a variable, the dynamic part is metadata:
The context fields are identical on both paths. On v4 to v6 the same object goes into fog.with({...}), a per-call foglamp: {...} key, or fog.run({...}, fn) for run-scoped context; see wrap.

4. Flush in serverless

Long-running servers (Node, Bun) flush on a timer automatically. Serverless is detected automatically (the VERCEL / AWS_LAMBDA_FUNCTION_NAME env vars) and switches to per-call flushing, so check what the deployment target needs before adding flush plumbing:
  • Vercel: nothing to do. Foglamp reads waitUntil from the runtime’s request context automatically (no @vercel/functions dependency needed).
  • Cloudflare Workers / other serverless: pass waitUntil in the config (foglamp({ waitUntil: ctx.waitUntil })), or await fog.flush() before each handler returns.

5. Optional: live HUD (dev only)

If the app has a React UI and a local dev server, offer to wire up the live HUD: a dev-only floating overlay that streams runs (steps, tool calls, tokens, cost) on top of the app as the user develops. It needs no API key and does nothing in production or on edge/serverless, so it’s safe to leave in. Two lines:
  • Server: pass hud: true to the existing foglamp({ ... }) call.
  • Client: render <FoglampHUD /> from foglamp/hud once near the root of the client app (for example the root layout).
The route or handler that creates foglamp({ hud: true }) must run on the Node runtime, not edge. Skip this step entirely if there’s no React frontend. Full reference: Live HUD.

6. Hand off

A trace only exists once a real model call runs, and that’s the user’s job, not yours. Do not write smoke tests, test scripts, demo endpoints, or synthetic “first trace” calls; they add code the user has to delete and burn real model tokens. Once the build and typecheck pass, finish by telling the user exactly how to trigger their own instrumented flows: which command to run, which page to hit, which job to kick off. Then they can run the app and watch the first traces appear in the dashboard (Overview / Traces), and stream live in the HUD if they enabled it. See the SDK reference and data model for every option.