Skip to content

fix(ai): keep Anthropic stream tool arguments after server tool blocks - #984

Merged
dustinbyrne merged 1 commit into
PostHog:mainfrom
breken-ai:fix/anthropic-stream-block-index
Oct 2, 2026
Merged

dustinbyrne merged 1 commit into
PostHog:mainfrom
breken-ai:fix/anthropic-stream-block-index

Conversation

@breken-ai

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

Anthropic stream events address content blocks by their index in the message. _AnthropicStreamAccumulator passed content_blocks to handle_anthropic_tool_delta and finalize_anthropic_tool_input, which look the block up with content_blocks[event.index]. But content_blocks only holds the block types the wrapper formats (text, thinking, redacted_thinking, tool_use). A server_tool_use or web_search_tool_result block still takes an index in the stream and is skipped in the list.

So once a response uses a server tool (web search, web fetch, code execution) before a client tool call, the list and the stream index no longer line up:

  • the tool call's input_json_delta events point past the end of the list, and $ai_output_choices records the call with arguments: {};
  • if a tool call came before the server tool, the server tool's input deltas land on the next tool block and its own arguments are replaced.

The fix keeps a second list that lines up with the stream index (an empty placeholder for block types that are not formatted) and uses it only for tool deltas and finalization. content_blocks and the captured output are unchanged.

💚 How did you test it?

  • New test test_streaming_tool_call_after_server_tool_blocks builds the stream from the real anthropic.types events: server_tool_use (0), web_search_tool_result (1), text (2), tool_use with two input_json_delta chunks (3). It goes through the wrapped Anthropic client.
    • On main (4a138e6) it fails: the tool call is captured with 'arguments': {}.
    • With the fix it passes with {'city': 'SF'}.
  • pytest posthog 4144 passed, 16 skipped. ruff format --check, ruff check, mypy through mypy-baseline filter and python -W error -c "import posthog" are clean.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran sampo add to generate a changeset file

🤖 Agent context

Autonomy: Fully autonomous

  • Found and fixed by an autonomous agent (Claude Code, Claude Opus) while reviewing the AI wrappers' streaming accumulators. The failing test was run against main before the fix.
  • I kept the fix inside the accumulator instead of changing the handle_anthropic_* helper signatures, so the non-streaming path and the formatted output stay as they are.

Commits here are unsigned; this repo squash-merges, so GitHub signs the merged commit.

@breken-ai
breken-ai requested a review from a team as a code owner September 26, 2026 04:25

@dustinbyrne dustinbyrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @breken-ai

this looks correct to me (and if it is, we could benefit from the same strategy in posthog-js) - worth @PostHog/team-ai-observability signing off

@dustinbyrne
dustinbyrne requested a review from a team October 2, 2026 18:13
Stream delta and stop events address content blocks by their index in the
message. The accumulator looked them up in content_blocks, which skips block
types it does not format (server_tool_use, web_search_tool_result, ...). After
a web search, a client tool call's input_json_delta events pointed past the
end of the list (arguments captured as {}) or at a different tool block.

Keep a list that lines up with the stream index and use it for tool deltas
and finalization. content_blocks and the captured output are unchanged.
@dustinbyrne
dustinbyrne force-pushed the fix/anthropic-stream-block-index branch from 9e2eb58 to 98efd59 Compare October 2, 2026 18:27
@dustinbyrne
dustinbyrne merged commit 053e734 into PostHog:main Oct 2, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants