From 2ec8b08ed197bbcf0b2bd46977e102a3a470ee0c Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 26 Oct 2026 20:06:57 -0400 Subject: [PATCH] docs(integrations): clarify setup docs and example imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > 🤖 **This text was AI-generated.** Setup helpers and the examples index were thin or wrong in a few places. Callers could copy an import that does not exist, or miss a fact that changes how a trace is read (who owns the model span, which clients get patched, which spans actually carry tokens). ```python from braintrust.contrib.temporal import BraintrustPlugin from braintrust.wrappers.langsmith import setup_langsmith braintrust.patch_dspy() ``` Public docstrings now say what each entry point does and one behavior a caller would otherwise miss. The examples index no longer claims a sample for every integration, and the sample imports point at the current modules: ```python from braintrust.integrations.temporal import BraintrustPlugin from braintrust.wrappers.langsmith_wrapper import setup_langsmith from braintrust.integrations.dspy import patch_dspy ``` Tracing behavior is unchanged. Eight integrations still have no example directory (`ai_sdk`, `google_discoveryengine`, `huggingface_hub`, `instructor`, `livekit_agents`, `pipecat`, `transformers`, `typesafe`). The short notes describe current behavior; they do not restate the instrumentation guide. Co-authored-by: Cursor --- README.md | 4 +- examples/README.md | 16 ++++++- examples/adk/README.md | 2 +- examples/langsmith/README.md | 4 +- examples/openrouter/README.md | 2 +- examples/pydantic_ai/README.md | 2 +- examples/temporal/README.md | 2 + examples/temporal/run.py | 2 +- examples/temporal/worker.py | 2 +- .../braintrust/integrations/adk/__init__.py | 17 +++---- py/src/braintrust/integrations/adk/tracing.py | 1 - .../integrations/agentscope/__init__.py | 6 ++- .../braintrust/integrations/agno/__init__.py | 7 ++- .../integrations/ai_sdk/__init__.py | 6 ++- .../braintrust/integrations/ai_sdk/tracing.py | 3 -- .../integrations/anthropic/__init__.py | 3 ++ .../integrations/anthropic/tracing.py | 8 +--- .../integrations/autogen/__init__.py | 6 ++- py/src/braintrust/integrations/base.py | 45 ++++++++++++++++--- .../integrations/bedrock_runtime/__init__.py | 9 ++-- .../integrations/bedrock_runtime/tracing.py | 2 + .../integrations/claude_agent_sdk/__init__.py | 7 +-- .../integrations/crewai/__init__.py | 25 +++++------ .../braintrust/integrations/crewai/tracing.py | 23 +--------- .../integrations/cursor_sdk/__init__.py | 14 +++--- .../braintrust/integrations/dspy/patchers.py | 5 ++- .../braintrust/integrations/dspy/tracing.py | 7 +-- .../google_discoveryengine/__init__.py | 5 ++- .../google_discoveryengine/integration.py | 2 + .../google_discoveryengine/patchers.py | 2 +- .../integrations/google_genai/__init__.py | 11 +---- .../braintrust/integrations/harbor/plugin.py | 6 ++- .../integrations/langchain/__init__.py | 6 ++- .../integrations/langchain/callbacks.py | 2 + .../integrations/livekit_agents/__init__.py | 9 ++-- .../integrations/livekit_agents/patchers.py | 1 + .../integrations/llamaindex/__init__.py | 5 +++ .../integrations/mistral/tracing.py | 2 +- .../integrations/openai/__init__.py | 12 +---- .../integrations/openai_agents/__init__.py | 8 +++- .../integrations/openrouter/tracing.py | 2 +- .../integrations/pydantic_ai/__init__.py | 11 ++--- .../integrations/pydantic_ai/tracing.py | 2 - .../integrations/strands/__init__.py | 6 ++- .../integrations/temporal/__init__.py | 2 +- .../integrations/temporal/plugin.py | 13 ++++-- .../integrations/transformers/__init__.py | 2 +- .../integrations/transformers/integration.py | 2 +- .../integrations/typesafe/__init__.py | 4 +- 49 files changed, 197 insertions(+), 148 deletions(-) diff --git a/README.md b/README.md index 685adfe4a..7ea2a4a94 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This repository contains Braintrust's Python SDKs and integrations, including: - The main `braintrust` SDK package in [`./py`](./py) - Built-in integrations under [`py/src/braintrust/integrations`](py/src/braintrust/integrations) and related compatibility packages under [`./integrations`](./integrations) -- Self-contained `uv`-project examples for every integration in [`./examples`](./examples) +- Self-contained `uv`-project examples for the integrations that have a directory under [`./examples`](./examples) - Tests and local development tooling for Python SDK development ## Quickstart @@ -63,6 +63,7 @@ BRAINTRUST_API_KEY= braintrust eval tutorial_eval.py | [OpenRouter](py/src/braintrust/integrations/openrouter/) | Yes | `openrouter>=0.6.0` | | [Vercel AI SDK for Python](py/src/braintrust/integrations/ai_sdk/) | Yes | `ai>=0.4.0` | | [Google GenAI](py/src/braintrust/integrations/google_genai/) | Yes | `google-genai>=1.30.0` | +| [Google Discovery Engine](py/src/braintrust/integrations/google_discoveryengine/) | Yes | `google-cloud-discoveryengine>=0.20.3` | | [Bedrock Runtime](py/src/braintrust/integrations/bedrock_runtime/) | Yes | `boto3>=1.34.116` | | [HuggingFace Hub](py/src/braintrust/integrations/huggingface_hub/) | Yes | `huggingface-hub>=0.32.0` | | [Hugging Face Transformers](py/src/braintrust/integrations/transformers/) | Yes | `transformers>=4.42.0` | @@ -71,6 +72,7 @@ BRAINTRUST_API_KEY= braintrust eval tutorial_eval.py | [LangChain](py/src/braintrust/integrations/langchain/) | Yes | `langchain-core>=0.3.28` | | [LlamaIndex](py/src/braintrust/integrations/llamaindex/) | Yes | `llama-index-core>=0.13.0` | | [Instructor](py/src/braintrust/integrations/instructor/) | Yes | `instructor>=1.11.0` | +| [TypeSafe](py/src/braintrust/integrations/typesafe/) | Yes | `typesafe-sdk>=0.6.0` | | [DSPy](py/src/braintrust/integrations/dspy/) | Yes | `dspy>=2.6.0` | | [OpenAI Agents](py/src/braintrust/integrations/openai_agents/) | Yes | `openai-agents>=0.0.19` | | [Claude Agent SDK](py/src/braintrust/integrations/claude_agent_sdk/) | Yes | `claude_agent_sdk>=0.1.10` | diff --git a/examples/README.md b/examples/README.md index c9bb52e28..8df866a6a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -47,7 +47,7 @@ braintrust.init_logger(project="example-") # now import and use the library normally ``` -`braintrust.auto_instrument()` patches every supported integration that's installed in the current environment — there's no need to call individual `setup_*()` or `wrap_*()` helpers. The exceptions are examples that demonstrate non-tracing concerns (`evals/`, `langsmith/`, `otel/`, `temporal/`). +`braintrust.auto_instrument()` patches every supported integration that's installed in the current environment — there's no need to call individual `setup_*()` or `wrap_*()` helpers. `setup_*()`, `wrap_*()`, and `patch_*()` in `braintrust.integrations.` are the manual alternatives. The exceptions are examples that demonstrate non-tracing concerns (`evals/`, `langsmith/`, `otel/`, `temporal/`). If you want to see `auto_instrument()` light up multiple providers in one trace, the `openai/`, `anthropic/`, and any other provider example can be combined trivially — just install both packages in the same environment, call `auto_instrument()` once, and use both clients. @@ -66,6 +66,7 @@ Unless noted otherwise, every example below uses `braintrust.auto_instrument()`. | `claude_agent_sdk/` | Claude Agent SDK subprocess query | | `cohere/` | Cohere `ClientV2` chat call | | `crewai/` | CrewAI `Agent` + `Task` + `Crew` end-to-end | +| `deepagents/` | Deep Agents traced through LangChain; there is no `setup_deepagents()` | | `dspy/` | DSPy `ReAct` agent with two tools (LiteLLM token metrics propagate) | | `evals/` | The `Eval` framework — does **not** use `auto_instrument()` | | `google_genai/` | Google GenAI `generate_content` against Gemini | @@ -83,6 +84,19 @@ Unless noted otherwise, every example below uses `braintrust.auto_instrument()`. | `strands/` | Strands `Agent` against `gpt-4o-mini` | | `temporal/` | Distributed Temporal workflow tracing via `BraintrustPlugin` | +## Integrations without a sample yet + +These integrations ship in the SDK and do not have a directory under `examples/` yet: + +- `ai_sdk` +- `google_discoveryengine` +- `huggingface_hub` +- `instructor` +- `livekit_agents` +- `pipecat` +- `transformers` +- `typesafe` + ## Why no committed `uv.lock`? Examples are meant to demonstrate the **current** SDK against **current** provider releases, not snapshot a specific point in time. Committing lockfiles would create constant churn (a new lockfile for every transitive bump on PyPI) and would actively work against the demo goal — someone running an example next quarter wants it to work with whatever's on PyPI today, not a 3-month-old pin. Lockfiles are gitignored. diff --git a/examples/adk/README.md b/examples/adk/README.md index da4b41162..591940677 100644 --- a/examples/adk/README.md +++ b/examples/adk/README.md @@ -1,6 +1,6 @@ # Google ADK + Braintrust -Calls `braintrust.auto_instrument()` so Google ADK is patched automatically, then runs a weather agent against `gemini-3.8-flash` with one tool. The trace shows the runner span, the agent span, the LLM span, and the tool call. +Calls `braintrust.auto_instrument()` so Google ADK is patched automatically, then runs a weather agent against `gemini-3.8-flash` with one tool. ## Run diff --git a/examples/langsmith/README.md b/examples/langsmith/README.md index 0a73abc58..6e7e5b3b9 100644 --- a/examples/langsmith/README.md +++ b/examples/langsmith/README.md @@ -23,7 +23,7 @@ The wrapper supports two modes: Both LangSmith and Braintrust tracing are active. Use this during migration to verify everything works before fully switching. ```python -from braintrust.wrappers.langsmith import setup_langsmith +from braintrust.wrappers.langsmith_wrapper import setup_langsmith setup_langsmith(project_name="my-project") ``` @@ -33,7 +33,7 @@ setup_langsmith(project_name="my-project") Only Braintrust runs - LangSmith code is completely replaced. Use this when you're ready to fully migrate. ```python -from braintrust.wrappers.langsmith import setup_langsmith +from braintrust.wrappers.langsmith_wrapper import setup_langsmith setup_langsmith(project_name="my-project", standalone=True) ``` diff --git a/examples/openrouter/README.md b/examples/openrouter/README.md index 5495f7689..dbb6c1b0a 100644 --- a/examples/openrouter/README.md +++ b/examples/openrouter/README.md @@ -1,6 +1,6 @@ # OpenRouter + Braintrust -Calls `braintrust.auto_instrument()` to patch the OpenRouter SDK so chat, embeddings, and responses calls are traced. The resulting LLM spans include the provider that OpenRouter dispatched to (e.g. `metadata.provider == "openai"`). +Calls `braintrust.auto_instrument()` so OpenRouter chat completions are traced. ## Run diff --git a/examples/pydantic_ai/README.md b/examples/pydantic_ai/README.md index a6084cfc3..f7c493e41 100644 --- a/examples/pydantic_ai/README.md +++ b/examples/pydantic_ai/README.md @@ -1,6 +1,6 @@ # Pydantic AI + Braintrust -Calls `braintrust.auto_instrument()` so the Pydantic AI agent's underlying provider calls are captured as Braintrust spans automatically. The agent itself is wrapped in `start_span` so the run gets a permalink. +Calls `braintrust.auto_instrument()`, which traces the Pydantic AI agent. The script also opens `start_span` so it can print a permalink. ## Run diff --git a/examples/temporal/README.md b/examples/temporal/README.md index ddf151b65..cc6511fb7 100644 --- a/examples/temporal/README.md +++ b/examples/temporal/README.md @@ -2,6 +2,8 @@ This example demonstrates distributed tracing for Temporal workflows using Braintrust. +This example passes `BraintrustPlugin` explicitly. Import it from `braintrust.integrations.temporal`. + ## Setup 1. Install dependencies. This is a uv project that installs `braintrust[temporal]` from the local checkout: diff --git a/examples/temporal/run.py b/examples/temporal/run.py index 2ecbdfa71..23c3d29e2 100644 --- a/examples/temporal/run.py +++ b/examples/temporal/run.py @@ -3,7 +3,7 @@ import uuid import braintrust -from braintrust.contrib.temporal import BraintrustPlugin +from braintrust.integrations.temporal import BraintrustPlugin from temporalio.client import Client from workflow import TASK_QUEUE_NAME, SimpleWorkflow, TaskInput diff --git a/examples/temporal/worker.py b/examples/temporal/worker.py index 847a27868..d2f21cd6b 100644 --- a/examples/temporal/worker.py +++ b/examples/temporal/worker.py @@ -1,7 +1,7 @@ import asyncio import os -from braintrust.contrib.temporal import BraintrustPlugin +from braintrust.integrations.temporal import BraintrustPlugin # Import only what we need to avoid loading optional dependencies from braintrust.logger import init_logger diff --git a/py/src/braintrust/integrations/adk/__init__.py b/py/src/braintrust/integrations/adk/__init__.py index a556f49eb..b56904c02 100644 --- a/py/src/braintrust/integrations/adk/__init__.py +++ b/py/src/braintrust/integrations/adk/__init__.py @@ -30,6 +30,10 @@ def setup_braintrust(*args, **kwargs): + """Deprecated. Call :func:`setup_adk` instead. + + Forwards ``*args`` and ``**kwargs`` to :func:`setup_adk`. + """ warnings.warn("setup_braintrust is deprecated, use setup_adk instead", DeprecationWarning, stacklevel=2) return setup_adk(*args, **kwargs) @@ -40,16 +44,7 @@ def setup_adk( project_name: str | None = None, SpanProcessor: type | None = None, ) -> bool: - """ - Setup Braintrust integration with Google ADK. Will automatically patch Google ADK agents, runners, flows, and MCP tools for automatic tracing. - - Also enables the Google GenAI integration, which ADK's Gemini models call - through. It owns the ``llm`` span and token usage for each Gemini request; - ADK's ``llm_call`` spans are ``task`` spans so usage is counted once. For - other ADK models (e.g. LiteLLM or Anthropic), enable that provider's - integration, or use ``braintrust.auto_instrument()``, to record usage. - - If you prefer manual patching take a look at `wrap_agent`, `wrap_runner`, `wrap_workflow`, `wrap_flow`, and `wrap_mcp_tool`. + """Set up Braintrust tracing for Google ADK. Args: api_key (Optional[str]): Braintrust API key. @@ -58,7 +53,7 @@ def setup_adk( SpanProcessor (Optional[type]): Deprecated parameter. Returns: - bool: True if setup was successful, False otherwise. + True if patched or already patched, False if ADK is missing or too old. """ if SpanProcessor is not None: warnings.warn("SpanProcessor parameter is deprecated and will be ignored", DeprecationWarning, stacklevel=2) diff --git a/py/src/braintrust/integrations/adk/tracing.py b/py/src/braintrust/integrations/adk/tracing.py index e9aec4946..319090b94 100644 --- a/py/src/braintrust/integrations/adk/tracing.py +++ b/py/src/braintrust/integrations/adk/tracing.py @@ -505,7 +505,6 @@ async def _trace(): async with aclosing(wrapped(*args, **kwargs)) as agen: async for event in agen: - # Record time to first token if first_token_time is None: first_token_time = time.time() diff --git a/py/src/braintrust/integrations/agentscope/__init__.py b/py/src/braintrust/integrations/agentscope/__init__.py index 534f1db8f..70ae3860f 100644 --- a/py/src/braintrust/integrations/agentscope/__init__.py +++ b/py/src/braintrust/integrations/agentscope/__init__.py @@ -13,7 +13,11 @@ def setup_agentscope( project_id: str | None = None, project_name: str | None = None, ) -> bool: - """Setup Braintrust integration with AgentScope.""" + """Set up Braintrust tracing for AgentScope. + + Returns: + True if patched or already patched, False if AgentScope is missing or too old. + """ if current_span() == NOOP_SPAN: init_logger(project=project_name, api_key=api_key, project_id=project_id) diff --git a/py/src/braintrust/integrations/agno/__init__.py b/py/src/braintrust/integrations/agno/__init__.py index c9410b7f2..c91077796 100644 --- a/py/src/braintrust/integrations/agno/__init__.py +++ b/py/src/braintrust/integrations/agno/__init__.py @@ -44,9 +44,7 @@ def setup_agno( project_name: str | None = None, eval_experiments: bool | None = None, ) -> bool: - """ - Setup Braintrust integration with Agno. Will automatically patch Agno agents, models, - function calls, and evals (``agno.eval``) for tracing. + """Set up Braintrust tracing for Agno. Args: api_key: Braintrust API key (optional, can use env var BRAINTRUST_API_KEY) @@ -59,7 +57,8 @@ def setup_agno( current, so pass eval_experiments=False to keep suite runs in logs too. Returns: - True if setup was successful, False otherwise + ``True`` when patching ran or was already applied. ``False`` when Agno is missing or outside the version + range. """ _configure_eval_experiments(eval_experiments) diff --git a/py/src/braintrust/integrations/ai_sdk/__init__.py b/py/src/braintrust/integrations/ai_sdk/__init__.py index 3c786a9d2..1ee7fd1da 100644 --- a/py/src/braintrust/integrations/ai_sdk/__init__.py +++ b/py/src/braintrust/integrations/ai_sdk/__init__.py @@ -21,7 +21,11 @@ def setup_ai_sdk( project_id: str | None = None, project_name: str | None = None, ) -> bool: - """Initialize Braintrust and register the Vercel AI SDK telemetry adapter.""" + """Set up Braintrust tracing for the Vercel AI SDK. + + Returns: + True if patched or already patched, False if the SDK is missing or too old. + """ if current_span() == NOOP_SPAN: init_logger(project=project_name, api_key=api_key, project_id=project_id) return AISDKIntegration.setup() diff --git a/py/src/braintrust/integrations/ai_sdk/tracing.py b/py/src/braintrust/integrations/ai_sdk/tracing.py index 84aef833b..a3c1fa440 100644 --- a/py/src/braintrust/integrations/ai_sdk/tracing.py +++ b/py/src/braintrust/integrations/ai_sdk/tracing.py @@ -323,9 +323,6 @@ def _loop_turn_start(_upstream_span: Any, _data: Any) -> dict[str, Any]: def _stream_start(_upstream_span: Any, data: Any) -> dict[str, Any]: - # The AI SDK delegates transport to an instrumentable provider client. - # Keep this framework-level span a task and let that provider own the - # single LLM span for the request. return { "name": "ai.stream", "type": SpanTypeAttribute.TASK, diff --git a/py/src/braintrust/integrations/anthropic/__init__.py b/py/src/braintrust/integrations/anthropic/__init__.py index 26b36ba82..8356f8b0e 100644 --- a/py/src/braintrust/integrations/anthropic/__init__.py +++ b/py/src/braintrust/integrations/anthropic/__init__.py @@ -1,3 +1,5 @@ +"""Braintrust integration for the Anthropic Python SDK.""" + import warnings from .integration import AnthropicIntegration @@ -8,6 +10,7 @@ def wrap_anthropic_client(client): + """Deprecated. Use ``wrap_anthropic``.""" warnings.warn( "wrap_anthropic_client() is deprecated. Use wrap_anthropic() instead.", DeprecationWarning, diff --git a/py/src/braintrust/integrations/anthropic/tracing.py b/py/src/braintrust/integrations/anthropic/tracing.py index 4c6ada922..06bb58fce 100644 --- a/py/src/braintrust/integrations/anthropic/tracing.py +++ b/py/src/braintrust/integrations/anthropic/tracing.py @@ -1016,8 +1016,6 @@ def __close(self, exc_type, exc_value, traceback): class TracedMessageStream(Wrapper): - """TracedMessageStream wraps both sync and async message streams.""" - def __init__(self, msg_stream, span, request_start_time: float): super().__init__(msg_stream) self.__msg_stream = msg_stream @@ -2047,11 +2045,7 @@ async def _trace_async_parsed_message_call(method, args, kwargs): def _wrap_anthropic(client): - """Wrap an Anthropic object (or AsyncAnthropic) to add tracing. - - If the client is already traced (e.g. via ``AnthropicIntegration.setup()``), - it is returned unchanged to avoid double-wrapping. - """ + """Wrap an Anthropic or async Anthropic client. Already-traced clients are returned unchanged.""" if getattr(client, _BRAINTRUST_TRACED, False): return client diff --git a/py/src/braintrust/integrations/autogen/__init__.py b/py/src/braintrust/integrations/autogen/__init__.py index 87c61d668..b2744f5dd 100644 --- a/py/src/braintrust/integrations/autogen/__init__.py +++ b/py/src/braintrust/integrations/autogen/__init__.py @@ -10,7 +10,11 @@ def setup_autogen( project_id: str | None = None, project_name: str | None = None, ) -> bool: - """Setup Braintrust integration with AutoGen.""" + """Set up Braintrust tracing for AutoGen. + + Returns: + True if patched or already patched, False if AutoGen is missing or too old. + """ if current_span() == NOOP_SPAN: init_logger(project=project_name, api_key=api_key, project_id=project_id) diff --git a/py/src/braintrust/integrations/base.py b/py/src/braintrust/integrations/base.py index 1d052807a..3446db6bf 100644 --- a/py/src/braintrust/integrations/base.py +++ b/py/src/braintrust/integrations/base.py @@ -1,4 +1,10 @@ -"""Shared integration orchestration primitives.""" +"""Orchestration for third-party integrations. + +Subclass :class:`BaseIntegration` and keep the provider import inside the patcher. +:meth:`BaseIntegration.setup` returns ``False`` when the package is missing or +outside ``min_version`` / ``max_version``. An undetectable version still patches. +Patchers run in ascending ``priority`` and must be idempotent. +""" import importlib import importlib.metadata @@ -16,7 +22,13 @@ class BasePatcher(ABC): - """Base class for one concrete integration patch strategy.""" + """One patch strategy. + + ``priority`` runs ascending from a default of 100. ``rescan_on_setup`` + re-runs ``patch`` on later ``setup()`` calls instead of treating an existing + marker as success. A callback or ``patch_class`` that returns ``False`` + leaves the target unmarked so the next ``setup()`` retries. + """ name: ClassVar[str] patch_id: ClassVar[str | None] = None @@ -132,7 +144,12 @@ def patch(cls, module: Any | None, version: str | None, *, target: Any | None = class ClassScanPatcher(BasePatcher): - """Base patcher for rescanning and patching discovered class hierarchies.""" + """Rescan a class hierarchy on every ``setup()``. + + Subclasses imported later are still found. A scan that finds nothing new + returns ``False``. Abstract classes are skipped unless + ``include_abstract_classes`` is set. + """ rescan_on_setup: ClassVar[bool] = True include_abstract_classes: ClassVar[bool] = False @@ -564,7 +581,14 @@ def wrap_target(cls, target: Any) -> Any: class BaseIntegration(ABC): - """Base class for an instrumentable third-party integration.""" + """Base class for an instrumentable third-party integration. + + ``import_names`` are tried in order; the first importable module wins. + ``distribution_names`` are the PyPI names tried before + :func:`detect_module_version`, for packages whose distribution name differs + from the import root. ``min_version`` and ``max_version`` are inclusive. + ``patchers`` must not repeat an identifier. + """ name: ClassVar[str] import_names: ClassVar[tuple[str, ...]] @@ -597,7 +621,12 @@ def setup( *, target: Any | None = None, ) -> bool: - """Apply all applicable patchers for this integration.""" + """Apply applicable patchers. + + Returns ``False`` when the package is missing or outside the version + range. An undetectable version still patches. An already-applied patcher + counts as success unless ``rescan_on_setup`` is set. + """ module = _import_first_available(cls.import_names) if module is None: return False @@ -619,7 +648,11 @@ def setup( @classmethod def detect_version(cls, module: Any) -> str | None: - """Return the installed provider version for this integration.""" + """Return the installed provider version for this integration. + + ``distribution_names`` are tried first. A distribution whose metadata + file is missing falls through to :func:`detect_module_version`. + """ for distribution_name in cls.distribution_names: try: return importlib.metadata.version(distribution_name) diff --git a/py/src/braintrust/integrations/bedrock_runtime/__init__.py b/py/src/braintrust/integrations/bedrock_runtime/__init__.py index 1ef69152e..01d127aca 100644 --- a/py/src/braintrust/integrations/bedrock_runtime/__init__.py +++ b/py/src/braintrust/integrations/bedrock_runtime/__init__.py @@ -1,4 +1,4 @@ -"""Public entry points for the boto3 Bedrock Runtime integration.""" +"""Braintrust integration for boto3 Bedrock Runtime.""" from .integration import BedrockRuntimeIntegration from .patchers import wrap_bedrock_client @@ -8,10 +8,13 @@ def setup_bedrock() -> bool: - """Patch botocore client creation to auto-wrap Bedrock Runtime clients.""" + """Set up Braintrust tracing for Bedrock Runtime. + + Returns True if patched or already patched, False if botocore is missing or too old. + """ return BedrockRuntimeIntegration.setup() def wrap_bedrock(client): - """Instrument a boto3 Bedrock Runtime client instance in place.""" + """Instrument a Bedrock Runtime client in place.""" return wrap_bedrock_client(client) diff --git a/py/src/braintrust/integrations/bedrock_runtime/tracing.py b/py/src/braintrust/integrations/bedrock_runtime/tracing.py index c778e359e..5e7ba772a 100644 --- a/py/src/braintrust/integrations/bedrock_runtime/tracing.py +++ b/py/src/braintrust/integrations/bedrock_runtime/tracing.py @@ -105,6 +105,7 @@ def _invoke_model_wrapper(wrapped, instance, args, kwargs): # noqa: ARG001 output = None if isinstance(result, dict) and "body" in result: + # InvokeModel body is a one-shot stream that is read and replaced. body_bytes = _read_streaming_body(result["body"]) if body_bytes is not None: output = _parse_json_bytes(body_bytes) @@ -211,6 +212,7 @@ def _tool_choice_to_openai(tool_choice: Any) -> Any: if "auto" in tool_choice: return "auto" if "any" in tool_choice: + # toolChoice.any is logged as "required". return "required" if isinstance(tool_choice.get("tool"), dict): name = tool_choice["tool"].get("name") diff --git a/py/src/braintrust/integrations/claude_agent_sdk/__init__.py b/py/src/braintrust/integrations/claude_agent_sdk/__init__.py index b043e9582..9e27c9159 100644 --- a/py/src/braintrust/integrations/claude_agent_sdk/__init__.py +++ b/py/src/braintrust/integrations/claude_agent_sdk/__init__.py @@ -31,8 +31,9 @@ def setup_claude_agent_sdk( project_id: str | None = None, project: str | None = None, ) -> bool: - """ - Setup Braintrust integration with Claude Agent SDK. Will automatically patch the SDK for automatic tracing. + """Set up Braintrust tracing for the Claude Agent SDK. + + ``project`` is the project name. Args: api_key (Optional[str]): Braintrust API key. @@ -40,7 +41,7 @@ def setup_claude_agent_sdk( project (Optional[str]): Braintrust project name. Returns: - bool: True if setup was successful, False otherwise. + True if patched or already patched, False if the Claude Agent SDK is missing or too old. Example: ```python diff --git a/py/src/braintrust/integrations/crewai/__init__.py b/py/src/braintrust/integrations/crewai/__init__.py index 8524cfebf..4fe047439 100644 --- a/py/src/braintrust/integrations/crewai/__init__.py +++ b/py/src/braintrust/integrations/crewai/__init__.py @@ -2,15 +2,13 @@ Public entry points: -- :func:`setup_crewai` — mirrors :func:`setup_agno`/``setup_dspy`` ergonomics. - Initializes a Braintrust logger (when one is not already set) and - registers the CrewAI event-bus listener. -- :func:`patch_crewai` — thin setup-only helper (no logger init), matches - the ``patch_*`` naming used elsewhere. -- :class:`CrewAIIntegration` — used by :func:`braintrust.auto_instrument`. -- :class:`BraintrustCrewAIListener` — exposed for advanced users who want - to register the listener manually on their own event-bus instance (e.g. - for tests). +- :func:`setup_crewai` initializes a Braintrust logger (when one is not already set) and registers the CrewAI + event-bus listener. +- :func:`patch_crewai` is a thin setup-only helper (no logger init) and matches the ``patch_*`` naming used + elsewhere. +- :class:`CrewAIIntegration` is used by :func:`braintrust.auto_instrument`. +- :class:`BraintrustCrewAIListener` is exposed for advanced users who want to register the listener manually on + their own event-bus instance (for example, in tests). """ import logging @@ -39,9 +37,8 @@ def setup_crewai( ) -> bool: """Set up Braintrust tracing for CrewAI. - Initializes a Braintrust logger (unless one is already active) and - registers :class:`BraintrustCrewAIListener` on the singleton - ``crewai_event_bus``. Safe to call multiple times. + Initializes a Braintrust logger (unless one is already active) and registers :class:`BraintrustCrewAIListener` + on the singleton ``crewai_event_bus``. Safe to call multiple times. Args: api_key: Braintrust API key (optional, ``BRAINTRUST_API_KEY`` env var works too). @@ -49,8 +46,8 @@ def setup_crewai( project_name: Braintrust project name (optional, ``BRAINTRUST_PROJECT`` env var works too). Returns: - ``True`` on successful (or already-registered) setup, ``False`` when - CrewAI is not importable at the required minimum version. + ``True`` when patching ran or was already applied. ``False`` when CrewAI is missing or outside the version + range. """ span = current_span() if span == NOOP_SPAN: diff --git a/py/src/braintrust/integrations/crewai/tracing.py b/py/src/braintrust/integrations/crewai/tracing.py index 48dff638e..4cd699e33 100644 --- a/py/src/braintrust/integrations/crewai/tracing.py +++ b/py/src/braintrust/integrations/crewai/tracing.py @@ -19,22 +19,6 @@ Thread-safety: the bus uses up to ``max_workers=10`` workers, so start and end events for the same scope can race across threads. A listener-level :class:`threading.Lock` guards the ``event_id -> Span`` map. - -Token-metric rule (wrapper-only): - -CrewAI is always an orchestration layer: every LLM call it emits is -routed through an underlying provider SDK (LiteLLM, or a native -``openai`` / ``anthropic`` / ``bedrock`` / ``google-genai`` client). -Whichever of those the user has patched — commonly all of them via -``auto_instrument()`` — owns the leaf span with real token accounting. -If ``crewai.llm`` also logged tokens, trace-tree rollup would -double-count them at every ancestor. - -We therefore follow the same rule ``pydantic_ai`` uses for its wrapper -spans (see ``_wrapper_span_metrics`` in ``pydantic_ai/tracing.py``): -``crewai.llm`` emits timing + ``time_to_first_token`` only. Tokens live -on the leaf provider span. This is the "clear ownership" pattern the -sdk-integrations SKILL prefers over "if X is patched, skip" checks. """ # pylint: disable=import-error @@ -266,12 +250,7 @@ def _listener_init(self: Any) -> None: def _listener_setup_listeners(self: Any, crewai_event_bus: "CrewAIEventsBus") -> None: - """Wire handlers onto the CrewAI event bus. - - The list of subscribed events matches the v1 scope documented in - ``BraintrustCrewAIListener``: crew kickoff, tasks, agent execution, - LLM calls (including streaming first-token timing), and tool usage. - """ + """Wire handlers onto the CrewAI event bus.""" # Imports are scoped here so that importing this module never forces a # CrewAI import. from crewai.events import ( diff --git a/py/src/braintrust/integrations/cursor_sdk/__init__.py b/py/src/braintrust/integrations/cursor_sdk/__init__.py index 2e29fd673..c7791ec20 100644 --- a/py/src/braintrust/integrations/cursor_sdk/__init__.py +++ b/py/src/braintrust/integrations/cursor_sdk/__init__.py @@ -17,18 +17,20 @@ def setup_cursor_sdk( project_id: str | None = None, project: str | None = None, ) -> bool: - """Patch Cursor SDK agent runs for Braintrust tracing.""" + """Set up Braintrust tracing for Cursor SDK agent runs. + + ``project`` is the project name. + + Returns: + True if patched or already patched, False if the Cursor SDK is missing or too old. + """ if current_span() == NOOP_SPAN: init_logger(project=project, api_key=api_key, project_id=project_id) return CursorSDKIntegration.setup() def wrap_cursor_sdk_agent(agent_class: Any) -> Any: - """Instrument a Cursor ``Agent`` or ``AsyncAgent`` class in place. - - Cursor traces model turns off ``Run``, not ``Agent``, so this also runs - the full integration setup to patch the run lifecycle. - """ + """Instrument a Cursor ``Agent`` or ``AsyncAgent`` class in place.""" CursorSDKIntegration.setup() # Both flavors spell these methods `send`/`close`, so the composite # patcher cannot tell them apart when wrapping a class directly. diff --git a/py/src/braintrust/integrations/dspy/patchers.py b/py/src/braintrust/integrations/dspy/patchers.py index 16fcbb660..bcedd9f76 100644 --- a/py/src/braintrust/integrations/dspy/patchers.py +++ b/py/src/braintrust/integrations/dspy/patchers.py @@ -30,8 +30,9 @@ def patch_dspy() -> bool: Example: ```python - import braintrust - braintrust.patch_dspy() + from braintrust.integrations.dspy import patch_dspy + + patch_dspy() import dspy lm = dspy.LM("openai/gpt-4o-mini") diff --git a/py/src/braintrust/integrations/dspy/tracing.py b/py/src/braintrust/integrations/dspy/tracing.py index ecdf1a505..1ed5c4a77 100644 --- a/py/src/braintrust/integrations/dspy/tracing.py +++ b/py/src/braintrust/integrations/dspy/tracing.py @@ -105,8 +105,9 @@ def _process_images_impl(value: Any) -> Any: class BraintrustDSpyCallback(BaseCallback): """Callback handler that logs DSPy execution traces to Braintrust. - This callback integrates DSPy with Braintrust's observability platform, automatically - logging language model calls, module executions, tool invocations, and evaluations. + This callback integrates DSPy with Braintrust's observability platform, automatically logging module executions, + tool invocations, evaluations, and LM activity. :func:`braintrust.integrations.dspy.patch_dspy` installs this + callback. Logged information includes: - Input parameters and output results @@ -247,7 +248,7 @@ def on_lm_end( outputs: dict[str, Any] | None, exception: Exception | None = None, ): - """Log the end of a language model call. + """Log the end of a DSPy LM call. Args: call_id: Unique identifier for this call diff --git a/py/src/braintrust/integrations/google_discoveryengine/__init__.py b/py/src/braintrust/integrations/google_discoveryengine/__init__.py index 543b57d93..b39d6604a 100644 --- a/py/src/braintrust/integrations/google_discoveryengine/__init__.py +++ b/py/src/braintrust/integrations/google_discoveryengine/__init__.py @@ -8,5 +8,8 @@ def setup_google_discoveryengine() -> bool: - """Instrument supported v1 clients in this process.""" + """Set up Braintrust tracing for Discovery Engine. + + Returns True if patched or already patched, False if the library is missing or too old. + """ return GoogleDiscoveryEngineIntegration.setup() diff --git a/py/src/braintrust/integrations/google_discoveryengine/integration.py b/py/src/braintrust/integrations/google_discoveryengine/integration.py index 2ed7f3990..f99c9ecf2 100644 --- a/py/src/braintrust/integrations/google_discoveryengine/integration.py +++ b/py/src/braintrust/integrations/google_discoveryengine/integration.py @@ -6,6 +6,8 @@ class GoogleDiscoveryEngineIntegration(BaseIntegration): + """Braintrust instrumentation for Discovery Engine.""" + name = "google_discoveryengine" import_names = ("google.cloud.discoveryengine_v1",) distribution_names = ("google-cloud-discoveryengine",) diff --git a/py/src/braintrust/integrations/google_discoveryengine/patchers.py b/py/src/braintrust/integrations/google_discoveryengine/patchers.py index 2d2632f1e..5f386e893 100644 --- a/py/src/braintrust/integrations/google_discoveryengine/patchers.py +++ b/py/src/braintrust/integrations/google_discoveryengine/patchers.py @@ -82,7 +82,7 @@ class AsyncRankPatcher(FunctionWrapperPatcher): def wrap_google_discoveryengine(client): - """Instrument one v1 client instance, returning the same client.""" + """Instrument a Discovery Engine client and return it.""" from google.cloud import discoveryengine_v1 for patcher in PATCHERS: diff --git a/py/src/braintrust/integrations/google_genai/__init__.py b/py/src/braintrust/integrations/google_genai/__init__.py index 1b8a24ddd..92f955866 100644 --- a/py/src/braintrust/integrations/google_genai/__init__.py +++ b/py/src/braintrust/integrations/google_genai/__init__.py @@ -20,17 +20,10 @@ def setup_genai( project_id: str | None = None, project_name: str | None = None, ) -> bool: - """Setup Braintrust integration with Google GenAI. - - Will automatically patch Google GenAI models for automatic tracing. - - Args: - api_key: Braintrust API key. - project_id: Braintrust project ID. - project_name: Braintrust project name. + """Set up Braintrust tracing for the Google GenAI SDK. Returns: - True if setup was successful, False if google-genai is not installed. + True if patched or already patched, False if google-genai is missing or too old. """ span = current_span() if span == NOOP_SPAN: diff --git a/py/src/braintrust/integrations/harbor/plugin.py b/py/src/braintrust/integrations/harbor/plugin.py index aebff6052..245dd20c8 100644 --- a/py/src/braintrust/integrations/harbor/plugin.py +++ b/py/src/braintrust/integrations/harbor/plugin.py @@ -395,7 +395,11 @@ def _verifier_evidence(result: Any, config: PluginConfig) -> tuple[dict[str, Any class HarborPlugin: - """Harbor plugin that reconciles final trials into Braintrust experiments.""" + """Harbor plugin that writes finished trials to a Braintrust experiment. + + Loaded with ``--plugin braintrust``, not ``auto_instrument()``. The default project name is ``Harbor``. + ``strict=True`` cannot fail the Harbor job, because Harbor isolates finalizers. + """ def __init__( self, diff --git a/py/src/braintrust/integrations/langchain/__init__.py b/py/src/braintrust/integrations/langchain/__init__.py index f2a0aee79..889c9db0a 100644 --- a/py/src/braintrust/integrations/langchain/__init__.py +++ b/py/src/braintrust/integrations/langchain/__init__.py @@ -32,7 +32,11 @@ def setup_langchain( project_id: str | None = None, project_name: str | None = None, ) -> bool: - """Setup Braintrust integration with LangChain.""" + """Set up Braintrust tracing for LangChain. + + Returns: + True if patched or already patched, False if LangChain is missing or too old. + """ if current_span() == NOOP_SPAN: init_logger(project=project_name, api_key=api_key, project_id=project_id) diff --git a/py/src/braintrust/integrations/langchain/callbacks.py b/py/src/braintrust/integrations/langchain/callbacks.py index bf93bc1fc..3d0d5bee3 100644 --- a/py/src/braintrust/integrations/langchain/callbacks.py +++ b/py/src/braintrust/integrations/langchain/callbacks.py @@ -98,6 +98,8 @@ def _split_tools(invocation_params: Mapping[str, Any] | None) -> tuple[dict[str, class BraintrustCallbackHandler(BaseCallbackHandler): + """LangChain callback handler that logs runs to Braintrust.""" + root_run_id: UUID | None = None def __init__( diff --git a/py/src/braintrust/integrations/livekit_agents/__init__.py b/py/src/braintrust/integrations/livekit_agents/__init__.py index 588053f1c..8e45ba070 100644 --- a/py/src/braintrust/integrations/livekit_agents/__init__.py +++ b/py/src/braintrust/integrations/livekit_agents/__init__.py @@ -1,14 +1,11 @@ +"""Braintrust tracing for LiveKit Agents.""" + from .integration import LiveKitAgentsIntegration from .patchers import wrap_livekit_agents def setup_livekit_agents() -> bool: - """Set up LiveKit Agents tracing. - - Agent playback audio attachments are disabled by default. Set - ``BRAINTRUST_CAPTURE_AGENT_AUDIO_ATTACHMENTS=true`` to include them on - ``agent_speaking`` spans. - """ + """Set up Braintrust tracing for LiveKit Agents.""" return LiveKitAgentsIntegration.setup() diff --git a/py/src/braintrust/integrations/livekit_agents/patchers.py b/py/src/braintrust/integrations/livekit_agents/patchers.py index e4fa88980..dd3f51806 100644 --- a/py/src/braintrust/integrations/livekit_agents/patchers.py +++ b/py/src/braintrust/integrations/livekit_agents/patchers.py @@ -209,6 +209,7 @@ class MetricsEmitterPatcher(CompositeFunctionWrapperPatcher): def wrap_livekit_agents(target: Any) -> Any: + """Instrument a LiveKit Agents target in place.""" AgentSessionPatcher.wrap_target(target) MetricsEmitterPatcher.wrap_target(target) return target diff --git a/py/src/braintrust/integrations/llamaindex/__init__.py b/py/src/braintrust/integrations/llamaindex/__init__.py index be68ffd72..e94a6d02d 100644 --- a/py/src/braintrust/integrations/llamaindex/__init__.py +++ b/py/src/braintrust/integrations/llamaindex/__init__.py @@ -38,6 +38,11 @@ def setup_llamaindex( project_id: str | None = None, project_name: str | None = None, ) -> bool: + """Set up Braintrust tracing for LlamaIndex. + + Returns: + True if patched or already patched, False if LlamaIndex is missing or too old. + """ if current_span() == NOOP_SPAN: init_logger(project=project_name, api_key=api_key, project_id=project_id) diff --git a/py/src/braintrust/integrations/mistral/tracing.py b/py/src/braintrust/integrations/mistral/tracing.py index e4ec84360..9c8344a3d 100644 --- a/py/src/braintrust/integrations/mistral/tracing.py +++ b/py/src/braintrust/integrations/mistral/tracing.py @@ -1903,7 +1903,7 @@ async def _ocr_process_async_wrapper(wrapped, instance, args, kwargs): def wrap_mistral(client: Any) -> Any: - """Wrap a single Mistral client instance for tracing.""" + """Instrument a Mistral client in place.""" from .patchers import ( AgentsPatcher, ChatPatcher, diff --git a/py/src/braintrust/integrations/openai/__init__.py b/py/src/braintrust/integrations/openai/__init__.py index 0a8b99e7b..6785afbec 100644 --- a/py/src/braintrust/integrations/openai/__init__.py +++ b/py/src/braintrust/integrations/openai/__init__.py @@ -18,18 +18,10 @@ def setup_openai( project_id: str | None = None, project_name: str | None = None, ) -> bool: - """Setup Braintrust integration with OpenAI. - - Patches OpenAI resource classes at the module level so that all clients - produce Braintrust tracing spans. - - Args: - api_key: Braintrust API key (optional, can use env var BRAINTRUST_API_KEY) - project_id: Braintrust project ID (optional) - project_name: Braintrust project name (optional, can use env var BRAINTRUST_PROJECT) + """Set up Braintrust tracing for the OpenAI Python SDK. Returns: - True if setup was successful, False otherwise + True if patched or already patched, False if OpenAI is not installed. """ span = current_span() if span == NOOP_SPAN: diff --git a/py/src/braintrust/integrations/openai_agents/__init__.py b/py/src/braintrust/integrations/openai_agents/__init__.py index a000b3587..dd77e06d0 100644 --- a/py/src/braintrust/integrations/openai_agents/__init__.py +++ b/py/src/braintrust/integrations/openai_agents/__init__.py @@ -24,7 +24,13 @@ def setup_openai_agents( project: str | None = None, project_name: str | None = None, ) -> bool: - """Setup Braintrust tracing for the OpenAI Agents SDK.""" + """Set up Braintrust tracing for the OpenAI Agents SDK. + + ``project_name`` wins over ``project`` when both are set. + + Returns: + True if patched or already patched, False if the Agents SDK is missing or too old. + """ if current_span() == NOOP_SPAN: init_logger(project=project_name or project, api_key=api_key, project_id=project_id) diff --git a/py/src/braintrust/integrations/openrouter/tracing.py b/py/src/braintrust/integrations/openrouter/tracing.py index 9a7dbb6d3..165acd820 100644 --- a/py/src/braintrust/integrations/openrouter/tracing.py +++ b/py/src/braintrust/integrations/openrouter/tracing.py @@ -698,7 +698,7 @@ async def _responses_send_async_wrapper(wrapped, instance, args, kwargs, *, span def wrap_openrouter(client: Any) -> Any: - """Wrap a single OpenRouter client instance for tracing.""" + """Instrument an OpenRouter client in place.""" from .patchers import BetaResponsesPatcher, ChatPatcher, EmbeddingsPatcher, ResponsesPatcher chat = getattr(client, "chat", None) diff --git a/py/src/braintrust/integrations/pydantic_ai/__init__.py b/py/src/braintrust/integrations/pydantic_ai/__init__.py index 141fa6675..58660afef 100644 --- a/py/src/braintrust/integrations/pydantic_ai/__init__.py +++ b/py/src/braintrust/integrations/pydantic_ai/__init__.py @@ -33,17 +33,12 @@ def setup_pydantic_ai( project_id: str | None = None, project_name: str | None = None, ) -> bool: - """ - Setup Braintrust integration with Pydantic AI. Will automatically patch Pydantic AI - agents and direct API functions for automatic tracing. + """Set up Braintrust tracing for Pydantic AI. - Args: - api_key: Braintrust API key. - project_id: Braintrust project ID. - project_name: Braintrust project name. + :func:`wrap_model_classes` is deprecated. Returns: - True if setup was successful, False otherwise. + True if patched or already patched, False if Pydantic AI is missing or too old. """ span = current_span() if span == NOOP_SPAN: diff --git a/py/src/braintrust/integrations/pydantic_ai/tracing.py b/py/src/braintrust/integrations/pydantic_ai/tracing.py index d03c33789..5d6c84d5f 100644 --- a/py/src/braintrust/integrations/pydantic_ai/tracing.py +++ b/py/src/braintrust/integrations/pydantic_ai/tracing.py @@ -210,7 +210,6 @@ def _agent_run_stream_sync_wrapper(wrapped: Any, instance: Any, args: Any, kwarg start_time = time.time() try: - # Call the original function within the span context stream_result = wrapped(*args, **kwargs) return _AgentStreamResultSyncProxy( stream_result, @@ -221,7 +220,6 @@ def _agent_run_stream_sync_wrapper(wrapped: Any, instance: Any, args: Any, kwarg tool_trace_token, ) except Exception: - # Clean up span on error _reset_tool_trace_capture(tool_trace_token) span_cm.__exit__(*sys.exc_info()) raise diff --git a/py/src/braintrust/integrations/strands/__init__.py b/py/src/braintrust/integrations/strands/__init__.py index ee15575da..dac7ce5ac 100644 --- a/py/src/braintrust/integrations/strands/__init__.py +++ b/py/src/braintrust/integrations/strands/__init__.py @@ -14,7 +14,11 @@ def setup_strands( project_id: str | None = None, project_name: str | None = None, ) -> bool: - """Set up Braintrust tracing for Strands Agents.""" + """Set up Braintrust tracing for Strands Agents. + + Returns: + True if patched or already patched, False if Strands is missing or too old. + """ span = current_span() if span == NOOP_SPAN: init_logger(project=project_name, api_key=api_key, project_id=project_id) diff --git a/py/src/braintrust/integrations/temporal/__init__.py b/py/src/braintrust/integrations/temporal/__init__.py index 9cfe364f3..962d69dca 100644 --- a/py/src/braintrust/integrations/temporal/__init__.py +++ b/py/src/braintrust/integrations/temporal/__init__.py @@ -27,7 +27,7 @@ def setup_temporal( project_id: str | None = None, project_name: str | None = None, ) -> bool: - """Set up Braintrust auto-instrumentation for Temporal.""" + """Set up Braintrust tracing for Temporal.""" span = current_span() if span == NOOP_SPAN: init_logger(project=project_name, api_key=api_key, project_id=project_id) diff --git a/py/src/braintrust/integrations/temporal/plugin.py b/py/src/braintrust/integrations/temporal/plugin.py index 60881c9f9..46e035043 100644 --- a/py/src/braintrust/integrations/temporal/plugin.py +++ b/py/src/braintrust/integrations/temporal/plugin.py @@ -6,6 +6,13 @@ pip install braintrust[temporal] +``setup_temporal()`` and ``braintrust.auto_instrument()`` inject ``BraintrustPlugin``, so callers do not have +to pass it. The samples below remain valid for callers who pass the plugin themselves. + +The workflow sandbox blocks ``os.environ``. Braintrust reads ``BRAINTRUST_OTEL_COMPAT`` on the first access of +its context implementation, so this module calls ``current_span()`` at import time before workflow code runs +inside the sandbox. + Components ---------- @@ -23,7 +30,7 @@ Use ``BraintrustPlugin`` when creating a worker:: import braintrust - from braintrust.contrib.temporal import BraintrustPlugin + from braintrust.integrations.temporal import BraintrustPlugin from temporalio.client import Client from temporalio.worker import Worker @@ -47,7 +54,7 @@ Use ``BraintrustPlugin`` when creating a client to propagate span context to workflows:: import braintrust - from braintrust.contrib.temporal import BraintrustPlugin + from braintrust.integrations.temporal import BraintrustPlugin from temporalio.client import Client braintrust.init_logger(project="my-project") @@ -417,7 +424,7 @@ class BraintrustPlugin(SimplePlugin): - Configuring the sandbox to allow braintrust imports without unsafe.imports_passed_through() Example usage: - from braintrust.contrib.temporal import BraintrustPlugin + from braintrust.integrations.temporal import BraintrustPlugin from temporalio.worker import Worker worker = Worker( diff --git a/py/src/braintrust/integrations/transformers/__init__.py b/py/src/braintrust/integrations/transformers/__init__.py index ce83bb71f..e24499610 100644 --- a/py/src/braintrust/integrations/transformers/__init__.py +++ b/py/src/braintrust/integrations/transformers/__init__.py @@ -12,5 +12,5 @@ def setup_transformers() -> bool: - """Instrument supported Transformers pipeline classes.""" + """Set up Braintrust tracing for local Transformers pipelines.""" return TransformersIntegration.setup() diff --git a/py/src/braintrust/integrations/transformers/integration.py b/py/src/braintrust/integrations/transformers/integration.py index 1fdaa6c76..e678fd1e3 100644 --- a/py/src/braintrust/integrations/transformers/integration.py +++ b/py/src/braintrust/integrations/transformers/integration.py @@ -6,7 +6,7 @@ class TransformersIntegration(BaseIntegration): - """Instrument supported local ``transformers`` text pipelines.""" + """Braintrust instrumentation for local Transformers pipelines.""" name = "transformers" import_names = ("transformers",) diff --git a/py/src/braintrust/integrations/typesafe/__init__.py b/py/src/braintrust/integrations/typesafe/__init__.py index 34b5a41eb..958bfdf46 100644 --- a/py/src/braintrust/integrations/typesafe/__init__.py +++ b/py/src/braintrust/integrations/typesafe/__init__.py @@ -7,12 +7,12 @@ def setup_typesafe() -> bool: - """Instrument installed TypeSafe sync and async clients.""" + """Set up Braintrust tracing for TypeSafe.""" return TypeSafeIntegration.setup() def wrap_typesafe(client: Any) -> Any: - """Instrument a TypeSafe sync or async client in place.""" + """Instrument a TypeSafe client in place.""" from typesafe_sdk import AsyncTypeSafeClient patcher = AsyncSystemOnePatcher if isinstance(client, AsyncTypeSafeClient) else SystemOnePatcher