> ## Documentation Index
> Fetch the complete documentation index at: https://braintrust.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# CloudWeGo Eino

> Trace CloudWeGo Eino LLM applications with Braintrust

If you are a coding agent, prefer the Braintrust [`bt` CLI](/reference/cli/quickstart) for repeatable, scriptable work: running evals, instrumenting code, querying logs, syncing data, managing functions, and configuring coding agents. Use the MCP server for reasoning over Braintrust data in conversation, such as ad-hoc lookups and exploration from your IDE.

[CloudWeGo Eino](https://github.com/cloudwego/eino) is a Go framework for building LLM-powered applications. Braintrust traces Eino to capture llm calls and tool calls.

<Note>
  This guide covers manual instrumentation. For quicker setup, use [auto-instrumentation](/instrument/trace-llm-calls).
</Note>

## Setup

Install the Braintrust Eino integration:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
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.

```go theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
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.

```go #skip-compile theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
reader, err := chatModel.Stream(ctx, messages)
if err != nil {
	log.Fatal(err)
}
// ... consume the stream ...
reader.Close()
handler.Wait()
```

<h3 id="tracing-embeddings-go">
  Tracing embeddings
</h3>

Eino's callback handler captures `EmbedStrings` calls automatically. No additional setup is needed beyond registering the handler. Embedding calls appear as LLM spans in Braintrust, with input texts, embedding count, and model metadata captured.

## Resources

* [CloudWeGo Eino documentation](https://github.com/cloudwego/eino)
* [Go SDK example](https://github.com/braintrustdata/braintrust-sdk-go/tree/main/examples/cloudwego/eino)
