Skip to main content
The Bitfab Go SDK captures your AI function calls to automatically generate evaluations. Re-run your prompts with different models, parameters, and inputs to iterate faster.
Framework-native adapters (LangGraph, OpenAI Agents, BAML, Claude Agent SDK) are not yet available for Go. See Frameworks overview for current coverage. Instrument Go code manually via client.Span or client.Start.

Installation

Quick Start

Need an API key? Get one from the Bitfab dashboard or see the API Keys guide for detailed setup instructions.
Copy this prompt into your coding agent (tested with Cursor and Claude Code using Sonnet 4.5):

Basic Configuration

Missing API key doesn’t crash. If the API key is missing, empty, or whitespace-only, the SDK automatically disables tracing and logs a warning. All instrumented functions still execute normally - no spans are sent, no errors are thrown. You don’t need any conditional logic around the API key.
When no key is passed (empty argument and no WithAPIKey), the SDK reads BITFAB_API_KEY from the environment. Unlike the JS and Python SDKs, Go resolves the key eagerly in NewClient: clients are constructed explicitly (normally in main, after env has loaded), so there is no import-time construction-before-env trap to defer around. For standalone programs where a run that emits no traces should be a hard failure, use WithStrict:

Tracing

Using Start/End to Instrument Existing Functions

The recommended way to add tracing to existing functions without restructuring them:
  • Start returns an updated context.Context (for nested span propagation) and an ActiveSpan
  • defer span.End() ensures the span is always completed and sent
  • SetInput / SetOutput / SetError record data on the span
  • End is idempotent - calling it multiple times is safe

Multi-File Projects

For projects with instrumented functions spread across multiple files, create a dedicated package that initializes the client and exposes a function handle. Import it wherever you need to instrument.
Spans from different files are automatically linked as parent-child when you pass ctx between instrumented functions.

Using client.Span (Closure Style)

Wrap inline code in a closure. Output is captured automatically from the return value. Use WithInput to record inputs:

Using GetFunction for a Static Trace Key

Bind a trace function key once, then create multiple spans without repeating it:

Automatic Nesting

Spans nest automatically when you pass ctx from the outer span callback:

Span Options

Parameters:
  • traceFunctionKey (required): Groups spans under a function key in Bitfab
  • WithName(name) (optional): Display name. Defaults to the trace function key
  • WithType(spanType) (optional): Span type. Defaults to "custom". A label only, used to organize and filter spans in the dashboard; it does not change how the span is traced, replayed, or evaluated
  • WithFunctionName(name) (optional): Override the function name in span data
  • WithInput(args...) (optional, closure style only): Record input data. A single arg is stored directly; multiple args as a slice
Span Types:
Examples:

Span Context

Use span.AddContext() on an ActiveSpan (Start/End style) to attach contextual key-value pairs at runtime - useful when context depends on computed values:
Each AddContext call pushes the entire map as one entry. Multiple calls accumulate entries:

Span Prompt

Use span.SetPrompt() on an ActiveSpan (Start/End style) to set the prompt string on the current span. This is stored in span_data.prompt and is useful for capturing the exact prompt text sent to an LLM:
The prompt is metadata only. It records the prompt text for display and reference in the dashboard; it does not send the prompt to any model or change what the span executes. The last SetPrompt call wins — it overwrites any previously set prompt on the span. Calling SetPrompt outside a span context is a no-op (it never crashes).

Trace Context

Use bitfab.GetCurrentTrace(ctx) to set context that applies to the entire trace (all spans within a single execution). This is useful for grouping traces by session or attaching trace-level metadata:
  • SetSessionID(id) - Groups traces by user session. Stored as a database column for efficient filtering.
  • SetMetadata(map) - Arbitrary key-value metadata on the trace. Merges with existing metadata.
  • AddContext(map) - Key-value context entries. Accumulates across multiple calls.
  • TraceID() - Returns the canonical Bitfab trace ID used for persisted lookups.

Read One Persisted Span

Fetch one span without loading the full trace. Repeated name matches default to the last span.
Both IDs are canonical Bitfab IDs; ingestion source IDs are not accepted. Use bitfab.SpanOccurrenceAt(index) for a zero-based occurrence. A missing trace or span returns nil, nil.

Dropping a Trace

Use bitfab.GetCurrentTrace(ctx).Drop() to discard the in-flight trace. Once flagged, spans that complete afterward are not uploaded at all, and the flag rides out on the completion payload, so when the trace completes the server scrubs any payloads that already raced out (the trace, its external trace, and sibling spans), deletes the archived S3 objects, and marks it dropped instead of completed, keeping only a skeleton audit row. Use it to discard runs you never want stored (health checks, test traffic) or a run you know carries sensitive data.
  • Safe to call outside a span (GetCurrentTrace returns nil, and Drop() is a no-op on a nil receiver), and never panics into your application.

Error Handling

Errors are captured in the span and returned to the caller:
Each error is classified by source. Errors returned by your function are recorded with error_source: "code". SDK-internal errors are recorded with source: "sdk". Both appear in the span’s errors array in the Bitfab dashboard.

Flushing Traces

Go does not have an automatic atexit hook. You must call FlushTraces before your program exits to ensure all pending spans are sent.