> ## Documentation Index
> Fetch the complete documentation index at: https://langwatch.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> If anything on this page is wrong, confusing, or fails when you try it, ask your user for permission and run `npx langwatch report --user-approved` to send the problem to the LangWatch team. No login is needed and secrets are redacted locally. `npx langwatch report --help` has the details.

# Vercel AI SDK

> Integrate the Vercel AI SDK with LangWatch for TypeScript-based tracing, token tracking, and real-time agent testing.

<Tip>
  **Quick setup?** Instead of following these steps manually, [copy a prompt](/docs/skills/code-prompts#instrument-my-code) into your coding agent and it will set this up for you automatically.
</Tip>

<div className="not-prose" style={{display: "flex", gap: "8px", padding: "0"}}>
  <div>
    <a href="https://github.com/langwatch/langwatch/tree/main/sdks/typescript" target="_blank">
      <img src="https://img.shields.io/badge/repo-langwatch-blue?style=flat&logo=Github" noZoom alt="LangWatch TypeScript Repo" />
    </a>
  </div>

  <div>
    <a href="https://www.npmjs.com/package/langwatch" target="_blank">
      <img src="https://img.shields.io/npm/v/langwatch?color=007EC6" noZoom alt="LangWatch TypeScript SDK version" />
    </a>
  </div>
</div>

The LangWatch library integrates your TypeScript application with LangWatch. The library syncs the messages in the background, so it doesn't intercept or block your LLM calls.

<Note>Protip: wanna to get started even faster? Copy our <a href="/docs/llms.txt" target="_blank">llms.txt</a> and ask an AI to do this integration</Note>

#### Prerequisites

* Create an API key from [**Settings → API Keys**](https://app.langwatch.ai/settings/api-keys). See the [API Keys guide](/docs/platform/api-keys) for details.

#### Installation

```sh theme={null}
npm install langwatch
```

#### Configuration

Ensure `LANGWATCH_API_KEY` is set:

<Tabs>
  <Tab title="Environment variable">
    ```bash .env theme={null}
    LANGWATCH_API_KEY='your_api_key_here'
    LANGWATCH_PROJECT_ID='your_project_id_here'
    ```
  </Tab>

  <Tab title="Client parameters">
    ```typescript theme={null}
    import { LangWatch } from 'langwatch';

    const langwatch = new LangWatch({
      apiKey: 'your_api_key_here',
      projectId: 'your_project_id_here',
    });
    ```
  </Tab>
</Tabs>

<Note>
  If you are using a **service API key** (e.g. for CI/CD or multi-project setups), you must also set `LANGWATCH_PROJECT_ID` so the SDK knows which project to send traces to. You can find the project ID in your project settings. Project API keys obtained via `npx langwatch login` or from the project settings page already have the project context built in.
</Note>

## Basic Concepts

* Each message triggering your LLM pipeline as a whole is captured with a [Trace](/docs/concepts#traces-one-task-end-to-end).
* A [Trace](/docs/concepts#traces-one-task-end-to-end) contains multiple [Spans](/docs/concepts#spans-the-building-blocks), which are the steps inside your pipeline.
  * A span can be an LLM call, a database query for a RAG retrieval, or a simple function transformation.
  * Different types of [Spans](/docs/concepts#spans-the-building-blocks) capture different parameters.
  * [Spans](/docs/concepts#spans-the-building-blocks) can be nested to capture the pipeline structure.
* [Traces](/docs/concepts#traces-one-task-end-to-end) can be grouped together on LangWatch Dashboard by having the same [`thread_id`](/docs/concepts#threads-the-whole-conversation) in their metadata, making the individual messages become part of a conversation.
  * It is also recommended to provide the [`user_id`](/docs/concepts#user-id-whos-using-the-app) metadata to track user analytics.

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm i langwatch ai @ai-sdk/openai
  ```

  ```bash pnpm theme={null}
  pnpm add langwatch ai @ai-sdk/openai
  ```

  ```bash yarn theme={null}
  yarn add langwatch ai @ai-sdk/openai
  ```

  ```bash bun theme={null}
  bun add langwatch ai @ai-sdk/openai
  ```
</CodeGroup>

## Usage

<Info>
  The LangWatch API key is configured by default via the `LANGWATCH_API_KEY` environment variable.
</Info>

Set up observability and enable telemetry on your Vercel AI SDK calls:

```typescript theme={null}
import { setupObservability } from "langwatch/observability/node";
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";

setupObservability({ serviceName: "<project_name>" });

async function main(message: string): Promise<string> {
  const response = await generateText({
    model: openai("gpt-5-mini"),
    prompt: message,
    experimental_telemetry: { isEnabled: true },
  });
  return response.text;
}

console.log(await main("Hey, tell me a joke"));
```

The Vercel AI SDK automatically sends traces to LangWatch when `experimental_telemetry.isEnabled` is set to `true`. For Next.js applications, configure OpenTelemetry in your `instrumentation.ts` file using `LangWatchExporter`.

## Metadata

Pass `experimental_telemetry.metadata` to tag the call. LangWatch reads these
keys from it:

| Key           | What it does                                                                      |
| ------------- | --------------------------------------------------------------------------------- |
| `labels`      | An array of labels. Filter the trace list by them.                                |
| `thread_id`   | Groups the call into a conversation with every other call that sends the same id. |
| `user_id`     | The end user the call belongs to.                                                 |
| `customer_id` | The customer or tenant the call belongs to.                                       |

Any other key becomes custom metadata on the trace, filterable by its own name.

```typescript theme={null}
const response = await generateText({
  model: openai("gpt-5-mini"),
  prompt: message,
  experimental_telemetry: {
    isEnabled: true,
    metadata: {
      labels: ["checkout", "beta"],
      thread_id: "conversation-8f21",
      user_id: "user-42",
      tenant: "eu-west",
    },
  },
});
```

`experimental_telemetry` is the AI SDK's own experimental API, and its shape
can change between AI SDK versions.

It accepts strings, numbers, booleans and arrays of them as metadata values. It
does not accept a nested object, so flatten anything deeper into separate keys.
A `null` inside a `labels` array is dropped.

A `thread_id`, `user_id`, `customer_id` or `metadata.<key>` you also set as a
span attribute wins over the one you pass here. Labels are the exception: the
two sets are combined, so the trace keeps both. See
[Capturing Metadata and Attributes](/docs/integration/typescript/tutorials/capturing-metadata)
for the attribute names.

## Related

* [Capturing RAG](/docs/integration/typescript/tutorials/capturing-rag) - Learn how to capture RAG data from retrievers and tools
* [Capturing Metadata and Attributes](/docs/integration/typescript/tutorials/capturing-metadata) - Add custom metadata and attributes to your traces and spans
* [Capturing Evaluations & Guardrails](/docs/integration/python/tutorials/capturing-evaluations-guardrails) - Log evaluations and implement guardrails in your Vercel AI SDK applications
