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

# Firebase Genkit

> Trace Firebase Genkit calls in Braintrust to debug prompts, evaluate models, and monitor production usage

[Firebase Genkit](https://firebase.google.com/docs/genkit) is Google's open-source framework for building AI-powered applications. Braintrust traces Genkit calls from your application.

**TypeScript**

## Setup

Install Braintrust alongside Genkit and a model plugin.

```bash pnpm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
pnpm add braintrust genkit @genkit-ai/googleai
```

```bash npm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
npm install braintrust genkit @genkit-ai/googleai
```

## Auto-instrumentation

To trace Genkit calls without modifying your application code, initialize Braintrust normally, then run your app with Braintrust's import hook to patch Genkit at runtime. Requires `genkit` v1.0.0 or later.

**1. Initialize Braintrust and call Genkit**

```javascript title="trace-genkit-auto.js" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import { initLogger } from "braintrust";
import { genkit } from "genkit";
import { googleAI } from "@genkit-ai/googleai";

initLogger({
  projectName: "my-genkit-project",
  apiKey: process.env.BRAINTRUST_API_KEY,
});

const ai = genkit({
  plugins: [googleAI()],
});

const { text } = await ai.generate({
  model: googleAI.model("gemini-2.5-flash"),
  prompt: "What is the capital of France?",
});

console.log(text);
```

**2. Run with the import hook**

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
node --import braintrust/hook.mjs trace-genkit-auto.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 and run the compiled file with the import hook, or [run TypeScript directly](https://docs.braintrust.dev/instrument/trace-llm-calls.md#auto-instrumentation) with a TypeScript loader.

> [!NOTE]
>
> If you're using a bundler, see [Trace LLM calls](https://docs.braintrust.dev/instrument/trace-llm-calls.md#auto-instrumentation) for plugin and loader setup.

## Manual instrumentation

To trace Genkit manually, wrap your Genkit instance yourself with `wrapGenkit()`. Use this when you want to instrument a specific instance rather than patching Genkit globally.

```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import { initLogger, wrapGenkit } from "braintrust";
import { genkit } from "genkit";
import { googleAI } from "@genkit-ai/googleai";

initLogger({
  projectName: "my-genkit-project",
  apiKey: process.env.BRAINTRUST_API_KEY,
});

const ai = wrapGenkit(
  genkit({
    plugins: [googleAI()],
  }),
);

const { text } = await ai.generate({
  model: googleAI.model("gemini-2.5-flash"),
  prompt: "What is the capital of France?",
});

console.log(text);
```

## What Braintrust traces

Braintrust patches the Genkit SDK and captures:

* Generate spans (`genkit.generate`), with the prompt and messages as input, model and request parameters in metadata, and the response as output.
* Streaming generate spans (`genkit.generateStream`), with streamed text output and `time_to_first_token`.
* Embedding spans (`genkit.embed` and `genkit.embedMany`), with input as input and a summarized result (embedding count and dimensions).
* Action spans (`genkit.<action_type>: <name>`) for flows, tools, and other Genkit actions, with input, output, and duration, plus action type, name, and key in metadata.
* Token usage metrics (prompt, completion, total, plus cached and reasoning tokens when reported).
* Errors captured on every call.

## Tracing resources

* [Firebase Genkit documentation](https://firebase.google.com/docs/genkit)
* [Genkit JS on GitHub](https://github.com/firebase/genkit)

**Go**

## Setup

Install the Braintrust Genkit integration:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
go get github.com/braintrustdata/braintrust-sdk-go/trace/contrib/genkit
```

## Manual instrumentation

To trace Firebase Genkit calls, attach Braintrust's middleware by passing `tracegenkit.NewMiddleware()` to `ai.WithMiddleware(...)` on each Genkit call you want to trace. The middleware infers provider and model metadata from the request configuration and response metadata when Genkit exposes them. Pass `tracegenkit.WithProvider` and `tracegenkit.WithModel` to override those values or fill them in for custom model implementations and proxies.

```go Go theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
package main

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

	"github.com/firebase/genkit/go/ai"
	"github.com/firebase/genkit/go/genkit"
	"github.com/firebase/genkit/go/plugins/googlegenai"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/sdk/trace"

	"github.com/braintrustdata/braintrust-sdk-go"
	tracegenkit "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/genkit"
)

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

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

	ctx := context.Background()
	g := genkit.Init(ctx,
		genkit.WithPlugins(&googlegenai.GoogleAI{
			APIKey: os.Getenv("GOOGLE_API_KEY"),
		}),
		genkit.WithDefaultModel("googleai/gemini-2.5-flash"),
	)

	tracer := otel.Tracer("genkit-example")
	ctx, span := tracer.Start(ctx, "genkit-call")
	defer span.End()

	mw := tracegenkit.NewMiddleware()
	resp, err := genkit.Generate(ctx, g,
		ai.WithPrompt("What is the capital of France?"),
		ai.WithMiddleware(mw),
	)
	if err != nil {
		log.Fatal(err)
	}

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

### Tracing tools

To trace Genkit tool calls, define your tools with the `tracegenkit` drop-in replacements instead of the standard `genkit` functions. Each traced tool emits a `tool` span for its full execution, including failures.

```go #skip-compile theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import (
	tracegenkit "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/genkit"
)

// Drop-in for genkit.DefineTool
weatherTool := tracegenkit.DefineTool(g, "get_weather",
	"Get the current weather for a city",
	func(ctx *ai.ToolContext, input WeatherInput) (string, error) {
		// tool implementation
	},
)

// Drop-in for genkit.DefineToolWithInputSchema (custom input schema)
// tracegenkit.DefineToolWithInputSchema(g, "name", "desc", schema, fn)

// Drop-in for genkit.DefineMultipartTool (multipart output)
// tracegenkit.DefineMultipartTool(g, "name", "desc", fn)
```

With auto-instrumentation (Orchestrion), `genkit.DefineTool`, `genkit.DefineToolWithInputSchema`, and `genkit.DefineMultipartTool` calls are replaced with their traced equivalents automatically.

### Streaming

To trace streaming responses from `genkit.GenerateStream`, pass the same middleware to that call:

```go #skip-compile theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
stream, err := genkit.GenerateStream(ctx, g,
	ai.WithPrompt("Tell me a story"),
	ai.WithMiddleware(mw),
)
if err != nil {
	log.Fatal(err)
}
_ = stream
```

### Tracing embeddings

Genkit does not route embedding calls through its model middleware, so `tracegenkit.NewMiddleware()` does not capture them. To trace embeddings, wrap each embedder with `tracegenkit.WrapEmbedder`. The wrapped value implements `ai.Embedder` and can be used as a drop-in replacement with `ai.WithEmbedder(...)`.

```go #skip-compile theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import (
	"github.com/firebase/genkit/go/ai"
	"github.com/firebase/genkit/go/genkit"

	tracegenkit "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/genkit"
)

embedder := tracegenkit.WrapEmbedder(
	genkit.LookupEmbedder(g, "googleai/gemini-embedding-001"),
	tracegenkit.WithEmbedderModel("gemini-embedding-001"),
	tracegenkit.WithEmbedderProvider("google"),
)

resp, err := genkit.Embed(ctx, g,
	ai.WithEmbedder(embedder),
	ai.WithTextDocs("text 1", "text 2"),
)
```

## What Braintrust traces

Braintrust captures:

* `genkit.Generate`, `genkit.GenerateText`, and `genkit.GenerateStream` inputs, outputs, and finish reasons.
* Streaming responses, with `time_to_first_token` captured on the first chunk.
* Token usage, including cached input tokens and reasoning (thoughts) tokens.
* Tool calls and tool results.
* Tool execution spans, emitted when tools are defined with `tracegenkit.DefineTool`, `tracegenkit.DefineToolWithInputSchema`, or `tracegenkit.DefineMultipartTool` (or via auto-instrumentation).
* Model configuration (model, temperature, top\_p, max output tokens, etc.) and response metadata (latency, provider, request id).
* `genkit.Embed` inputs, embedding count, and dimensions when wrapped with `WrapEmbedder`.

## Tracing resources

* [Firebase Genkit documentation](https://firebase.google.com/docs/genkit)
* [Go SDK example](https://github.com/braintrustdata/braintrust-sdk-go/tree/main/examples/genkit)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.