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.
Rules
- Check the AI SDK version first and pick the matching path (step 2):
wrap()fromfoglamp/wrapon AI SDK v4 to v6, orfog.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()coversgenerateText,streamText,generateObject,streamObject, and theToolLoopAgent/Experimental_Agentclasses. Wrap in place; do not rewrite agent classes intogenerateTextcalls 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, andtraceNamemust be written as literal strings in the source, never template literals, concatenation, or variables. Anything dynamic (a slug, URL, id, date) goes inmetadata,workflowRunId, orsessionIdinstead. See the mapping rules. - Instrument one real entry point first, verify a trace appears, then expand.
1. Install and configure
Installfoglamp 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 installedai 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.
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
traceNameoragentName(both is fine; the trace belongs to the agent and displays thetraceName). workflowNameandworkflowRunIdgo together; one without the other is an error. Calls sharing aworkflowRunIdare stitched into one run, so the id must be shared by every call in the run and unique per execution.
-
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
agentNametaken 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+workflowRunIdon every call in it, including calls made by nested agents. Usefog.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), sofog.run()is mainly for the entry point and for the v4 to v6wrappath. -
Find the threads. If the app has conversations (a chat, a support
thread), pass its id as
sessionIdon 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 withworkflowName+workflowRunIdand put longer-lived business ids (campaign, cycle, tenant) inmetadata. When in doubt, omitsessionId; it is optional. -
Don’t overload the names. High-cardinality values (user ids, slugs,
URLs, dates, ticket numbers) belong in
workflowRunId,sessionId, ormetadata, never inagentName,workflowName, ortraceName, 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:
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 (theVERCEL / 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
waitUntilfrom the runtime’s request context automatically (no@vercel/functionsdependency needed). - Cloudflare Workers / other serverless: pass
waitUntilin the config (foglamp({ waitUntil: ctx.waitUntil })), orawait 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: trueto the existingfoglamp({ ... })call. - Client: render
<FoglampHUD />fromfoglamp/hudonce near the root of the client app (for example the root layout).
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.
.png?fit=max&auto=format&n=1sml0kwCw1BNtiz-&q=85&s=a7c846a133aa3480dc1e03a2da5fec2b)
.png?fit=max&auto=format&n=1sml0kwCw1BNtiz-&q=85&s=6534218552b79980770f11c40aafd6ec)