Skip to content
Merged
443 changes: 188 additions & 255 deletions .agents/skills/sdk-integrations/SKILL.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions py/src/braintrust/integrations/adk/test_adk.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ async def run_message(text: str) -> str:

invocation_spans = [row for row in spans if row["span_attributes"]["name"] == f"invocation [{app_name}]"]
assert len(invocation_spans) == 2
for span in invocation_spans:
assert span["context"]["span_origin"]["instrumentation"]["name"] == "adk-auto"
assert {span["metadata"]["session_id"] for span in invocation_spans} == {session_id}
assert {span["input"]["new_message"]["parts"][0]["text"] for span in invocation_spans} == {
"Hi, my name is Alice.",
Expand Down
14 changes: 13 additions & 1 deletion py/src/braintrust/integrations/adk/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,19 @@

from braintrust.bt_json import bt_safe_deep_copy
from braintrust.integrations.utils import _materialize_attachment
from braintrust.logger import start_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "adk-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ async def test_agentscope_simple_agent_run(memory_logger):
agent_span = next(span for span in spans if span["span_attributes"]["name"] == "Friday.reply")
llm_spans = [span for span in spans if _span_type(span) == SpanTypeAttribute.LLM]

assert agent_span["context"]["span_origin"]["instrumentation"]["name"] == "agentscope-auto"
assert _span_type(agent_span) == "task"
assert llm_spans
assert llm_spans[0]["metadata"]["model"] == "gpt-4o-mini"
Expand Down
14 changes: 13 additions & 1 deletion py/src/braintrust/integrations/agentscope/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,19 @@
from contextlib import aclosing
from typing import Any

from braintrust.logger import start_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "agentscope-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute
from braintrust.util import clean_nones

Expand Down
1 change: 1 addition & 0 deletions py/src/braintrust/integrations/agno/test_agno.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def test_agno_simple_agent_execution(memory_logger):
assert len(spans) == 2, f"Expected 2 spans, got {len(spans)}"

root_span = spans[0]
assert root_span["context"]["span_origin"]["instrumentation"]["name"] == "agno-auto"
assert root_span["span_attributes"]["name"] == "Author Agent.run"
assert root_span["span_attributes"]["type"].value == "task"
root_input = root_span["input"]
Expand Down
14 changes: 13 additions & 1 deletion py/src/braintrust/integrations/agno/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,19 @@
from typing import Any

from braintrust.integrations.utils import _try_to_dict
from braintrust.logger import start_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "agno-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute
from braintrust.util import is_numeric

Expand Down
1 change: 1 addition & 0 deletions py/src/braintrust/integrations/anthropic/test_anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ def test_anthropic_messages_create_with_image_attachment_input(memory_logger):
spans = memory_logger.pop()
assert len(spans) == 1
span = spans[0]
assert span["context"]["span_origin"]["instrumentation"]["name"] == "anthropic-auto"
content = span["input"][0]["content"]
image_block = content[1]

Expand Down
15 changes: 14 additions & 1 deletion py/src/braintrust/integrations/anthropic/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,20 @@
from braintrust.bt_json import bt_safe_deep_copy
from braintrust.integrations.anthropic._utils import Wrapper, _try_to_dict, extract_anthropic_usage
from braintrust.integrations.utils import _materialize_attachment
from braintrust.logger import log_exc_info_to_span, start_span
from braintrust.logger import log_exc_info_to_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "anthropic-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute
from braintrust.util import is_numeric

Expand Down
1 change: 1 addition & 0 deletions py/src/braintrust/integrations/autogen/test_autogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async def test_autogen_agent_run_creates_braintrust_spans(memory_logger):
assert result.messages[-1].content
spans = memory_logger.pop()
agent_span = next(span for span in spans if span["span_attributes"]["name"] == "assistant.run")
assert agent_span["context"]["span_origin"]["instrumentation"]["name"] == "autogen-auto"
assert _span_type(agent_span) == "task"
assert agent_span["input"]["task"] == "Say hello in exactly two words."
assert agent_span["metadata"]["component"] == "agent"
Expand Down
14 changes: 13 additions & 1 deletion py/src/braintrust/integrations/autogen/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,19 @@
from contextvars import ContextVar
from typing import Any

from braintrust.logger import start_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "autogen-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute
from braintrust.util import clean_nones

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ def test_wrap_bedrock_converse_stream(memory_logger):
spans = memory_logger.pop()
assert len(spans) == 1
span = spans[0]
assert span["context"]["span_origin"]["instrumentation"]["name"] == "bedrock-runtime-auto"
_assert_converse_span(span, name="bedrock.converse-stream", start=start, end=end, model_id=CONVERSE_STREAM_MODEL)
assert span["metadata"]["endpoint"] == "converse-stream"
assert span["metadata"]["stream"] is True
Expand Down
14 changes: 13 additions & 1 deletion py/src/braintrust/integrations/bedrock_runtime/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,19 @@
_materialize_attachment,
_timing_metrics,
)
from braintrust.logger import start_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "bedrock-runtime-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute
from braintrust.util import is_numeric

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ async def calculator_handler(args):
assert len(task_spans) == 1, f"Should have exactly one task span, got {len(task_spans)}"

task_span = task_spans[0]
assert task_span["context"]["span_origin"]["instrumentation"]["name"] == "claude-agent-sdk-auto"
assert task_span["span_attributes"]["name"] == "Claude Agent"
assert "15 multiplied by 7" in task_span["input"]
assert task_span["output"] is not None
Expand Down
14 changes: 13 additions & 1 deletion py/src/braintrust/integrations/claude_agent_sdk/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,19 @@
MessageClassName,
SerializedContentType,
)
from braintrust.logger import start_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "claude-agent-sdk-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute


