Quickstart
Install the BrowserStack AI Evals SDK and send your first trace in under 5 minutes.
Quickstart
This guide walks you from a blank project to sending traces and running an evaluation. The whole thing takes about 5 minutes.
Prerequisites
- A BrowserStack account with AI Evals access
- Your public and secret API keys from the BrowserStack Automate dashboard
- Node.js 18+, Python 3.9+, or Java 11+ depending on your language
Your credentials are available under Account > Settings > Access Key in the BrowserStack dashboard. You need both the public key (username) and the secret key (access key).
Step 1: Install the SDK
npm install @browserstack/ai-sdk
# or
pnpm add @browserstack/ai-sdk
# or
yarn add @browserstack/ai-sdkpip install browserstack-ai-sdkMaven:
<dependency>
<groupId>com.browserstack</groupId>
<artifactId>browserstack-ai-sdk-java</artifactId>
<version>1.0.0</version>
</dependency>Gradle:
implementation 'com.browserstack:browserstack-ai-sdk-java:1.0.0'Step 2: Set Your Credentials
Set your keys as environment variables. Never hardcode credentials in source code.
export AISDK_PUBLIC_KEY=your_public_key
export AISDK_SECRET_KEY=your_secret_keyOr add them to a .env file (and add .env to .gitignore):
AISDK_PUBLIC_KEY=your_public_key
AISDK_SECRET_KEY=your_secret_keyStep 3: Initialize the Client
import { AISDK } from '@browserstack/ai-sdk';
const testOps = new AISDK({
publicKey: process.env.AISDK_PUBLIC_KEY,
secretKey: process.env.AISDK_SECRET_KEY,
});Or use auto-instrumentation to initialize from environment variables automatically:
// Import this once at the top of your entry point, before any LLM client imports
import '@browserstack/ai-sdk/instrument';from browserstack_ai_sdk import AISDK
import os
test_ops = AISDK(
public_key=os.environ["AISDK_PUBLIC_KEY"],
secret_key=os.environ["AISDK_SECRET_KEY"],
)Or use auto-instrumentation:
# Import this once at the top of your entry point
import browserstack_ai_sdk.instrumentimport com.browserstack.TestOps;
// Initialize from environment variables (reads AISDK_PUBLIC_KEY / AISDK_SECRET_KEY)
TestOps testOps = TestOps.fromEnv();
// Or provide credentials explicitly
TestOps testOps = new TestOps.Builder()
.publicKey(System.getenv("AISDK_PUBLIC_KEY"))
.secretKey(System.getenv("AISDK_SECRET_KEY"))
.build();The Java SDK uses ByteBuddy for automatic OpenAI client instrumentation. No further setup is needed after TestOps.fromEnv().
Step 4: Send Your First Trace
With auto-instrumentation enabled, all LLM calls are captured automatically. Here's a complete working example:
import { Observe } from '@browserstack/ai-sdk';
async function main() {
await Observe.init({
publicKey: process.env.AISDK_PUBLIC_KEY,
secretKey: process.env.AISDK_SECRET_KEY,
});
// The SDK wraps the OpenAI client automatically via the instrument import
const OpenAI = (await import('openai')).default;
const openai = new OpenAI();
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'What are three benefits of writing unit tests?' },
],
});
console.log(response.choices[0].message.content);
}
main();from browserstack_ai_sdk import Observe
Observe.init(
public_key="AISDK_PUBLIC_KEY",
secret_key="AISDK_SECRET_KEY",
) # must be first
import openai
import os
client = openai.OpenAI(api_key=os.environ["OPENAI_API_KEY"])
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What are three benefits of writing unit tests?"},
],
)
print(response.choices[0].message.content)import com.browserstack.TestOps;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.ChatCompletion;
import com.openai.models.ChatCompletionCreateParams;
import com.openai.models.ChatCompletionMessageParam;
public class QuickstartExample {
public static void main(String[] args) {
// Initialize TestOps — auto-instruments the OpenAI client via ByteBuddy
TestOps testOps = TestOps.fromEnv();
OpenAIClient openai = OpenAIOkHttpClient.fromEnv();
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("gpt-4o")
.addMessage(ChatCompletionMessageParam.ofSystem(
"You are a helpful assistant."))
.addMessage(ChatCompletionMessageParam.ofUser(
"What are three benefits of writing unit tests?"))
.build();
ChatCompletion completion = openai.chat().completions().create(params);
System.out.println(completion.choices().get(0).message().content());
}
}Run your code. The SDK captures the LLM call and sends the trace to BrowserStack AI Evals in the background.
Traces are sent asynchronously and typically appear in the dashboard within a few seconds.
Step 5: View the Trace in the Dashboard
- Open the BrowserStack AI Evals dashboard
- Navigate to Traces in the left sidebar
- You should see your trace listed with:
- The model name and request timestamp
- Input and output messages
- Token usage (prompt tokens, completion tokens, total)
- Latency in milliseconds
- Estimated cost
Click the trace to expand it and see the full request/response, observation tree, and any metadata.
Step 6: Run Your First Evaluation
Once you have traces appearing in the dashboard, you can attach an online evaluation rule from Settings → Automated Rules. The evaluator runs automatically on each incoming trace and attaches a score.
To include an expected output so evaluators have a reference answer to compare against, set it on the trace:
import { AISDK } from '@browserstack/ai-sdk';
import OpenAI from 'openai';
const testOps = new AISDK({
publicKey: process.env.AISDK_PUBLIC_KEY,
secretKey: process.env.AISDK_SECRET_KEY,
});
const openai = new OpenAI();
async function main() {
const trace = testOps.trace({
name: 'explain-recursion',
input: { question: 'Explain recursion in plain English.' },
});
const generation = trace.generation({
name: 'openai-call',
model: 'gpt-4o',
input: [{ role: 'user', content: 'Explain recursion in plain English.' }],
});
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Explain recursion in plain English.' }],
});
const output = response.choices[0].message.content ?? '';
generation.end({ output, usage: { input: response.usage?.prompt_tokens, output: response.usage?.completion_tokens } });
trace.update({ output, metadata: { expectedOutput: 'A clear explanation of recursion without technical jargon.' } });
console.log('Trace ID:', trace.id);
await testOps.shutdown();
}
main();from browserstack_ai_sdk import AISDK
import openai
import os
test_ops = AISDK(
public_key=os.environ["AISDK_PUBLIC_KEY"],
secret_key=os.environ["AISDK_SECRET_KEY"],
)
client = openai.OpenAI()
trace = test_ops.trace(
name="explain-recursion",
input={"question": "Explain recursion in plain English."},
)
generation = trace.start_generation(
name="openai-call",
model="gpt-4o",
prompt=[{"role": "user", "content": "Explain recursion in plain English."}],
)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Explain recursion in plain English."}],
)
output = response.choices[0].message.content
generation.update(output=output)
trace.update(
output=output,
metadata={"expectedOutput": "A clear explanation of recursion without technical jargon."},
)
print("Trace ID:", trace.id)
test_ops.flush()import com.browserstack.TestOps;
import com.browserstack.tracing.TraceManager;
import com.browserstack.tracing.Trace;
import com.browserstack.tracing.Generation;
import com.browserstack.tracing.body.TraceBody;
import com.browserstack.tracing.body.GenerationBody;
TestOps sdk = TestOps.fromEnv();
TraceManager traceManager = sdk.traceManager();
Trace trace = traceManager.trace(TraceBody.builder()
.name("explain-recursion")
.input("Explain recursion in plain English.")
.build());
Generation generation = trace.span().generation(GenerationBody.builder()
.name("openai-call")
.model("gpt-4o")
.build());
// ... make your OpenAI call here (auto-traced if sdk.observe().init() was called)
String output = "A function that calls itself until a base case is reached.";
generation.end(output);
sdk.flush();
System.out.println("Trace ID: " + trace.getId());After running this, navigate to the trace in the dashboard. Under the Scores tab you'll see evaluation results once the evaluator runs (usually within a few seconds).
What's Next
Core Concepts
Understand the data model: traces, observations, evaluators, datasets, and experiments.
Node.js SDK Reference
Full API reference, auto-instrumentation options, and advanced patterns.
Python SDK Reference
Full API reference for Python applications.
API Reference
Direct REST API access for custom integrations.