@@ -4087,3 +4087,71 @@ def bar() -> str:
4087
4087
assert run .result .output == snapshot (Foo (a = 0 , b = 'a' ))
4088
4088
assert test_model .last_model_request_parameters is not None
4089
4089
assert [t .name for t in test_model .last_model_request_parameters .function_tools ] == snapshot (['bar' ])
4090
+
4091
+
4092
+ async def test_thinking_only_response_retry ():
4093
+ """Test that thinking-only responses trigger a retry mechanism."""
4094
+ from pydantic_ai .messages import ThinkingPart
4095
+ from pydantic_ai .models .function import FunctionModel
4096
+
4097
+ call_count = 0
4098
+
4099
+ def model_function (messages : list [ModelMessage ], info : AgentInfo ) -> ModelResponse :
4100
+ nonlocal call_count
4101
+ call_count += 1
4102
+
4103
+ if call_count == 1 :
4104
+ # First call: return thinking-only response
4105
+ return ModelResponse (
4106
+ parts = [ThinkingPart (content = 'Let me think about this...' )],
4107
+ model_name = 'thinking-test-model' ,
4108
+ )
4109
+ else :
4110
+ # Second call: return proper response
4111
+ return ModelResponse (
4112
+ parts = [TextPart (content = 'Final answer' )],
4113
+ model_name = 'thinking-test-model' ,
4114
+ )
4115
+
4116
+ model = FunctionModel (model_function )
4117
+ agent = Agent (model , system_prompt = 'You are a helpful assistant.' )
4118
+
4119
+ result = await agent .run ('Hello' )
4120
+
4121
+ assert result .all_messages () == snapshot (
4122
+ [
4123
+ ModelRequest (
4124
+ parts = [
4125
+ SystemPromptPart (
4126
+ content = 'You are a helpful assistant.' ,
4127
+ timestamp = IsDatetime (),
4128
+ ),
4129
+ UserPromptPart (
4130
+ content = 'Hello' ,
4131
+ timestamp = IsDatetime (),
4132
+ ),
4133
+ ]
4134
+ ),
4135
+ ModelResponse (
4136
+ parts = [ThinkingPart (content = 'Let me think about this...' )],
4137
+ usage = Usage (requests = 1 , request_tokens = 57 , response_tokens = 6 , total_tokens = 63 ),
4138
+ model_name = 'function:model_function:' ,
4139
+ timestamp = IsDatetime (),
4140
+ ),
4141
+ ModelRequest (
4142
+ parts = [
4143
+ RetryPromptPart (
4144
+ content = 'Responses without text or tool calls are not permitted.' ,
4145
+ tool_call_id = IsStr (),
4146
+ timestamp = IsDatetime (),
4147
+ )
4148
+ ]
4149
+ ),
4150
+ ModelResponse (
4151
+ parts = [TextPart (content = 'Final answer' )],
4152
+ usage = Usage (requests = 1 , request_tokens = 75 , response_tokens = 8 , total_tokens = 83 ),
4153
+ model_name = 'function:model_function:' ,
4154
+ timestamp = IsDatetime (),
4155
+ ),
4156
+ ]
4157
+ )
0 commit comments