Skip to content

braintrustdata/braintrust-sdk-go

Repository files navigation

Braintrust Go SDK

Go Reference Beta

Overview

This library provides tools for evaluating and tracing AI applications in Braintrust. Use it to:

  • Evaluate your AI models with custom test cases and scoring functions
  • Trace LLM calls and monitor AI application performance with OpenTelemetry
  • Integrate seamlessly with OpenAI, Anthropic, Google Gemini, LangChainGo, and other LLM providers

This SDK is currently in BETA status and APIs may change.

Installation

go get github.com/braintrustdata/braintrust-sdk-go

export BRAINTRUST_API_KEY="your-api-key"  # Get from https://www.braintrust.dev/app/settings

Quick Start

Braintrust uses OpenTelemetry for distributed tracing. Set up a TracerProvider and initialize the client:

package main

import (
    "context"
    "log"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/trace"

    "github.com/braintrustdata/braintrust-sdk-go"
)

func main() {
    tp := trace.NewTracerProvider()
    defer tp.Shutdown(context.Background())
    otel.SetTracerProvider(tp)

    client, err := braintrust.New(tp, braintrust.WithProject("my-project"))
    if err != nil {
        log.Fatal(err)
    }
    _ = client // Your client is ready to use
}

Usage

Evaluations

Run systematic evaluations with custom test cases and scoring functions:

package main

import (
    "context"
    "log"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/trace"

    "github.com/braintrustdata/braintrust-sdk-go"
    "github.com/braintrustdata/braintrust-sdk-go/eval"
)

func main() {
    ctx := context.Background()

    // Set up OpenTelemetry tracer
    tp := trace.NewTracerProvider()
    defer tp.Shutdown(ctx)
    otel.SetTracerProvider(tp)

    // Initialize Braintrust
    client, err := braintrust.New(tp)
    if err != nil {
        log.Fatal(err)
    }

    // Create an evaluator with your task's input and output types
    evaluator := braintrust.NewEvaluator[string, string](client)

    // Run an evaluation
    _, err = evaluator.Run(ctx, eval.Opts[string, string]{
        Experiment: "greeting-experiment",
        Dataset: eval.NewDataset([]eval.Case[string, string]{
            {Input: "World", Expected: "Hello World"},
            {Input: "Alice", Expected: "Hello Alice"},
        }),
        Task: eval.T(func(ctx context.Context, input string) (string, error) {
            return "Hello " + input, nil
        }),
        Scorers: []eval.Scorer[string, string]{
            eval.NewScorer("exact_match", func(ctx context.Context, r eval.TaskResult[string, string]) (eval.Scores, error) {
                score := 0.0
                if r.Expected == r.Output {
                    score = 1.0
                }
                return eval.S(score), nil
            }),
        },
    })
    if err != nil {
        log.Fatal(err)
    }
}

Tracing LLM Calls

Trace LLM calls with automatic or manual instrumentation.

Automatic Instrumentation (Recommended)

Use Orchestrion to automatically inject tracing at compile time—no code changes required.

1. Install orchestrion:

go install github.com/DataDog/orchestrion@latest

2. Create orchestrion.tool.go in your project root:

//go:build tools

package main

import (
    _ "github.com/DataDog/orchestrion"
    _ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/all" // All LLM providers
)

Or import only the integrations you need:

import (
    _ "github.com/DataDog/orchestrion"
    _ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/openai"    // OpenAI (openai-go)
    _ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/anthropic" // Anthropic
    _ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/genai"     // Google GenAI
    _ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/github.com/sashabaranov/go-openai" // sashabaranov/go-openai
)

3. Build with orchestrion:

orchestrion go build ./...

That's it! Your LLM client calls are now automatically traced. No middleware or wrapper code needed in your application.

Manual Instrumentation

Alternatively, add tracing middleware explicitly to your clients:

OpenAI:

package main

import (
    "context"
    "log"

    "github.com/openai/openai-go"
    "github.com/openai/openai-go/option"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/trace"

    "github.com/braintrustdata/braintrust-sdk-go"
    traceopenai "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/openai"
)

func main() {
    // Set up OpenTelemetry tracer
    tp := trace.NewTracerProvider()
    defer tp.Shutdown(context.Background())
    otel.SetTracerProvider(tp)

    // Initialize Braintrust
    _, err := braintrust.New(tp)
    if err != nil {
        log.Fatal(err)
    }

    // Create OpenAI client with tracing middleware
    client := openai.NewClient(
        option.WithMiddleware(traceopenai.NewMiddleware()),
    )

    // Make API calls - they'll be automatically traced and logged to Braintrust
    _, err = client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
        Messages: []openai.ChatCompletionMessageParamUnion{
            openai.UserMessage("Hello!"),
        },
        Model: openai.ChatModelGPT4oMini,
    })
    if err != nil {
        log.Fatal(err)
    }
}