Expand Down
1 change: 1 addition & 0 deletions py/src/braintrust/integrations/cohere/test_cohere.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ def test_wrap_cohere_chat_v2_sync(memory_logger):
assert len(spans) == 1
span = spans[0]

assert span["context"]["span_origin"]["instrumentation"]["name"] == "cohere-auto"
assert span["span_attributes"]["name"] == "cohere.chat"
assert span["span_attributes"]["type"] == "llm"
assert span["metadata"]["provider"] == "cohere"
Expand Down
14 changes: 13 additions & 1 deletion py/src/braintrust/integrations/cohere/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,19 @@
_timing_metrics,
_try_to_dict,
)
from braintrust.logger import start_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "cohere-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute
from braintrust.util import is_numeric

Expand Down
1 change: 1 addition & 0 deletions py/src/braintrust/integrations/crewai/test_crewai.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ def test_kickoff_llm_event_tree_parents_and_shape(memory_logger):
kickoff_span = by_name["crewai.kickoff"][0]
llm_span = by_name["crewai.llm"][0]

assert kickoff_span["context"]["span_origin"]["instrumentation"]["name"] == "crewai-auto"
assert kickoff_span["span_attributes"]["type"] == "task"
assert llm_span["span_attributes"]["type"] == "llm"

Expand Down
15 changes: 14 additions & 1 deletion py/src/braintrust/integrations/crewai/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,20 @@
_parse_openai_usage_metrics,
_try_to_dict,
)
from braintrust.logger import NOOP_SPAN, Span, current_span, start_span
from braintrust.logger import NOOP_SPAN, Span, current_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "crewai-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute


Expand Down
1 change: 1 addition & 0 deletions py/src/braintrust/integrations/dspy/test_dspy.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def test_dspy_callback(memory_logger):
spans_by_name = {span["span_attributes"]["name"]: span for span in spans}

lm_span = spans_by_name["dspy.lm"]
assert lm_span["context"]["span_origin"]["instrumentation"]["name"] == "dspy-auto"
assert "metadata" in lm_span
assert "model" in lm_span["metadata"]
assert MODEL in lm_span["metadata"]["model"]
Expand Down
15 changes: 14 additions & 1 deletion py/src/braintrust/integrations/dspy/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,20 @@

from typing import Any

from braintrust.logger import current_span, start_span
from braintrust.logger import current_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "dspy-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def test_basic_completion(memory_logger, mode):
spans = memory_logger.pop()
assert len(spans) == 1
span = spans[0]
assert span["context"]["span_origin"]["instrumentation"]["name"] == "google-genai-auto"
assert span["metadata"]["model"] == MODEL
assert "What is the capital of France?" in str(span["input"])
assert span["output"]
Expand Down
24 changes: 23 additions & 1 deletion py/src/braintrust/integrations/google_genai/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,28 @@

from braintrust.bt_json import bt_safe_deep_copy
from braintrust.integrations.utils import _materialize_attachment
from braintrust.logger import NOOP_SPAN, _state, current_logger, current_span, parent_context, start_span
from braintrust.logger import (
NOOP_SPAN,
_state,
current_logger,
current_span,
parent_context,
)
from braintrust.logger import (
start_span as _bt_start_span,
)


_INSTRUMENTATION = "google-genai-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute
from braintrust.util import clean_nones

Expand Down Expand Up @@ -1158,6 +1179,7 @@ def _stream_span_context(
input=input,
metadata=metadata,
lookup_span_parent=False,
internal={"instrumentation": _INSTRUMENTATION},
) as span:
yield span
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ def test_wrap_huggingface_hub_chat_completion_sync(memory_logger):
assert len(spans) == 1
span = spans[0]

assert span["context"]["span_origin"]["instrumentation"]["name"] == "huggingface-hub-auto"
assert span["span_attributes"]["name"] == "huggingface.chat_completion"
assert span["span_attributes"]["type"] == "llm"
# With no parent span on the stack, the LLM span is its own root and has
Expand Down
14 changes: 13 additions & 1 deletion py/src/braintrust/integrations/huggingface_hub/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,19 @@
_timing_metrics,
_try_to_dict,
)
from braintrust.logger import start_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "huggingface-hub-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute
from braintrust.util import is_numeric

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ def test_instructor_openai_single_success(self, setup_logger, memory_logger):
assert len(llm_spans) == 1, f"Expected 1 llm span, got {len(llm_spans)}: names={_names(spans)}"

parent = task_spans[0]
assert parent["context"]["span_origin"]["instrumentation"]["name"] == "instructor-auto"
assert parent["span_attributes"]["name"] == "instructor.create"
meta = parent.get("metadata", {})
assert meta.get("response_model") == "Person"
Expand Down
14 changes: 13 additions & 1 deletion py/src/braintrust/integrations/instructor/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,19 @@
from collections.abc import AsyncIterator, Iterator
from typing import Any

from braintrust.logger import start_span
from braintrust.logger import start_span as _bt_start_span


_INSTRUMENTATION = "instructor-auto"


def start_span(*args, **kwargs):
internal = dict(kwargs.get("internal") or {})
internal.setdefault("instrumentation", _INSTRUMENTATION)
kwargs["internal"] = internal
return _bt_start_span(*args, **kwargs)


from braintrust.span_types import SpanTypeAttribute


Expand Down
Loading