Skip to content

Tracing follow-ups from the 2026-10-26 dependency update (anthropic tool_runner/streaming, mistral Responses, and more) #1001

Closed
6 of 6 issues completed

Description

Follow-ups found while reviewing the 2026-10-26 weekly dependency update (#998). None are regressions from that bump; they are existing bugs or new provider features we don't trace yet. File/line references are against main after #998.

Suggested grouping: items 1 and 2 as one anthropic PR (fix 2 first), item 3 as a separate mistral PR, and fold 4 and 5 into whichever lands next.

Worth doing

1. anthropic: tool_runner and message threads aren't traced at all

  • client.beta.messages.tool_runner(...) and, on 2.2+, client.beta.messages.thread(...) produce zero spans on a wrapped client, in all four modes (sync/async, streaming or not). Reproduced live on anthropic 1.17.0 and 2.3.0.
  • Cause: the Messages wrapper forwards unknown attributes to the raw object (Wrapper.__getattr__ in integrations/anthropic/_utils.py). The runner gets a method bound to the raw client, so every model call in the loop skips our create / stream.
  • Why it matters: the tool runner is Anthropic's recommended agent loop, so users of it get no LLM spans, token metrics or tool spans.
  • Fix: wrap tool_runner and thread on the beta Messages wrapper.
    • Option A: an outer span per run, with child LLM spans by routing the runner's client back through our wrappers.
    • Option B: patch the runner's per-iteration request. In 2.x the loop runs over a thread that calls self._client.beta.messages.create(...), which makes this workable.
    • Carry thread metadata (type, previous_message_id). On follow-up turns the SDK sends only the new messages and drops system / tools, so span input looks incomplete unless it's linked to the earlier turn.
  • Depends on item 2: once these calls go through our wrapper, the runner's streaming mode iterates create(stream=True) directly.
  • Tests: cassette-backed tool_runner tests (sync/async × stream/non-stream) with a real @beta_tool, recorded at latest.

2. anthropic: iterating messages.create(stream=True) directly raises TypeError on wrapped clients

  • for event in client.messages.create(..., stream=True) fails with TypeError: 'TracedMessageStreamManager' object is not iterable. Only the with ... as stream: form works. Reproduced on 1.17.0 and 2.3.0. The code works unwrapped and breaks once wrapped.
  • Cause: sync create(stream=True) wraps the result in TracedMessageStreamManager (integrations/anthropic/tracing.py), which only implements __enter__ / __exit__.
  • Fix: return a TracedMessageStream (or give the manager __iter__ / close() / .response) that ends the span when iteration finishes or the stream closes.
    • The async path returns a bare async generator with no .response / .close(). Make it consistent at the same time.
    • Hardening: since anthropic 1.16 the SDK passes along SSE events it doesn't recognize. TracedMessageStream.__process_message calls accumulate_event on every event, which raises if a non-message_start event arrives first. Skip unknown events the way the SDK's own helper does.
  • Tests: red→green cassette test iterating create(stream=True) without with, sync and async.

3. mistral: new Responses API (client.responses) isn't patched

  • mistralai 3.5 added client.responses.create / create_async (typed overloads, stream=True returns an event stream) and count_input_tokens. Nothing in integrations/mistral/patchers.py patches them, so these generation calls go completely untraced.
  • Fix: add a patcher and tracing for create / create_async, streaming and non-streaming, gated on mistralai.client.responses existing.
    • Usage carries input_tokens, output_tokens, input_tokens_details.{cached_tokens, cache_write_tokens} and output_tokens_details.reasoning_tokens. These map directly to our prompt_* / completion_* metrics.
    • The shape mirrors OpenAI Responses, so some openai Responses tracing may be reusable.
  • Tests: new cassette tests at latest. Older mistral matrix pins skip via a version gate.

Small, worth batching

4. cohere: rerank drops relevant_spans (7.3)

  • v2 rerank gained a relevant_spans request option (Rerank v5+ models only), and each result can carry relevant_spans: [{start, end, score}].
  • We drop both: the option isn't in _RERANK_METADATA_KEYS (integrations/cohere/tracing.py:81), and _rerank_output (:337) keeps only index and relevance_score.
  • Fix: add the key to the metadata list and include relevant_spans per result when present. Needs one re-recorded rerank test with a v5 model.

5. pydantic-ai: read RequestUsage.output_reasoning_tokens first (2.61)

  • We get reasoning tokens by checking provider-specific keys in usage.details (integrations/pydantic_ai/tracing.py:1424-1440). That still works because pydantic-ai keeps filling those keys.
  • The new field is provider-agnostic. Reading it first, with the keys as fallback, guards against the keys going away or providers we don't map. Covered by existing cassettes.

Low priority

6. pipecat: external function-call frames (1.14)

  • New ExternalFunctionCallsStartedFrame, ExternalFunctionCallInProgressFrame, ExternalFunctionCallResultFrame and ExternalFunctionCallCancelFrame report tool calls that run outside the pipeline. They're emitted by LLMWithBackend and OpenAI Live client delegation.
  • Our observer handles only the in-pipeline FunctionCall* frames (integrations/pipecat/tracing.py:159-167), so those tool calls get no tool spans. The fix would mostly mirror the existing handlers.

7. openai Decisions: generator-valued instructions (3.37)

  • questions[].instructions now also accepts a list of input parts. _decisions_span_params (integrations/openai/tracing.py:2198) only turns generators into lists for choices / levels and content, so a generator passed as instructions is logged as the generator object.
  • One-line fix: add "instructions", and "output" for tool outputs, to the nested-field lists.

Noted, not planned

  • harbor 0.25: TrialResult.reward_valid could flag rewards that shouldn't be scored.
  • strands 1.62: new public middleware API (Agent.add_middleware).
  • anthropic 2.x: new admin endpoints (user profiles, org webhooks, usage/cost reports).

Metadata

Metadata

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions