initialize() must run before your LLM SDK is imported (the rule is explained on Installation). In Next.js the only place that’s guaranteed is the instrumentation.ts hook at your project root (or src/instrumentation.ts if you use a src/ folder):
initialize() from inside a route file. Always pass instrumentModules in Next.js (only the SDKs you actually use): the bundler can load LLM SDKs in ways auto-instrumentation can’t see, which silently drops all LLM spans.
Keep LLM SDKs external
Keep the LLM SDKs external so every bundle shares one runtime copy. If they get inlined, each bundle has its own private copy andinstrumentModules patches one your routes never use. List belvedir itself as well: a route or server action that bundles its own copy calls withSession()/flush() on an uninitialized duplicate, so flush silently no-ops and spans drop on serverless.
experimental.serverComponentsExternalPackages; the Next 15 name is silently ignored there, and the build prints an Unrecognized key(s) warning you shouldn’t ignore.
Use the Node.js runtime
The SDK needs Node.js APIs, so a route declared withexport const runtime = "edge" runs untraced: the logs show initialize() failed; the app will run untraced and no spans arrive. Use the Node.js runtime (export const runtime = "nodejs", the default) for every route that makes LLM calls.
Deploying on Vercel
SetBELVEDIR_API_KEY in your Vercel project’s Environment Variables, then redeploy. Vercel functions can freeze or exit as soon as the response is sent, before batched spans export, so await flush() at the end of every handler that makes LLM calls; see Flush on serverless.