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

# OpenAI SDK

> Capture traces from the OpenAI Python or TypeScript SDK with OpenInference

## Language support

| Setup option                       | Python | TypeScript |
| ---------------------------------- | :----: | :--------: |
| Agnost AI skill                    |    ✓   |      ✓     |
| Agnost AI SDK                      |    ✓   |      ✓     |
| OpenTelemetry auto-instrumentation |    ✓   |      ✓     |

## Choose a setup method

| Method              | Use it when                                                                    |
| ------------------- | ------------------------------------------------------------------------------ |
| **Agnost AI skill** | You want your coding agent to inspect the app, make the change, and verify it. |
| **Agnost AI SDK**   | You want explicit control over the interaction boundaries and fields.          |
| **OpenTelemetry**   | The framework already emits useful spans or you operate an OTel pipeline.      |

Start with one method for a call path. Combining SDK tracking with framework
OpenTelemetry on the same call can create duplicate interactions.

## Recommended: Agnost AI skill

<Note>
  **Recommended.** Choose this path when you want your coding agent to inspect the
  project, select a supported transport, make the smallest instrumentation change,
  send a test event, and verify that it reached Agnost AI.
</Note>

Install the skill once in your coding-agent environment:

```bash theme={null}
npx skills add AgnostAI/skills --skill agnost-ai
```

Run the framework-specific prompt below from the application root. Review the
resulting diff before deploying it.

```text theme={null}
Use the agnost-ai skill to add Agnost AI analytics to this OpenAI SDK application.
Org ID: your-org-id
Instrument the real Responses API call and verify one fresh interaction.
```

## Manual setup: Agnost AI SDK

<CodeGroup>
  ```bash Python theme={null}
  pip install agnost
  ```

  ```bash TypeScript theme={null}
  npm install agnostai
  ```
</CodeGroup>

<CodeGroup>
  ```python Python theme={null}
  import agnost
  from openai import OpenAI

  agnost.init("your-org-id")
  client = OpenAI()
  interaction = agnost.begin(user_id="u-42", agent_name="openai-support", input=prompt)
  try:
      response = client.responses.create(model="gpt-4.1-mini", input=prompt)
      interaction.end(output=response.output_text)
  except Exception as exc:
      interaction.end(output=str(exc), success=False)
      raise
  finally:
      agnost.shutdown()
  ```

  ```typescript TypeScript theme={null}
  import OpenAI from 'openai';
  import * as agnost from 'agnostai';

  agnost.init('your-org-id');
  const client = new OpenAI();
  const interaction = agnost.begin({ userId: 'u-42', agentName: 'openai-support', input: prompt });
  try {
    const response = await client.responses.create({ model: 'gpt-4.1-mini', input: prompt });
    interaction.end(response.output_text);
  } catch (error) {
    interaction.end(String(error), false);
    throw error;
  } finally {
    await agnost.shutdown();
  }
  ```
</CodeGroup>

## Manual setup: OpenTelemetry

The `openai` SDK ships no first-party OTel: use OpenInference's auto-instrumentation. Pick your language in the code blocks below; the choice persists across the page.

### 1. Install

**Already have OpenInference + an OTLP exporter wired up?** Skip.

**No setup yet?**

<CodeGroup>
  ```bash Python theme={null}
  pip install openai openinference-instrumentation-openai \
              opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
  ```

  ```bash TypeScript theme={null}
  npm install openai @arizeai/openinference-instrumentation-openai \
              @arizeai/openinference-core @opentelemetry/sdk-node \
              @opentelemetry/exporter-trace-otlp-proto @opentelemetry/api
  ```
</CodeGroup>

### 2. Wire OpenInference + OTLP exporter pointing at Agnost AI

**Already have OpenInference (or any OTel TracerProvider) running?** Append Agnost AI as an additional span processor on the existing provider:

<CodeGroup>
  ```python Python theme={null}
  from opentelemetry import trace
  from opentelemetry.sdk.trace.export import BatchSpanProcessor
  from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

  trace.get_tracer_provider().add_span_processor(
      BatchSpanProcessor(
          OTLPSpanExporter(
              endpoint="https://otel.agnost.ai/v1/traces",
              headers={"X-Agnost-Org-ID": os.environ["AGNOST_ORG_ID"]},
          )
      )
  )
  ```

  ```typescript TypeScript theme={null}
  import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
  import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';

  provider.addSpanProcessor(
    new BatchSpanProcessor(
      new OTLPTraceExporter({
        url: 'https://otel.agnost.ai/v1/traces',
        headers: { 'X-Agnost-Org-ID': process.env.AGNOST_ORG_ID! },
      }),
    ),
  );
  ```
