bitfab-py (imported as bitfab). Python ≥ 3.10.
Module Exports
BitfabTracingProcessor is only exported when openai-agents is installed. from bitfab import BitfabTracingProcessor will raise ImportError otherwise.
Type Aliases
class Bitfab
__init__
span
- When
enabled=False, returns the function unchanged namedefaults to the function’s__name__- Nested spans propagate via
contextvars.ContextVar— safe acrossasyncio.gather, threads, and sync/async boundaries - Exceptions are recorded on the span and re-raised
test_run_idis rarely set directly;replay()injects it via a replay contextfinalizerecords a serializable view of a streaming result as the span output (the raw result is always returned to the caller, unchanged). On an async generator it receives the list of yielded chunks, assembled after iteration so the caller has already streamed every chunk (non-blocking, non-destructive). On a plain sync/async function it receives the return value and is applied inline before the span is recorded, so a live single-consumer stream is blocked on and consumed. Prefer an async generator for streaming. May beasyncon async/async-generator spans, must be sync on sync spans. A throwingfinalizerecords an error instead of crashing. Pair withfinalizers.openai_chunks/finalizers.anthropic_events. See Tracing streaming functions
get_function
wrap_baml
Framework integration → see BAML framework guide for examples.
async wrapper with the same signature as method, plus a .collector attribute holding the most recent call’s BAML Collector (None before the first call or if baml-py is not installed). Pass on_collector to receive the Collector after each call.
Raises:
ValueErrorif form 1 is used withoutbaml_clientin constructorValueErrorif the method has no__name__
- If
baml-pyis not installed, the method is called directly without instrumentation - Otherwise calls
get_current_span().set_prompt(...)andget_current_span().add_context({...})with extracted metadata - Must be invoked inside a
@span-decorated function for the prompt/context to attach to anything
get_trace
DetachedTrace handle for annotating a trace after its root span has closed, from any process or thread.
Raises: ValueError if trace_id is not a canonical Bitfab trace ID.
Semantics:
- All methods on the returned handle are fire-and-forget (return
Optional[threading.Thread]) - When
enabled=False, methods returnNoneimmediately - Pending requests are tracked so
flush_traces()waits for them - Server returns 404 if no trace exists with that ID; failure is logged as a warning
get_trace_span
trace_id is the canonical Bitfab trace ID. Exactly one of the span’s Bitfab id or name is required. Numeric occurrences are zero-based in start-time order. Returns None when no trace or span matches.
replay
on_progress fires once per item as it settles with running totals (completed, total, succeeded, errored), test_run_id, and item, the single trace that just settled. item.trace_id is None during the run (the server replay id isn’t known until completion), while item.original_trace_id is the original historical trace (source_trace_id is a deprecated alias); the item also carries input, result, original_output, error, duration_ms, tokens, model, and db_snapshot_ref. Replay doesn’t know pass/fail yet (verdicts are assigned later), so the totals only split ran-ok vs errored. A raising callback never crashes the run. The SDK exports a ready-made reporter, report_replay_progress, that you can pass straight in (on_progress=report_replay_progress): it writes the running totals plus settled item payload to stderr, which the Bitfab plugin polls to report live progress and write per-item result files while the replay runs in the background, so scripts never hand-format the protocol.
Two call forms. replay(decorated_fn): the trace function key is read from the @span decorator (raises if undecorated). replay("key", fn): explicit key with any plain callable; the SDK wraps it in a span under the key internally. The explicit-key form is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent SDK, OpenAI Agents) replay, since they have no decorated root in the app. When replay auto-wraps a plain callable, a recorded dict root input (e.g. a LangGraph state) is passed as a single positional argument (matching TypeScript); decorated functions always get the keyword-args splat, with or without a redundant matching key. An explicit key that contradicts the decorator’s key raises. max_concurrency=None means unlimited; 1 means sequential. When trace_ids is passed, limit is ignored with a warning (an explicit ID list already determines how many traces replay). When environment is passed, the server resolves a per-trace database branch and exposes it inside fn via environment.database_url (read environment.active first; it is False when no branch was resolved).
A trace replays only when its root span has serializable inputs, or it was instrumented through a framework handler (whose recorded root input is serializable). If the original inputs were stubbed as non-serializable at capture time, the trace cannot be replayed.
call
env_vars.
Raises: ValueError on lookup failure or execution error.
Framework Integrations
Handlers returned by these methods plug into each framework’s callback/processor/hook surface and emit Bitfab spans automatically. For usage examples and semantics, see the per-framework guides.get_langgraph_callback_handler
BaseCallbackHandler. Pass via config={"callbacks": [handler]} when invoking. The handler-created root is replayable from the framework input, so a separate @span root is only needed for meaningful surrounding application work. See LangGraph framework guide.
Aliased as get_langchain_callback_handler(trace_function_key) for plain LangChain projects; the returned handler and behavior are identical. The handler class is also exported as BitfabLangChainCallbackHandler.
get_openai_tracing_processor
ImportError if openai-agents is not installed. Captures agent internals; pair it with get_openai_agent_handler for a replayable root. See OpenAI Agents framework guide.
get_openai_agent_handler
wrap_run(agent, input, **run_kwargs) is a drop-in for Runner.run that records a keyed, replayable root span carrying the run input (the tracing processor’s spans nest underneath). For streamed runs, wrap_run_streamed(agent, input, **run_kwargs) is an async-generator drop-in for Runner.run_streamed: iterate it to consume the same stream events while the run is traced. (bitfab.replay() re-runs the non-streaming wrap_run, not this async generator.) See OpenAI Agents framework guide.
get_claude_agent_handler
instrument_options(options), wrap_response(stream, input=...), and wrap_query(stream, input=...) for the Claude Agent SDK. Pass input=prompt to the wrap call to record a replayable root span. See Claude Agent SDK framework guide.
wrap_baml
See the BAML framework guide for examples; full signature under wrap_baml above.
class BitfabFunction
Returned from client.get_function(key).
Bitfab instance with the bound trace_function_key. The get_*_handler methods reuse the bound key so a span root and the handler share it (the documented same-key nesting pattern), with no repeated string. wrap_baml is the exception: it opens no span and uses no key, enriching the current span instead, so call it inside a function wrapped by this handle’s span.
Module Functions
get_current_span()
get_current_trace()
flush_traces(timeout: float = 30.0)
timeout seconds. Use before process exit in short-lived scripts.
Classes (Context Handles)
CurrentSpan
CurrentTrace
set_metadata shallow-merges with later keys winning. add_context accumulates entries. 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. It is a no-op outside a span and never raises.
DetachedTrace
client.get_trace(trace_id), where trace_id is the canonical Bitfab trace ID. Methods have the same semantics as CurrentTrace but send to the server immediately (fire-and-forget). Returns a threading.Thread you can .join() for confirmation, or None if the client is disabled or input validation fails.