Mastra is a TypeScript framework for building AI agents. Braintrust integrates with Mastra’s observability system to automatically trace agent executions, LLM calls, and tool usage.
Setup
Install Mastra with the Braintrust exporter:
# pnpm
pnpm add @mastra/core @mastra/braintrust @mastra/observability braintrust
# npm
npm install @mastra/core @mastra/braintrust @mastra/observability braintrust
Trace with Mastra
Braintrust traces Mastra agent runs, workflows, steps, tool calls, and LLM calls. Enable tracing without code changes through auto-instrumentation, or configure a Braintrust exporter manually.
Auto-instrumentation
To trace Mastra without modifying your application code, run your app with Braintrust’s import hook. The hook adds a Braintrust exporter to Mastra’s observability automatically, so you don’t configure one yourself. Requires @mastra/core v1.20.0 or later and the @mastra/observability package.
Build your Mastra app
import { initLogger } from "braintrust";
import { Mastra } from "@mastra/core";
import { Agent } from "@mastra/core/agent";
initLogger({
projectName: "mastra-demo", // Replace with your project name
apiKey: process.env.BRAINTRUST_API_KEY,
});
const mastra = new Mastra({
agents: {
assistant: new Agent({
name: "Assistant",
instructions: "You only respond in haikus.",
model: "openai/gpt-5-mini",
}),
},
});
const response = await mastra
.getAgent("assistant")
.generate("Tell me about recursion in programming.");
console.log(response.text);
Run with the import hook
node --import braintrust/hook.mjs mastra-app.js
The auto-instrumentation example uses plain JavaScript so node --import can run the file directly. The Braintrust APIs work the same in TypeScript projects — compile your TypeScript to JavaScript, then run the compiled file with the import hook.If you’re using a bundler, see Trace LLM calls for plugin and loader setup.
Manual instrumentation
To configure tracing explicitly, add a Braintrust exporter to Mastra’s Observability settings yourself. Use the BraintrustObservabilityExporter built into the braintrust SDK:
import { Agent } from "@mastra/core/agent";
import { Mastra } from "@mastra/core/mastra";
import { Observability } from "@mastra/observability";
import { BraintrustObservabilityExporter, initLogger } from "braintrust";
initLogger({ projectName: "mastra-demo" });
const mastra = new Mastra({
agents: {
assistant: new Agent({
name: "Assistant",
instructions: "You only respond in haikus.",
model: "openai/gpt-5-mini",
}),
},
observability: new Observability({
configs: {
braintrust: {
serviceName: "mastra-demo",
exporters: [new BraintrustObservabilityExporter()],
},
},
}),
});
Alternatively, use the BraintrustExporter from the Mastra-maintained @mastra/braintrust package, which accepts a Braintrust logger directly:
import { Agent } from "@mastra/core/agent";
import { Mastra } from "@mastra/core/mastra";
import { Observability } from "@mastra/observability";
import { BraintrustExporter } from "@mastra/braintrust";
import { initLogger } from "braintrust";
const logger = initLogger({ projectName: "mastra-demo" });
const exporter = new BraintrustExporter({
braintrustLogger: logger,
});
const mastra = new Mastra({
agents: {
assistant: new Agent({
name: "Assistant",
instructions: "You only respond in haikus.",
model: "openai/gpt-4o-mini",
}),
},
observability: new Observability({
configs: {
braintrust: {
serviceName: "demo",
exporters: [exporter],
},
},
}),
});
async function main() {
const agent = mastra.getAgent("assistant");
const response = await agent.generate("Tell me about recursion in programming.");
console.log(response.text);
}
main();
The BraintrustExporter constructor can accept a braintrust.Span, braintrust.Experiment, or braintrust.Logger as the braintrustLogger option. This enables automatic nesting of Mastra traces within Braintrust contexts like evals or traced functions.
What Braintrust traces
Braintrust captures:
- Agent run spans (
agent run: <name>) and workflow run spans (workflow run: <name>) as task spans, with inputs and outputs.
- LLM spans (
llm: <model>) for model generations, with the messages as input and the response as output.
- Workflow step spans (
workflow step: <id>) and tool call spans for the steps and tools an agent or workflow runs.
- Token usage metrics (prompt, completion, total, plus cached, cache-creation, and reasoning tokens when reported) on LLM spans.
- Span metadata, including
entity_id, entity_name, and entity_type, plus the model and provider on LLM spans.
- Errors captured on every span.
Evaluate with Mastra
Use Mastra agents as the task in a Braintrust Eval to build and evaluate agentic workflows:
import { Agent } from "@mastra/core/agent";
import { Mastra } from "@mastra/core/mastra";
import { Observability } from "@mastra/observability";
import { BraintrustExporter } from "@mastra/braintrust";
import { Eval, initLogger } from "braintrust";
const logger = initLogger({ projectName: "mastra-demo" });
const exporter = new BraintrustExporter({
braintrustLogger: logger,
});
const mastra = new Mastra({
agents: {
assistant: new Agent({
name: "Assistant",
instructions: "You only respond in haikus.",
model: "openai/gpt-4o-mini",
}),
},
observability: new Observability({
configs: {
braintrust: {
serviceName: "demo",
exporters: [exporter],
},
},
}),
});
Eval('mastra-demo', {
data: () => [
{ input: 'What is the capital of France?', expected: 'Paris' },
{ input: 'What is 2+2?', expected: '4' },
],
task: async (input: string) => {
const agent = mastra.getAgent('assistant');
return (await agent.generate(input)).text;
},
scores: [
(args: { output: string; expected: string }) => ({
name: 'contains_answer',
score: String(args.output).toLowerCase().includes(String(args.expected).toLowerCase()) ? 1 : 0,
}),
],
});
Resources