</CodeGroup>

**No OTel yet?** Full setup:

<CodeGroup>
  ```python Python theme={null}
  import os
  from opentelemetry import trace
  from opentelemetry.sdk.trace import TracerProvider
  from opentelemetry.sdk.trace.export import BatchSpanProcessor
  from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
  from opentelemetry.sdk.resources import Resource
  from openinference.instrumentation.openai import OpenAIInstrumentor

  provider = TracerProvider(resource=Resource.create({"service.name": "openai-py"}))
  provider.add_span_processor(
      BatchSpanProcessor(
          OTLPSpanExporter(
              endpoint="https://otel.agnost.ai/v1/traces",
              headers={"X-Agnost-Org-ID": os.environ["AGNOST_ORG_ID"]},
          )
      )
  )
  trace.set_tracer_provider(provider)

  OpenAIInstrumentor().instrument(tracer_provider=provider)
  ```

  ```typescript TypeScript theme={null}
  import { NodeSDK } from '@opentelemetry/sdk-node';
  import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
  import { OpenAIInstrumentation } from '@arizeai/openinference-instrumentation-openai';

  const openAIInstrumentation = new OpenAIInstrumentation();

  const sdk = new NodeSDK({
    traceExporter: new OTLPTraceExporter({
      url: 'https://otel.agnost.ai/v1/traces',
      headers: { 'X-Agnost-Org-ID': process.env.AGNOST_ORG_ID! },
    }),
    instrumentations: [openAIInstrumentation],
  });
  sdk.start();

  // Import openai AFTER sdk.start() and apply the ESM patch.
  import OpenAI from 'openai';
  openAIInstrumentation.manuallyInstrument(OpenAI as never);
  ```
</CodeGroup>

### 3. Pass userId / sessionId per call

<CodeGroup>
  ```python Python theme={null}
  from openinference.instrumentation import using_attributes

  with using_attributes(user_id="user-42", session_id="conv-abc123"):
      client.chat.completions.create(
          model="gpt-4o",
          messages=[{"role": "user", "content": "Hello"}],
      )
  ```

  ```typescript TypeScript theme={null}
  import { context } from '@opentelemetry/api';
  import { setUser, setSession } from '@arizeai/openinference-core';

  let ctx = context.active();
  ctx = setUser(ctx, { userId: 'user-42' });
  ctx = setSession(ctx, { sessionId: 'conv-abc123' });

  await context.with(ctx, () =>
    client.chat.completions.create({
      model: 'gpt-4o',
      messages: [{ role: 'user', content: 'Hello' }],
    }),
  );
  ```
</CodeGroup>

`using_attributes` (Python) and `setUser` / `setSession` (TS) propagate via OTel context, landing as `user.id` / `session.id` on every span the OpenAI SDK emits inside the block.

### What appears in Agnost AI

* **Conversations** grouped by `session.id`.
* **User-level analytics** grouped by `user.id`.
* **Events** containing OpenInference spans.
* **Tool calls** when OpenAI tool-use spans are emitted.

### Verify

Run one OpenAI call inside the context block, then open **Events** in Agnost AI. Confirm `user.id`, `session.id`, model, and message attributes are present.

### Troubleshooting

* Import and initialize instrumentation before creating the OpenAI client.
* Confirm the OTLP exporter points at `https://otel.agnost.ai/v1/traces`.
* For TypeScript, confirm the `openai` and `@arizeai/openinference-instrumentation-openai` versions match the table below.

### TypeScript version compatibility

Pin matching majors: version mismatches throw `does not provide an export named 'APIPromise'` at import time:

| `openai`           | `@arizeai/openinference-instrumentation-openai` |
| ------------------ | ----------------------------------------------- |
| `^6.7.0`           | `^4.0.0`                                        |
| `^4.95.0` – `^5.x` | `~2.3.1`                                        |

### References

* [Enable OpenTelemetry export](https://arize.com/docs/phoenix/tracing/integrations-tracing/openai)
* [Add custom metadata](https://arize.com/docs/phoenix/tracing/how-to-tracing/add-metadata/customize-spans)

## Next steps

* [Conversations](/using-conversations): review the complete OpenAI interaction.
* [Events](/using-events): inspect SDK or OpenTelemetry activity.
* [Intents](/using-intents): organize production conversations by what users wanted.
