Integration API for 3rd-party libraries #72
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR introduces a standardized integration framework for adding instrumentation to the Braintrust Ruby SDK. It provides a consistent architecture and tooling for building, testing, and registering new integrations (e.g., OpenAI, Anthropic, RubyLLM).
Goals
Non-goals
Architecture
The framework separates concerns into four components:
Integration - Declares metadata about a provider: gem name, version constraints, and whether the library is loaded. Answers "can we instrument this?" and delegates patching to its Patcher.
Patcher - Encapsulates the actual monkey-patching logic. Prepends instrumentation modules onto target classes (e.g.,
OpenAI::Client). Thread-safe and idempotent.Registry - Singleton that discovers and manages all available integrations. Used by
Braintrust.instrument!to find and activate the right patcher for a given provider.Context - Attaches per-instance configuration to instrumented objects. When instrumenting a specific client with custom options (e.g.,
tracer_provider), Context stores those options on the instance for later retrieval.Class-level instrumentation (
Braintrust.instrument!(:openai)):Instance-level instrumentation (
Braintrust.instrument!(:openai, target: client, tracer_provider: custom)):Creating a New Integration
Use the generator to scaffold a new integration:
This creates:
lib/braintrust/contrib/my_llm/integration.rb- Integration metadatalib/braintrust/contrib/my_llm/patcher.rb- Patching logic (fill in target class and instrumentation)test/braintrust/contrib/my_llm/integration_test.rbtest/braintrust/contrib/my_llm/patcher_test.rbAdditional generator options:
GEM_NAMESREQUIRE_PATHSMIN_VERSIONMAX_VERSIONAUTO_REGISTERcontrib.rb(default: false)