Skip to content

Commit d1ca041

Browse files
committed
better output marker logic
1 parent fd36e03 commit d1ca041

2 files changed

Lines changed: 14 additions & 2 deletions

File tree

‎py/src/braintrust/integrations/claude_agent_sdk/test_claude_agent_sdk.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@ async def calculator_handler(args):
263263
assert len(ordered_llm_spans) == len(expected_partial_usage)
264264
for llm_span, usage in zip(ordered_llm_spans, expected_partial_usage, strict=True):
265265
assert llm_span["metrics"] | _metrics_from_exact_anthropic_usage(usage) == llm_span["metrics"]
266+
llm_spans_with_output = [span for span in llm_spans if "completion_tokens" in span["metrics"]]
267+
assert llm_spans_with_output
268+
for llm_span in llm_spans_with_output:
269+
assert "usage_output_tokens_unknown" not in llm_span.get("metadata", {})
266270
elif _sdk_version_at_least("0.1.11"):
267271
expected_usage_by_message_id: dict[str, dict[str, Any]] = {}
268272
for message in received_messages:

‎py/src/braintrust/integrations/claude_agent_sdk/tracing.py‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,7 @@ def cleanup(self) -> None:
744744
"""End all open LLM spans, TASK spans, and TOOL spans; clear thread-local."""
745745
for ctx in self._contexts.values():
746746
if ctx.llm_span:
747+
self._mark_output_usage_unknown(ctx)
747748
ctx.llm_span.end()
748749
ctx.llm_span = None
749750
if ctx.task_span:
@@ -884,6 +885,8 @@ def _handle_stream_event(self, message: Any) -> None:
884885

885886
def _handle_result(self, message: Any) -> None:
886887
self._active_key = None
888+
for ctx in self._contexts.values():
889+
self._mark_output_usage_unknown(ctx)
887890
result_value = getattr(message, "result", None)
888891
if result_value is not None:
889892
self._result_output = result_value
@@ -1014,6 +1017,7 @@ def _start_or_merge_llm_span(
10141017
first_token_time = time.time()
10151018

10161019
if ctx.llm_span:
1020+
self._mark_output_usage_unknown(ctx)
10171021
ctx.llm_span.end(end_time=resolved_start)
10181022

10191023
final_content, span = _create_llm_span_for_messages(
@@ -1051,10 +1055,14 @@ def _log_assistant_usage(
10511055
has_final_output = message_id in self._final_output_usage_message_ids if message_id else False
10521056
metrics, _ = extract_anthropic_usage(usage, include_output=has_final_output)
10531057
_, metadata = extract_anthropic_usage(raw_message_usage, include_output=False)
1054-
if not has_final_output and "prompt_tokens" in metrics:
1055-
metadata["usage_output_tokens_unknown"] = True
10561058
ctx.llm_span.log(metrics=metrics or None, metadata=metadata or None)
10571059

1060+
def _mark_output_usage_unknown(self, ctx: _AgentContext) -> None:
1061+
"""Mark missing output only once an LLM span is finalized."""
1062+
if ctx.llm_span is None or ctx.llm_message_id in self._final_output_usage_message_ids:
1063+
return
1064+
ctx.llm_span.log(metadata={"usage_output_tokens_unknown": True})
1065+
10581066
def _process_task_event(self, message: Any, agent_span_export: str | None) -> None:
10591067
"""Handle TaskStarted / TaskProgress / TaskNotification system messages."""
10601068
task_id = _msg_field(message, "task_id")

0 commit comments

Comments
 (0)