Skip to content

[Bug]: thinking_delta not populated on AgentStream events when thinking is enabled. #20349

@alexplazas-wk

Description

@alexplazas-wk

Bug Description

I believe this is a bug and unintended behavior, but if it is not, then please give guidance on how we should be utilizing AgentStream events from BedrockConverse!

Version(s) used:

llama-index-core==0.14.10, llama-index-llms-bedrock-converse==0.12.2

Behavior:

Currently, we're creating an instance of a BedrockConverse model with thinking enabled like so:

claude_4_sonnet = BedrockConverse(
    model=f"{AWS_BEDROCK_GEO}.anthropic.claude-sonnet-4-20250514-v1:0",
    region_name=AWS_REGION,
    thinking={"type": "enabled", "budget_tokens": 1024},
)

We then use the model as part of the following FunctionAgent configuration:

constructor_kwargs = {
    "llm": llm,
    "tools": function_tools,
    "system_prompt": AGENT_SYSTEM_PROMPT.format(agent_instructions=agent_request.system_prompt),
}
.
.
.
agent = FunctionAgent(**constructor_kwargs)

We then create a WorkflowHandler instance and pull stream_events() from the handler, which are AgentStream events:

handler = agent.run(
        user_msg=make_user_message(agent_request.prompt),
        ctx=ctx,
        memory=memory,
        system_prompt=AGENT_SYSTEM_PROMPT.format(agent_instructions=agent_request.system_prompt),
    )
.
.
.
async for event in handler.stream_events():
    # custom serializer
    payload = _serialize_event(event, stream_event_types, thinking)
    if not payload or payload.get("delta") == "":
        continue
    yield f"data: {json.dumps(payload, ensure_ascii=False)}\n\n"

At this point when we're handling the AgentStream events returned from the WorkflowHandler with thinking mode on, the events returned for the "thinking" phase of the AgentStream lack the delta and thinking_delta fields. Here's a view of the values of attributes present on the AgentStream event during the thinking phase:

event.raw:
{'contentBlockDelta': {'delta': {'reasoningContent': {'text': 'The user is asking'}}, 'contentBlockIndex': 0}}
event.delta:
""
event.thinking_delta:
None

As shown above, there is no event.thinking_delta that can be easily accessed. Instead, if I wanted to access the thinking content, we have to inspect the raw attribute and select down into the models per event like so:
thinking_content = event['raw']['delta']['reasoningContent']['text']

Contrast this with what is returned from the AgentOutput event when returned:

event.raw:
{'contentBlockDelta': {'delta': {'text': '-Week Performance'}, 'contentBlockIndex': 0}}
event.delta:
-Week Performance
event.thinking_delta:
None

Accessing thinking content from a nested dictionary is not intuitive and feels fragile, especially considering the thinking_delta field already exists, in addition to the delta field on the AgentStream events. We would expect either one of those fields to be present.

Version

llama-index-core==0.14.10, llama-index-llms-bedrock-converse==0.12.2

Steps to Reproduce

The Behavior section of the Bug Description section has information on our setup to reproduce the issue. A checklist is provided below:

  • Create an instance of a BedrockConverse model with thinking enabled
  • Create an instance of a FunctionAgent using the BedrockConverse model with thinking enabled
  • Call the FunctionAgent with agent.run to yield a WorkflowHandler
  • Stream the events from the WorkflowHandler with handler.stream_events()
  • Inspect the AgentStream events from the thinking portion of the workflow and verify delta nor thinking_delta are populated

Relevant Logs/Tracbacks

Sample of data dump from AgentStream/AgentOutput events from WorkflowHandler

---
event.raw:
{'contentBlockDelta': {'delta': {'reasoningContent': {'text': "'t need to ask for"}}, 'contentBlockIndex': 0}}
event.delta:

event.thinking_delta:
None
---
event.raw:
{'contentBlockDelta': {'delta': {'reasoningContent': {'text': ' any missing'}}, 'contentBlockIndex': 0}}
event.delta:

event.thinking_delta:
None
---
event.raw:
{'contentBlockDelta': {'delta': {'reasoningContent': {'text': ' information.'}}, 'contentBlockIndex': 0}}
event.delta:

event.thinking_delta:
None
---
event.raw:
{'contentBlockDelta': {'delta': {'reasoningContent': {'signature': 'EoQFCkgIChABGAIqQEZN54U92o9LzJReFIQ7ySWGVnUthUxHCGHGKJLvxt4zSAoWZMzz2XY5BTk/MFNOXyHL0iTDPqmNdlwIsOF8xRUSDJHiRa3bM1FelTsTOxoMmP+F/d+fn0YLepEJIjD/EFGlR6PpCmNecbmb/I9+MLFQrUVLj0NQusO7FsrBJDDuHT+BAuIDoECJxRvrxk8q6QNqXF1YIgAc7g3LCdR+LlmQBYG7gEp3w1bRhop4XSlCilXLwJh5eiHOi+L7y4q05aKE8vc0zbj2u8M10TylwR2Dt8N5wPKNdOhT7f14uAQt9Z9hdZMF09l6XEFOZYlkFaZtCgG+0Ixo61BBMDvE+VwLrjGfu19cSxTLQ3xpbvkbNFTJZvT1imm+DLXn1TzYzh8pulH68fp/icVO6Z+ZhE9T+pXlVSups3pc7bs3BethT28kmK5nAFQcHwS5Nbx/9Y444rAfHsAPHEm+DOauzeTeR4oz6WHryyEjtggIdmAItm9Weg6Q+PUrGU7WoOuzyp64wHGSDaZWuT8O0nVGp/Wn+hisCljsVRzCM8ffxo55QheFJoAj118F/HqbLl7qPJCocPAQqCSXj7Bst0QoiptnE+S+zIk9jHBZBbP9sBrnZxjKCclNQMHUJWj4mgOcvzIWu83ww2irbjHm/GwR9MB3Orb5Lr/yreojJrjiaaRPda+zygMJ0Qk8vT0luABfShYZIaQ2sl66J9EPFga7UgqZ3nYRJCbvalrkFOGGVVXJO8o075t+qLPD1ulIynXCHVjof7AmhuO6ZTvvo87Gmv/wFbZwqeh7m08wUXZEaZHinN0zPu4Xocmw873qrEDTmAmsD3HIXiU2GCwYAQ=='}}, 'contentBlockIndex': 0}}
event.delta:

event.thinking_delta:
None
---
event.raw:
{'contentBlockDelta': {'delta': {'text': "I'll fetch the stock information for"}, 'contentBlockIndex': 1}}
event.delta:
I'll fetch the stock information for
event.thinking_delta:
None
---
event.raw:
{'contentBlockDelta': {'delta': {'text': ' AAPL,'}, 'contentBlockIndex': 1}}
event.delta:
 AAPL,
event.thinking_delta:
None
---
event.raw:
{'contentBlockDelta': {'delta': {'text': ' TSLA, an'}, 'contentBlockIndex': 1}}
event.delta:
 TSLA, an
event.thinking_delta:
None
---```

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriageIssue needs to be triaged/prioritized

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions