fix: propagate reasoningSignature on Gemini tool use#1703
fix: propagate reasoningSignature on Gemini tool use#1703afarntrog merged 4 commits intostrands-agents:mainfrom
Conversation
- Add reasoningSignature field to ToolUse TypedDict and streaming handlers - Pass reasoning signatures through content block start/stop in event loop - Fix Gemini model to use base64 encode/decode for thought_signature instead of raw UTF-8, ensuring correct binary data handling - Thread reasoning signatures on function_call parts for Gemini
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Review SummaryAssessment: Comment This PR correctly propagates the Review Categories
The implementation approach is clean and follows existing patterns in the codebase. |
Review SummaryAssessment: Approve The PR now looks ready to merge. All previous review feedback has been addressed with comprehensive test coverage. Changes Verified
Nice work on the clean implementation and thorough test coverage! 🎉 |
|
My local run test: #!/usr/bin/env python3
"""Manual test: Gemini thought signatures with parallel function calls.
Requires: GOOGLE_API_KEY env var set.
Uses gemini-2.5-flash which supports thinking + thought signatures on tool calls.
"""
import json
from strands import Agent, tool
from strands.models.gemini import GeminiModel
@tool
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
weather_data = {
"new york": "72°F, sunny",
"london": "58°F, cloudy",
"tokyo": "80°F, humid",
}
return weather_data.get(city.lower(), f"No data for {city}")
@tool
def get_time(city: str) -> str:
"""Get the current time for a city."""
time_data = {
"new york": "2:00 PM EST",
"london": "7:00 PM GMT",
"tokyo": "3:00 AM JST",
}
return time_data.get(city.lower(), f"No data for {city}")
def main():
model = GeminiModel(
model_id="gemini-2.5-flash",
params={"thinking_config": {"thinking_budget": 1024}},
)
agent = Agent(model=model, tools=[get_weather, get_time])
# This prompt should trigger parallel function calls
result = agent("What's the weather and time in New York and London right now?")
print("\n=== RESULT ===")
print(result)
# Inspect the message history for thought signatures
print("\n=== MESSAGE HISTORY INSPECTION ===")
for i, msg in enumerate(agent.messages):
role = msg.get("role", "unknown")
print(f"\n--- Message {i} ({role}) ---")
for j, block in enumerate(msg.get("content", [])):
if "toolUse" in block:
tu = block["toolUse"]
sig = tu.get("reasoningSignature")
print(f" toolUse: {tu['name']}({json.dumps(tu['input'])})")
print(f" reasoningSignature: {'YES (' + sig[:20] + '...)' if sig else 'None'}")
elif "reasoningContent" in block:
rc = block["reasoningContent"]
if "reasoningText" in rc:
rt = rc["reasoningText"]
sig = rt.get("signature")
print(f" reasoningContent: {rt['text'][:80]}...")
print(f" signature: {'YES (' + sig[:20] + '...)' if sig else 'None'}")
elif "toolResult" in block:
tr = block["toolResult"]
print(f" toolResult: {tr['toolUseId']} -> {tr['content']}")
elif "text" in block:
print(f" text: {block['text'][:100]}...")
if __name__ == "__main__":
main()Output: |
Review SummaryAssessment: Approve Excellent work! The PR is ready to merge. Final Status
Thanks for the thorough manual test output showing |
Description
Related Issues
Fixes #1622
Documentation PR
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
hatch run prepareChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.