PlatformEvaluationTools
Decorators & Annotations
Instrument TypeScript functions with OpenTelemetry spans using tool, agent, task, and workflow decorators.
Decorators & Annotations
Decorators are a TypeScript-only feature. They are not available in the Python or Java SDKs.
Decorators instrument functions with OpenTelemetry spans, automatically capturing inputs, outputs, and errors. Four span types are supported — tool, agent, task, and workflow — each with a function wrapper variant and a method decorator variant.
import { withTool, withAgent, withTask, withWorkflow } from '@browserstack/ai-sdk';
// or method decorator variants:
import { tool, agent, task, workflow } from '@browserstack/ai-sdk';| Decorator | Span Kind | gen_ai.operation.name |
|---|---|---|
@tool / withTool | tool | execute_tool |
@agent / withAgent | agent | invoke_agent |
@task / withTask | task | task_call |
@workflow / withWorkflow | workflow | workflow_call |
All decorators capture function arguments as span input, capture return value as span output, and record exceptions on error.
withTool — Function Wrapper
import { withTool } from '@browserstack/ai-sdk';
async function searchWeb(query: string): Promise<string[]> {
return ['result1', 'result2'];
}
const tracedSearch = withTool({ name: 'search_web' }, searchWeb);
const results = await tracedSearch('AI news today');
// Creates a span with gen_ai.operation.name=execute_tool@tool — Method Decorator
import { tool } from '@browserstack/ai-sdk';
class SearchService {
@tool({ name: 'search_web' })
async search(query: string): Promise<string[]> {
return ['result1', 'result2'];
}
}
const service = new SearchService();
await service.search('latest news'); // automatically tracedwithAgent, withTask, withWorkflow
import { withAgent, withTask, withWorkflow } from '@browserstack/ai-sdk';
const tracedAgent = withAgent({ name: 'research-agent' }, async (task: string) => {
return 'Agent result';
});
const tracedTask = withTask({ name: 'document-processing' }, async (doc: string) => {
return 'processed';
});
const tracedPipeline = withWorkflow({ name: 'rag-pipeline' }, async (input: string) => {
return 'pipeline output';
});Complete Agent Example
import '@browserstack/ai-sdk/instrument';
import { AISDK, withAgent, withTool } 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();
const searchWeb = withTool({ name: 'search_web' }, async (query: string) => {
return [`Result for: ${query}`];
});
const researchAgent = withAgent(
{ name: 'research-agent' },
async (userRequest: string): Promise<string> => {
const response = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: userRequest }],
tools: [
{
type: 'function',
function: {
name: 'search_web',
description: 'Search the web',
parameters: {
type: 'object',
properties: { query: { type: 'string' } },
required: ['query'],
},
},
},
],
tool_choice: 'auto',
});
const choice = response.choices[0];
if (choice.finish_reason === 'tool_calls') {
for (const toolCall of choice.message.tool_calls ?? []) {
if (toolCall.function.name === 'search_web') {
const args = JSON.parse(toolCall.function.arguments);
const results = await searchWeb(args.query);
return results.join('\n');
}
}
}
return choice.message.content ?? '';
}
);
const result = await researchAgent('Find the latest news about AI safety.');
console.log(result);
await testOps.shutdown();