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

# Multiple AI providers (example)

> A single app that calls both OpenAI and Anthropic.

`autoInstrument()` accepts an array of providers, so one call wires both up; subsequent `propagateMetadata()` blocks tag every LLM call inside them regardless of which provider runs.

## Install

<CodeGroup>
  ```js Node.js theme={null}
  npm install weflayr openai @anthropic-ai/sdk \
    @traceloop/instrumentation-openai @traceloop/instrumentation-anthropic
  ```

  ```python Python theme={null}
  pip install weflayr openai anthropic \
    opentelemetry-instrumentation-openai opentelemetry-instrumentation-anthropic
  ```
</CodeGroup>

## Setup

<CodeGroup>
  ```js Node.js theme={null}
  const weflayr = require('weflayr');
  const OpenAI = require('openai');
  const Anthropic = require('@anthropic-ai/sdk');

  await weflayr.autoInstrument({
    aiSdks: ['openai', 'anthropic'],
    defaultTags: { app: 'support-bot', env: 'production', region: 'eu-west-1' },
  });

  const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
  const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
  ```

  ```python Python theme={null}
  import os
  import weflayr
  from openai import OpenAI
  import anthropic

  weflayr.auto_instrument(
      ai_sdks=[weflayr.AiSdk.OPENAI, weflayr.AiSdk.ANTHROPIC],
      default_tags={"app": "support-bot", "release": "v.1.3"},
  )

  openai_client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
  anthropic_client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
  ```
</CodeGroup>

## Use

`propagateMetadata` wraps an entire request handler. Both LLM calls inside, regardless of provider, are stamped with the same `customer_name` and `feature_name`.

<CodeGroup>
  ```js Node.js theme={null}
  async function handleSupportTicket(customerName, ticket) {
    return weflayr.propagateMetadata(
      {
        featureName: 'support-ticket',
        customerName,
        extraTags: { plan_tier: 'enterprise', priority: 'high' },
      },
      async () => {
        const classification = await openai.chat.completions.create({
          model: 'gpt-5.1',
          messages: [{ role: 'user', content: `Classify: ${ticket}` }],
        });

        const answer = await anthropic.messages.create({
          model: 'claude-opus-4-8',
          max_tokens: 512,
          messages: [{ role: 'user', content: `Answer this ticket: ${ticket}` }],
        });

        return { classification, answer };
      }
    );
  }
  ```

  ```python Python theme={null}
  def handle_support_ticket(customer_name: str, ticket: str):
      with weflayr.propagate_metadata(
          feature_name="support-ticket",
          customer_name=customer_name,
          extra_tags={"plan_tier": "enterprise", "priority": "high"},
      ):
          classification = openai_client.chat.completions.create(
              model="gpt-5.1",
              messages=[{"role": "user", "content": f"Classify: {ticket}"}],
          )
          answer = anthropic_client.messages.create(
              model="claude-opus-4-8",
              max_tokens=512,
              messages=[{"role": "user", "content": f"Answer this ticket: {ticket}"}],
          )
          return classification, answer
  ```
</CodeGroup>

In your dashboard, both spans land under the same `customer_name` + `feature_name`, but the provider field (auto-detected) is `openai` for the first and `anthropic` for the second.
