Skip to content

Conversation

pgrayy
Copy link
Member

@pgrayy pgrayy commented Sep 30, 2025

Description

We need to explicitly mark the start and stop of the reasoning content stream in the litellm model provider. With these changes, users can now do the following:

import json

from strands import Agent
from strands.models.litellm import LiteLLMModel

agent = Agent(
    model=LiteLLMModel(
        client_args={
            "api_key": "***",
        },
        model_id="anthropic/claude-sonnet-4-20250514",
        params={
            "thinking": {
                "budget_tokens": 1024,
                "type": "enabled",
            },
        },
    ),
)
result = agent("What is 2+2? Think through the answer step by step.")

print(json.dumps(result.message, indent=2))

The result of the above script will look something like:

{
  "role": "assistant",
  "content": [
    {
      "reasoningContent": {
        "reasoningText": {
          "text": "This is a very basic addition problem. Let me think through it step by step as requested.\n\n2 + 2\n\nI can think of this in several ways:\n\n1. Counting: If I have 2 objects, and I add 2 more objects, I can count them: 1, 2, 3, 4. So 2 + 2 = 4.\n\n2. Using the definition of addition: Addition means combining quantities. So if I have a quantity of 2, and I combine it with another quantity of 2, I get a total quantity of 4.\n\n3. Using basic arithmetic facts: This is one of the fundamental addition facts that 2 + 2 = 4.\n\nThe answer is 4."
        }
      }
    },
    {
      "text": "I'll work through this basic addition problem step by step:\n\n**Step 1: Understand what we're adding**\n- We have the number 2\n- We're adding another 2 to it\n- This can be written as: 2 + 2\n\n**Step 2: Think about what addition means**\n- Addition means combining or putting together quantities\n- We're combining a group of 2 with another group of 2\n\n**Step 3: Count or calculate**\n- We can count: 1, 2 (first group) + 1, 2 (second group) = 1, 2, 3, 4 total\n- Or we can recall that 2 + 2 is a basic math fact\n\n**Answer: 2 + 2 = 4**"
    }
  ]
}

Related Issues

#523

Documentation PR

N/A

Type of Change

Bug fix

Testing

How have you tested the change? Verify that the changes do not break functionality or introduce warnings in consuming repositories: agents-docs, agents-tools, agents-cli

  • I ran hatch run prepare: Updated the unit tests.

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@pgrayy pgrayy changed the title models - litellm - stop reasoning models - litellm - start and stop reasoning Sep 30, 2025
@pgrayy pgrayy marked this pull request as ready for review September 30, 2025 00:32
zastrowm
zastrowm previously approved these changes Sep 30, 2025
Copy link
Member

@zastrowm zastrowm left a comment

Choose a reason for hiding this comment

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

Would an integ test be helpful here? Ensuring that we get back reasoning content and normal content in the stream?

)

if choice.delta.content:
if started_reasoning:
Copy link
Member

Choose a reason for hiding this comment

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

Can a model switch between streaming reasoning content and text content in a single streamed response? If so, I think we might need to change this implementation:

Reasoning: Let me think about this problem
Text: I have thought about this problem, let me think about a solution
Reasoning: Im thinking about a solution
Text: I have thought about a solution

Not sure if any models follow this pattern?

Copy link
Member Author

Choose a reason for hiding this comment

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

Initially I tried to account for this but the code was a bit more complex. Since I wasn't aware of any model supporting this pattern, I decided instead to take a simpler approach and just implement for the pattern where reasoning is streamed first. I'm open to this being more flexible though.



def test_stream_reasoning(skip_for, model):
skip_for([cohere, gemini, llama, mistral, openai, writer], "reasoning is not supported")
Copy link
Member Author

Choose a reason for hiding this comment

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

Note, reasoning is supported in gemini but there is a similar bug to what we are fixing here for litellm. We need to yield a content stop block. Will address in a follow up PR.

@pgrayy pgrayy closed this Oct 2, 2025
@pgrayy pgrayy deleted the tool-validation branch October 2, 2025 18:35
@pgrayy pgrayy restored the tool-validation branch October 2, 2025 18:36
@pgrayy pgrayy reopened this Oct 2, 2025
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