Skip to main content
CloudWeGo Eino is a Go framework for building LLM-powered applications. Braintrust traces Eino to capture llm calls and tool calls.
This guide covers manual instrumentation. For quicker setup, use auto-instrumentation.

Setup

Install the Braintrust Eino integration:
go get github.com/braintrustdata/braintrust-sdk-go/trace/contrib/cloudwego/eino

Trace with CloudWeGo Eino

Register the Braintrust handler once with Eino’s callback system. All subsequent ChatModel calls are traced automatically.
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	einoopenai "github.com/cloudwego/eino-ext/components/model/openai"
	"github.com/cloudwego/eino/callbacks"
	"github.com/cloudwego/eino/schema"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/sdk/trace"

	"github.com/braintrustdata/braintrust-sdk-go"
	traceeino "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/cloudwego/eino"
)

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

	bt, err := braintrust.New(tp,
		braintrust.WithProject("my-eino-project"),
		braintrust.WithAPIKey(os.Getenv("BRAINTRUST_API_KEY")),
	)
	if err != nil {
		log.Fatal(err)
	}

	handler := traceeino.NewHandler()
	callbacks.AppendGlobalHandlers(handler)

	ctx := context.Background()
	tracer := otel.Tracer("eino-example")
	ctx, span := tracer.Start(ctx, "eino-chat")
	defer span.End()

	chatModel, err := einoopenai.NewChatModel(ctx, &einoopenai.ChatModelConfig{
		Model:  "gpt-4o-mini",
		APIKey: os.Getenv("OPENAI_API_KEY"),
	})
	if err != nil {
		log.Fatal(err)
	}

	messages := []*schema.Message{{
		Role:    schema.User,
		Content: "What is the capital of France?",
	}}
	resp, err := chatModel.Generate(ctx, messages)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Response: %s\n", resp.Content)
	fmt.Printf("View trace: %s\n", bt.Permalink(span))
}

Streaming

For streaming, call handler.Wait() after closing the reader so asynchronously finalized span attributes are flushed before exit.
#skip-compile
reader, err := chatModel.Stream(ctx, messages)
if err != nil {
	log.Fatal(err)
}
// ... consume the stream ...
reader.Close()
handler.Wait()

Resources