Skip to content

[BUG] Bedrock streaming drops native tool calls, so the tool never runs #7438

Description

@alanhuangyoo

Description

With a Bedrock model and streaming on (LLM(..., stream=True), or Crew(stream=True)), native tool calls are dropped. The tool never runs, and the task's answer becomes "I apologize, but I couldn't generate a response. Please try again." No error is raised.

The agent executor calls the LLM with available_functions=None and runs the returned tool calls itself. _handle_converse returns the tool uses in that case, but _handle_streaming_converse and _ahandle_streaming_converse only use a tool call when available_functions is set, then throw it away. The stream has no text, so the empty-content fallback string is returned as the final answer.

Steps to Reproduce

  1. Create an agent with a Bedrock LLM (stream=True) and one tool.
  2. Mock converse_stream to return a toolUse block, then a text answer on the next call.
  3. Kick off a crew with one task for that agent.

Expected behavior

Same as stream=False: the tool runs and the crew returns the model's answer.

Screenshots/Code snippets

stream=False tool ran with=['Paris'] final answer='It is sunny in Paris.'
stream=True  tool ran with=[]        final answer="I apologize, but I couldn't generate a response. Please try again."

The Converse stream events are the same shape as _make_tool_use_stream() in tests/llms/bedrock/test_bedrock_streaming_tool_args.py.

Operating System

macOS

Python Version

3.12

crewAI Version

1.15.21 (main at 894898f)

crewAI Tools Version

not used

Virtual Environment

uv venv

Evidence

Non-streaming returns the calls at bedrock/completion.py:741-752. The streaming handlers only use them under if available_functions: (sync at 1096, async at 1707), and the executor always passes available_functions=None (experimental/agent_executor.py:1567). #6150 fixed the streamed arguments, but its tests always pass available_functions, so this path isn't covered.

Possible Solution

When available_functions is empty, collect the parsed tool uses in the streaming handlers and return them after the stream ends, the way the non-streaming path does. I have a fix with tests and will open a PR.

Additional context

This issue was written with AI assistance (Claude Code). I can't add the llm-generated label as an outside contributor; could a maintainer add it?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions