Genkit (Go)
Firebase Genkit for Go is built directly on the OpenTelemetry Go SDK and emits its
spans through the global TracerProvider. So to send Genkit traces to Logfire, register a standard
OpenTelemetry OTLP exporter (pointed at Logfire) as the global provider before genkit.Init(...) — and
Genkit’s agent, model, and tool spans flow in automatically.
go get github.com/firebase/genkit/go
go get go.opentelemetry.io/otel \
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp \
go.opentelemetry.io/otel/sdk
package main
import (
"context"
"fmt"
"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/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/sdk/trace"
)
func main() {
ctx := context.Background()
writeToken := os.Getenv("LOGFIRE_WRITE_TOKEN")
if writeToken == "" {
fmt.Println("LOGFIRE_WRITE_TOKEN is required; copy it from your Logfire project settings")
return
}
// 1. Point the global OTel TracerProvider at Logfire (HTTP/protobuf).
// Endpoint + Authorization can also come from
// OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_HEADERS.
exp, err := otlptracehttp.New(ctx,
otlptracehttp.WithEndpointURL("https://logfire-us.pydantic.dev/v1/traces"),
otlptracehttp.WithHeaders(map[string]string{"Authorization": writeToken}),
)
if err != nil {
fmt.Println("telemetry setup error:", err)
return
}
tp := trace.NewTracerProvider(trace.WithBatcher(exp))
defer tp.Shutdown(ctx)
otel.SetTracerProvider(tp) // MUST be before genkit.Init
// 2. Init Genkit; its spans now export to Logfire.
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithDefaultModel("googleai/gemini-2.5-flash"),
)
type incidentInput struct {
IncidentID string `json:"incident_id" jsonschema:"description=The incident identifier"`
}
toolCalls := 0
lookupIncident := genkit.DefineTool(
g,
"lookup_incident",
"Look up the current status and owner of an incident by ID.",
func(_ *ai.ToolContext, input incidentInput) (string, error) {
toolCalls++
return fmt.Sprintf("%s is resolved; owner=platform-observability", input.IncidentID), nil
},
)
resp, err := genkit.Generate(
ctx,
g,
ai.WithPrompt("Call lookup_incident exactly once with incident_id incident-42, then report the result."),
ai.WithTools(lookupIncident),
)
if err != nil {
fmt.Println("model error:", err)
return
}
if resp == nil {
fmt.Println("model returned no response")
return
}
if toolCalls != 1 {
fmt.Printf("expected one tool call, received %d\n", toolCalls)
return
}
fmt.Println(resp.Text())
}
Set GEMINI_API_KEY (or your provider’s key) and run go run .. The example verifies that Genkit executes its
native lookup_incident tool. You’ll see the generation, model, and tool spans in Logfire. Genkit runs are
detected in the specialized Agents view; the support matrix shows which columns each
view populates. Use https://logfire-eu.pydantic.dev/v1/traces for the EU region.
Managed prompts are authored and versioned in
Prompt Management. The dedicated prompt-fetching SDK
helpers currently ship in the Python and
TypeScript SDKs. From Go you can consume managed variables
over the language-agnostic
OpenFeature Remote Evaluation Protocol (OFREP) HTTP API, or resolve
the prompt in a small Python/TypeScript sidecar and pass the rendered text into ai.WithPrompt(...).