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

# Go SDK Reference

> Pure API reference for the bitfab-go module.

Module: `github.com/Project-White-Rabbit/bitfab-go`. Go ≥ 1.21. Runtime dependencies: `github.com/google/uuid`.

## Framework Integrations

No framework-native adapters are shipped for Go yet. Instrument Go code manually via `client.Span` / `client.Start` - see the [Go SDK guide](/go-sdk). Framework coverage status: [Frameworks overview](/frameworks/overview).

## Package Constants

```go theme={null}
const DefaultServiceURL = "https://bitfab.ai"
```

## Constructor

### `NewClient`

```go theme={null}
func NewClient(apiKey string, opts ...Option) *Client
```

| Param    | Type        | Description                                          |
| -------- | ----------- | ---------------------------------------------------- |
| `apiKey` | `string`    | Empty/whitespace disables tracing with `log.Println` |
| `opts`   | `...Option` | Functional options                                   |

### `Option`

```go theme={null}
type Option func(*Client)
```

#### `WithServiceURL`

```go theme={null}
func WithServiceURL(url string) Option
```

#### `WithEnabled`

```go theme={null}
func WithEnabled(enabled bool) Option
```

When `false`: `Span` still executes the callback, `Start` returns a no-op `*ActiveSpan`, no data sent.

## `type Client`

Opaque struct. Construct via `NewClient`.

## Span lookup types

```go theme={null}
type SpanLookup struct {
    ID         string
    Name       string
    Occurrence SpanOccurrence
}

const FirstSpanOccurrence SpanOccurrence = "first"
const LastSpanOccurrence SpanOccurrence = "last"
func SpanOccurrenceAt(index int) SpanOccurrence
```

`CapturedSpan` contains the normalized span identity, parent, name, type, input, output, contexts, prompt, metadata, metrics, errors, and timestamps.

### `(c *Client) Span`

```go theme={null}
func (c *Client) Span(
    ctx context.Context,
    traceFunctionKey string,
    fn SpanFunc,
    opts ...SpanOption,
) (any, error)
```

Executes `fn` inside a traced span. `fn`'s return value is captured as the span output.

**Returns:** `fn`'s `(any, error)` return values.

**Errors:** Only `fn`'s own error, captured on the span and returned to the caller. Tracing never fails the call: an unknown `WithType` value degrades to `custom` (with a one-time warning) instead of returning an error, and any internal instrumentation failure runs `fn` untraced rather than crashing the host.

### `(c *Client) Start`

```go theme={null}
func (c *Client) Start(
    ctx context.Context,
    traceFunctionKey string,
    spanName string,
    opts ...SpanOption,
) (context.Context, *ActiveSpan)
```

Start/End-style span for instrumenting existing functions. Always call `defer span.End()`.

Returns a child context carrying the span, and an `*ActiveSpan` for recording data. When `enabled == false`, returns the original context and a zero `*ActiveSpan` whose methods are all no-ops.

### `(c *Client) FlushTraces`

```go theme={null}
func (c *Client) FlushTraces(timeout time.Duration)
```

Waits for all pending background span deliveries, up to `timeout`. **Go has no `atexit` - always `defer client.FlushTraces(...)` in `main()`.**

### `(c *Client) GetFunction`

```go theme={null}
func (c *Client) GetFunction(traceFunctionKey string) *Function
```

### `(c *Client) GetTraceSpan`

```go theme={null}
func (c *Client) GetTraceSpan(
    ctx context.Context,
    traceID string,
    lookup SpanLookup,
) (*CapturedSpan, error)
```

Fetches one persisted span without loading its trace. `traceID` is the canonical Bitfab trace ID. Set exactly one of the span's Bitfab `SpanLookup.ID` or `SpanLookup.Name`. Name lookup defaults to the last match; use `FirstSpanOccurrence` or `SpanOccurrenceAt(index)` to override it. A miss returns `nil, nil`.

## `type SpanFunc`

```go theme={null}
type SpanFunc func(ctx context.Context) (any, error)
```

## `type SpanOption`

```go theme={null}
type SpanOption func(*spanConfig)
```

### `WithName`

```go theme={null}
func WithName(name string) SpanOption
```

Defaults to `traceFunctionKey` for `Span`, or the `spanName` arg for `Start`.

### `WithType`

```go theme={null}
func WithType(spanType string) SpanOption
```

One of `"llm"`, `"agent"`, `"function"`, `"guardrail"`, `"handoff"`, `"custom"`. Validated at span creation time for `Span` (returns an error on invalid). Defaults to `"custom"`.

### `WithFunctionName`

```go theme={null}
func WithFunctionName(name string) SpanOption
```

Recorded as `span_data.function_name`.

### `WithInput`

```go theme={null}
func WithInput(args ...any) SpanOption
```

One arg stored directly. Multiple args stored as a slice. Only relevant to `Span` - for `Start`, use `ActiveSpan.SetInput`.

## `type Function`

```go theme={null}
type Function struct { /* ... */ }
```

