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

npm install weflayr openai @anthropic-ai/sdk \
  @traceloop/instrumentation-openai @traceloop/instrumentation-anthropic
pip install weflayr openai anthropic \
  opentelemetry-instrumentation-openai opentelemetry-instrumentation-anthropic

Setup

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 });
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"])

Use

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

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 };
    }
  );
}
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

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.