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.
Gem: bitfab. Ruby ≥ 3.1. Uses a global singleton client pattern (Bitfab.configure / Bitfab.client).
Framework Integrations
No framework-native adapters are shipped for Ruby yet. Instrument Ruby code manually via Bitfab::Traceable / Bitfab.span — see the Ruby SDK guide. Framework coverage status: Frameworks overview.
Module Layout
Bitfab # top-level module & singleton facade
Bitfab::Client # the underlying client class
Bitfab::BitfabFunction # fluent wrapper bound to one trace_function_key
Bitfab::Traceable # mixin for declarative span tracing
Bitfab::CurrentSpan # span handle
Bitfab::CurrentTrace # trace handle
Bitfab::NoOpCurrentSpan # returned outside a span context
Bitfab::NoOpCurrentTrace # returned outside a span context
Bitfab::Replay # replay orchestration (internal)
Bitfab::ReplayContext # thread-local replay context (internal)
Bitfab::SpanContext # thread-local span stack (internal)
Bitfab::TraceState # trace state storage (internal)
Bitfab::MOCK_STRATEGIES # %w[none all marked]
Module-Level API
Creates the global client. Subsequent calls replace it.
| Param | Type | Default |
|---|
api_key: | String | — |
service_url: | String, nil | "https://bitfab.ai" |
enabled: | Boolean | true |
Empty/whitespace api_key prints a warning and sets enabled = false.
Bitfab.client
Returns the configured Bitfab::Client. Raises RuntimeError("Bitfab not configured...") if configure has not been called.
Bitfab.reset!
Resets the global client to nil. Intended for tests.
Bitfab.current_span
Returns the active CurrentSpan, or Bitfab::NO_OP_SPAN outside a span context.
Bitfab.current_trace
Returns the active CurrentTrace, or Bitfab::NO_OP_TRACE outside a span context.
class Bitfab::Client
SPAN_TYPES
Bitfab::Client::SPAN_TYPES # => %w[llm agent function guardrail handoff custom]
attr_reader :api_key, :service_url, :enabled
initialize(api_key:, service_url: nil, enabled: true)
Same semantics as Bitfab.configure.
replay(receiver, method_name, trace_function_key:, limit: 5, trace_ids: nil, max_concurrency: 10, code_change_description: nil, code_change_files: nil, mock: "none")
| Param | Type | Description |
|---|
receiver | Object or Class | Instance for instance methods; class for class methods |
method_name | Symbol | Method to replay |
trace_function_key: | String | Trace function key for this method |
limit: | Integer | Max traces to replay (default 5) |
trace_ids: | Array<String>, nil | Optional explicit trace IDs |
max_concurrency: | Integer, nil | Max parallel threads (default 10; nil = unlimited) |
code_change_description: | String, nil | Optional rationale for the code change being tested (stored on the experiment) |
code_change_files: | Array<Hash>, nil | Optional list of edited files, each { path:, before:, after: } |
mock: | String | Mock strategy for child spans: "none" (default), "all", or "marked". Raises ArgumentError on any other value. |
Returns: Hash with keys :items, :test_run_id, :test_run_url.
Each item has :input, :result, :original_output, :error, :duration_ms (Integer, nil), :tokens ({ input:, output:, cached:, total: } or nil), and :model (String, nil). The metric fields come from the historical trace the item replays.
Mock strategies:
"none" — every child span runs real code (default).
"all" — every child span returns its historical output; real code is not executed.
"marked" — only child spans declared with mock_on_replay: true return historical output. Falls through to real execution when no historical entry matches.
Repeated calls to the same trace_function_key are distinguished by call order (step:0, step:1, …). The per-key counter advances on every non-root child invocation — including unmarked ones — so a marked sibling following an unmarked sibling lines up with the right historical entry.
get_function(trace_function_key)
Returns a Bitfab::BitfabFunction bound to trace_function_key. Mirrors client.get_function in the Python SDK and client.getFunction in TypeScript.
execute_span(...) (internal)
Called by Traceable. Not intended for direct use.
class Bitfab::BitfabFunction
Fluent wrapper bound to a single trace_function_key, returned by Bitfab::Client#get_function.
attr_reader :trace_function_key
wrap(klass, method_name, name: nil, type: "custom", mock_on_replay: false)
Wraps method_name on klass with span tracing under the bound trace_function_key. Delegates to Bitfab::Traceable.wrap.
module Bitfab::Traceable
Mixin for declarative instance-method tracing.
include Bitfab::Traceable
Extends the including class with ClassMethods below.
Class Methods (after include)
bitfab_function(key)
Sets the default trace_function_key for all bitfab_span declarations in this class.
bitfab_span(method_name, trace_function_key: nil, name: nil, type: "custom", mock_on_replay: false)
Wraps method_name with span tracing.
| Param | Type | Default |
|---|
method_name | Symbol | required |
trace_function_key: | String, nil | falls back to the class-level bitfab_function key |
name: | String, nil | defaults to method_name.to_s |
type: | String | "custom" — one of SPAN_TYPES |
mock_on_replay: | Boolean | false — when true, replay invoked with mock: "marked" returns this span’s historical output |
Supports three call styles:
- Before
def — registered via method_added hook, wrapped when method is defined
- Inline —
bitfab_span def foo ... end, type: "function" (Ruby’s def returns :foo)
- After
def — wraps immediately if the method already exists
Raises RuntimeError if no trace_function_key is provided and no class-level bitfab_function was set.
Module-Level Wrapping
Bitfab::Traceable.wrap(klass, method_name, trace_function_key:, name: nil, type: "custom", mock_on_replay: false)
Wraps a method on a class you do not own. Uses Module#prepend.
| Param | Type |
|---|
klass | Class or Module |
method_name | Symbol |
trace_function_key: | String |
name: | String, nil |
type: | String |
mock_on_replay: | Boolean |
class Bitfab::CurrentSpan
def trace_id # => String
def add_context(context) # Hash → appends one entry; ignores non-Hash; never raises
def set_prompt(prompt) # String → overwrites; ignores non-String; never raises
class Bitfab::CurrentTrace
def set_session_id(session_id) # String
def set_metadata(metadata) # Hash → shallow-merge, later keys win
def add_context(context) # Hash → appends entry
All methods swallow exceptions internally; they never raise.
class Bitfab::NoOpCurrentSpan / NoOpCurrentTrace
Singleton instances exposed as Bitfab::NO_OP_SPAN and Bitfab::NO_OP_TRACE. All methods are no-ops. trace_id returns "".
Thread & Concurrency Model
- Span stack is stored in
Thread.current[:__bitfab_span_stack] — not propagated to child threads automatically
- Trace state is stored in a mutex-protected module-level hash (
Bitfab::TraceState) keyed by trace_id
- Span HTTP sends run in background threads; the client tracks pending threads per trace
Error Behavior Summary
| Situation | Behavior |
|---|
Empty api_key | Warning via warn, enabled forced to false |
bitfab_span method raises | Span records error, exception re-raised |
add_context / set_prompt with invalid input | Silently ignored. Never raises |
| Span transport failure | Swallowed. Host app never crashes |
Bitfab.client before configure | RuntimeError("Bitfab not configured...") |
bitfab_span without trace_function_key | RuntimeError |