Obtained via `(*Client).GetFunction(key)`. Fluent wrapper that binds `traceFunctionKey`.

### `(f *Function) Span`

```go theme={null}
func (f *Function) Span(ctx context.Context, fn SpanFunc, opts ...SpanOption) (any, error)
```

### `(f *Function) Start`

```go theme={null}
func (f *Function) Start(ctx context.Context, spanName string, opts ...SpanOption) (context.Context, *ActiveSpan)
```

## `type ActiveSpan`

Returned by `Start`. All methods are safe on `nil`, safe under `recover()`, and idempotent where noted.

### `(s *ActiveSpan) SetInput`

```go theme={null}
func (s *ActiveSpan) SetInput(args ...any)
```

One arg stored directly. Multiple args stored as a slice. No-op on `nil` receiver.

### `(s *ActiveSpan) SetOutput`

```go theme={null}
func (s *ActiveSpan) SetOutput(output any)
```

### `(s *ActiveSpan) SetError`

```go theme={null}
func (s *ActiveSpan) SetError(err error)
```

### `(s *ActiveSpan) AddContext`

```go theme={null}
func (s *ActiveSpan) AddContext(context map[string]any)
```

Appends the map as one entry on `span_data.contexts`. No-op when `context == nil`.

### `(s *ActiveSpan) SetPrompt`

```go theme={null}
func (s *ActiveSpan) SetPrompt(prompt string)
```

Overwrites `span_data.prompt`. No-op on empty string.

### `(s *ActiveSpan) End`

```go theme={null}
func (s *ActiveSpan) End()
```

Idempotent via `sync.Once`. Sends the span in a background goroutine. Any panic inside the send path is recovered so the host app never crashes.

## Trace-Level API

### `type ContextEntry`

```go theme={null}
type ContextEntry = map[string]any
```

### `type CurrentSpan`

```go theme={null}
type CurrentSpan struct { /* ... */ }
func GetCurrentSpan(ctx context.Context) *CurrentSpan
func (cs *CurrentSpan) ID() string
func (cs *CurrentSpan) TraceID() string
```

Returns the active span's canonical Bitfab span and trace IDs. `GetCurrentSpan` returns `nil` outside a span; both methods are safe on a `nil` receiver and return `""`.

### `type CurrentTrace`

```go theme={null}
type CurrentTrace struct { /* ... */ }
```

Returned by `GetCurrentTrace`.

#### `(ct *CurrentTrace) TraceID`

```go theme={null}
func (ct *CurrentTrace) TraceID() string
```

Returns the canonical Bitfab trace ID. Safe on a `nil` receiver, where it returns `""`.

#### `(ct *CurrentTrace) SetSessionID`

```go theme={null}
func (ct *CurrentTrace) SetSessionID(sessionID string)
```

#### `(ct *CurrentTrace) SetMetadata`

```go theme={null}
func (ct *CurrentTrace) SetMetadata(metadata map[string]any)
```

Shallow-merges with existing trace metadata. Later keys win.

#### `(ct *CurrentTrace) AddContext`

```go theme={null}
func (ct *CurrentTrace) AddContext(context map[string]any)
```

Appends. Accumulates across calls.

#### `(ct *CurrentTrace) Drop`

```go theme={null}
func (ct *CurrentTrace) Drop()
```

Flags the trace to be dropped. Once flagged, spans that complete afterward are not uploaded at all, and the flag rides out on the completion payload, so at completion 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. Safe on a `nil` receiver (a no-op, so `GetCurrentTrace(ctx).Drop()` outside a span does nothing). Never panics.

### `GetCurrentTrace`

```go theme={null}
func GetCurrentTrace(ctx context.Context) *CurrentTrace
```

Returns `nil` when `ctx` carries no active span. Callers must nil-check.

## Concurrency Model

* Nested span context is carried on `context.Context` - safe across goroutines that inherit the context
* Goroutines that do **not** inherit the context will not see the parent span
* Span HTTP sends run in background goroutines. `FlushTraces` drains them
* Trace state is stored in a mutex-protected package-level map keyed by `traceID`

## Error Behavior Summary

| Situation                              | Behavior                                                                            |
| -------------------------------------- | ----------------------------------------------------------------------------------- |
| Empty `apiKey`                         | `log.Println` warning, `enabled` forced to `false`                                  |
| `SpanFunc` returns error               | Captured on span with `error_source: "code"`, returned to caller                    |
| Invalid `WithType` value               | `(*Client).Span` returns an error; `Start` does not validate                        |
| Panic inside user code                 | Not recovered - your code panics. The SDK only recovers panics on its own send path |
| Span transport failure                 | Swallowed. User's return value / error passes through                               |
| `ActiveSpan` methods on `nil` receiver | No-op                                                                               |
| `End()` called multiple times          | Only the first call has effect (`sync.Once`)                                        |
| `GetCurrentTrace(ctx)` outside a span  | Returns `nil`                                                                       |
