> For the complete documentation index, see [llms.txt](https://andrewkimjoseph.gitbook.io/celina-sdk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://andrewkimjoseph.gitbook.io/celina-sdk/guides/telemetry.md).

# Telemetry

On **Node.js**, the SDK sends usage counts for **read** operations. Each Amplitude event uses the same name as the corresponding Celina MCP tool (for example `get_stablecoin_balances`, `verify_self_agent`).

## What is sent

* Event name (MCP tool name)
* A `device_id` identifying the **npm package** that called `createCelinaClient()` (auto-detected from its `package.json` `name`, sanitized for Amplitude: strip leading `@`, replace `/` and `-` with `_`, e.g. `celeste_ai`, `andrewkimjoseph_celina_mcp`). Falls back to `celina-sdk` when detection fails.
* Amplitude **`user_id`** set to the lowercase wallet `0x…` address when the read is wallet-scoped (no `event_properties` — wallet is only on `user_id`)
* No tool arguments or private keys

Wallet resolution order:

1. Wallet address extracted from the read call args (catalog-driven)
2. `runWithAnalyticsWallet(address, fn)` request scope (singleton SDK clients)
3. `analyticsWalletAddress` on `createCelinaClient()` (e.g. MCP session signer)

Writes and `prepare*` flows are not tracked (on-chain `CELINA` attribution covers those).

## Default behavior

Telemetry is **on** for server-side use (MCP, your app's API routes, scripts) unless you opt out.

Browser bundles that import the SDK do not load the Amplitude Node client and do not send events.

On **serverless** hosts (Vercel, AWS Lambda), the SDK **flushes** after each tracked read so events are not dropped when the function freezes at response end. For long streaming handlers you can also call `flushCelinaAnalytics()` from `next/server` `after()` as a safety net.

### Singleton clients (e.g. Next.js API routes)

When one shared `createCelinaClient()` serves many users, wrap the handler:

```ts
import { runWithAnalyticsWallet, flushCelinaAnalytics } from "@andrewkimjoseph/celina-sdk";
import { after } from "next/server";

export async function POST(req: Request) {
  after(() => flushCelinaAnalytics());
  const { address } = await req.json();
  return runWithAnalyticsWallet(address, () => {
    // SDK reads inside this scope attach address as Amplitude user_id
  });
}
```

## Opt out

**Environment (recommended for production privacy):**

```bash
CELINA_ANALYTICS_DISABLED=1
```

**Per client:**

```ts
const celina = createCelinaClient({
  analyticsEnabled: false,
});
```

## Overrides

| Option / env                                       | Purpose                                                 |
| -------------------------------------------------- | ------------------------------------------------------- |
| `AMPLITUDE_API_KEY`                                | Replace the bundled project key                         |
| `amplitudeApiKey` in `createCelinaClient()`        | Same, in code                                           |
| `CELINA_ANALYTICS_DEVICE_ID` / `analyticsDeviceId` | Override auto-detected Amplitude `device_id`            |
| `analyticsWalletAddress` in `createCelinaClient()` | Default wallet for `user_id` when reads omit an address |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://andrewkimjoseph.gitbook.io/celina-sdk/guides/telemetry.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