Anthropic:

package main

import (
    "context"
    "log"

    "github.com/anthropics/anthropic-sdk-go"
    "github.com/anthropics/anthropic-sdk-go/option"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/trace"

    "github.com/braintrustdata/braintrust-sdk-go"
    traceanthropic "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/anthropic"
)

func main() {
    // Set up OpenTelemetry tracer
    tp := trace.NewTracerProvider()
    defer tp.Shutdown(context.Background())
    otel.SetTracerProvider(tp)

    // Initialize Braintrust
    _, err := braintrust.New(tp,
        braintrust.WithProject("my-project"),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Create Anthropic client with tracing middleware
    client := anthropic.NewClient(
        option.WithMiddleware(traceanthropic.NewMiddleware()),
    )

    // Make API calls - they'll be automatically traced and logged to Braintrust
    _, err = client.Messages.New(context.Background(), anthropic.MessageNewParams{
        Model: anthropic.ModelClaude3_7SonnetLatest,
        Messages: []anthropic.MessageParam{
            anthropic.NewUserMessage(anthropic.NewTextBlock("Hello!")),
        },
        MaxTokens: 1024,
    })
    if err != nil {
        log.Fatal(err)
    }
}

API Client

Manage Braintrust resources programmatically:

package main

import (
    "context"
    "log"

    "go.opentelemetry.io/otel/sdk/trace"

    "github.com/braintrustdata/braintrust-sdk-go"
    functionsapi "github.com/braintrustdata/braintrust-sdk-go/api/functions"
)

func main() {
    ctx := context.Background()

    // Create tracer provider
    tp := trace.NewTracerProvider()
    defer tp.Shutdown(ctx)

    // Initialize Braintrust
    client, err := braintrust.New(tp,
        braintrust.WithProject("my-project"),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Get API client
    api := client.API()

    // Create a prompt
    prompt, err := api.Functions().Create(ctx, functionsapi.CreateParams{
        ProjectID: "your-project-id",
        Name:      "My Prompt",
        Slug:      "my-prompt",
        FunctionData: map[string]any{
            "type": "prompt",
        },
        PromptData: map[string]any{
            "prompt": map[string]any{
                "type": "chat",
                "messages": []map[string]any{
                    {
                        "role":    "system",
                        "content": "You are a helpful assistant.",
                    },
                    {
                        "role":    "user",
                        "content": "{{input}}",
                    },
                },
            },
            "options": map[string]any{
                "model": "gpt-4o-mini",
            },
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    _ = prompt // Prompt is ready to use
}

Google Gemini:

package main

import (
    "context"
    "log"
    "os"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/sdk/trace"
    "google.golang.org/genai"

    "github.com/braintrustdata/braintrust-sdk-go"
    tracegenai "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/genai"
)

func main() {
    // Set up OpenTelemetry tracer
    tp := trace.NewTracerProvider()
    defer tp.Shutdown(context.Background())
    otel.SetTracerProvider(tp)

    // Initialize Braintrust
    _, err := braintrust.New(tp,
        braintrust.WithProject("my-project"),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Create Gemini client with tracing
    client, err := genai.NewClient(context.Background(), &genai.ClientConfig{
        HTTPClient: tracegenai.Client(),
        APIKey:     os.Getenv("GOOGLE_API_KEY"),
        Backend:    genai.BackendGeminiAPI,
    })
    if err != nil {
        log.Fatal(err)
    }

    // Make API calls - they'll be automatically traced and logged to Braintrust
    _, err = client.Models.GenerateContent(context.Background(),
        "gemini-1.5-flash",
        genai.Text("Hello!"),
        nil,
    )
    if err != nil {
        log.Fatal(err)
    }
}

LangChainGo: The SDK provides comprehensive tracing for LangChainGo applications. See examples/langchaingo for examples.

Examples

Complete working examples are available in examples/:

Features

  • Evaluations - Systematic testing with custom scoring functions
  • Tracing - Automatic instrumentation for major LLM providers
  • Datasets - Manage and version evaluation datasets
  • Experiments - Track versions and configurations
  • Observability - Monitor AI applications in production

Documentation

Contributing

See CONTRIBUTING.md for development setup and contribution guidelines.

License

Apache License 2.0. See LICENSE for details.