Skip to main content
Glama

mcp-run-python

Official
by pydantic
test_openai_responses.py456 kB
import json import re from dataclasses import replace from typing import Any, cast import pytest from inline_snapshot import snapshot from pydantic import BaseModel from typing_extensions import TypedDict from pydantic_ai import ( BinaryContent, BinaryImage, BuiltinToolCallPart, BuiltinToolReturnPart, DocumentUrl, FilePart, FinalResultEvent, ImageGenerationTool, ImageUrl, ModelRequest, ModelResponse, PartDeltaEvent, PartEndEvent, PartStartEvent, RetryPromptPart, TextPart, TextPartDelta, ThinkingPart, ThinkingPartDelta, ToolCallPart, ToolCallPartDelta, ToolReturnPart, UnexpectedModelBehavior, UserPromptPart, capture_run_messages, ) from pydantic_ai.agent import Agent from pydantic_ai.builtin_tools import CodeExecutionTool, MCPServerTool, WebSearchTool from pydantic_ai.exceptions import ModelHTTPError, ModelRetry from pydantic_ai.messages import ( BuiltinToolCallEvent, # pyright: ignore[reportDeprecated] BuiltinToolResultEvent, # pyright: ignore[reportDeprecated] ) from pydantic_ai.output import NativeOutput, PromptedOutput, TextOutput, ToolOutput from pydantic_ai.profiles.openai import openai_model_profile from pydantic_ai.tools import ToolDefinition from pydantic_ai.usage import RequestUsage, RunUsage from ..conftest import IsBytes, IsDatetime, IsStr, TestEnv, try_import from .mock_openai import MockOpenAIResponses, get_mock_responses_kwargs, response_message with try_import() as imports_successful: from openai.types.responses.response_output_message import Content, ResponseOutputMessage, ResponseOutputText from openai.types.responses.response_reasoning_item import ResponseReasoningItem, Summary from openai.types.responses.response_usage import ResponseUsage from pydantic_ai.models.anthropic import AnthropicModel, AnthropicModelSettings from pydantic_ai.models.openai import OpenAIResponsesModel, OpenAIResponsesModelSettings from pydantic_ai.providers.anthropic import AnthropicProvider from pydantic_ai.providers.openai import OpenAIProvider pytestmark = [ pytest.mark.skipif(not imports_successful(), reason='openai not installed'), pytest.mark.anyio, pytest.mark.vcr, pytest.mark.filterwarnings( 'ignore:`BuiltinToolCallEvent` is deprecated, look for `PartStartEvent` and `PartDeltaEvent` with `BuiltinToolCallPart` instead.:DeprecationWarning' ), pytest.mark.filterwarnings( 'ignore:`BuiltinToolResultEvent` is deprecated, look for `PartStartEvent` and `PartDeltaEvent` with `BuiltinToolReturnPart` instead.:DeprecationWarning' ), ] def test_openai_responses_model(env: TestEnv): env.set('OPENAI_API_KEY', 'test') model = OpenAIResponsesModel('gpt-4o') assert model.model_name == 'gpt-4o' assert model.system == 'openai' async def test_openai_responses_model_simple_response(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model) result = await agent.run('What is the capital of France?') assert result.output == snapshot('The capital of France is Paris.') async def test_openai_responses_image_detail_vendor_metadata(allow_model_requests: None): c = response_message( [ ResponseOutputMessage( id='output-1', content=cast(list[Content], [ResponseOutputText(text='done', type='output_text', annotations=[])]), role='assistant', status='completed', type='message', ) ] ) mock_client = MockOpenAIResponses.create_mock(c) model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(openai_client=mock_client)) agent = Agent(model=model) image_url = ImageUrl('https://example.com/image.png', vendor_metadata={'detail': 'high'}) binary_image = BinaryContent(b'\x89PNG', media_type='image/png', vendor_metadata={'detail': 'high'}) result = await agent.run(['Describe these inputs.', image_url, binary_image]) assert result.output == 'done' response_kwargs = get_mock_responses_kwargs(mock_client) image_parts = [ item for message in response_kwargs[0]['input'] if message.get('role') == 'user' for item in message['content'] if item['type'] == 'input_image' ] assert image_parts assert all(part['detail'] == 'high' for part in image_parts) async def test_openai_responses_model_simple_response_with_tool_call(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model) @agent.tool_plain async def get_capital(country: str) -> str: return 'Potato City' result = await agent.run('What is the capital of PotatoLand?') assert result.output == snapshot('The capital of PotatoLand is Potato City.') async def test_openai_responses_output_type(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) class MyOutput(TypedDict): name: str age: int agent = Agent(model=model, output_type=MyOutput) result = await agent.run('Give me the name and age of Brazil, Argentina, and Chile.') assert result.output == snapshot({'name': 'Brazil', 'age': 2023}) async def test_openai_responses_reasoning_effort(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('o3-mini', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, model_settings=OpenAIResponsesModelSettings(openai_reasoning_effort='low')) result = await agent.run( 'Explain me how to cook uruguayan alfajor. Do not send whitespaces at the end of the lines.' ) assert [line.strip() for line in result.output.splitlines()] == snapshot( [ 'Ingredients for the dough:', '• 300 g cornstarch', '• 200 g flour', '• 150 g powdered sugar', '• 200 g unsalted butter', '• 3 egg yolks', '• Zest of 1 lemon', '• 1 teaspoon vanilla extract', '• A pinch of salt', '', 'Ingredients for the filling (dulce de leche):', '• 400 g dulce de leche', '', 'Optional coating:', '• Powdered sugar for dusting', '• Grated coconut', '• Crushed peanuts or walnuts', '• Melted chocolate', '', 'Steps:', '1. In a bowl, mix together the cornstarch, flour, powdered sugar, and salt.', '2. Add the unsalted butter cut into small pieces. Work it into the dry ingredients until the mixture resembles coarse breadcrumbs.', '3. Incorporate the egg yolks, lemon zest, and vanilla extract. Mix until you obtain a smooth and homogeneous dough.', '4. Wrap the dough in plastic wrap and let it rest in the refrigerator for at least one hour.', '5. Meanwhile, prepare a clean workspace by lightly dusting it with flour.', '6. Roll out the dough on the working surface until it is about 0.5 cm thick.', '7. Use a round cutter (approximately 3-4 cm in diameter) to cut out circles. Re-roll any scraps to maximize the number of cookies.', '8. Arrange the circles on a baking sheet lined with parchment paper.', '9. Preheat the oven to 180°C (350°F) and bake the cookies for about 10-12 minutes until they are lightly golden at the edges. They should remain soft.', '10. Remove the cookies from the oven and allow them to cool completely on a rack.', '11. Once the cookies are cool, spread dulce de leche on the flat side of one cookie and sandwich it with another.', '12. If desired, roll the edges of the alfajores in powdered sugar, grated coconut, crushed nuts, or dip them in melted chocolate.', '13. Allow any coatings to set before serving.', '', 'Enjoy your homemade Uruguayan alfajores!', ] ) async def test_openai_responses_reasoning_generate_summary(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('computer-use-preview', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent( model=model, model_settings=OpenAIResponsesModelSettings( openai_reasoning_summary='concise', openai_truncation='auto', ), ) result = await agent.run('What should I do to cross the street?') assert result.output == snapshot("""\ To cross the street safely, follow these steps: 1. **Use a Crosswalk**: Always use a designated crosswalk or pedestrian crossing whenever available. 2. **Press the Button**: If there is a pedestrian signal button, press it and wait for the signal. 3. **Look Both Ways**: Look left, right, and left again before stepping off the curb. 4. **Wait for the Signal**: Cross only when the pedestrian signal indicates it is safe to do so or when there is a clear gap in traffic. 5. **Stay Alert**: Be mindful of turning vehicles and stay attentive while crossing. 6. **Walk, Don't Run**: Walk across the street; running can increase the risk of falling or not noticing an oncoming vehicle. Always follow local traffic rules and be cautious, even when crossing at a crosswalk. Safety is the priority.\ """) async def test_openai_responses_system_prompt(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, system_prompt='You are a helpful assistant.') result = await agent.run('What is the capital of France?') assert result.output == snapshot('The capital of France is Paris.') async def test_openai_responses_model_retry(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model) @agent.tool_plain async def get_location(loc_name: str) -> str: if loc_name == 'London': return json.dumps({'lat': 51, 'lng': 0}) else: raise ModelRetry('Wrong location, I only know about "London".') result = await agent.run('What is the location of Londos and London?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the location of Londos and London?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ToolCallPart( tool_name='get_location', args='{"loc_name":"Londos"}', tool_call_id=IsStr(), id='fc_67e547c540648191bc7505ac667e023f0ae6111e84dd5c08', ), ToolCallPart( tool_name='get_location', args='{"loc_name":"London"}', tool_call_id=IsStr(), id='fc_67e547c55c3081919da7a3f7fe81a1030ae6111e84dd5c08', ), ], usage=RequestUsage(details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_67e547c48c9481918c5c4394464ce0c60ae6111e84dd5c08', finish_reason='stop', ), ModelRequest( parts=[ RetryPromptPart( content='Wrong location, I only know about "London".', tool_name='get_location', tool_call_id=IsStr(), timestamp=IsDatetime(), ), ToolReturnPart( tool_name='get_location', content='{"lat": 51, "lng": 0}', tool_call_id=IsStr(), timestamp=IsDatetime(), ), ] ), ModelResponse( parts=[ TextPart( content="""\ It seems "Londos" might be incorrect or unknown. If you meant something else, please clarify. For **London**, it's located at approximately latitude 51° N and longitude 0° W.\ """, id='msg_67e547c615ec81918d6671a184f82a1803a2086afed73b47', ) ], usage=RequestUsage(input_tokens=335, output_tokens=44, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_67e547c5a2f08191802a1f43620f348503a2086afed73b47', finish_reason='stop', ), ] ) @pytest.mark.vcr() async def test_image_as_binary_content_tool_response( allow_model_requests: None, image_content: BinaryContent, openai_api_key: str ): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m) @agent.tool_plain async def get_image() -> BinaryContent: return image_content result = await agent.run(['What fruit is in the image you can get from the get_image tool?']) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content=['What fruit is in the image you can get from the get_image tool?'], timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ToolCallPart( tool_name='get_image', args='{}', tool_call_id=IsStr(), id='fc_681134d47cf48191b3f62e4d28b6c3820fe7a5a4e2123dc3', ) ], usage=RequestUsage(input_tokens=40, output_tokens=11, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_681134d3aa3481919ca581a267db1e510fe7a5a4e2123dc3', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_image', content='See file 1c8566', tool_call_id='call_FLm3B1f8QAan0KpbUXhNY8bA', timestamp=IsDatetime(), ), UserPromptPart( content=[ 'This is file 1c8566:', image_content, ], timestamp=IsDatetime(), ), ] ), ModelResponse( parts=[ TextPart( content='The fruit in the image is a kiwi.', id='msg_681134d770d881919f3a3148badde27802cbfeaababb040c', ) ], usage=RequestUsage(input_tokens=1185, output_tokens=11, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_681134d53c48819198ce7b89db78dffd02cbfeaababb040c', finish_reason='stop', ), ] ) async def test_image_as_binary_content_input( allow_model_requests: None, image_content: BinaryContent, openai_api_key: str ): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m) result = await agent.run(['What fruit is in the image?', image_content]) assert result.output == snapshot('The fruit in the image is a kiwi.') async def test_openai_responses_audio_as_binary_content_input( allow_model_requests: None, audio_content: BinaryContent, openai_api_key: str ): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m) with pytest.raises(NotImplementedError): await agent.run(['Whose name is mentioned in the audio?', audio_content]) async def test_openai_responses_document_as_binary_content_input( allow_model_requests: None, document_content: BinaryContent, openai_api_key: str ): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m) result = await agent.run(['What is in the document?', document_content]) assert result.output == snapshot('The document contains the text "Dummy PDF file."') async def test_openai_responses_document_url_input(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m) document_url = DocumentUrl(url='https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf') result = await agent.run(['What is the main content on this document?', document_url]) assert result.output == snapshot( 'The main content of this document is a simple text placeholder: "Dummy PDF file."' ) async def test_openai_responses_text_document_url_input(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m) text_document_url = DocumentUrl(url='https://example-files.online-convert.com/document/txt/example.txt') result = await agent.run(['What is the main content on this document?', text_document_url]) assert result.output == snapshot( 'The main content of this document is an example of a TXT file type, with an explanation of the use of placeholder names like "John Doe" and "Jane Doe" in legal, medical, and other contexts. It discusses the practice in the U.S. and Canada, mentions equivalent practices in other English-speaking countries, and touches on cultural references. The document also notes that it\'s an example file created by an online conversion tool, with content sourced from Wikipedia under a Creative Commons license.' ) async def test_openai_responses_image_url_input(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m) result = await agent.run( [ 'hello', ImageUrl(url='https://t3.ftcdn.net/jpg/00/85/79/92/360_F_85799278_0BBGV9OAdQDTLnKwAPBCcg1J7QtiieJY.jpg'), ] ) assert result.output == snapshot("Hello! I see you've shared an image of a potato. How can I assist you today?") async def test_openai_responses_stream(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model) @agent.tool_plain async def get_capital(country: str) -> str: return 'Paris' output_text: list[str] = [] async with agent.run_stream('What is the capital of France?') as result: async for output in result.stream_text(): output_text.append(output) async for response, is_last in result.stream_responses(debounce_by=None): if is_last: assert response == snapshot( ModelResponse( parts=[ TextPart( content='The capital of France is Paris.', id='msg_67e554a28bec8191b56d3e2331eff88006c52f0e511c76ed', ) ], usage=RequestUsage(input_tokens=278, output_tokens=9, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_67e554a21aa88191b65876ac5e5bbe0406c52f0e511c76ed', finish_reason='stop', ) ) assert output_text == snapshot(['The capital of France is Paris.']) async def test_openai_responses_model_http_error(allow_model_requests: None, openai_api_key: str): """Set temperature to -1 to trigger an error, given only values between 0 and 1 are allowed.""" model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, model_settings=OpenAIResponsesModelSettings(temperature=-1)) with pytest.raises(ModelHTTPError): async with agent.run_stream('What is the capital of France?'): ... # pragma: lax no cover async def test_openai_responses_model_builtin_tools_web_search(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) settings = OpenAIResponsesModelSettings(openai_builtin_tools=[{'type': 'web_search'}]) agent = Agent(model=model, model_settings=settings) result = await agent.run('Give me the top 3 news in the world today') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Give me the top 3 news in the world today', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_0e3d55e9502941380068c4aaa4efb081958605d7b31e838366', signature='gAAAAABoxKrgd0uCWxLjgCiIWj3ei9eYp9sdRdHLVNWOpZvOS6TS_8hF6IEgz5acjqUiaGnXfLl3kn78UERavEItdZ-6PupaB2V7M8btQ2v76ZJCPXR5DGvXe3K2y_zrSLC-qbX4ui3hPfGG01qGiftAM7m04zuCdJ33SVDyOasB8uzV7vSqFzM4CkcAeN0jueQtuGDJ9U5Qq9blCXo6Vxx4BVOVPYnCONMQvwJXlbZ7i_s3VmUFFDf2GlNYtkT07Z1Uc5ESVUVDYfVC2qlOWWp2MLh20tbsUMqHPYzO0R7Y1lmwAqNxaT4HIhhlQ0xVer1qBRgUfLn1fGXX0vBb4rN0N_w7c2w-iwY-4XAvhAr-Y3pejueHfepmv76G67cJVQjzgM37wlQFdl_UmDfkVDIxmAE62QjOjPs8TweVPEXUXAK4itTDQiS7M42dS6QzxivPVvzoMkNOjJ58vUy83DCr-Obw8SMfFGB5sd1hGg9enLYiGxN_Qzs9IGegBU4cH1wpCvARmuVP10-CJe0jzSFy0OI76JUgGMVido_cEgrAF5eEOS-3vkel6L07Q9Sl_f8C-ZW04zF40ZIvCZ4RJfRAKr2bfXH6IVNhu528-ilQTCoCeFy_CG6UYlUY2jws_DRuTsAVb6691hPRI8mG28NCPXNGV5h8sVgypbeqWyBNZEnSgqFcNVplAPTxDNqlcFps5bEND4Q0SLSNTZv9vFbRvfyrf-4s3UWqn-SI4QAmGzKRRuTumEpldsTuZgv69Nu2qA7px1ZNu-hN7S0E7ONGDs2fCaUG4X-Xp3j2fizfaTkZpOC_sdTK5e10lIG019zKGngXSrBy_sOWyTIsjiRGdr0Va-RjDw2ruFr3ewQcH5vZ8LgUwTzijfqLqbkF1zgZopHTnz1Gpt42AbZiyP30S9BQuDODD8RmtZQ5oB1NKmISeGkLCJRd6dZKGibFskFFMFr53YvUfVZx4mRpxSjuadceNKPhTVkbGPYE6XrZbChCxDL9aJJ37ctRxf91r9QAXMqeFZR-4HR13_Pp0AyN_H7gqBR2yVuGbXkhs1QwkEhl-6_keNsJYUaRSSf5QN9gRjsuWchWEsTr8AqTbIApGO24a5Rr4GDnZ_6ICYBr-IhUesv0VJKQF3DcNFaOQCLtLTKCC4G4SqURt60V0zkQKWBdUdUGFkxDUN5gtcKrR0F4J5hvZ6OMV3XaP6kpgx62TL_gd9g_QyV8QDFwXuDDrGyXi6l68veZXOElkZ4lpVAjfeXnysK401DRt3vF0z99wUc-QVMjZG0wVZUr5rYHjKKaB2vG85n_onMrddThz2_a1NG_THQZ3L1rprThcQY7FdPtw1JXWfXWeS7ZuOOZCZvjyCrVhevaxTl5UKNbkguqYhNJQfx5X8IkwJWVRObA3QxFD0ZEgW9OKt-v-g_EAsjtftPbeeqaDfPBwqVguYJUEZqPPwcsG2cv8Xu5sCc6h7J8fvwTK-MY847JS5Q5CSDe4GDFvJn4Tk4aIOeGlr-VlrgwOS_yaKd1GogBIDzjh8pXIXXSDP2UkEOd2T0zSoa0u8oewPf8Pwmd7pmVb10Y9tHPgEo44ZQRiyVCe9S36BVjf1iZgTYetfBfq9JJom1Ksz-WUf74sHYfLkUY96lOlSvziyFFmTXxFgssLFgtBuWNaehKeuJ0QiQm2r4jEvX3n7dvUj09tWw_boLWGUJqL5YkxVadlw8wF1KRFJjGIAvEvO7YNoEoyolmS9616ZBvWNlBg54A5DITXEfIMloXVYNmYomoBloM74USiV7AjQE5hPIIqO97dW4btd2zMx9Nbr8G-nZsLgCqrqzDVz0UorAHTgaThtp9BW6VJZJ9q3Ew_z_494P7GNv9ehuK6m3fT-MXIq-t0Bo28YGgGhiFjoYSSYUd1adlHQdPHZCxZojt4-DxgD3iFoWQGc7BBRU3f9rRVRzbDvlHpaLRUQUFXiaB6rQ=', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'top world news September 12, 2025 Reuters', 'type': 'search'}, tool_call_id='ws_0e3d55e9502941380068c4aaab56508195a1effa9583720d20', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_0e3d55e9502941380068c4aaab56508195a1effa9583720d20', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0e3d55e9502941380068c4aaaef4b481959dfd7d8031662152', signature='gAAAAABoxKrgnD1AQrb0I2TSTLa6DiSpAwMbkF6gxz_b8tkkns4MZ4Rr6a8ejwmX7aGMoXEgOO2nkuLFeKoQBzQBrfNZIhmCy68QZMQQKZfKBUv1k8OAKzz4A1dO-xNH6xLMS-3cG4ev4zqjQEOBSGoZNKcZMU9L3B0VCvZsBU7S50g7zCcVwEk6H0wx4HO6IuUEOzgqqx8NYHmOkudSv3ikiHn1xhLc1JEzXkupTyRxyw1O81jJEpNzLlEUIFeu0vkAJrlwQzAHeEzxFMMQMoru3pKwnzujgljefGG8RY34jsAc6XcbJSstAa5GnKn24ehA_CQu80ICcibs7LBKsa3oO8wWWHXgDhMCPJn0N322MZcHfH77PhgEr-T1YSIRrSMPXcxoPaptN0O4ceK9BYN4FDRddaR1jXzWdZ3VhYBNbRrQEuO6z0TOWsPmzIlDql1a20jiOteGNQgIX94Af4PB5g_DYWzJW8YVffnhKXJEmU7BmYuctQgyewLj_CoQYfQ9HtGcae6ZElUEP96lo1ID3AW2iMa3iP4C2xULWDVh-8rWf0D2fgS1toexXXCtWbXn8XlYMGWVjq3WX5q16Kq0KyInuCZleABTeFRuzh0MTx1GaYhDTwHxG8BRPYUxz0bHHESz-h_UGmhGu8-a49YdBpLe36_Z1wprXJ82Yg7KvJy68VwKnLeH1Zm56aMHviJl143iZYgiZaVmRBIRExMvnI9LVAT5pv0Y3CdCCSq8Bs2jSbhU0xe26HAqfZZnAsE0LpPAfW1tMCiKzqhtzoKR6yauAYCXP5YtnX6BqFr-J8px6owPJhepjyrSVCObyya7v7_rV81BkYOtLQSwCUUhOjbawgI6XDQ_FK0hye5lFVKckFNM3cVpgRcZymeqx-XoQeoFOR8uLtcXv2DIoo0TfP7RxgBvAvdohv8vZx7xJSXlrYKqLEK1ASQDcc36gIfNQuNXM24WuXForXTO2l_sTeos58eX5FGxWJFDghhrNa_ia1dL7towjcegQzf9LtLjLlnqUGpEte-o23DKKQQEiFfMpLlvGu2cOVwYUuoeOpEBe7QpDbJGdBjq0hOKdakHGl6KwBw6vCkRp_wtW4R7QBuncdYyRT6AJ1_Z_byBP7kH1A2-P6QMVycBVcXlUgc0BzuGlkt51l__O3CM4z-PmI8zR5cL6ZCXoQzG2Yp-OhQ-n-3hgMaCfBGca6J3wP1vgQpR2AF0', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'Nepal protests September 12 2025 Reuters', 'type': 'search'}, tool_call_id='ws_0e3d55e9502941380068c4aab0c534819593df0190332e7aa3', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_0e3d55e9502941380068c4aab0c534819593df0190332e7aa3', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0e3d55e9502941380068c4aab3df148195bdec4fe186f23877', signature='gAAAAABoxKrgZN3V5pGaqoIM8EEiFso41O_kxOTWpzAh5Nlj3pqqDjIGrFH2zcmDyURpUmXdExY8L9K6KcwGOAlF6okEgQojeTxysBi4-gDVFNCVfp6c6K4tAtCBrvq5wC2g22Ny1pU2OMyxVU2GCxIIehCZiPQio_7IS8WY_VWkwLOag7bT4FBGn-aVFyoEfDDpIPF-4Zpcal6bAvdjD2hYGl6_-8alwh36ttUkJroo2qG-Mn0LsAWJ7YEzfrHgoPTDF7TB3Mfvvc5M_eP3pzY8O4WhZKMLBSnM92iIt5J3nSJYhRoiwEjaCamIM4vK0cnJR0oX87u_XtGvnNBX93ttrIrXDKK-mh-LIoe_sK1dViFINxk6rJHZvkFK12J6UXMK4me-C3uQ_qGygpw4uYvWhYk7LDR9Zgxfv1OoDg13DCYWWrHX7Oa1ALXPotk1Uw_Tof-Wc_wDqE16Elm1a5TP-ISH45v9W_Xl1IXo7J_jwOlAjkXvrh2a8YNljWQqBFCca-M2hSWvKuX8JuNF_tkI2q2E7jIDNt77jGd2yavqb1W2WoB_s7jqyAWomT91E2gZQtGJa4X2ydeTPQ_oWv2hgdTUynV0nbOKWA6suZixvxVDLLedhYHRnKY6EOtyso9MZav1qhr_DpHExn1_woquJXtS7c3Fe3Rs_YrU6PpRx5_DEVjVKme-3XjLJNclx6NF-rbXYqhXXExqPk-od7n-YMyrYhpfVP8lmLCewwyzVRb1koOEcCqnuhqM9DWyazKAcdvejM7VEM1AEk8ugT02cTiF7CfLefYFsLSYVBM0Ox47Ceh4BOA82jdlf1pZNvGqgHi8kKm9HLVh-yM_DAhD8O5Ub-SCd3bNi8735XPDWVIm6sKMdg1bcgVehz_R4iEBr_pguKfZUJLcckUTI6fitAQ6YSLpLAfRA0nMDBfM6p43jqsSCP8Ovjx58TwAPElgpme4ENBCozS_VaxmqawpfUfvnD60xia57wtSBYr5s1j-FUUjBsFTInjHdKcp0EBd3Pv-mpVE-Yj0MYExbn1upi3RxWN6jwVeYc603HQBjsjqsb-op9Tb0GZxf5Z4DpZ_eeb4IBTWNf3FTLIbsVg18Oyl128Std9CkMGak8iI_dFCvm1ZQQ6u3CyLEwxGsMZnkZl6OhSKDlnHDvRsF0F0OcRtFV5i7j92kMs9_qJ2JLdb5LzdqOBnFfKOcUCXBOflL58PYIav', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={ 'query': 'UN Security Council condemns attack in Doha September 12 2025 Reuters', 'type': 'search', }, tool_call_id='ws_0e3d55e9502941380068c4aab597f48195ac7021b00e057308', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_0e3d55e9502941380068c4aab597f48195ac7021b00e057308', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0e3d55e9502941380068c4aab85e7c81958c4b4ae526792e49', signature='gAAAAABoxKrghWofTkZCzljg86Akl6ch3bNwR70Wz37t6mBpLah1wZ-7U6isPixPCn0t66fA6xKxGX75bmjRu8Gts4cIaYpm78c8n6R44UULYfQoDC9ZEyGgImbQUKoHFU63nSbsjuPTTFtLdLHhEebDE_t6AfqIWBlyZKRqYlXS_8mTZ_NwM5_JgJun1Xz-I3Pb0X5ZgX8RTP_Kh7Kk79PStvg0-qcVoxMtFsK4ZN3fzQBOSUwvkMhglIweiS3s9CpTbtOs0PYqFCOIjKEYZ2-Rt_7SKhOGaWEMuvuWggMLeO_Wkl8HyIHre5JolVFR9M-43XByZXQxrvBxFzzwHubiyCs-WHFicgMyZcAF8e2KR9KdUJxAwQ3acCi3zBc7e5q1jgc8-Csm-vZQJMTyABDu4yuLena6rF777C8jq-naUe5M-bBpiimK1nbpg5YDiwx7-TbZz5eiTpptHL3P6izhgEOXuEvLhlrhxPBKTezDkiwu-wjs0tHguRYbOIMf-3NZGHuYnOcGfC2wJKkE9DmRvbicnChrLqzHmiXWblYhPwsH9wt-QDvrz3tgCH4B3ri9APreQjBmxtZEVGQAtfdm1qpgiDcWqEijrj05rvr4HxbSReCFszZJDYAufNhJSPhuJXl4e7EHRLyVd2uJA264ONj-MxT2WRr4MGzubSXtPd1QJn7IEkCCuPZxbLf9q27DTSpAvS1oZVs1Ad0J4lbRV5tS_sG54JLvpXf4jtYHD-R2CG0vkL1i0273IJroXScLaPELp0iJMn-WzAkbEjjMsX8gmZlV2X06XuvSjry-dh2sU9Yldqw4NHMLM8rpZIfKbsm6w0ub5Icmu19E856R57JM3K3Pjm3fdO3HR-adVsJTAaIusyUVX3SOiTY53-X6UbqBJh5H3WOORqkwW2nGbNur6B_tyRjlegD3CGJzC-A9rNxMWrecALmCEJBwnXxOuvpsGkSgjP8vjnY9JJNj53hxAirHFIxknDMrKt5qlsRHxGlCdN9H7YuTGdTSgPWH_L9C4BtZrr2Qk41osiDCpacMwBeUDwo1YwYWd1SO0DEzm2qGlXSYeuAQ6Fvyc7sZHCkOsl-bINhCuY1aEBOLzXS7kcu0YAIuEZGVp5wUrr2L6YssdrzpzQ_KENFI7LiB2v5CrF1wZN85H2dkwaGciOXznAa0Su1fWD3BUdpyR0h_mVIcHUxmeoCywWbWO-Do3LFu70MMxKmfSzVfL9hlU2B2jo1aqJ5HesWsWbsbslW5FfREayeUzK7hxkrjliDePhN6gkfy0HOYQijPN6dko4TNEeKFO6Q-aw7c4X5IF3WBCYd_IszlLBK-vTX4EX2J5QtaLRfwFgRwz_K2fkOTT64eknQ6R3fFJpgeyLBZ5ut7j2o7xhEuHeE4KPm2T_AJi8yRScMU-ZsDcUZ8IVYAduy2TGov51AM7K2WojgvqWi62AwSLd16eEnd7SUD8fiCwtRN3zTdmh3MenUogxtKG2YL4hUvSN6Ia1STXpfU4ToLvBnPS5FoY2GuOG-EdEAHdKfYsSUZmSauAlQy7sT43STLkDE42lOKWqtSNHOygkGUodv1GNR0sA6CIg_gVAOyUG-o20rMsfANynNokpoKxJBPJScf1Mbivm-7wJFRipf2-Ay4HzXhXZ4RTkpoq2MMC7cZkHkEprUlLshEhCIHF_6sb1Uhqg4E3UPCCNZ-X0epbQ2GmhtaaIt6BCnWz4SccN5qTks5XpQarlyTW1HubLoLjjXmwJ5DImdUGZkitiJw6ermiOFAFhLfhug-XVKBcTBZOG_CHjrR_2j5TPn6FNLHbYpLYS5hkrUWCJy4U_1xebGl3F6VdQDy3LHZehxuKPowPtdYFenqdJ-naK_A2ygjDUdGBoB2-QFaq8ZPTAti5_Ca6LgiZPvzZdGZ712BED-Opges0mwyAhhsgKRvjjztcsiZ21QpfUaSGLS0vO7J-NcRVvCDyBisMRKfRcWk0PFa4LKcqx9_FNU9nqXH1RXYh_WNAJRVLJDR3WzpNzDv7xMcPOYUUx0wuAYAWcGbc3i5mkVRlzRW_WymBibPF_Y9Yf5yt7plmai5dzlg6aoRdrzSwT9Lphrf79QI3LfYzOV4sXmRGEnN1ud0FyfVB4aLHSsc59_eiPswLL-xg8XT0L27IU_Gja0VuE3zBlErtlQB4uPq778Ojs8hucNTD0rjxs2qqA==', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={ 'query': 'Israel airstrikes Yemen Sanaa September 10 2025 Reuters death toll', 'type': 'search', }, tool_call_id='ws_0e3d55e9502941380068c4aabe83a88195b7a5ec62ec10a26e', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_0e3d55e9502941380068c4aabe83a88195b7a5ec62ec10a26e', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0e3d55e9502941380068c4aac1c2e081959628b721b679ddfb', signature='gAAAAABoxKrgINXOfVTRxYfQpc8ZZGXsBHdv43DhHkpUjfExhAS41ACM9vHyRgDNfC9E62QVMWRCWPuz5QX9ks0NtD76PYS8n5bessBYeBtYgbiMtl0piW1gE5dlw-BeKLiijMhIVwytWhF3JTzoxoA60FjPK_sA8mFk6wDCNKDXlaLWsLaECxUwCtdktN9SQnQFgxKNemRKQTyRTNKsurCZSSt0tHyd4lxO0Ei3F2mO3WB4Oq28BeVG7RKlcZ9BmLRdBhFQX5eoLxTBHwC_qgSIGzoVCiyClW1OzFzXzmaCUCm3oUDQjooYIZtQqK1b8FBArzN9seOJ4vuxu2qqdtF-JC1vAi-_9J61EwELhN5gYvld83zGCSPg_asjeKeoA6qnA5RFtYwh5kmMSFo9VzGp9MlCmb4_-L-iux3JKc7Kz-jvF1sXSH7YfKgBvcn8HcOdXGjU-aBJTmdP3hCZSL9ko-NNsUO31667QwMZsQTlVoTCAfWS_xDEI0QgmV2kFReKhKanzMmOToUECPPQHQfofCGxwxjbGllSyhpSZHIdyjXpHBmwFALBflPAfeM8wUbqQbNyWbWTdx4Uz62Z4j0OGfcMpgMlDb6BON8vvpIjmlV-fOqRlzkP97klPBygPKeRyT-UezEN5Vj5t00nmB-cV2kNj1WYmL8-eBuJPs3LOU_4Q3ysb90AxYxRJGOsl74lEBqfUKb6b4JWff9JFv11EVJ-puIpE7MA3DPM4NcgGfDZYyDvLS589wbTVxSngBqEOIOEcAZF5Tae93Drajy_x8fXm9uWc8daMf5kqUeq_vwr-ZqEz5ZBUvhvGPL7xkYfTfn-RrQXBx2JfyDRakf4X4D1W6jaO_LXfExH922e9hQ1vH8VA_GPdOIqL5BTiIeO3qFjDSRxMi94XWPPRm87yStxEjx8bse00Bzi3grZ1c6M5dEUXNaHrnvEdJZECT6lz365_Qbl73_Ma_2CLYZhLhtqZRZ6Tycfpprg7rWxqTftOKq4twUgCzzv7kg0e1f_JM_om5loPP6r4MOeAL9O1p49tWmj1kQt_nmYcX1WFTQOgRuB_h3t6ZeOsDb3-VYjIjK0pvj_X_VArrT2suBVitTBXumnG2dXg_z2k5t4KTbWVe-aaGhije0VNxgPWCcu1RlIxOaz', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'typhoon September 12 2025', 'type': 'search'}, tool_call_id='ws_0e3d55e9502941380068c4aac378308195aca61a302c5ebae6', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_0e3d55e9502941380068c4aac378308195aca61a302c5ebae6', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0e3d55e9502941380068c4aac5d2bc8195b79e407fee2673cc', signature='gAAAAABoxKrgkfoWE9D7tW3LtG9Hb8kBR9vHgjhSKvDrW0_FUU34LIByJhhBiwZOr5RfbqX9mBwahQKrIVAev3WGtBfgtJF0kP67CIXXRjA1-RHuY-4QXL_w-t9gttak5Dje2NU5hNyp-LyW0plO7DZwZDkFUgeW5plxMzcAFNTdflBSC_-zYqBFl9p-11YKOslzKYxkfQrDiodarFGFhDOJr97qwo-l4BhSg8jywQwgFOTSrOjJMlZRSrTkHd8CUaSF5rUaLKpY4AZWtpiR71otchA9N-d0AaVwnnzJbe53PXJpe4fGUkmkcZt-ZOcNTQlIpifirDsXln2Sc3jxSM05fteSPKoUeUFIIqbCaZwBPau45DKq54PvkVQ4Fpv8JtfqKEuQtJ6EVlNJALuDlskdxM2H3Z7XJsXkcNCVAKmpA80yYwh3eApMr_cERl2bLS9jJpGt8QN3z1yRe5oCPCNWj2_NTgtzjknxcFy8HdT-pcTzLDOhLJPYyl66psc0Hn8V_GFIFkRBa8tWb7CTLt77a3pW3Ifnxov5ANAaaJLM9gGiH_DgkkuNZMR3dz2sVnHzAG5TxmSQteu-uYQgIYanBH_D2BN24JfBFxckpT0z-kGHbJnL5q_wBeyy7o2puohaH3MNIluzWARcDWaFa1tGkzeZg59woqrrddAdWLRNULpnX9fzr7aAWXr1U5-XkSjyfWa4nmIFtchwPSC-12wHRNFDzdZiUvQDdJ2ENGoIXeYpob_O4Wa5zx4zZj_qHXoQWXLELyEMJZCVADjAjO8uy2gXDxZKcUxyDgi17hIyFtC9Z_4rxDbV_S_JJ68s1qHBZljuH0mrkLU0KXmYi5ZgB_z1CEaz9KkL32FGBt0YXuFoR0LjnrdpOTa9ifWC82ZhDfjz1E4y9FUoGPVl-QYQ5ihDY0LswB1x_FJfvwRLvLRtMeeGqNYEwnkX-XAcVa72acijnRJVxd5WjV5nolIrtq55l941oeun2ThZJZWujP7eMDuQ8SycBOx_6Bz6wECDbnCrfyxypwpVhKSPGuI1IoP_8fCeFDWzZZhD2bTbH2Uw6nzm9SLODQ47GqYlZ6ZtTIgNBlGpiSUrqXhtj9_1hkGZuGv6AE9UAjFNqAWX25db2I2uH1MXdsYRPLZFhYan9G60cozj6N0ekasNkbaAod39JQ7zL6Np2O_qz85s3bcJSS1_aIxW4YFSEv5IYFlztQrhnlyE_gloA8eRntHAinUaGbL9IKTmuj4w74Al1sN7ELITivL6aZ-EM-F7vvFM6Rt4gL0NvlfTYsafoUL99EfBTh3Rfl7pIwOQWXxg_p-51s13BQ1-HWOQxu1lyxbZdJHmhi-tIzk9iyQh1tbkCZJeh_qF-eGH6voxUlcz07gvTckVKR147UPjIrfSm6EO5zXBgva0Zk3nvGFCZshZSau3tLQrAnB7hQ3AAyQT8_6eFBHtsscuApVGtRYIw3vi9decgXmFdvSEg4Iq6JNObTilSq6a3zmUt8fop_M5qYzq-0ctNsXN5lkqi9iB19lLw9EyHNDgClaTAviXWh6aDdbWP-atkQQ82PXBnKJAiP7luW1qf-YVHtKkwNadbMy82CT-dMNu9c-chRSx3g0tdwTex6tgwKMdBRbPWa8NVZreuTy8x2yarHskXhHM21jrexM0pMbk', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'Nepal protests September 12 2025 BBC', 'type': 'search'}, tool_call_id='ws_0e3d55e9502941380068c4aac9b92081958054d2ec8fabe63f', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_0e3d55e9502941380068c4aac9b92081958054d2ec8fabe63f', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0e3d55e9502941380068c4aaccad0c8195bc667f0e38c64c2b', signature='gAAAAABoxKrgxBU1Y3g_B0Eo5nVBHYxLC3Lgh2vNx7AcpSm-o7XiHfQvzLqaLvkI-Cc3F15mQexU0OTvx9FePdIKbwkMNm_X_s_K7YazPjZUTQ0TEod2VereH-Ebh6Xjq3bHm7mh5PWWGnY2SqVMCdKGtrXkoMzBraxedlv2-Tz8o0p6SYuyzM8yHecIfkG6Zd40AdZSiDzsnRNg7gA0zCddrDrRcOpeMTzSPw1z74UZtng-_pPeiv-TGCgwdlmBv8RRr2cuQTYE-yhcp6doCMKqemL8ShuIyfJz0KhQPwYE1zM1CB8sFc_TuArJJD3V2U-Bl3o8anIA8X7YclTlzz_N7HROtVI5qFQjSNhSrbxZKUBFDfAayrpQBEOyIRu7J42uAiBmoyms1WG1E2UtO69nx2ELSJs5yheEuVy4cTXyndBJr2sCs8VkVvcX7xvYkfKeChvkAbUfCotc991qAiyVNzhncM2Z31IEXDEDypeo2IFSwAcKuuXgePFFPBiJxmNQAQmErqbSoB3Woe1j5XjAzJ2eY5YEBZ-68GI3B5wmiZOLsPla_L4iBrczHI1iwGASgtMsuHPj5KVzwef093kg9QBlt-7pZHM3yoU1l5DFSJ5C168MdMdNGF3hn0T2Q3teUmJ5khgcKMKz4_ZVUjEDq8bPwp8DiaWlFgTv-Y-I8etik4o35EFmmmZbIZ7tk69xlBrGizm_KlcYWHBQ5BfuNyZDXZ13MKDyn4uyYxRvkHq4z4jPFEiZ3xX79mlNP3-B0T9g8CsqX1G1prKI7lde6oAHcWPFSWqZmM_JxvYXDBbck2DpEpx4xTuE_iJfGnKiNzanqV4EdOXiCTBVLZhMvXj9rAbwnhttvz5WhIeYAdsKEE0M1MUHuSWuWFVtClp6lPKSLtHQCBtE6mpPDyzUuaw6S1DoixZ6f33Sr8DB-EwF_deHRa95kEN9w4i_LqNbl5QQPF_1je6spo-yQTDpHc5wUidI0fBEQzM57rr9XH0F2afZtrQv9HcLfWKVufBTdd7ScpyOaKj70zgqTAq08Te-Yrj9eo3tbDt698U1fKEYW_uqP48ZKmnSNtFzKOoBzkPpKcwA5AQUiFOYH4-iDPDTOH23SYx8vlymoRiK1imCdPwWYI3miMURxPr9-zCHoM7AiB8cnJlD--zk-j1vQqcf3AntIKPwqycSEuJ7MWb9iN5Ybd1YE25_ZiXKJNVg8wnmTueelRdeM-2JVzAQwth1_3gnsemXn5v0uDVNpxvXoRtR1w8L_zQzKzag8kZMvfESnLCAEwYsCcrP-ngO97iKVvUQnII4RUtG_mSPV4V6Ses_cMUVqyHiM_W_frIosY-7dXnlox89-SPWrRwyC1jlGRA_LE1fpPZ2cZU7Gcyzrxp6yBuTCx8BHr9FJvqgbqtAUeYDpr_Sv-RsG8-w4IulSNZLH5Bh8TyvBGDhi8_lUbDCFTS3KI1ZJ8KJwbNLxF4YUI156zkWIN5yU0WDVlwoxpJD0naMPZzR0sQadMuaXEvLXTFm9Gtb667B2cjdzJqbb8z6NkAx3txRRD6EoezoYADq_ZR_LYha0iwv3bHvg4HIblhU_GVhnU-a-lQGQhTJ5Mh4OmrnTGUVD2Is1OVI0EmNscUuaVc7M1_ga5KbOgyff6bYS0ARh3Io5ekKQKkPVyBLgjjKlej4tB-vSEgitDhEJ-PD__ouuFaogm6twZy7hWVn9cgJmt-RHDZ6gOZm4QP8dWqRpuyEAtTpWR2TLTQVgM05hWpDqDL5AvBjAQ_GWkHCvdCvUINyyl5TsyXUcL207shrLUDCpBe_kESpF5dpAVng8_Zfu1dt3c04cCG1eg40e9JcO5iA9-upTrEPIPrXnAKy4vw-vbhQyL1r2jZWRVga9Do2idmzVf-c7yQ_AHGmf62SHGm-qqbljw0sXJe1rdPt2IHxzYXkhxpqqoaUueQk-pXLUvpMFeMcH97sK3toeCO3oiWQPG-nev0B0b__U8ntgI5m9df6n4IA97iS2zSylSY-F-XEJmLM2TKuSEdgAx1EBL_jyRQKB_8PW-0hSQGJLT70SQqDUJexwyrKABkApv3FuSH4FO0rXZ9TGN3GsnJSkIrTrzE2NG4OXK4syrmtBCb8DjsiicvjAvQhcouOM1xMZ89aSG9Psx5HRnViy6M73TIhYmWO71BRNEayMJaOMgUlgpl5alvV1YFBsChL6mxLVAJWUFuv2YPNaaDRqZEXYHWljhwSn24ASetweLc5GhnehdiT4JVJ_nfT3bygPIjEzvvIa7bbJSeL_bcY-qGAgsuR5m70BdjIH6xLmuqn3lEqulh9n6IPaDciryWqRr1OwxZJQ0-x3u6-G1wrbtrhVMK2Z6cyNUX6MvIMz39B_782X4JcLMrVm9Jgt6qzmfbJPnGA_NK3e9dlz6hP_AYoY-Je-IZEtpv4wyXAYE8v7QXsZbf6DetAM2LzGmxkEI647-pwVPQua-L-84L56GoAw9yDeoXxgyxyf40sbaPIiVLgl_3A4Nghl7uOnOX_1VnZL2X85zCkOZbmm5pZbuSeKesBYbX002PN-_P-P5xRv5b8dZzD0utGv4GUuZJXKJPhbpv8cuBUR0BYHKBQkmOzOBxgCFCDtX84VkZcrFwmQHcS7zmjgqEl39UNrqq6NZXW6HZDyi_SSvEYV7eJfJfxnUUF7RJ49RtSbC9n0AkzorBi0mSMnCC_A1zhamNLjT1-tj4E2a1zI9YsBZ8lPv3t7a6U85iMYjl3kCPiAXkRIDVBihBK4ki_OEa4v6kNBEgXNMuFmd1l8O3WTqZRSTLek4yH95V_uE5DQ9NH52pkgrN7QOe0QXxZ0aErqjkSQRbbhFVVRYp2VN7QpvMGZIAtu_mGssA5Id3X1ZsLEU9zGNibIzAmJdBjS98fVj2MsD-4qZmzlWiCGcC5ko2bbpTrFGtr4r3-SNc4UMOa3dsdyrRlnK3o_tbXbPN7c1H44oneAsqWuekfUVFGvCRm3yA0X7njFB2l8tSXkAuophgRUlWnzp4mEMcpFRwEX3WEnK9hPqXEhdirLtC18yupkKYBtIpCIT98zgJNb5TRbfwRplInEG1E8dk4gCbwyXCNu67QEI2NM2yqCHc4P5rWhwTGAl30tmDQ064ba920L9ZV8d6PgpBHZmUxpJ-JUZuYMzXfCFdlBQANdjtuxCy3-Pi0-cO7UEA84WN-keYB-kHck3aPpeTG7-lv3je0N-407H_A1TKUqkSknjlmwVdL3h41bbGmqxFGizNXfq-uCGUD2tWaZ-cdmZZtGXxgEQ2z7_tLur28eS1tlx43y9CKtKPPJruJm_7BljMOCMPnSmOJDI0JnoGpjNRqzKbSuZFTihaQSBo_Vc-NxRpFwM4xJgq3z5eShb_WamKw9uYrjCBEEwYFTW2QjmiQJtM9eVHBuLkfOVa66YZowcCvL8aCccsuPbe7KBMCD21IGzH4nlhfgUKa1cTAUiWjRSgn6SO5Wqahxs7dEf44F5HvPG6XUy9HFOe-d61ZE-tJQsHZgssQWqV1UfPsccqgyWIc2yv9aK4pPpu2lcrlGu8aDZDz7pBD-dPUG_B9XWt5c0CQj4CCnURDATNWqH8J8VvKap6Zn7pBHW_PxNSJ3f0z_l-GjBlx7U4w6XmOMBtJK8lE_Y8CuuQY9dNVnTGMPibCeJt7M_Q9-IYcqhriUh7Q5WkCvDVu8157gIRwwUAvgqsWcD2msXtO9svRkXKxNxYFdW7KolF-y8oxXRPwVJy1bf89pAOa8djb21ovJuJmbvrRzplFGYNj8rGZ2hXenxDoYiKv71LGALVU63mS9q-Y1zfTHCPpA-Rw7oR6T5G_Q35H-elaA_u-vkgh64mQNP5sgc_kpwbVlM0wSl79RcExnmBTpA-kn7B4w_QPwt185WD9jQRjhh3LMQa_crf4nCWLlsYcDCyB07TU0vXQiQ3nynqsX2MstUc2DaiseVG1SO0UEv8oobwLhnSvl3n8zWMWq93NSuISAsaWmqriNhM74aSHw4CVPoO68RSSdNrpxaKGf8kuO9Xy6iLr3VPE_vyMJDq65q42AEvKqP0TCoFUzXA28Tkrg0tsMLsXIhuT5MGtO3O8RpLnthF9vT0lM64jMp9_QSH2BuWYtwgok7xk3gRX5yBQeksAos3c7Jn2bLM9VNrV9dLi7MH_mRl5C64b0Lgj6Zi1USCyyPhL95ZJIvdxLWHSII2RFbL9ToCThKp_cgPZklLAVJXBeIOqG09pIQ==', provider_name='openai', ), TextPart( content=IsStr(), id='msg_0e3d55e9502941380068c4aada6d8c8195b8b6f92edbb53b4f', ), ], usage=RequestUsage( input_tokens=115886, cache_read_tokens=92160, output_tokens=1720, details={'reasoning_tokens': 1472}, ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0e3d55e9502941380068c4aa9a62f48195a373978ed720ac63', finish_reason='stop', ), ] ) @pytest.mark.vcr() async def test_openai_responses_model_instructions(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m, instructions='You are a helpful assistant.') result = await agent.run('What is the capital of France?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[UserPromptPart(content='What is the capital of France?', timestamp=IsDatetime())], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ TextPart( content='The capital of France is Paris.', id='msg_67f3fdfe15b881918d7b865e6a5f4fb1003bc73febb56d77', ) ], usage=RequestUsage(input_tokens=24, output_tokens=8, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_67f3fdfd9fa08191a3d5825db81b8df6003bc73febb56d77', finish_reason='stop', ), ] ) async def test_openai_responses_model_web_search_tool(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m, instructions='You are a helpful assistant.', builtin_tools=[WebSearchTool()]) result = await agent.run('What is the weather in San Francisco today?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the weather in San Francisco today?', timestamp=IsDatetime(), ) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_028829e50fbcad090068c9c82f1b148195863375312bf5dc00', signature='gAAAAABoycg20IcGnesrSxQLRh2yjCjaCx-O9xA4RVYLpo0E7n_6m0T1IUyes5d6U4gDzUNRWbxasFx_3NEhFIuRx4ymcqI_K-nZ6QNsq3V4CgwBbWBXRcBEDVzXSZZ4IoFASBzHpQGbs80RvZkgqmJkk8UzBw0ikt1q9jlUrwMKf1iGdH-S0fIgZn_uEbli1yGWRDryyS2YQWDKNTYuaER_WHVg8DadL6_ltUTwJ9dMzaXyFEenPfuLdDgmba8DP_-WYFMbggATUfdMNfM0O4YqnTmjR5ZnSA6kAbXvnp9sBoC-t8e2mWiCXzvy8iIJozNPo_NE_O1IcMdj1lsaY3__yWzoyLOFCgkrZEnB-_WQNCSx-sVcWWLZO_Tqxw2Afw9sWAvFR6CvTTKdigzDpbmRlvlAJCiOkFQCMrQeEiyGEu0SSfqmx6ptOukfJn4HtQguvigLDWUctpjmNPutwP880S1YwAcd7A-3xp611erVJtYFf6oxGDXKKb63QAff_nZ57-7LdlzSSUr6VaJa5dneGwCgKl-9J3H0Mo-cOns-8ahZOL8Qlpj8Z2vZLS5_JQrNgtmDaaoze13ONE5R84e6fcgHK8eRhBNTULgSD13F59Xx7ww3chlqWeiYfHFwmOkNZp0iNO7RJ-s7crs79n2l6Ppxx5kd4abA0c58k1AZj7avFrexN_t7snuYqCNPsUHMUK_1fSq1toGa7hTVX5b8A56WFSdMlFD51AuzeIzgaEqBtGvq51murGbghqUmOy9g-6_vHz-WOPZeE1M2p13VB1n5fIh3-V7nd9PAXLX1kLLKiS2ox5tODYvkxf6oqjgR56n5KCuWtF9WzCwikaSMN8pwC3ewW6nkkSCPhTBASEJ7BK9a7lDlV60T6gikDbZGHcAfSKDZ5mBBwSBRpDfH3F0MI0Uo4oQ83J63J8a5r3JKy4KVa-5eNsNZsCgxO-7xx_fan1MH9zT85SLwocpvryGSbIDD9itBHK7Yo7REFRV6_U_cdi5RhDpEc13QETSsFT6CaeoL4GAwvJDCrcKjW5u64StH8l-Z4XDAtChG-znHeme6WlJNElY5unp9L-IolqqypTS6lybk7bfUtGPBDeuZp6CD80qFkyd46M16vP1mudv8rMC_ZEdFvCoHDmUg6_KxBxdVbYi-jaXtXYY9D8G6SlfVkeBcNiDCWjsDXSlhE1ibI2pHHN2E-kJLRaHA_Pse0Gknu6ZecQLaUCKWr_mKh3axV9d-pkvxpCcVVakOF08By0bUe8h5ORELsRe5zzMpfbYGaUVhB360OxwqzizyISXmqhW3Q7FHcgZQOCZQVfpuk6ccAYpZwgZbft2YZWqw7_1MyK6TitpdyIwdLFnt2t81JNoJ8zWLveZGpuKABxW6krhjQ0_qJCnLHm03o_D-9BximrLUCs0PbleK5mu4Le8lCCs4eoVjeDHQs4xMm-VtJk_3KMT6EVe4nrb41ddSKX8hH9rh9l2NlPpmPh5UTledwhbtQYdJdQBNFkGei5gpAQ1oHaLkSOYRqrRmy-VIBobxAVBaQWNKcv8CrGx8RIMxrAiU8JoyRsU7Vsobwt1Jboo=', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'weather: San Francisco, CA', 'type': 'search'}, tool_call_id='ws_028829e50fbcad090068c9c8306aec8195ae9451d32175ed69', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_028829e50fbcad090068c9c8306aec8195ae9451d32175ed69', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_028829e50fbcad090068c9c83115608195bd323499ece67477', signature='gAAAAABoycg2MBei1jlOMd9YfezZ45PArjJAExhzJt4YG36vuQT_e4K6W78Awn6mrJEueCnEAbciBRoPBd8n0YMXbqTiKdgeceqAoZu_UJAVWxgY7tVDlkg4e8BgJ_SrAumbi0yL4Ttwy5yZNU8g1aICCSdjGqfI0cmVbJpXEyCU8Wt4UKV_912jaG62vA6Tlqii0ikc8UItcrgk94TEGpOEQXlG1HXsWyAryCvOMSM2F785Q4Jx2XOrNv4klRPEZGUeIbp4ReTVXVi0JT-cjc6O3gKNxN6vxzUbvPhmcyTa9UogLuCTHjv3KpcIvBOw-_pF3Z02oQE0GaJKBpP4SJLE2yZsIII4uMls7Lw07EuHZjsZoCQRg12dRle6rwba7IeRw0RJWYEp9aavT0Ttrj69dO0e20NpispmeAXLh0xxrRCKcjxAn6c5XtEbJP54_ka1FUSVY4x8IaU_pCKI85fGmHIx-HarXBtWzZO9B5O1K4Pqr3BE7LELTXaMwWQ2SU-RGsvgmDpmUZjwifQ2YgamjIJPt0UcuGWb8BTwssP81XT5mQ2Tsq1YjQmgfzeF28yeb7XhkEaBUNejSou3SuEXZ9aEuSaMz62gzPSpsSrr51QoBJpMBF9Jd7LXuFJwaQV7jP9NJawF9GT-CMWj2IOXgVca7cL_d99IMSR94vNyg8yPzDsncJZ9Dw3HXFsPfdGHtO2FaFUB3RRZAVKoHy7S1NTNfLxdtB-p0eDuu1JbcsgtULWC71E6TbPxg8OguiEgAPTXJviUAed6udruUrSMlZQv-AgRYfxYPPMXLeUIWTTUo6PKICy_PO3U5CF6VBkaNUvCLf317L47FCeEAJNTb9Uj_S67ZqoAnEG0tQG7tVPuN13cy12xO2-8xFQSpO7gg0DzF8vCD1cAcKAvo0FUEnIeXOVHVQxThLHDiXOmB_ZpoT-qJYb88RTLNoAq5oI0ZuZYvPHJ63EhVjaANKwNe4DrfAvoPpf0qWiBOH2vHxnlIJc84pRh33ixB-azK7arhetqwIuLhDo4u9REcD2avxew8rDEOTqb5Tk02hhCKX9drLYCriNdkQh3mrC3KYzOWZ9aebwOR1c-s54KbvGDHAjTNPCLlROf30MmTON3jb-NW15YyzQrVFfV1c-egUiWRwMVE3KeWi4wmicK_QGMZkdyEqZMSzNcgOZMFfUWxdUKxACHY5J_7lUZltrz9JnhsfuM7KMuEW3GMASIP8f8WmR03nleJTi7k21oLtX-xz1gjble9WzSzd5pTz9GrFw4KWatCyrLXtKWw9fAqm_k5HpIJdya9KK3jNve6MirP6jdetIUNIbN3MGkMJ8lfavyTaa6-t4hsQSmyTQn6OKwhK_PA8-KTluNMW-dpqZU2YPFYk_QHYW6EJe_Kw5aOq-zpKR3hGgoHm75Ossr23QERsVgP0LChljPzR4OQlce1GMDtRNqLX0wGu1RO7OdM9R_lqJWMlIaAa5wfvdH5LznaQV1vuGPrfpzGL4mlocKDv8ASvrxA4bm5fWBoqsfzcLu-H8uz069vLDyHgrPNse6W4Ex1BVY6By0K_f7sidbmc1FxwP3ypVv4nX_lncg6RiZzaQTHTxXJFmvVO8_L9XBHJcGkQGpEuEjx2aMTWZGJNxfaO2fKJ8U3XflYVXJkSg5b5ixTHuvDYjCOELs3fTVAy50CuMXMoCEgyZlqZNg_EJXEmz5niLNQnwQPRWUbe3kicaLzJqvZrtrvPOPcTM31Ph2-_dfEOeKNOIE2B0pvMgTaFRck_xOc7s5J2tWAEYszDz6aMXvnvzm1WH9cXYLbgZPyJmMUxeGZ70DdnueVbrNr8VA5bzvjkgjEkhks_BQprXEAZL1lSL2s0O9G8ekgFnt75JBJmSFGT0twl-t1ia1BFkRtMGXLIj91xWJb2GsF6ZN9Uknfm0Akfk1STtRbxFIeBRlwQsix5rQ7EstyhfsBXiBILky2rSfj0UJwH1NjDskXjFxxpy-FEE7KRYwMws9rKKuMQMyURUK-DbLvMmQoxekYvqu7bJfWqxj3lndGwD1sQL78cpVVPVfJeqnlAw7k_xd6QdHg9DwSlGNb4OCYdFWT4xaaltFIJfo6g1Pay7HD8gWTrrgUzHgEWfbJxcKIXs1etHx1lxYVTmm9TFkXshmsbKptL7kAaxBy9JknSsGsh9gZXf3YFkocEj1xa8f8Xcuf3zatefAeFFh1Q629b0Sc-GzfXnu-KfuSyJzAZulrP1IQ0jlOiGP5hKnvzePVL_JZGTNJrJxmtWXejLodY-JzLzUjIeALKtyUsu1ELFtwDxyadPSsFW8qvMeolLcVDysGm8NkmRgLzQTBDGR4AcipdozZmElDRTm5P6JArLlqdZCxXpiOH2x4juPIYUfRrrTT2g6emTXHz_AurjFgYn55G6xv1YGSuM5tNBXc_WP5ya9cdpBIEYj1i05DIMsvUPsNAkt0MIeTiVSPPDMgpT4lLsR1ezwBMx2kQBJI6E7rmH9f3Abn5H6yeKQLZckAAru1SLkVwoDxcTTJZqD3sZt6RhBDuuMWX5ZoB21K-zkE3Tde6caBupWLK-W2eGJSJ_oOaG2YGQxL56irxU6DIVxLuMWUTOVH5vpqeo2RlrGpXu-lJkg3tC69gXlNd55233uIkchhihakwSIxFF1Ka-hcBlKtn0Kz7CXrXam4B0sSWjc9xGRfSOaQ6LiameoozXfhj8r_GSOwoV8EMa2vIBFggFGrPEzaczNkOKBiA-xTQtdEPqmfQNznuZ-B-VX-s0E0Ew2EopP4ljZ4QMW8k6pbNX1aegBBxbxkNc5ugJhBBoSVJeEAC2Lw3iCZUnX_leWUJBp2up09oJtRWlnGG4mLAu7nYsI7blues0ZLZE4C49v2eYBmfkeyq1DBAGXu0RC1qMz5729tzLPUEPYpKS1H7w2iGHQ9P1jBBWAAfFoqgn1lYtBF1ioxL7ry6YMrvCgTlqvVRXB7zmAUlsJdPq-CTWpF79YSco4fAhrDVCmxdS6Y4arD7p26YWk8PioCDt9ranaUi7--wlyh2OTdJPHAUHW2-o5NaXXfhqaIVfCqH1sbVmNwP0BRiAmUlwK7GB_m7dtEztYz1sHl5sXmXEDcFjJtr6uozFDjEA42F48AVuZMlQfQ3eJNSRqHEThYeyzbtCdYZ6J6ntg2XS0uDHISgM4zi1mDeur6-ZCw4rGwUXvB1BWXifFeh2miEGtvRzw3sa1zBKBCGtYtRsl4Iz5Plo9RNN8eQ_vvwmfDk2F-5YWsDZbpJuSXQXy1hjDvyM7TVGj4uL9gxFQ-ZCxFl9cufUeqfEGgHX38mZoJAT2emXbe4A4byFYvWfM-NxjpbNA67ZkOWgcDPtY853Y6dKoBihh49ZAzvmEjmPixKp2rBuNX26jJzhW2OJH91GpsncHGwJ3ajWht88XbKBp4Lb8sNVxYD3hK4c-mB95WYYaUKe5_ugc-PhC4FGu-FYNLYTX2ZxLKpk_T4uEG64zBQ0NbS9y8WWiTojeQ7b4-MBG_j3VJr5Pi0T0meC623J2ldwud3DRBZXB5q5rKgofFF6WqvwhIDi8YLL7CVUJ9aOE57SkUKVrYYD48Cv8Wv9piI2hbTgXwWkCpg_tVROBjl4RYfYVlOBV4pM1G5AK73PXfDGsPdiCxhmxHlvzanAm30eVKIctRaS1xlcBqLp8CUPkgnPDlPVclMagd1CjIlN4igMnFN9gDPOUckrA0-VBlg-EKsHG3o_jNMbsvgfXg8BuApc=', provider_name='openai', ), TextPart( content=IsStr(), id='msg_028829e50fbcad090068c9c8362ef08195a8a69090feef1ac8', ), ], usage=RequestUsage( input_tokens=9299, cache_read_tokens=8448, output_tokens=577, details={'reasoning_tokens': 512} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_028829e50fbcad090068c9c82e1e0081958ddc581008b39428', finish_reason='stop', ), ] ) messages = result.all_messages() result = await agent.run(user_prompt='how about Mexico City?', message_history=messages) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='how about Mexico City?', timestamp=IsDatetime(), ) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_028829e50fbcad090068c9c83c3bc88195a040e3b9fa2b3ee4', signature='gAAAAABoychCJ5ngp_Es2S-gVyH01AJS0uQK5F4HdAkVFJcXPiZanGRjmEPXNGx45nUyTonk62hht1dZ8siaE7v0SCE-oBFoP3du4UqNqtCmJ_0_EmkXG7sHh3pR_zuS_iEDGae9S_qM-vcVXyqFYbEtEVD9ZimiQGtLEU7WFyQq4UeLuD-U4vRhpFreMCAfen1DkV9txJijEPRL_2cTUGT47rpi2HYyuN1CzYKzRrn2qbHsgDjnPtZ8cY-QGTm5Mm0LHV9GeDh4MmRY5Lgxt0slssKI7vy3OqTWR3OCESp-5VmMR3fbyVNxkeogT9XqPfnl_9maf5jYLv57tVGVRJUEx50QvMJ9V20qbUzIAuMw5d11s8q627IyyFu-bD8QmjGsaBj_wsjdMe6adDF8hzOau3svjuouGf066I73I2euw2NpokdNA8fbI3bAHfqyXpFDADKXg7WL_zYB0eyREbWe3n2mo3KL2sLW2908ScYEvsv9VlAo6q1vByI0wfGmnkqkgBvh04Fe15ljjSkvLy7iRnOFL_CCPakpDcViIOD-yRSDk-MSHpQsK1sP2GgxHHy8jGO2g_ef2bOH4FkcYZK1oJLIUGqhLJI0LurXFnLZ3zcUML01aV0rMFyweQwbdIjpivIGaAg1BUPU1Tc8nCNmZC5aRcbixMzzu21HtW1SWnMziebhKHyN66b5skUXl_RHrCoKhFyJxSJJjxHeuUKHQ5VxvJDJSylZjHvMkX0KQ-Vn78pv-Be5ETRxR2G3Agp-a-iX0zM4HbwVyoF5l5t7g07pTrfEMP0WFJu4_OG_tsy4u53JGMQwQLB_RNYcd2n1yXPCpZYHuq8Vkt6-A7kYHW3wvUmI2cSyZGBNpwt-pL7kqdPaGyqnfhMTDzTS_CTXBBrCjjQg-RsWGu9hYon5iKgHFv-w_qGykzyPtEzZt_VWUrVm0WFOinLqLXTQgiKm0sypDdGRht69Rbfe9WqP3fhFychLwcP22IvDQsh_OenHiF5ytB1XTI90VB4e890QUI2CzsnH-8fFkQT9Bj7ou-MstjIeOQrCwDGAPRnxP8PWoCg3uYk0DuAWuJY0lYq6isqGKc57Lz1bLaGRG3oYpWH0MC6b-D2y7c4cAgOYMhOzYq2ufblZDinvBLrr9TV5jtog21xrBy22o7dbVEgIJ2T2HI2XOmjG-l7qrchcAykaosXQkW3ASIv0OpfG-SSd9UU1_1dOUFzOXGej5UMxZidzQa_dW3XPLCqVqgiDW9HCu_XCmSZo36DY95I2hofXq5mXUHT4qxdZ48y7KGiM6mllFudcdyXu1w8ZGFlU0BfzKDOfbhEJz7MRLuXL6GO0bCHqgFo5WHJrsTNrXuHNNTe2LxPPIpejVl6kvE_1LtHy2jKffOR_BcBCS1c_KLIIbl7U10__OWglq3KpDXuupMa9-fXXSn0Ko8rRybTLQpXIn1D6phbi8hhS93EkaVE-9zZZGBvgcYhPP2fa0XniiexQcX-VDQ==', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'weather: Mexico City, Mexico', 'type': 'search'}, tool_call_id='ws_028829e50fbcad090068c9c83e3a648195a241c1a97eddfee8', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_028829e50fbcad090068c9c83e3a648195a241c1a97eddfee8', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_028829e50fbcad090068c9c83eeb7c8195ad29c9e8eaf82127', signature='gAAAAABoychC16oV3bX-2fpfsHcxFWoRnoEx69lgG3ff6IIJemlYvbM8OVbf4e41oydklk1kkBbyWg2spj4puPrSV9w19NOknK00NJ170UxqM5jqvtZHcvAAdeBjA9XSyRObTamXE16W3KtXvRvyRBmBpqpC6pQGX15fxxdAESZUV6uUexSQIYZEfCT2q2aRj7YV4kCGXUQoMRvjzFE9YLE4LDNrQykcrIytjZ95hz6czjxsd95qmYtGdjMU-s4BlOvs34pE-d-H7cR3a3cQHI8SkpaQrL7bCOxZk2fYws-t0YBXEsOIRNCpX3uEany3iGgq_8jn-ggeZtwvnA6oRFtIkzpscLaU4kwhlZbYHNI_RinezdR5ByRjwSdc2UHvqoLb4a2rYmHSLLpSmvr1f9UesAz2M5AexJYlk4sDmGhMD5DoiLy05lbnbo86osBDmRpwXhb4F0pSVgPxUEadMvvr_l69Mv_VAhTJdr_iLFn3E15HCLPCFND9TcROgxPzhW7aeDrt8fJPwEZZ4fZ3BAphxP5sOzzmd3-6uwCHLZxB-51ILHGMkBVmGxFSXB3u5mr7TtaDafh7bxWQv2bpLoV3Y5QD1lRvBj6sx95B6J-CWgw0WeOd7jSgHR2Y6nDzD6XAGgg-aEK5Jk3CDGLsSqv6SxYMoY9MvT16syFsNuEki6XDx3cF252VeOHIPNPQiqBB5NRgf0Vx1zAMgAn8EYWarg8bWsJrazh_nSKWmM4gCFFAUK3Tqi2rfbx6eCPlPBYHxX73GdiHrypeAA50pqVySFxXzXgeRKghzGEQetBPzNMPykyUmiDuq3oPc_bliFQu_15-rDhEfmJcfS65DpL-_tLdtTFV4-BeAjVNsdPjX-7I1bTHdZzyuBiMr5sltxKzmHd4fLWLKv_ZsAustyfUmQnO5_reR0T3SwlY2Ytg4wJo96dtx-XUqJxWgZ9tAW8_rhwgejaH2H8zTM2wczgWVXJZxlsIl_U1xY4pSgxosqBq8a5EPrAqJFnpcZqj9ctCImVN5oElb8o4474pOhSeY0qFQgL5iol5d6QB1gNTKugU_rCgAPbHwBAvnONLJ0v3hQXncgcuIJgQw8BjpOgS6KTXLmf-5uH6CyXum-oE3JJy8EMBjvyerecMMQl6dpeJxYHlB6B0RUUzTI5bHFaoJeSGetoKH7t-L2lUwgcL7F84Wf1ZU3EUkCPWl6DdUq99aLfYLWPqd3bQ2JCvWiMVrlwuHZr_8l_N3gCWuy2t43N2nAKBBc3HWoWRJPgHCmkj0MIMdnZBiUD7IXz-b9jO_1ASYT0NhOPc3gqipzP_9lFE0EojjvqUXV1P_OiAX-Cl2cFpn7ACDQpxAGyW0yr-lgffzLI0GA6dP47DMYs0P6dQBD6XJFbvlxigcl_9GURApvAb66ITpFWMeQAJOCGdMMPZF2CahK8Riq9b0RtkSmgmmEL9SUNaMpEJBlk6j41_IdZnxnO4Qm0Fqos6RFKFbwqfxEopy9rVWvkbjFzRS_B7gAc0kH9AbFx0CZ61NZYNVnQcN1qpr0iuJtSGG-DW9EjT56IFtnt_clgrjfFuFj3cwX5ZcKMrN_RTQNgY5QhAPShSXUB4MDstvHgFhBObn-4rDl3TIFJiIgNY9lBz5egE8YZZXg8XxW7nFZpP0fmQD9a0CPdA1BhafzNcvCbReTjddrVeJcHhflTNjy0YiXrXUyJmlmjO1y0opcXkS8R3E-Md73KKEW9wJUOuEFDDr9PAaocHUsvqWPTNb_Lu90knDMKEi_NnlB8SHf2Agg6FkyMo4Z_k-T_51IGYfFJHPuGRZ8-CqK-qI8-6BRIDpnei_UIi2K9ALXGOuYrcG9A4YexW_vPg2qmoVgishgzr-ddFGOuWr_j05j7AKffDc6wqK0PNBTEqpnMKSVICOdOEBcilXsncLhjFm_JmS3JfxaM0Ly83tKhZqjP83hxrL_JvBjBQRuW7LwyYuFbE_8dAysUMI5jYwqPd40mGPALADFca0U1rolFD41tdX6LijA7Wz9JjYpfuphLiXNH5cGqTe4T_ReZAN29DffISVS08dRiQUEnw2-OMBYz_nY2qe1vyEItwYmUe2fjOgec4ClJPdRDXBW0HWVS6ei1sgOOD6FvA0moRFpSJypcEC2R1PiRqN_FEoTXzRsSAPF6pXoQIlgXxudLwitpW5xSZS4v_DZTlGa7GgHnq_dhDRdSw5GzCvqPU3CSlP7GmvxZKA_9WoiHNd6JdOSVJg6x8BGpxDjvJy9T-XB8SIKyNx2ymCVKaEhnNTh9UefBGcEXR32oYiRa6GOLtVLt_7OJ_YOqSU4XB9OEjoWlWisBxCrvnAI6URp-wxVLLkLzAPhX-O1sbjcOkCillvnJWyDbnL12JkI0NsvenYonUdprMbVKcX68KdkkpgmKyMICY7eUKpZfWy32E5stRQFUE1GMZ6wYKGOBFa8a5QiIwIx_4IAU44BZCqBDaV57H9KAlsHhqY0K9PJa2fetDVGb2MKohfcEmF4lAzmHKiu22OINYHBYX1LZulsVrcQUj6zSA7r3GEEP6K6wBmk6i1SuLgf4ze9WC2pyb9zemaZ7dHbb3btZw_xAk5a-RVoNb2hIXfiX9clN3BkMw5V2vbpDHaNM80N8z_3VC5uXkQ_v1543ZFWvxbdvEVHlR8P9JyG_Asts0VrwDnFAo6rTGmPj52GJcmhLVAgZ0KPDrujpGHu9HTV7sO-3KvqxOMHYuKG34GvpjfZzlgV8GzbXtpsRk2E-GJPKLfLN9KIHYMxdfkaWBurYvea7iMYe954Gcwehfvlk83foG1ez6FtysZ2V4eLjg9IcVJVAWucdnUWyIIgYMocgpS6ESkO2wRs6pUz4mg8MT8q-h03BJXmWiJIi-4_3TOhz0owLKMza_1IljVaMAUIHp6Kd9yEPohWQo3uyGulXU-vEsSeSkId_sVxLphe9yuimK3CtzU7FBjewoGhaj9vnTdv5_abDRZ13Glp_b4vpfUrr37CBAX_RwJ_mTqGhbv-mPuFRVD6ESjlg-JrJDCUY605dcyU_0hyvjSFepiHQ4FCEHzL6GNSfR', provider_name='openai', ), TextPart( content='Today (Tuesday, September 16, 2025) in Mexico City: mostly cloudy, around 73°F (23°C) now. High near 74°F (23°C), low around 57°F (14°C) tonight.', id='msg_028829e50fbcad090068c9c8422f108195b9836a498cc32b98', ), ], usage=RequestUsage( input_tokens=9506, cache_read_tokens=8576, output_tokens=439, details={'reasoning_tokens': 384} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_028829e50fbcad090068c9c83b9fb88195b6b84a32e1fc83c0', finish_reason='stop', ), ] ) async def test_openai_responses_model_web_search_tool_with_user_location( allow_model_requests: None, openai_api_key: str ): m = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent( m, instructions='You are a helpful assistant.', builtin_tools=[WebSearchTool(user_location={'city': 'Utrecht', 'region': 'NL'})], ) result = await agent.run('What is the weather?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the weather?', timestamp=IsDatetime(), ) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_0b385a0fdc82fd920068c4aaf48ec08197be1398090bcf313b', signature='gAAAAABoxKsLzYlqCMk-hnKu6ctqpIydzdi403okaNJo_-bPYc4bxS_ICvnX_bpkqwPT_LEd0bZq6X-3L2XLY0WNvH_0SrcNCc-tByTcFHNFkQnE_K7tiXA9H5-IA_93M-2CqB2GVOASFmCMBMu5KwzsYIYlAb-swkkEzltsf5JEmn1Fx9Dqh5V0hxkZI6cz35VsK0LEJSYpkJjAMcfoax1mXlnTMo7tDQ_eBtoCa_O2IQqdxwPnzAalvnO_F4tlycUBM5JQkGfocppxsh9CQWpr7bZysWq0zGfuUvtuOi1YJkHVlrqdeWJGDZN7bgBuTAHMiuzx68N-ZrNgQ2fvot0aoVYBnBDxJFbr82VJexB-Kuk_Zf3_FVm-MGcQfiMxvwHgEYsnaJBvMA56__KLlc3G4nL91fibIXbh3AZ24p3j1Dl1V3D03LaEdU3x6RF7fF47y5eyaFWyWkmPl1RwiEaYy9Pi7WHuh-6n69ADGYWbv0m4mgvECbmvbBIIkZWr4y0UK0B8hbC-Oqz776Taww73OmchIzgkg09rIz9CfoKcGMXgvzbpIBa4sME5BQ3mQtfIdPLY7uUIwya4o_g5wVy583MQva75jNsR4A6sRVW9SgVEWusMJPHv6NLzHCdWehp6SBcKuovxZayoM4KQrIvUMNlUkrSR-euoBaa_WNc1HeY8ikKolX6emm2LhRzXH5HssCgH0g8GUvWilYx7U-UFSB0r6yoy44_DzsyH85pXN1ivsSU5dGIBQgG7WiN3bfk6oBGSrz4XkBLiHJiBX9ZUe270TeDNfpgjmKO34_k35zviIUd7-kVY4EsJGGijEhjbkInFwhilyH08EdKvYDzrzpKJIHT235drt3eLTKXKEA-g3iW-qOMqH15KPk-slzPNkE8yahWEkLrYsqGsjwdHVXiKF77-i8rwvDWOf-pOs9d3bBxily3t-22D6RsOL6wFYQS6BsuroKdlO3b_0Ju5E2Kq4P3jxtZ8jnG9D2--XEcEB5x9yX_brfdFuFHrF3C4mYVWTrNN3_S9V8zUp4CdIh3EqAuSs_QJPJuN-RNlorK3bwYqOymgNlcezKIqxhWnqtS1vxuxC7msRlJRmzTN_Lg6XuLRNS1uIp8jmx7TcCnDx62ynYn2oGCOCLSspK_T_LVTG6js4Oiw9ZB5A_I3TfDLrtnLRh7pGJnAv9nVnfYd4Y1czSjhPui5LF-FvLOlzWxSu_1Mo56QA1BIerB9lCQsDjPOkLF_XHOFLWGLQANx5nQ2wlbgBNyMcPacQowRyn3NncjfzlSLyaPijEZ0HROyL_Hff5JXCMu5-6muvxQz1TirmbyjBbLjtv93JpXrVvby14mdXdNs97dMATIiqpwF2r0873_dijDKRxIDMZxqFB2ZBaHJc80khjG_NaA_jxv1GEqVWmllBXBz-wUDbUJKtNtI86YmcZboZIA71V416UW94-TXbtyQpGlB8tj_764sn9fKitg3vCqC42mr5Kj_aTzAN34BXLykkFWYl_AfVL5PRbJXc0Uh0GW0xTH8eD0hvqd2Xsr9eCoP0nGM6TBNMCl4T82wOhRy7jelWMpt8LBxAYkw3nAlVVOi2puCoYRaRFWNQnLcO5iYBF8_rg9oX-cUsBFepGGDmoOfwUmWLlYqNZDho3AJ_SL3azAVJz7lqa3vcFubrRMFiGcee6sHj0HJI_2N2mZqBO77kEbXrJ6SiUV0EXX5vrjZGzpU_wZ9G8AUz9Tdgistq8XLVsMC0uZWlbRdqD6-UjmnsJW7XINzH6MnkQwPvbduRKF4ywViUUbKVs5XRVFUQF5gTdVMTK8mIIppJx6fQRfZBju1NuNrdTDjd-5P9_QNBQj89_Y_N1fow_676bSvYrhlrIXVuLGy0-RuWezuqEwenIZ_U5wSTp9remqWzeuolwKnF7xG_QlcxGOgCivkRvqAyDxWiqlBhUtC-oPEQtychFa_W9uLHyBhm4bcSUz9KvOlUTt9fNYgvDWFciGCE7B5iPz2s-lCS-Onq0ZvUiZY5nB63htK1bIMzB5lc4N7XVh6COcSIArGBnXKARHdIenJ9vYBSmB4XBrKOIU6SmNNM4fq3ZFoWIc4gsS8L5LZyhTX_qlmY2L6znek3XT0Z7kjEHs5qQ87_sw9ho2KaqNSjMalbUEp7L0JlU73szrtdpMkmBk3BK0of4Nl_v_CCbmYWW9z_rsNpTpPQgUHNVn1s38DX3cesMqlzlBOky-rpLAj2-sS-Xj6WZWBs_8n0lLFS7FL3IpKzveOXE9eV4zjJSZ0y74b_g7u5US3dT8EgSEeHa_pGOMn3t3J37oz1pZcSufD8vjyG7wtGxYUGn8L9U3zJHN1VdOR9id5VYOo3OLtMjCrSqPO', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'weather: Utrecht, Netherlands', 'type': 'search'}, tool_call_id='ws_0b385a0fdc82fd920068c4aaf7037081978e951ac15bf07978', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_0b385a0fdc82fd920068c4aaf7037081978e951ac15bf07978', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0b385a0fdc82fd920068c4aaf877808197aaba6a27b43b39aa', signature='gAAAAABoxKsLhc5YCXvcJidIAJvFyzs2T3IwW0fie9oMN3Nk5fAcAP3apWArzw8DdWjWjR0tn8Fpw_H_xATFGktsCeA5nzkcKvdc0Bbu2bwMo2QUkQZfFcLHqlcNnAcvrw49XpolGFl-mu7hAyP38LGGtjbTBNRh4dHkd-hYZzy3nYd56JQi5GLS_KuxdU78xUW3gNOtAvrseTx1fcY2eseUcNLm8uDi8a_qDw16nFvuY31ZkrmuVCESawkppmxrhGFVg0Y99dgyufnSVXXMKyE89tmXMc60yZiaB1i5cIJQcZMkwupod7yZNGqmr1GtFru5uJq-bJfGx7nAEs50jUcu-rP-_ZbvptkuADDC-bfzFjaeq13wCih8wCXqDWqnGjqIHlFkBM6agn6VKOcuDC18L3caqcH3KEYT4f3TGwg_ZZjsiRDdBC-saqIduaAjjMDqMKx9XpmreRq5BLfC7fPjRykpUcWQQYbQ07J9pe0EW2VhZwoGtd1u96fmz55MzryX4VOWIwDsUTEZAoCzULvVrEBnzFqnfvQwejBxJX2XU4fIlOtT_XpOcI2afolh8KgitzHHpJ8Dr9ELI-Be2KEd6enxmdaPhgYUif2D8ZCVfOoXZEmrFBMQTRyuxtp9H0U3zGamEYuUxRavxkQD77HhmqWOSr1Agm8pWzAN97jxJSxxY4BEnjtrgp1mavtv4G7VHjrpNWrL-smZEWmnCPGKVxP9afrdSZYL-HXKY9yO6__0PR6DdX1o0JvUq1KFPx2dzag4eXDxb56HI5MKNr6J5P8Smmxxwoelx6UXEKw_hyFWMmPUHYD5Yw5dxrXeYmAiomYKFpG0bxVbuAb4_iAVliHkdIsOBcWoix0KLxmS-4RJnikZPMvDwLDWfENZ2sh9_RrQbuMBAgjHwlfWM_tww0ufm_aVdDZ1CULJ5Ki3ZxH_0oIRRyyB-a25q3DARnVzutgo32H9X6qjMb06ExMn--ndCinBglTTGvj1QOIJews6UMrcKj5ZPTc7GyPbHXvdPmPdIrtJ0wCqFj4cgNRuxjiaZDSCqmEQERYyX9Fxu8tY4f7-Fxje6A_zflqrIyhLfzo1iMaoNbba4HNkzRMWba1L1fC8St8MO4ZuZTGs_60FwzSUmBDW4Gl0CcRAdY39BE65uEpKGZeRqDfxvLUelG9YlJTowqN8hzAYShzcPPkgWk_s1AtY0RT_roregPuQ8PQayvHcJzKqnijOIhRA9k6LjF6cnHj90d6fSzTYn8F27rhufLySe56n9SA2WDWhVcjsFEFAcsL461tjiQ5U0mjaFdBQ5H__s09dhp0NzhE35I4q0pzM2KI1YWgLnwlyPFnnfce9bbL81jvbXw8DDC2KfZVOGU-ZDdqIqF0UmwNyBaMYb4SonrG8vrj5bFmCMPSFsEeuDPv_bmD8HRx8536b30RmYD0K38Wf6-UoatMxzgMpgmwsBP6Wh0HCpFeIhjRsJLxYXeoafypcKJPQgKXJwuXVLi4iejXkrbjBdc2Sq2dqIVzzUhULLJSPBYouyjeyVSbYYp9WPoBNWj67uQsX7OUbQN1_qxopsPJdqqQynJIAtULNHjKrDA0GKpyZ3OUV660OkogPAWoxTVevRemwkIJZbr2hXyy0Nx6Xc1Vf9xC0nPclJ6VXapdnjK69bIDHxDUZGCh8UZt6DbcA7azBrugcXlbaMJzoHWkzmusJoTh_2UXRjrS3B33jsxf6LQnUl0s1ETo3Tif868zLvkTEtfo6btbND0FPDFFQrdeVlW4mUWEOJhPeOmwnDeLsafTfRCI_V_xTzgkpQxx7pVZt6mkYZ2qDTE--NhqgFfHPlw-nC4zU6klRdbaO8284QGlbJvHmdsmHi4AtMSWAf-_jegocmaneM1wUquNKoy6hnbkZFul9qV2c-_L077uC4nZYNjRay3lT_3giVH6Ra6WnBovt9ocCYIwSeygVAyqBHxo5EJpfyJhNCtak3bl-CIz2TraYqqUCiB0h1fyxIF7M0uENZKALtwqRVHOtEsN5JVotgv-8YzaBRFs3qvtjQn7eEcw-zrIg5fwMP7tDi8O3TXl6qPVWTCHMa1wkfb7OkfuwXREognLvO-3qdRgxinodvKyHn9XbsUcQMQjPPFMLOs4wpEhTJpcIFPqtR6tArjTT3P-T21mc8B56K1wXfEDvpU64XQ0HnfZWaqS1TbDyfL2i12ddhhnxbCV-0f3lUGnZVsfeGEc4FlST7iqUguhwPGb4mBpjBVFu2dv3DMCIPHew1v92gZH1OJqZJJVDUpu0vvFGTqxHz31LSX6lWa4gn2l6hvkT1e4aXkjHg93iy0ZXMpB0JqJbbWseZY0LDYzpH9noHq626Q9H4ZEKPo_MYBWSS_yH-V2_cN6a4HarqhcRwD9oT1QJ4_4AzWeFIrCZlClYbA-84H1CbBfQjgtRh6zTZLDHM2In2M8mKGyFSfeIhMHIcfPBTpG4flLBmTNrwwbuOP-0ss_bb5gxLeDsgU5xjwfaUzOWXudPJOEorz4t6Oc88MiRH42troV2fun6Uf7e7j1OQSGtTQ1kXf0rroz2ykDfVIXCefX_3io_xJ7ev9dH54CNlARSF6cVpTqzbyLWkA0BJeAVYcX2JW_AT-9VYTOo1Vixja7KtMAmMMk1E08japeGnoAd_a_4-bEfklFTChseUDgZhOt5_XtBiuQdPvJDorSQWQl8VCPKdMATr-EdUiZN54GSM46pdBr6p-Dg7LvB-zBAbTlm_6SET0O0k4RkkHxUCtgRMZQ52aC4brcym771djtWC-BbaR5CefibOoSo-i-BP2Zf-RVaS_MuFar0dT03zXdb0XuC2vuhbVPPF-7gsJez2dufEiU9LBhV3__zTDlFc-rGwwf04Fh5KuleNzr1QNyVPH9GZSS8jZkja6EcRfGn0X-oBr2oRLyxuL5vWgOdPadBOJGjIoRnMhCAxGla_gD_5m0qwF9CtWWv7ugW7YpATe62zE0O1icYDPwaXGovzTOeRDRn4BfJzgzwLRkP3-zOgF_09X41umrq0TCnCujXe-JOhFuIcYx8IxOb_cCcfGRqGXeZYP7z', provider_name='openai', ), TextPart( content=IsStr(), id='msg_0b385a0fdc82fd920068c4ab0996c08197a1adfce3593080f0', ), ], usage=RequestUsage( input_tokens=9463, cache_read_tokens=8320, output_tokens=660, details={'reasoning_tokens': 512} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0b385a0fdc82fd920068c4aaf3ced88197a88711e356b032c4', finish_reason='stop', ), ] ) assert result.output == snapshot(IsStr()) async def test_openai_responses_model_web_search_tool_with_invalid_region( allow_model_requests: None, openai_api_key: str ): m = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent( m, instructions='You are a helpful assistant.', builtin_tools=[WebSearchTool(user_location={'city': 'Salvador', 'region': 'BRLO'})], ) result = await agent.run('What is the weather?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the weather?', timestamp=IsDatetime(), ) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_0b4f29854724a3120068c4ab0be6a08191b495f9009b885649', signature='gAAAAABoxKsml4Y3hqqolEa8BSvPr6mIoOyAbWRJz9FeLHoqX03v4b6Kni2j9HxfifAm2cHD_m9-b2nOHcwDPOeJA28LQpl_BfOakn7h4saDElA_yz3WgVfy8ZN_oTLQz2ONqptBxdxCaLMGOADqBJ1tJ93B5s8bsFNZUdGXe382lPpCNX0aKPGxd0e-UBAICRmjGVnKd9cVzB8jhtQWBrITvMOLBvi6bE_TqnpXWf8-rhed78mFVMRweh6zAzukkJPMAjD7QfUAiODvD6oynwU6G04UOJoFTItUsAULPfyAw-YZqRwfcfMxoiLAE0rOOj9V7-eyp_J7DYu2uF16jaOopnrehFDJr-0pIGMFRxMSyFp7Ze7z3gWvcCOB4VwpSFao12nozedMeinybf71wo0750TNXXQ9Uye6qsUxxMamqcNiB02LjCM3nyBQ6FpWa59TD5O5UytT5FPOWSflYEhuiTFknt_JRHbKoeqVTfe_CTeSVlYBtiW8ouhkTHAAVI5lXi_mgvUMHINTYw5MEilzBSPunuMRquopRjt_07YMKuwPDQ8o__s1NlyrDAYKLA0gPzse4tWMkKREcfxuvU948pEJwVN9RuKS-NNXI2KiKKOAtPoXLbflAEtpx9N9PpPdwvz_z3yhF6S1_D_9P8OrSdxd8ldqvnqec75Jwt-a0fuQvRTSC3GsYuhk1Cb1aBvZdBtfcwBd2CXRuDUEdtzbLZ5AUNBy3f0mC3ITHG9aSpuD4GUHQDTjF_10-Qr4Rzygnj4-qubY5ibVxGtHlXkI0QzvGMVf7obhHMNxEQNaJ4k2dKddRJEhrSFWmAVYdWbKiZp-Dwx8veUSlpwMu8kLfGUq64MBQOApf-Srtry0eJAr3cTBqzmUIU5OOPg2C8j9SbAuTLbbcR6XeWizp5fbxdcVipVRqqp_PJptIJhaAUpHaaOB9u1nZbtlKWFJhJbrZzdktth5DNim4ayYBbBX1VAefwCugReld4C6QtB5Q-j_Tt3dug3Jh9TJmkhS8pJE4aHURzbCikFohJHAukZYgMY7wCuLWlahQ8snlIj8kbhPP-l-iH-e0xM2vFDF8rZnfYblnDLZYQBezfiZ4GtvO64SB5apQuRXkxExfZyBd6Kv-WhAxhPGoQdmTXfVEXePJLvbzAJcAXYpmmzt1STxoxR9cnaeLL13fFXZ4DGXe4j68-R7xCC52jfoV-l8JZjI0NDRJ3Mx1R26bp-lnvoertQBs1c18QHVShluHtH5c6V3j4yOMgG6cA2aVM25i6sjhUV3iltijuRv3E19ZlzgVTtrypeCVH7ab0PQ3Qki28mFI9s5M1z1TSuFis1qhHwf3r0kkmjLXIUbXAnfJkcv50tlcweXRTLKs0ZX0nxsxiZptBo95wxqBf4VaqfOY4NUNAWVoZ4AS5oSIgjGfUZtfrLisWmX8NjDWiOiENLmn9fCCq9nxDDsaucnwNhsMZo9jJqJS_99kryMXi0yGX4GManClCTe31Fj5zOrtRIezlEILiTla6fZwvD6vcl8GWO2wuyEY9zsEvfjyuvcU6Ernvw9S5HFPnQ-FnDxNtSTe1A8IHTspfEROnuSNVCMs6j02eFZMbXFKMaVi6LNDD2i7SYn3dMbN7aOfubtjeilMpIZ20U-J3uBUsc0rr8s4b-szDB1lkmiMvRDVY8YKNqH3iJFCToE3OibVwHeaUnMmEHJkIvJvBOX4hSwmAMxjZArusTnlYnLE2raAD707H_Q5JhpWXwtgFPj5ra6HFtOjtbPtDWrDn5_M180klxvF-JxfSxSl6U6y2FYeou36ttPRprWJynfcPSPY_sdrB9ZupHDR5zZy01Uby1J7XXOZt5an91kuHr0qU4bQJsq6AigFQ72C_YxpDNmQXcy5awJDBlXv9SoLiXRcTxpoXgii9alV8MeorRbc23O0fP_O6XKUso-lp-e7Q6bOqzV0c9K3imYUDzM9cqlvEyUGMDLlWzEvVGSwpag1CsLCNQ5bPc31W8hc-2WXrlltP6JZ9gYpcueL5AIud6RUTSJWg4Li6Th4ZGNs5cqh6Nk6oSu07P4Ie2JJ5bt1tAJbE4EupK3NVzUpzYzFdPrQkBY-VQ-klCFq4icnvlpD3pajYv9OoCpo0z8GfsdLeJlefIQ1NejuMg3EwbGRA_OEWn7sJzR2RFCYkt3YIuWRJb2UzIzvWhZsLxr4UpihrsieNKggGBh7nDpOXeAZhS8pGrNSlKjfvWtvmWG9NKXSpx79dNLSkumiD3FsQjk-L1Ov-K5WksY0yJTgc3ipgO2UpN9zolpXhXum9Uy8UeKLlB35cCtte15t_HSogTh2HDkc9SuCq4d3adSdstdXodr9jLbST50cHYn-F9qmkKiqV2nBzxW-9A4BB9WB_tWEoazKWYHtIdmjRm6O9NxvOxYuWIwhMmRf-OE6MHOeH0emhuTFaeuZ4zjbM0T9peRh9shiUw6T1NT0doCgfyRAq1NL1rG7iSc4jxrc5ahP0gN', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'weather: Brazil, Bahia, Salvador', 'type': 'search'}, tool_call_id='ws_0b4f29854724a3120068c4ab0f070c8191b903ff534320cb64', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed'}, tool_call_id='ws_0b4f29854724a3120068c4ab0f070c8191b903ff534320cb64', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0b4f29854724a3120068c4ab1022f88191b2e3e726df9f635e', signature='gAAAAABoxKsmZCctfduUbipds6REy8FkoOiADLcLER75WMHyO7PtQt26NIhcGkiXReZWucbDdEBRKk7_g9PUuu9g-zEBe6kIQwm4lwjxCGPy-rQdmfJpueznyPJ14Ood-wazqT9a8ab_BMFS7VLonsOjZR_b1gxcx5yO62oLvv1GnZfkEykIgRbGIBSYDWX6I55Sfwkf0JRaiOFgeHoOvQ6f2mdb5UetdJwbIFgRh9Bk-_l6goC-ONyElqvPxrh8zlLxqEhL-KtTVw6TPNW67QeYxekA4vdXseYT4W2oJMcMKp8aIfxYr3-ZWSy81UqGPD2PAfs1DoOYkWMHxt_VnZjLQs0qkO-JBPsWBFWEofZC1GxOIT6gd_dDvExBXkaFdNH7xf0OxsxSMWfyKSXMlq3kmVsDIN3hKImwfZQ171mkFEwgwIBeo4XiY58YJXmzyNXSs3c82gAeGpS8cOQw5shjC449uJZkixSaXmwOKwtm0z1MOVAp17QLGeD_2YVa-DZUy1z6xTqStuZWnwLDOz8HPL_rW3MXGcmC63kWmcTCsFngwR_IArcTd8lsRAXJghnEdOZDYgrU7uc7bbqO8W_PyzPDDnrAbcwo0InMqJ2BZErMXOmy2dEm1jlJPEn23PL26k8r_sKNCZpg-I-q8epjbF225NJ9S8g_vvqLsyCzo-WnHPHaFDMfUhRxU-ylSReCZO3pcjNJXAfmsNiBs3g272BtvNWn7GpDqlJL9aB9Erc79CpLghKKV9JiVRsr79aW-JSzn9gJET3JteU2MMCvRxv3ePPkmZUvQdKOmzZQMwQ8j0FQHd--4qMkXDdAz-lsUjitCKK0z2ES0oSnWOVVPoR5AVIUCSfg-yGwBWhKv6qIkMTsCYaCaR86j_hGlCSxNqYdbMwy7sr6nwqDmqgmcsiNkAVUAUeU7LLXmVfGDR9InNL3lNCICpmcHMd8YJO5A1wFMPHFgfXt3o4CZP1ZSjQjQuQ-Oh2AfLaAYSNbU4y8JDtKPiini_rWIqH1yykwV0Xt__QvQtj600ksUqij_zxbKnZKy_u3Ud5E04bNgTZ0Mq9ihVtPBlcDCtWSsp5U8Sm6JL0ZXV5XaT3CVG3T7Mj-kKs4yHHOLNoR2rKAGPTA6VRzaJDNO4goMeE7aIqWKhFTYMBcKJEGD-B2J2J36iZ2RNGo9JbxmUw4ZPMVaPPulSfpLvDptYEN3LX0D6L4Xu5iaW900EQ_Ym60siMB257NRxfVPb5Sg8hqxGeKKgg6NGa6y-qyVXvqjy4HA-ODvHLbiT2n75fTD_OE2CX1FpLgmpmKkSopjT5G1vv5qtXqdhigDy-l_b9Qxwvbd7XXD72EUVPzDVwMDBZNeJkylcCecaRVJZRnhmOMkGbV4WFrMxjy7eoYrIBQ6zytutBFXNkAb6a6UXdTrlOlzclPP4P81sp3J6BytVSaLJXCIpZ3pAM9aWVzfavRW22R-rIMbmCWT9hq-1ZDfjdglHN7yowAF_rjVGrgl02wsh8IlLKfJreh7ughi9vSk1WMinlsiZfZynp33IfB3ayv00a_huU4oSKXstf1KaeQ1Z8L-ReCdPRwDYaLbP1ZT7BQAbXKgIjUsLdSiU3MmW8FVBdevLQq8AUUKsXxfQLS4TsjMYTNZ_8LkMcVeuwTDQTBYkBdyTl7jawXy2jujxDJe5mK3ZvvS_70sWokuPXkCApVFkJpNRDdcvBuoLG3g_KZ7dA0oQW9QHkKpd_-FEuUZFnL6-ZhjR7pe-EmR6gqJbuQVs19N2qho2pnNEe21WqAN-anBb4H7QN2V1ODJkW6vDDRH5sV8Ya7YYUScSI3TUASWH3MWapL1_-lRiXtVIM9Q8leFFIO_qkr8DFXoDOHp29HNa3gpQkjOqAFqX0VLg1Ub6X6C-kUbXWMcYIUoKNvQx5-Yhy5Lo0N6izxdE4Zw6U6Lfu90rA2DWeQ5-iae79H9yUy74jZw3bclkJFzGkydXWIP4OkKnDPemIKmsh28ovmfgtz_gJ99SlQDBmI6paH6P8wmHd7QvDQkMBnuACOnTnTud_MqdNUR4-qtcnPoNkFPXoTfYJNDDBkxvaEIXylqKK0wPf9aBsICsvB0N96nPpQTYuV2YHfIr8PagOi8wWC9ceUmDib8fMq3xgClujOcXOPk2Hh4Xuslecn315m-SoLjRg-dIdmTjuIyT9CrSdXMto5Jp7vcPTsRPebw41Tf4iR78BOTuGhbe_B7_WDm5FH10EptF1e3GZ0eO--VdgqLY3T3ivuoxtXIkTvDHvLHqNwFJIvH4ULUAIx3UGqJwE84_OqGwKBRT4UuQRm5wwZUZ0teyzOQx0cp7aKhsOkBzKY8jVFMmTBKin52ioD1inMiyBUYICYwYUngdYRmE5Qx7qzqB6Mg5CSW_7TaXuZFNVuVnitQp5uw2RrOlookLqyKYIQhruNjaUAvvDnhhIrTjh_Bi7f-wv7znhbJDE7YWy_zC_ufQj9VfxJcz6eXKu3fXr4EKlLayk2nwO5BkwaijetPdBNs4SOroEo6WfvFgVtbt-c6kkEfY5abo5zK6OPVHrpBVyew-A53SA0bQNptBVMNkZDiPczaviF3H3fnkMQH59RhIhMV9knjfCbAhP5BTmBFyFIXjX_ErOJgb3RtUObwjnifMNwN2hIE_-eMqk8K-jxMrT7xNoojwqcCgmzcY5w8hbmA77xW4ZnlBuTZORjFhppokfhLPcoVCcbt1AEWLc3oFYhquugqG9WZbS_7p_pI8C_zB4Q4x8MTn7lO9RZFufBeI9iTm6JP95asBuEafpQxP91ZAhfiU93UybWsoaKQb78PvjqwwK2D-LRumK6ftSMU3LNn1MBmiFowwzOLPxrkN4dzqF89rXEXJCuqS3jl9fEwKOdCvhpXyVRN6Kx5VBxSrY8KO9ItwWkrjHF4cWCTRVNePbw92TzRnzgLB4aEZ9T5TkIvdNgOyCQYSaOZ1TMSgO3a-i03avh9KisZcyt-gUbD11-EJmt_KOSeK5o-Jn3GmUKnZJJX9hKCOWCmN00qv8DzYCfIO9Bd6kfOXAqJJ0RFDHn6a4VHv4NrZNyXQWrX12_V3H4oHVZhDurhlhhak-6xoSC6KWeHFFlU39xzKx-2BfggTfghpTj4x8WiObhHvg7I6OY67vzfyRtJoA4muFzqq0c-RJ1QMvOXLGDEMJMSmuXxT0GOux0GvkB6VB4snKw5ZWdzTdm-maT6LBL9POZ8f2psW9CtE9tuzs1EfrBS9SHn9s_B6NHRCahEwwaIRFePU0v9mT3hhQoq_CawOykzNVGAPPAKyA8PNZr5GGmdmV7v0fWppgHUZA_sQPbq0XuxgoQFLJttwnCEf_mkS1zPYMYBv16U9G-kZQ25-rdHBFyZG-Wa6nBCSk7lm6ZNkDKSN7L-lBAVgpPgzDvXlCHaklZmQXwtNnBSPOZ3yO2-MBcDmSyoDbXpdM0zYZhMCyv0vMf2mKhEP91a2xD4tsp-Og6gAo0AXgk6Ge_be4zhMaUxm_NdPGg65mkaSaOZqCuevYVh0En18B7x2erzzUAMuJoo5C8ab1yLVGZSKNda3z8j40JeqcaYLN-yS4RaGaNdva_pmCq0dXYadIjaoivy4TqnHig9uJtboQqBevHPq2xXdsSutQOyEEexxjYbEz1USu25bTvog4tJs5okxNWDnL_0vBXZTpYCGdVo2WcMJgwqNBp-CPoZjMxCQ9IM6iS3KKETc9U46ksBbN95ZSeRUoUUtO_i0AoBsxE9A4NFbK9Uox2RGcJxOlC9HM2n5D6LmOyIO5KaYl16sfmURTRlcNpgTYAvat5HbfDYMFrH9EgSxu0y735-2wvZSuD0credILM3XFTyBmM7-278If-6-QaDX7zV9JxJaXrXx92T-srNH2Z5DLBOJDkl7oo1lVGKcFAmEgHjnkT_rPt8DvU4tlh0eI8HzSe7B35oA02GJE17hiWk-_VOUG2zNaOaesGK437EOzcCcc1dMZAtN206qPtzDZsNPhQNEBUx9Ta_jPG6waGpwihNxVfhwVvrR0zFUy1IspR9B1ONXttsi7nQ0YAtDSJaBuUgwwtYk2KL4QqRAixv_KSma8mOfuxs0th-sTyFGQ5f77q71ZcLUeYqVqrsjcDsh0K9pDvj4-KXcQXgd6EzY8zfh7VvXOHIr2aHBcHk1tw9zjYAR19sP87lo7YdVNrYlB09IkCICT9N1RSWJHUsszCvP0oBSmdNPfelx1CvHlClrc2qNGcyalsF8hc4wnG3mrYIC0rb4sHLc6Xp47g7vWnXH1ud169K4dB5YwnLam08lPwSYJwqculJw5d_L2egSoNIdYGvlvH-4prN6EkkyiqmZCHXYSNoKorU-ce7cRpc6mbxxU6CLCS_1FhlgfG_mZFP-KAZ3b-lQVdimYcudQeCgtjaydeAcUP4raEP_Wa3bhMB-GK90eskPs0cZgeRDvwohATR8ynHvxFCAeoiQcL-3bQgdOhZxY6r8dn6HF3RWWaeA6o4xS0XTlxecl4rOXs4nJAvn3jGZ4VmU9qkYcoVBW44IkLnbx0q07n4rRiurI4596rknVRJwbeb--_d9l9gSqn_ZwIHHyO4tk9np7I8yMTGp0j3ea_GbKrss2_8gU-XDU57ihgCQyOrAcyyfljyHTE6m-upNK0glJ-2m9r0ktOToCN-6ve4H3trSNvRL26rmH_WV8d-gwsF76cPYdlCZu46pC3Ib_R4sHUeBjg39ilY0IxUTOsLz-34NuMeKKnaViX68pZw1XzMLb7ZJOYhe0AKKO4Yrrkwpwlqvbpgd369PENtcqdakdbn44wKOfp49d9czQYQcYlRK3L08MhGsHXuDTlUcqqEYSDpwM_D2__AicfRazviJzdWQQMNJHA_0COIuhQ4c0dbPOOZqCMM9BxQe69fNlTfZEpFL2Axh_6-TqEXdqU8CO2fYScvQfuXZ2AMbmit46qlhUJMj5082R_XYNwIR_b-QMqm0e6aI_vZRVw8MwdJHG73Z_u4whBIR36VHrrK1qUYLxC2pYyLOwHlPEYlyN7HlTs6i_iJ9z4TQuK_mk_b1bc4-1XfgQUU8ZfjYPNoQNII_Dtym-9k7Ukv-pU5Nk1lItlLk07wiCcKMlui8Y-23K9mb03O38x9ZhN051SusVM9ItehAp684sy-kb6MymRW0LsXXIPdRc9LxI85RZ3aANfAtMaHbRov2jpVvZT4OQhTQIJLg3656y_NG32DJvFQoBLEgfFCTKYQgpKWmbxj1gRsVDrdk8EBF3rz1ohyUfxqyrHSYM39YGs2bnk9TkvaOaHOluV_ZoY-qIDysJ_p1eKxJVdpF2VCxZ1ctwuKCbVx6pl6XLuN-g2KaJnpgxVcVbrnxsgLrh5OGeDuXiBFYeLYaF09wFBHTHF0naw63TgB8jy61c5r7_y4DVAiicoSJ3B8SJxEmB5qgXVse_vwmKOxvULXcgU9XLaONbYYIUulkSNOSK_x_xWnVRL7yWHj9xMjWTvBXgVcux1CmehPPQ7dGhooXgzCoipDZ_y_sRl43wYZiaqG7Nl79ciyfdwi6xKUb0CgLQp1D2Q90bHKRUV1Y1IdcIUl-atTUcMGYDyLKmYQQ0BWvqXeaZtHra_yDzoIlB7rR9Hg9agchVJsUA46egTwwvlHdiYPIxJidKAQFgpDospYReegQxCIZHg_PI0FPVfXBfNR2Vc8fIrXiNwzPi4jvj83YmDTvTJ1xBLYDao7QzDQUjkpl09EnP4UoGlvFYlrXH0Ev1sWz_svhFVAduqJzHke7BW5b7gYipmIqQCvPgehCMuD8-NkaEAtE613V6BLPTu51IPtkvFoS_zSRCkLnspDFVTeDToBKQlN0-u1LlMF9f1dQDPxBE8ZLacKFP2F6lezHhikzuoJTyfCzF0xT4nn8alqzDzRV3K0wAl_4NKjhwSHz9i8MRxPo1WEfO8Xpt1aKa6WIbZ2rr5ayhX3H4ASPQ7UDoMNrRZP82lcAerRb_j7wyL57W6oE7VetxnmbexD15h_7LukUqUNSSgg6D0zxX2C23EhpBaQ7Bw4Va_costesVZBuYwEig3VR5Y-9WvmN0CuaeE1oZkXJ5zBCBgO5F_hIESxHP9zx9Z4fs7fswQDJHaick1xpSSZNDbBghUqlswGvI4TTtUWGPc5R1mf9dLQDF6j5wTo1kycMpfXIUF6hVqZRlKHgP4DRetOCsAgb_WMW0b_GCVyK8JyeZsTSXN547g8Q6WMRYikbZDP25hglrI5hU03GLf3m2WLJAd4eKB5e1nlDhIqAGn289gdttwfe8rUzB5BhdSZ6BcaWAEVp64EHYFmtco1aBleXa0RVlSDS6gt7U7ozAp0YxkBW7YlqXxfM8A8y-Dn8LkKewv5p7q7yL5Bkun5Cy7rZ_FPQ_4ktHUr_RzqpQbgSgtXwOSyCfoDKqIPNg4AhjaI33nD93HuRQeV_mhxYwXN5GNTq-7SxkulMwTSgg7b2UhmOSu87pX_FMk5nFaglzYzHKpoZA3QuNxwHzTVInF8Ufu6fAIOPT5fEuhfilDU3uxCkpC-us4yeLwm8e36ICJZFfcqa5dXHkFezEXPKvFbhpVgjTO-TI2EH_vb4QcYNQxtQGWUqFcuQ7IaIgYChVS7ifjkPc65wR9ffjTEEqFAt6e-_mviI4ltyiTLTNTWY68JV64SnjeMQ9qR9gPYmefUp_E_LyOdwfetRYKBJ81jAMz2piWNoJHwHbFjBxeZj8iZ34TnirgvWRltUi20aN09b8TN_IbFNPFjkI1UwshqMwLY9GXT4eq0QaIdvhW9CE90--KNVjGvqyRLodo0gsGTpmTcoTPDgF_AuaeDlaBrbAnW-pFr1HOV5YqUGja5_vkDvi9mdKooFrlSau-Dt1HmZf81izJ8odFR-tHl0u-wT66G0aEkk1DS81IXvSLLNAQlIpj5FoZYx2RPFWyw1WBlY8iSa4r6HyN5YKW9taJ7ljUliA8KClax8VM282lqYL5Fd-wtYu5Iceez8jGGj4cZ7JetWp6X-wjLHeo6SDUGjNO7k7h3ODmCRnIKJZVtbx6qJEVX1u8J9mIAXEjdArqa_7YiUBTuka0W7IxVXZUx9R96h5f', provider_name='openai', ), TextPart( content=IsStr(), id='msg_0b4f29854724a3120068c4ab22122081918f25e06f1368274e', ), ], usage=RequestUsage( input_tokens=9939, cache_read_tokens=8320, output_tokens=1610, details={'reasoning_tokens': 1344} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0b4f29854724a3120068c4ab0b660081919707b95b47552782', finish_reason='stop', ), ] ) async def test_openai_responses_model_web_search_tool_stream(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent( m, instructions='You are a helpful assistant.', builtin_tools=[WebSearchTool()], model_settings=OpenAIResponsesModelSettings(openai_include_web_search_sources=True), ) event_parts: list[Any] = [] async with agent.iter(user_prompt='What is the weather in San Francisco today?') as agent_run: async for node in agent_run: if Agent.is_model_request_node(node) or Agent.is_call_tools_node(node): async with node.stream(agent_run.ctx) as request_stream: async for event in request_stream: event_parts.append(event) assert agent_run.result is not None messages = agent_run.result.all_messages() assert messages == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the weather in San Francisco today?', timestamp=IsDatetime(), ) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_00a60507bf41223d0068c9d2fc927081a088e0b920cdfe3866', signature='gAAAAABoydMADQ6HaJB8mYQXlwd-4MrCfzmKqMHXUnSAXWV3huK1UrU1h3Do3pbK4bcD4BAvNiHTH-Pn27MGZDP_53IhKj_vB0egVf6Z_Y2uFPtzmyasYtTzrTkGSfAMR0xfI4wJk99aatk3UyLPNE7EO_vWYzN6CSX5ifJNNcmY3ArW1A7XnmsnMSBys05PsWqLMHZOUFuBvM2W37QUW6QOfBXZy0TamoO5UknNUfZb_TwvSnMEDpa-lXyDn4VuzfxreEGVHGdSyz5oLN0nBr3KwHIfxMRZIf9gi9-hKCnxX7i-ZktNIfTgd_WEmNKlaPO-qjKHPlO_XPKbEfpBdMv5b2P9BIC20ZG3m6qnEc4OqafWZa1iC2szi4eKOEa6neh2ltVLsLS3MlurF4sO-EHQT4O9t-zJ-738mZsOgjsI9rTrLm_aTAJrntSSWRLcP6PI6_ILHyeAl_aN4svtnwQJZhv4_Qf62q70SZQ5fSfqoqfO1YHLcXq6Op99iH3CfAhOjH-NcgThFLpT4-VLYABl8wiWBTsWzdndZoPmvMLEOaEGJOcM6_922FC0Q-fUio3psm_pLcElaG-XIkyn4oNuk6OJQonFE-Bm6WS_1I9sMF0ncSD4gH1Ey-5y2Ayxi3Kb3XWjFvs1RKW17KFXj8sthF3vY5WHUeRKA14WtN-cHsi4lXBFYJmn2FiD3CmV-_4ErzXH8sIMJrDDsqfCoiSbHwih25INTTIj7KAPL2QtIpU6A8zbzQIK-GOKqb0n4wGeOIyf7J4C2-5jhmlF2a6HUApFXZsRcD8e3X1WqSjdTdnRu_0GzDuHhPghRQJ3DHfGwDvoZy6UK55zb2MaxpNyMHT149sMwUWkCVg0BruxnOUfziuURWhT-VJWzv5mr3Z765TFB1PfHJhznKPFiZN0MTStVtqKQlOe8nkwLevCgZY4oT1Mysg7YJhcWtkquKILXe-y6luJBHzUy_aFAgFliUbcrOhkoBk5olAbSz8Y4sSz5vWugYA1kwlIofnRm4sPcvoIXgUD_SGGI3QNsQyRWQEhf7G5mNRrxmLhZZLXAcBAzkw10nEjRfew2Fri7bdvyzJ1OS_af9fHmeqCZG5ievKIX6keUkIYQo_qm4FQFkXZSl9lMHsUSF-di4F6ws31vM0zVLMmH52u12Z3SZhvAFzIV5Vtyt_IfrMV3ANMqVF4SmS4k2qUlv1KuPQVgqGCVHvfeE1oSyYgYF6oFX8ThXNB79wxvi4Oo8fWEZLzZMFH9QEr2c7sOWHYWk-wUMP1auXTQNExEVz22pBxueZGZhRyLdpcA12v8o6vJkVuBj-2eR8GRI7P6InJdQAO9TIBhM7NtJU2NUpeP_84js3RTBVktqBT74nWPaHIddGMSfW2aGmFJovvshhxGMLtN_6XMh4wRKW0IE_-Rfbhk8_-xHKI5McYI048N_TMYOS8KqPPAmGVklRGqPZ5xXMNvQEVweThDTYTo3NoAsS0fN2yMmSwrjRYBHsgYMtil4pd6ddp8dvF_XSJUkW0nF8t6ciI_k47sug3gyw4usqspWxY9Hwbzb4OFzzrgtO_7Ll6lFFFUx2oHy8AO9sJ97Y3Fg6luuew7ZRDzA_4XMrT7mNW6YuT-o2DunaZw-jvQezNHjPN2WhaTS7fkisyhFSFTMBYE-H4psfj_sizutv-LjwbumTcX2mnYE9SZhVr8dL0c7sgwHP1831RxTSSl3ql_obE3ICDooyuM8PYE56Jx0HOOGbEeJd3w91SzNHPG_3SQfXszrZlw4BGWrEUHBbtVY2ZEnsyGNAx6vKO8lz9D-6yZ618foDJSH-Ilk56a5rhr0beWjSd9mYMsr3zpVz6HcpTLYGEgHfPxpT2eaYaC1H_znw7y1eMKamwudYmtz_azX5LrOtwc0p-pXH-kdoNe248pSz9qsmHcXA41fuj2weKQNrmBcghwtfM95B060tnmebJ_B_KkLXL4cNF-hZqi0wAHrHYrZ_WM0Dy90AFH-b7iiWuWz5M1EhZXo179iEdybM-1PgccFJ0zvOqODl7FNxSgWVyNS1k9R42aZx2PzFAfAbBtJ-KVMhUayAvGLNmi35EAT0G6FK65VBEe7A6zPFqzrrAiG8dy3Z0I0253WzIblHPNMpmxI_ca5tIx3u8Za6Nu9rx8mi0CY2jsRSKnqb7RZvLuB78Uj32lb_9jbq5_gL9_y7Bt7U7i7FospyqMFzEYQLvdyrtfNrfY0rB4zr4Mo0tDn_4YOD_d_nP5axUh9_ruqXZ_d3eVdNmlITjQZj8ALe1EfidP8a-Dl62t6STVv8d2y8v9-jy3J7wReLJbJ6gDDnygJllY7NrIVXSjR45FXiCDnpaRonu--I_0b_LRJFOoJUJX0S9YMaXAkKyHSEj-UWjiuk8cIBNcXxwlxnqqNMezvvV113MAOEbfHygDnphzjzZQxteAVbSy0ucGDR2FPi30d6z51NxGnXNS_sM7wnjBMNp4Li0hhttOp6PgvDKPSMAcgUtKLFKE8iWQAvERoUVxw5Et20hNTNXf_0sXOyh0bF0URPGDxSYz9uZI6-nlwVlo1aobdEnn7STSq2_tuTDIrQyfBGZzhv8OB0H3cj9mBs=', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'weather: San Francisco, CA', 'type': 'search'}, tool_call_id='ws_00a60507bf41223d0068c9d30021d081a0962d80d50c12e317', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={ 'sources': [{'type': 'api', 'url': None, 'name': 'oai-weather'}], 'status': 'completed', }, tool_call_id='ws_00a60507bf41223d0068c9d30021d081a0962d80d50c12e317', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_00a60507bf41223d0068c9d300b23481a0b77a03d911213220', signature='gAAAAABoydMLww_4DcIPiCy5zW1t-Dtx57JodsdP9YkyDCvY9r0nBfoD-bwcBl8FfcFxRuq5nK5ndf90J6Xdxmvl9kGVbCUYSFaOd-kWeE4tgwXM8BwwE3jVs6ZMG3BdiWyXS3alnUO5jcE6kuXeun1LufAdZ6rWtJl3zSmqPycnTh9zoQ4cBBxLDq_qcVS1fgU4WjsWgjCZw6ZWRPWwZk8hywmU7ykCLH7SXItM4oH1m_GCEounJAS8YR4ajUh5KAdN6a1wngfGnXhYdzov98yiNLP6Nrkgr--K4vMTTqWXLTcR6fbWgkijanIeKmfSErCjMT6k5TrAbkFx0rgblHbdQii7zj8seV1BWZse92_k4sltxfc5Ocpyho1YSHhgxyGL7g442xMUEibjPCv6kwPMcW9yGu9wPMWsfPYCXpBbG6kQibQPNFJ_bEubwBRaqdSDq93Aqr1YkTYBja7Tewn8UfzZ8YYaGe5y_K4ZD47lfvDp019dOdXmOuZGC1ECRrMqKzSFYVG1CFY1VhjGdPmzobDoMcpZcLn25s1pg6lnNqNQwOk_IA4MvUcCU5HHD5YjmFkEy5-i_iRoDVu5coK0zyEMvPJ_h10y_ByszcfzS9e0ht5CSilckkFdxTBkZ5epp0YIg1e-PrZ790P-I35Ucquam9OXyULV1Y5bn9ohZa93Tv0JZRxUeTDG72_28xRj8tkJaBAZjoCC7VICw39KVmz-ZkuVN6IIX1WdNzyC4d808-2Tz4UZaU42-wxEWDnSDMD7iZu1Bi9fKKwAYBJt_OcEsJwpW63ZaUSG2PVFfm7a3wRcSMxMTUTTJB7L1Keu1hmNepif5tavn3P35nSq28D_IJyAqAgX7ZyROk2bJqjzSE4A0MddqAoBFFqKBi68n49KH09vDtDXIoh8jVWuIgowgVGr8pN3kuhLI9cir4Pr_WES0tPD7yWHPTzrD7OIJCfQbr_4Y4dEza4ixNi0RTADWzMUZBfr7bvwIsgvg6ZNuQlx_d71Go5VDsT2KI8H8AldiRvNWoLyYTFGyK9Kot97YsS5sEmSYgNAH48NU7pgnM0jNDQU1G39nTNFEjL_ziDwjDT5g3jm4S_gbQfwx-XFT3Pv-JYR-E71AqR--Lg71OsASq49rrlULfl5OENfiT-NB6x8MqnfUI6NpcCsOWLp8XfRbgqmZFutLIi43pcnxEe3cXHLWGF77qJXP6dFb-G5Ide7n9tAOoEgfsVu7hCDPEQ_xrIYRdc2DzDPUMCtXBai24E0AnQF8kxsEtlDW_YmAgGNTl9Gx0tFSGdDuUCsNx__c7v-_LOMWycXUKmH3iEr_su83oGIMapNp2PnLccN4iOxspdZQq0C6WBaR6SrdnGzK-0KwRPRoyKDLNWS8zfluR5bIgKlqd3Sbv_7eL-WO4LQXMvdKP3KS-DBt1HbA-gmyFW03iX2smPQbtVmRLWi1vG329R_07-tHMJSO9OQy6_6aiyO8Rgpbl_CHa1Q9BEkI2csonayDJRPvEXBPuk9-NPUP4VLNPB7npWBLlAqes5ZmhagnC7srTL0fFiLGLJiAxWo1f0BBiIlXjwqHdlgBjTw0KryCnEU8Ic8ATzrqEXXhs-FTBCcWInf3Bt5bzUhy20g7cTtYP-VCbsku-lXQ6wceWrfQVFtjKKICD8I4g9QusAIAvgCUm7J2rR3TLkzwOKngdTFPGQrQ1TYzlkA7q_Ew1uZpaPRckMaEioZYC6Sv_B0rgW0nyBJ0GLrB3AUN60hDrOFntyFHp0FM-Zh1SY-GKGBwZwVetOzM0ZAJ-NreFg1XVgyLTYDNjUrYJjRhr_JARsZ5t0pU4_yI6dPqM5jKO5_k4UpZspfQon6d2-NlWX0EDmz6G4CMTx0TScehYHrQZtPzpVnivc8h_pmXV3jO5GLzNeLWoB70SDPTETo1Of4txiEUaC2komu5B7MN9aR4c7VBOTv1NIjoiZcrd1HFACzZ7r1qAE-G38j1f1YhfZ0_TiMmtfR1cqjAKcFkyRM7rZMyMvvnsH7NFq59gFgWZt0dy0aAdw03XWXFNT67lrw58OYC3NcVozH4SKlmleu7TfjHNWSnJVjJ66riLn9DZWVxPeTk4zuISZn0yyaoXcdW8OMn_mJ9vP-8L1wElMyxKbtBRz-0cW7MshmJ3YXmHWDKbnqETSbDMtqcN_QyRJovopwlptJ8VzL7biuURRFw-l63Kc9vKP72Z-QWOUIPLB4q4nX4yb-IV0mkWFxIUlfv5Cze2anf7zDFyGzeU9xG0onfhJE4HFKcoUT8MzfrHZ0dDZtnEYeL5Xem3GuHpwEVGCxRE_J1joTmJfeWxSVnr2Vey9gaPmXCyRrdKS75v9xSXJFfHvcOO8Qp35Dzk-yFqL3dSOJfOEwDZbEf6QnV7VU1EhJvW4XmRS-wsRLMLCYcLrOx96NHEwb2h2l6gNfbCVJoQrMhMg68qBPnoSYLhML2ho7hWkSNZFy61yX5I-oEJV5XdtjFcBkyurmUD6uYTkJSqXyxLexQiPbT-uv49Yp9cAfFBG23sC9lUQ=', provider_name='openai', ), TextPart( content='San Francisco weather today (Tuesday, September 16, 2025): Mostly sunny and pleasant. Current conditions around 71°F; expected high near 73°F and low around 58°F. A light jacket is useful for the cooler evening. ', id='msg_00a60507bf41223d0068c9d30b055481a0b0ee28a021919c94', ), ], usage=RequestUsage( input_tokens=9463, cache_read_tokens=8320, output_tokens=582, details={'reasoning_tokens': 512}, ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_00a60507bf41223d0068c9d2fbf93481a0ba2a7796ae2cab4c', finish_reason='stop', ), ] ) assert event_parts == snapshot( [ PartStartEvent( index=0, part=ThinkingPart( content='', id='rs_00a60507bf41223d0068c9d2fc927081a088e0b920cdfe3866', signature='gAAAAABoydMADQ6HaJB8mYQXlwd-4MrCfzmKqMHXUnSAXWV3huK1UrU1h3Do3pbK4bcD4BAvNiHTH-Pn27MGZDP_53IhKj_vB0egVf6Z_Y2uFPtzmyasYtTzrTkGSfAMR0xfI4wJk99aatk3UyLPNE7EO_vWYzN6CSX5ifJNNcmY3ArW1A7XnmsnMSBys05PsWqLMHZOUFuBvM2W37QUW6QOfBXZy0TamoO5UknNUfZb_TwvSnMEDpa-lXyDn4VuzfxreEGVHGdSyz5oLN0nBr3KwHIfxMRZIf9gi9-hKCnxX7i-ZktNIfTgd_WEmNKlaPO-qjKHPlO_XPKbEfpBdMv5b2P9BIC20ZG3m6qnEc4OqafWZa1iC2szi4eKOEa6neh2ltVLsLS3MlurF4sO-EHQT4O9t-zJ-738mZsOgjsI9rTrLm_aTAJrntSSWRLcP6PI6_ILHyeAl_aN4svtnwQJZhv4_Qf62q70SZQ5fSfqoqfO1YHLcXq6Op99iH3CfAhOjH-NcgThFLpT4-VLYABl8wiWBTsWzdndZoPmvMLEOaEGJOcM6_922FC0Q-fUio3psm_pLcElaG-XIkyn4oNuk6OJQonFE-Bm6WS_1I9sMF0ncSD4gH1Ey-5y2Ayxi3Kb3XWjFvs1RKW17KFXj8sthF3vY5WHUeRKA14WtN-cHsi4lXBFYJmn2FiD3CmV-_4ErzXH8sIMJrDDsqfCoiSbHwih25INTTIj7KAPL2QtIpU6A8zbzQIK-GOKqb0n4wGeOIyf7J4C2-5jhmlF2a6HUApFXZsRcD8e3X1WqSjdTdnRu_0GzDuHhPghRQJ3DHfGwDvoZy6UK55zb2MaxpNyMHT149sMwUWkCVg0BruxnOUfziuURWhT-VJWzv5mr3Z765TFB1PfHJhznKPFiZN0MTStVtqKQlOe8nkwLevCgZY4oT1Mysg7YJhcWtkquKILXe-y6luJBHzUy_aFAgFliUbcrOhkoBk5olAbSz8Y4sSz5vWugYA1kwlIofnRm4sPcvoIXgUD_SGGI3QNsQyRWQEhf7G5mNRrxmLhZZLXAcBAzkw10nEjRfew2Fri7bdvyzJ1OS_af9fHmeqCZG5ievKIX6keUkIYQo_qm4FQFkXZSl9lMHsUSF-di4F6ws31vM0zVLMmH52u12Z3SZhvAFzIV5Vtyt_IfrMV3ANMqVF4SmS4k2qUlv1KuPQVgqGCVHvfeE1oSyYgYF6oFX8ThXNB79wxvi4Oo8fWEZLzZMFH9QEr2c7sOWHYWk-wUMP1auXTQNExEVz22pBxueZGZhRyLdpcA12v8o6vJkVuBj-2eR8GRI7P6InJdQAO9TIBhM7NtJU2NUpeP_84js3RTBVktqBT74nWPaHIddGMSfW2aGmFJovvshhxGMLtN_6XMh4wRKW0IE_-Rfbhk8_-xHKI5McYI048N_TMYOS8KqPPAmGVklRGqPZ5xXMNvQEVweThDTYTo3NoAsS0fN2yMmSwrjRYBHsgYMtil4pd6ddp8dvF_XSJUkW0nF8t6ciI_k47sug3gyw4usqspWxY9Hwbzb4OFzzrgtO_7Ll6lFFFUx2oHy8AO9sJ97Y3Fg6luuew7ZRDzA_4XMrT7mNW6YuT-o2DunaZw-jvQezNHjPN2WhaTS7fkisyhFSFTMBYE-H4psfj_sizutv-LjwbumTcX2mnYE9SZhVr8dL0c7sgwHP1831RxTSSl3ql_obE3ICDooyuM8PYE56Jx0HOOGbEeJd3w91SzNHPG_3SQfXszrZlw4BGWrEUHBbtVY2ZEnsyGNAx6vKO8lz9D-6yZ618foDJSH-Ilk56a5rhr0beWjSd9mYMsr3zpVz6HcpTLYGEgHfPxpT2eaYaC1H_znw7y1eMKamwudYmtz_azX5LrOtwc0p-pXH-kdoNe248pSz9qsmHcXA41fuj2weKQNrmBcghwtfM95B060tnmebJ_B_KkLXL4cNF-hZqi0wAHrHYrZ_WM0Dy90AFH-b7iiWuWz5M1EhZXo179iEdybM-1PgccFJ0zvOqODl7FNxSgWVyNS1k9R42aZx2PzFAfAbBtJ-KVMhUayAvGLNmi35EAT0G6FK65VBEe7A6zPFqzrrAiG8dy3Z0I0253WzIblHPNMpmxI_ca5tIx3u8Za6Nu9rx8mi0CY2jsRSKnqb7RZvLuB78Uj32lb_9jbq5_gL9_y7Bt7U7i7FospyqMFzEYQLvdyrtfNrfY0rB4zr4Mo0tDn_4YOD_d_nP5axUh9_ruqXZ_d3eVdNmlITjQZj8ALe1EfidP8a-Dl62t6STVv8d2y8v9-jy3J7wReLJbJ6gDDnygJllY7NrIVXSjR45FXiCDnpaRonu--I_0b_LRJFOoJUJX0S9YMaXAkKyHSEj-UWjiuk8cIBNcXxwlxnqqNMezvvV113MAOEbfHygDnphzjzZQxteAVbSy0ucGDR2FPi30d6z51NxGnXNS_sM7wnjBMNp4Li0hhttOp6PgvDKPSMAcgUtKLFKE8iWQAvERoUVxw5Et20hNTNXf_0sXOyh0bF0URPGDxSYz9uZI6-nlwVlo1aobdEnn7STSq2_tuTDIrQyfBGZzhv8OB0H3cj9mBs=', provider_name='openai', ), ), PartEndEvent( index=0, part=ThinkingPart( content='', id='rs_00a60507bf41223d0068c9d2fc927081a088e0b920cdfe3866', signature='gAAAAABoydMADQ6HaJB8mYQXlwd-4MrCfzmKqMHXUnSAXWV3huK1UrU1h3Do3pbK4bcD4BAvNiHTH-Pn27MGZDP_53IhKj_vB0egVf6Z_Y2uFPtzmyasYtTzrTkGSfAMR0xfI4wJk99aatk3UyLPNE7EO_vWYzN6CSX5ifJNNcmY3ArW1A7XnmsnMSBys05PsWqLMHZOUFuBvM2W37QUW6QOfBXZy0TamoO5UknNUfZb_TwvSnMEDpa-lXyDn4VuzfxreEGVHGdSyz5oLN0nBr3KwHIfxMRZIf9gi9-hKCnxX7i-ZktNIfTgd_WEmNKlaPO-qjKHPlO_XPKbEfpBdMv5b2P9BIC20ZG3m6qnEc4OqafWZa1iC2szi4eKOEa6neh2ltVLsLS3MlurF4sO-EHQT4O9t-zJ-738mZsOgjsI9rTrLm_aTAJrntSSWRLcP6PI6_ILHyeAl_aN4svtnwQJZhv4_Qf62q70SZQ5fSfqoqfO1YHLcXq6Op99iH3CfAhOjH-NcgThFLpT4-VLYABl8wiWBTsWzdndZoPmvMLEOaEGJOcM6_922FC0Q-fUio3psm_pLcElaG-XIkyn4oNuk6OJQonFE-Bm6WS_1I9sMF0ncSD4gH1Ey-5y2Ayxi3Kb3XWjFvs1RKW17KFXj8sthF3vY5WHUeRKA14WtN-cHsi4lXBFYJmn2FiD3CmV-_4ErzXH8sIMJrDDsqfCoiSbHwih25INTTIj7KAPL2QtIpU6A8zbzQIK-GOKqb0n4wGeOIyf7J4C2-5jhmlF2a6HUApFXZsRcD8e3X1WqSjdTdnRu_0GzDuHhPghRQJ3DHfGwDvoZy6UK55zb2MaxpNyMHT149sMwUWkCVg0BruxnOUfziuURWhT-VJWzv5mr3Z765TFB1PfHJhznKPFiZN0MTStVtqKQlOe8nkwLevCgZY4oT1Mysg7YJhcWtkquKILXe-y6luJBHzUy_aFAgFliUbcrOhkoBk5olAbSz8Y4sSz5vWugYA1kwlIofnRm4sPcvoIXgUD_SGGI3QNsQyRWQEhf7G5mNRrxmLhZZLXAcBAzkw10nEjRfew2Fri7bdvyzJ1OS_af9fHmeqCZG5ievKIX6keUkIYQo_qm4FQFkXZSl9lMHsUSF-di4F6ws31vM0zVLMmH52u12Z3SZhvAFzIV5Vtyt_IfrMV3ANMqVF4SmS4k2qUlv1KuPQVgqGCVHvfeE1oSyYgYF6oFX8ThXNB79wxvi4Oo8fWEZLzZMFH9QEr2c7sOWHYWk-wUMP1auXTQNExEVz22pBxueZGZhRyLdpcA12v8o6vJkVuBj-2eR8GRI7P6InJdQAO9TIBhM7NtJU2NUpeP_84js3RTBVktqBT74nWPaHIddGMSfW2aGmFJovvshhxGMLtN_6XMh4wRKW0IE_-Rfbhk8_-xHKI5McYI048N_TMYOS8KqPPAmGVklRGqPZ5xXMNvQEVweThDTYTo3NoAsS0fN2yMmSwrjRYBHsgYMtil4pd6ddp8dvF_XSJUkW0nF8t6ciI_k47sug3gyw4usqspWxY9Hwbzb4OFzzrgtO_7Ll6lFFFUx2oHy8AO9sJ97Y3Fg6luuew7ZRDzA_4XMrT7mNW6YuT-o2DunaZw-jvQezNHjPN2WhaTS7fkisyhFSFTMBYE-H4psfj_sizutv-LjwbumTcX2mnYE9SZhVr8dL0c7sgwHP1831RxTSSl3ql_obE3ICDooyuM8PYE56Jx0HOOGbEeJd3w91SzNHPG_3SQfXszrZlw4BGWrEUHBbtVY2ZEnsyGNAx6vKO8lz9D-6yZ618foDJSH-Ilk56a5rhr0beWjSd9mYMsr3zpVz6HcpTLYGEgHfPxpT2eaYaC1H_znw7y1eMKamwudYmtz_azX5LrOtwc0p-pXH-kdoNe248pSz9qsmHcXA41fuj2weKQNrmBcghwtfM95B060tnmebJ_B_KkLXL4cNF-hZqi0wAHrHYrZ_WM0Dy90AFH-b7iiWuWz5M1EhZXo179iEdybM-1PgccFJ0zvOqODl7FNxSgWVyNS1k9R42aZx2PzFAfAbBtJ-KVMhUayAvGLNmi35EAT0G6FK65VBEe7A6zPFqzrrAiG8dy3Z0I0253WzIblHPNMpmxI_ca5tIx3u8Za6Nu9rx8mi0CY2jsRSKnqb7RZvLuB78Uj32lb_9jbq5_gL9_y7Bt7U7i7FospyqMFzEYQLvdyrtfNrfY0rB4zr4Mo0tDn_4YOD_d_nP5axUh9_ruqXZ_d3eVdNmlITjQZj8ALe1EfidP8a-Dl62t6STVv8d2y8v9-jy3J7wReLJbJ6gDDnygJllY7NrIVXSjR45FXiCDnpaRonu--I_0b_LRJFOoJUJX0S9YMaXAkKyHSEj-UWjiuk8cIBNcXxwlxnqqNMezvvV113MAOEbfHygDnphzjzZQxteAVbSy0ucGDR2FPi30d6z51NxGnXNS_sM7wnjBMNp4Li0hhttOp6PgvDKPSMAcgUtKLFKE8iWQAvERoUVxw5Et20hNTNXf_0sXOyh0bF0URPGDxSYz9uZI6-nlwVlo1aobdEnn7STSq2_tuTDIrQyfBGZzhv8OB0H3cj9mBs=', provider_name='openai', ), next_part_kind='builtin-tool-call', ), PartStartEvent( index=1, part=BuiltinToolCallPart( tool_name='web_search', tool_call_id='ws_00a60507bf41223d0068c9d30021d081a0962d80d50c12e317', provider_name='openai', ), previous_part_kind='thinking', ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta={'query': 'weather: San Francisco, CA', 'type': 'search'}, tool_call_id='ws_00a60507bf41223d0068c9d30021d081a0962d80d50c12e317', ), ), PartEndEvent( index=1, part=BuiltinToolCallPart( tool_name='web_search', args={'query': 'weather: San Francisco, CA', 'type': 'search'}, tool_call_id='ws_00a60507bf41223d0068c9d30021d081a0962d80d50c12e317', provider_name='openai', ), next_part_kind='builtin-tool-return', ), PartStartEvent( index=2, part=BuiltinToolReturnPart( tool_name='web_search', content={'status': 'completed', 'sources': [{'type': 'api', 'url': None, 'name': 'oai-weather'}]}, tool_call_id='ws_00a60507bf41223d0068c9d30021d081a0962d80d50c12e317', timestamp=IsDatetime(), provider_name='openai', ), previous_part_kind='builtin-tool-call', ), PartStartEvent( index=3, part=ThinkingPart( content='', id='rs_00a60507bf41223d0068c9d300b23481a0b77a03d911213220', signature='gAAAAABoydMLww_4DcIPiCy5zW1t-Dtx57JodsdP9YkyDCvY9r0nBfoD-bwcBl8FfcFxRuq5nK5ndf90J6Xdxmvl9kGVbCUYSFaOd-kWeE4tgwXM8BwwE3jVs6ZMG3BdiWyXS3alnUO5jcE6kuXeun1LufAdZ6rWtJl3zSmqPycnTh9zoQ4cBBxLDq_qcVS1fgU4WjsWgjCZw6ZWRPWwZk8hywmU7ykCLH7SXItM4oH1m_GCEounJAS8YR4ajUh5KAdN6a1wngfGnXhYdzov98yiNLP6Nrkgr--K4vMTTqWXLTcR6fbWgkijanIeKmfSErCjMT6k5TrAbkFx0rgblHbdQii7zj8seV1BWZse92_k4sltxfc5Ocpyho1YSHhgxyGL7g442xMUEibjPCv6kwPMcW9yGu9wPMWsfPYCXpBbG6kQibQPNFJ_bEubwBRaqdSDq93Aqr1YkTYBja7Tewn8UfzZ8YYaGe5y_K4ZD47lfvDp019dOdXmOuZGC1ECRrMqKzSFYVG1CFY1VhjGdPmzobDoMcpZcLn25s1pg6lnNqNQwOk_IA4MvUcCU5HHD5YjmFkEy5-i_iRoDVu5coK0zyEMvPJ_h10y_ByszcfzS9e0ht5CSilckkFdxTBkZ5epp0YIg1e-PrZ790P-I35Ucquam9OXyULV1Y5bn9ohZa93Tv0JZRxUeTDG72_28xRj8tkJaBAZjoCC7VICw39KVmz-ZkuVN6IIX1WdNzyC4d808-2Tz4UZaU42-wxEWDnSDMD7iZu1Bi9fKKwAYBJt_OcEsJwpW63ZaUSG2PVFfm7a3wRcSMxMTUTTJB7L1Keu1hmNepif5tavn3P35nSq28D_IJyAqAgX7ZyROk2bJqjzSE4A0MddqAoBFFqKBi68n49KH09vDtDXIoh8jVWuIgowgVGr8pN3kuhLI9cir4Pr_WES0tPD7yWHPTzrD7OIJCfQbr_4Y4dEza4ixNi0RTADWzMUZBfr7bvwIsgvg6ZNuQlx_d71Go5VDsT2KI8H8AldiRvNWoLyYTFGyK9Kot97YsS5sEmSYgNAH48NU7pgnM0jNDQU1G39nTNFEjL_ziDwjDT5g3jm4S_gbQfwx-XFT3Pv-JYR-E71AqR--Lg71OsASq49rrlULfl5OENfiT-NB6x8MqnfUI6NpcCsOWLp8XfRbgqmZFutLIi43pcnxEe3cXHLWGF77qJXP6dFb-G5Ide7n9tAOoEgfsVu7hCDPEQ_xrIYRdc2DzDPUMCtXBai24E0AnQF8kxsEtlDW_YmAgGNTl9Gx0tFSGdDuUCsNx__c7v-_LOMWycXUKmH3iEr_su83oGIMapNp2PnLccN4iOxspdZQq0C6WBaR6SrdnGzK-0KwRPRoyKDLNWS8zfluR5bIgKlqd3Sbv_7eL-WO4LQXMvdKP3KS-DBt1HbA-gmyFW03iX2smPQbtVmRLWi1vG329R_07-tHMJSO9OQy6_6aiyO8Rgpbl_CHa1Q9BEkI2csonayDJRPvEXBPuk9-NPUP4VLNPB7npWBLlAqes5ZmhagnC7srTL0fFiLGLJiAxWo1f0BBiIlXjwqHdlgBjTw0KryCnEU8Ic8ATzrqEXXhs-FTBCcWInf3Bt5bzUhy20g7cTtYP-VCbsku-lXQ6wceWrfQVFtjKKICD8I4g9QusAIAvgCUm7J2rR3TLkzwOKngdTFPGQrQ1TYzlkA7q_Ew1uZpaPRckMaEioZYC6Sv_B0rgW0nyBJ0GLrB3AUN60hDrOFntyFHp0FM-Zh1SY-GKGBwZwVetOzM0ZAJ-NreFg1XVgyLTYDNjUrYJjRhr_JARsZ5t0pU4_yI6dPqM5jKO5_k4UpZspfQon6d2-NlWX0EDmz6G4CMTx0TScehYHrQZtPzpVnivc8h_pmXV3jO5GLzNeLWoB70SDPTETo1Of4txiEUaC2komu5B7MN9aR4c7VBOTv1NIjoiZcrd1HFACzZ7r1qAE-G38j1f1YhfZ0_TiMmtfR1cqjAKcFkyRM7rZMyMvvnsH7NFq59gFgWZt0dy0aAdw03XWXFNT67lrw58OYC3NcVozH4SKlmleu7TfjHNWSnJVjJ66riLn9DZWVxPeTk4zuISZn0yyaoXcdW8OMn_mJ9vP-8L1wElMyxKbtBRz-0cW7MshmJ3YXmHWDKbnqETSbDMtqcN_QyRJovopwlptJ8VzL7biuURRFw-l63Kc9vKP72Z-QWOUIPLB4q4nX4yb-IV0mkWFxIUlfv5Cze2anf7zDFyGzeU9xG0onfhJE4HFKcoUT8MzfrHZ0dDZtnEYeL5Xem3GuHpwEVGCxRE_J1joTmJfeWxSVnr2Vey9gaPmXCyRrdKS75v9xSXJFfHvcOO8Qp35Dzk-yFqL3dSOJfOEwDZbEf6QnV7VU1EhJvW4XmRS-wsRLMLCYcLrOx96NHEwb2h2l6gNfbCVJoQrMhMg68qBPnoSYLhML2ho7hWkSNZFy61yX5I-oEJV5XdtjFcBkyurmUD6uYTkJSqXyxLexQiPbT-uv49Yp9cAfFBG23sC9lUQ=', provider_name='openai', ), previous_part_kind='builtin-tool-return', ), PartEndEvent( index=3, part=ThinkingPart( content='', id='rs_00a60507bf41223d0068c9d300b23481a0b77a03d911213220', signature='gAAAAABoydMLww_4DcIPiCy5zW1t-Dtx57JodsdP9YkyDCvY9r0nBfoD-bwcBl8FfcFxRuq5nK5ndf90J6Xdxmvl9kGVbCUYSFaOd-kWeE4tgwXM8BwwE3jVs6ZMG3BdiWyXS3alnUO5jcE6kuXeun1LufAdZ6rWtJl3zSmqPycnTh9zoQ4cBBxLDq_qcVS1fgU4WjsWgjCZw6ZWRPWwZk8hywmU7ykCLH7SXItM4oH1m_GCEounJAS8YR4ajUh5KAdN6a1wngfGnXhYdzov98yiNLP6Nrkgr--K4vMTTqWXLTcR6fbWgkijanIeKmfSErCjMT6k5TrAbkFx0rgblHbdQii7zj8seV1BWZse92_k4sltxfc5Ocpyho1YSHhgxyGL7g442xMUEibjPCv6kwPMcW9yGu9wPMWsfPYCXpBbG6kQibQPNFJ_bEubwBRaqdSDq93Aqr1YkTYBja7Tewn8UfzZ8YYaGe5y_K4ZD47lfvDp019dOdXmOuZGC1ECRrMqKzSFYVG1CFY1VhjGdPmzobDoMcpZcLn25s1pg6lnNqNQwOk_IA4MvUcCU5HHD5YjmFkEy5-i_iRoDVu5coK0zyEMvPJ_h10y_ByszcfzS9e0ht5CSilckkFdxTBkZ5epp0YIg1e-PrZ790P-I35Ucquam9OXyULV1Y5bn9ohZa93Tv0JZRxUeTDG72_28xRj8tkJaBAZjoCC7VICw39KVmz-ZkuVN6IIX1WdNzyC4d808-2Tz4UZaU42-wxEWDnSDMD7iZu1Bi9fKKwAYBJt_OcEsJwpW63ZaUSG2PVFfm7a3wRcSMxMTUTTJB7L1Keu1hmNepif5tavn3P35nSq28D_IJyAqAgX7ZyROk2bJqjzSE4A0MddqAoBFFqKBi68n49KH09vDtDXIoh8jVWuIgowgVGr8pN3kuhLI9cir4Pr_WES0tPD7yWHPTzrD7OIJCfQbr_4Y4dEza4ixNi0RTADWzMUZBfr7bvwIsgvg6ZNuQlx_d71Go5VDsT2KI8H8AldiRvNWoLyYTFGyK9Kot97YsS5sEmSYgNAH48NU7pgnM0jNDQU1G39nTNFEjL_ziDwjDT5g3jm4S_gbQfwx-XFT3Pv-JYR-E71AqR--Lg71OsASq49rrlULfl5OENfiT-NB6x8MqnfUI6NpcCsOWLp8XfRbgqmZFutLIi43pcnxEe3cXHLWGF77qJXP6dFb-G5Ide7n9tAOoEgfsVu7hCDPEQ_xrIYRdc2DzDPUMCtXBai24E0AnQF8kxsEtlDW_YmAgGNTl9Gx0tFSGdDuUCsNx__c7v-_LOMWycXUKmH3iEr_su83oGIMapNp2PnLccN4iOxspdZQq0C6WBaR6SrdnGzK-0KwRPRoyKDLNWS8zfluR5bIgKlqd3Sbv_7eL-WO4LQXMvdKP3KS-DBt1HbA-gmyFW03iX2smPQbtVmRLWi1vG329R_07-tHMJSO9OQy6_6aiyO8Rgpbl_CHa1Q9BEkI2csonayDJRPvEXBPuk9-NPUP4VLNPB7npWBLlAqes5ZmhagnC7srTL0fFiLGLJiAxWo1f0BBiIlXjwqHdlgBjTw0KryCnEU8Ic8ATzrqEXXhs-FTBCcWInf3Bt5bzUhy20g7cTtYP-VCbsku-lXQ6wceWrfQVFtjKKICD8I4g9QusAIAvgCUm7J2rR3TLkzwOKngdTFPGQrQ1TYzlkA7q_Ew1uZpaPRckMaEioZYC6Sv_B0rgW0nyBJ0GLrB3AUN60hDrOFntyFHp0FM-Zh1SY-GKGBwZwVetOzM0ZAJ-NreFg1XVgyLTYDNjUrYJjRhr_JARsZ5t0pU4_yI6dPqM5jKO5_k4UpZspfQon6d2-NlWX0EDmz6G4CMTx0TScehYHrQZtPzpVnivc8h_pmXV3jO5GLzNeLWoB70SDPTETo1Of4txiEUaC2komu5B7MN9aR4c7VBOTv1NIjoiZcrd1HFACzZ7r1qAE-G38j1f1YhfZ0_TiMmtfR1cqjAKcFkyRM7rZMyMvvnsH7NFq59gFgWZt0dy0aAdw03XWXFNT67lrw58OYC3NcVozH4SKlmleu7TfjHNWSnJVjJ66riLn9DZWVxPeTk4zuISZn0yyaoXcdW8OMn_mJ9vP-8L1wElMyxKbtBRz-0cW7MshmJ3YXmHWDKbnqETSbDMtqcN_QyRJovopwlptJ8VzL7biuURRFw-l63Kc9vKP72Z-QWOUIPLB4q4nX4yb-IV0mkWFxIUlfv5Cze2anf7zDFyGzeU9xG0onfhJE4HFKcoUT8MzfrHZ0dDZtnEYeL5Xem3GuHpwEVGCxRE_J1joTmJfeWxSVnr2Vey9gaPmXCyRrdKS75v9xSXJFfHvcOO8Qp35Dzk-yFqL3dSOJfOEwDZbEf6QnV7VU1EhJvW4XmRS-wsRLMLCYcLrOx96NHEwb2h2l6gNfbCVJoQrMhMg68qBPnoSYLhML2ho7hWkSNZFy61yX5I-oEJV5XdtjFcBkyurmUD6uYTkJSqXyxLexQiPbT-uv49Yp9cAfFBG23sC9lUQ=', provider_name='openai', ), next_part_kind='text', ), PartStartEvent( index=4, part=TextPart(content='San Francisco', id='msg_00a60507bf41223d0068c9d30b055481a0b0ee28a021919c94'), previous_part_kind='thinking', ), FinalResultEvent(tool_name=None, tool_call_id=None), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' weather')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' today')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' (')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='Tuesday')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=',')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' September')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' ')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='16')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=',')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' ')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='202')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='5')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='):')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' Mostly')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' sunny')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' and')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' pleasant')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='.')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' Current')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' conditions')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' around')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' ')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='71')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='°F')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=';')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' expected')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' high')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' near')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' ')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='73')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='°F')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' and')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' low')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' around')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' ')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='58')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='°F')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='.')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' A light jacket')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' is useful')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' for the')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' cooler evening')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='. ')), PartEndEvent( index=4, part=TextPart( content='San Francisco weather today (Tuesday, September 16, 2025): Mostly sunny and pleasant. Current conditions around 71°F; expected high near 73°F and low around 58°F. A light jacket is useful for the cooler evening. ', id='msg_00a60507bf41223d0068c9d30b055481a0b0ee28a021919c94', ), ), BuiltinToolCallEvent( # pyright: ignore[reportDeprecated] part=BuiltinToolCallPart( tool_name='web_search', args={'query': 'weather: San Francisco, CA', 'type': 'search'}, tool_call_id='ws_00a60507bf41223d0068c9d30021d081a0962d80d50c12e317', provider_name='openai', ) ), BuiltinToolResultEvent( # pyright: ignore[reportDeprecated] result=BuiltinToolReturnPart( tool_name='web_search', content={'sources': [{'type': 'api', 'url': None, 'name': 'oai-weather'}], 'status': 'completed'}, tool_call_id='ws_00a60507bf41223d0068c9d30021d081a0962d80d50c12e317', timestamp=IsDatetime(), provider_name='openai', ) ), ] ) result = await agent.run(user_prompt='how about Mexico City?', message_history=messages) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='how about Mexico City?', timestamp=IsDatetime(), ) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_00a60507bf41223d0068c9d316accc81a096fd539b77c931cd', signature='gAAAAABoydMovnl5STyQJfKyyT-LV6102tn7M3ppFZHklPnA1LWETYbnDdCSLgeh1OqOXicuil2GTd-peiKj033k_NL0ZF5mCymWY-g5qoovU8OauQyb2uR9zmLe-cjghlOuiIJjiZC1_DCbwY1MHObzuME-Hn5WiSlfTTcdKfZqaQpzIKVKgbx6cSDDyS5j29ClLw-M6GQUDVDsjkclLEcc8pdoAwvuWDoARgMYXwcS-7Ajl46_9oA92RP-64VjrO6Wxzz9HjKcnBTcSDUcyJxsdolHq6G0TjZFwECg4RWvzcpijO53OF58a4_SfgUqbupni7o-tMzITyF1lwE5Xq9fluUFHXmbH0QCrk_7lGRjeiFqY9tTv_VKbNeHSVj5obUnA5HyAYb5jEqgy9M-CgdN1DJeODMTq3Ncu1y81_p7sXqxpbh1c-2eHkGj6yMFjO-dF9LpX_GUZZgAoPXN-J0k3_6VFWc6FjwOGbPU_weslCBpBnS0USfiif9y8nzH2xg0VrHCUEliBOkN-QLqq68edZOBAmYgG8iRDx-yG762TzOBri-0EdFHGWnMij_onb0y4f0UOXD-qSqHvBj8WKasOSRkBpJmIkDViKXYab3nhOtUb4Y3jNhSh6KYEW1QETK9oOMc1zd0Osk-z0QBLQdGtMuFiR00Bs1M_E4T0lMYEsFRqQ8TZmM5-hmrAkBVx3u1f9-ccBZE0ANOiNWH-G75LozwgZhYrOwbuDSnG3wq2M0L7F1mkseg5lOGKgyaxkaifO6WyS6JCHMwDZUF4gZKyHItg3x3PACmTdUy_Wda55J5oIFklWtjFGbU-dY7vr8wvyF0Q0jEeMp8tFvMpGOGTVlydMBq6SCWrZAz8uDoMRxuNLecaHj3bSQHbfeC3hs8uKCLOMr0X_ZCQ8ATXSSjjml3onzNvqChlsspKcwtEKKSwHNTMUJbY6cyy45EQdYhbKg75k-ZL7Y6BXMRjCc5CJd-4uuD8_cXHi4ikmkpHmgZLHcQPOdFflXeDlpYVTF9-Hyblg4SsxvLX9Vp5h4T4J_RcalfwPsIAwIEn8RSutJyMAIm0tYsEzq5i4usmLMxyEBbekCgP5DlHbeWvj3B8h0WoPE7C4cA1m29A_7bRDcJiL06D2T13r9zh17W7UYucDtTcJF7dtKHJTFK_C9m6wW-rHhXi1CgTFU8acDLYGK_VhZhQmTD7tM5JX7IEw_yokWzqyZzWFHmN4mgvAn3imeOXliVLY2YxD7I8-6xAgez6tVyX6plXIpE4KL-GLnFXyqORwIhH4F4EvEm6AcurW8pPWBXXVOY8Ml25-3D1tSu6sQ4PFzgvE5FWiwkBUpLSKwBjZqfg3_aG3NQe4exExztofsCD1l12US7OTx76h7utifDiu_FuzSZHOq0sM0kWfsrzoaPW79T7CT0Ew97HqEJTvYvhkdmzgtA-57zYK-8kc2bUTmTNdl_nUovO-xRhvwamIjMTzgqo3FXjLAtj4QZYWIHInkGj8GIxLluow315yWxARpfTehrpgvwYbd-tJ0UFyCZ1J0RwXQ8QmBu7UV-qPxj88d8cuY9sn8xba3kFCLifxlohEOupJcDDNHjta5eunNYoE127ap0Pv5KdJHWaOUcpScrXz3dIEXBlax12ySZNkghKGgGqYzOyQBKvkAgcV2rHaUQjuAkEbV3uQuE7iG3413fqfRVyAOKHKv3ig0jUM2DqBfhK9Tmxdbh-5VI5H5r5dgw3GmTQtSZVd0Q3mIMCeghrfHeCW4Ms1lRjcwEbn1Uyffs7KylhabOdqmiRTUPavLgKZmSrh7q0Vrkmb3s-nZEcfnVL6o2OpuQrdm83K-aI0Pvnsf9V9U_qoW1HWf61ENQUhnMECD2P70EsSmXLnQ_7f3v4Nyw-MCWCPpdzJvCh0TrpcTpY4WcflgbkNxm9xorCEiTlnEaeGSYj0MDcNm8sJYZbWzNQoNmbj58XS4IgnfCIYcoyu6PTceMcE7o_w50MPC3LcMTzZWKSYnGA7xDrvfeD7boqfj-Xd37SDYSTp9OAifiwiTXZyl7FqVTk1Y-1RCYTvIPPpnhXedT4ehYPRL9_fYmTgVISPLK8IQyNHpme86nG1-0FOJoitzwOa94MICeNKJArYvZ4Kj9WlP5-cTjP6zoDlaYxXXuln6DRmOnqL5CDVqf3f-7Dg-n8ARgNFwaAuvLXhCxuuRdcnNN5gx1z5vnvusq2sMCZx-eRqaGQsRoAoWo1VsrW5bwPGHwZN9Ip97KeORMAV8ExDttxjS4DXO-nB5fVZ2KToAsglOjLfvoXi7ArwK4Du3u7N_kzERB8lVT25jOltMdhOISXCGzY-ORQr6WhS_fgM8s8wHJSAtEl2w5VaFku57kEgWmfmasDNz5O1iMlqKOzVGpd9qNUtWaqYDK9DIxaL-O1pQGbzzuCsq332tez68SMNdbjNaf5RS3MHgAKHmI0I2RaGdBcaXjlap3sEMANG7keCNYSrtU-vfoMfb708dt2Ux2dDktmtSMFwZyzbOnGOshGhxsW5O98Uo-I-PZLsHSj4ZJSD5yIayNiuf8bZ0_REJ-9I-5xdfyUDstO7xj4IRjwwnsF9Td8CUycBKxr4gsttwfOoo04LVLOg7mDbK1GtoLEP2e-nXBHsFsOObaW3bOTx7TZwQf5DLggHsEfqdArl1-MqhRllSJNFtBLV3T8bRIvDl-YCV_LYjvWqRvo0RsR3oxrrPGwHM5ROy0WdfHixv2t5voksrS40VJI-KVXqgvF4ixUTMCjpL_pKpBq3pVZEnsJc4yZgK-C-sz72NZNKFHZviJhcdPDuwd4dX7oiI9X2KbnRfoo67xMqTuQCryLeiF7FpFoBHIjH2OhMzk2HbJR5YK9Q8blsWHpAdy', provider_name='openai', ), BuiltinToolCallPart( tool_name='web_search', args={'query': 'weather: Mexico City, Mexico', 'type': 'search'}, tool_call_id='ws_00a60507bf41223d0068c9d31b6aec81a09d9e568afa7b59aa', provider_name='openai', ), BuiltinToolReturnPart( tool_name='web_search', content={ 'sources': [{'type': 'api', 'url': None, 'name': 'oai-weather'}], 'status': 'completed', }, tool_call_id='ws_00a60507bf41223d0068c9d31b6aec81a09d9e568afa7b59aa', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_00a60507bf41223d0068c9d31c935881a0b835341209f6ac8b', signature='gAAAAABoydMoKoctyyCO6gsPILkjEnvCX0VL-9Gqk9qAmNEdWKNRPvxRIBVCxX4hGZ4m5fZJmuSIjjrA-nU-cUj_XIsARJsJywo2ka8IDmGRF8m7lm5atgcSJQjytRVpIA6s7sz0Sw3iAKrjtQcbymz2sUViTiOn7OqUStKtW0h98UIubdU6d19hu3iDwNddCuAC4QDy8cg3qJhjq9QTtovoBwFpibBJ12ISJqoPLSs43YvWK26o-evCMfzVbkuqJ7Gqie14gZ0oQChxGj7-bopeml1MCaDAz0EUxD5EDfjSdgjB_JABqF13kTTFdAVJu8gY1WgjFt0m1CONQGlM2oQA7cywjU7NnGWSNOqZp_NSDeTBYsKykAmyJP_lTzIDhhG37GBW7PwvBwuUYbvPcMmsRR9FDXxcMeVcpZPmaDjXhRAkJ-Am48Xz676pYl5Sx732-Pv9w503O66ARt6jwQYB4ZW5GgJAnqoqugbmJoGfOV4TaF0glOfKB5XPNQx--_hARpmXuQX3M_Xg1zLa6n7xGmf9pv__Gnhk3V0OlEnTD5HPZzc13F2hKX1PZ8E4ykq4843ZHDV3vpc5WsNCp6C6Cq8STXq58_QAU8P9vpqEP8khnYt3EJTjzbweiqVrMj6cSoUS9C32z8dFcA0rQrTmt_tEMTaoTN1Q5nTboSm0jX1arXqGh3RhcDkqddBDLfI6PdTVulEPVnBkmZJmCFqdfm_aD9FCSCVJdKE5pktBFqtmGFRJ6RVeGbc_YB6XG9najhjXNhhXIpy176CIPLZbeXkxcgsJQBdDGm4PpUePHZAGKxOpFCNv7kZMyGcsd-Ye-envhfdGhJ5dMOqRq-1KtjopdvNFfmxASkrT8f33YFj6n07fXOOfY02pTl9Dyv7fp0gk_3DR6zKFZRwv-Y3u0sTjQTkk7xTZsuEb0iP_zpqMNcj834fq4FZFvmhJ_siVVOQUPMaP0OFJnYFTteQR8S8JXud4Er1jEZlVojHugyJ3K4yMoj5c16jIQLaFn1_Jk1G97LCO-WZjSxpDD5niEXmYEoC1cw5zweUE7MjkzG1cBU2Wgjw_K0zt0Ko9DxYMDDDS-ZphpCJFPKBiX7pDcpKDpkQnDkEpzIIyDQ3mEKoKvYAXLveKuhOnNnVpUVN28hvW5_QfhD3C1WEBTzz2-dfxLpiS_MHI9NVUZdIue_ThGAM8TFY9MqDrTfAMRMD_mdQHW8XE_QdxighLLuG56AqufuA4CutwifYdbMiAE_mWtApqG4U6dx8cMnmIxnN_lrerv3IQR9_rk6vgPG-MfyJ0drDmSaJGMKyBexYau6sCzyMZYzFO-YgPDa0Yz4DYwhjTnGqtoMSE94ciYiJWZV473WIcyvJ8lE2mQD735nf1OKk7FHsai2mmQzk6NHyyEvvltkTPN8ply0fqmxLksng1bKD43zkHjnP_wUU5uInfAPIGMtIXuwJJXUziMTFRcCawC0KcUUP1J9GK9nrIMeO2B-yM5GXwfvMq3TiI4VFHD9Dav18T5BufMsjIY6uOUuWKNHSOpSQ6VHoql3k7fh2NVGOWqq3juBo2P3BNwXpP6mPr_6diYK4ciukrh4MiUd3pkLZnaW_iv4XYoq0Wix4ENU4zI1kMj5ObFAQOEbeoqdC6u4I5MIOXU6Pep-kaFl6P3yb37Ce95GyPq6xx8q4G29DK6Rx9Qowha8x9BIphuSL01Z6snFTewQW9rqAP7GyEltkso456vXzay08wtzG0dGpxoCIc87mAhx7-ulTj1Wti0qekLhsavem7GPfNKqso4CPsiXMxtTBBoIHk0xAvXcpZcw33pY_71-SHpMafrMrkS-Rp2T6YztbX2u_Nx__O8NAD2V0T0l69gR4S0khT_z-rttSPuCfx0-C4_hz7mCjVPMlLGDzxahOxG25Z9LHst6NPvlfg0xxX5rQ80XAS9GtLJ5uKMEwMxoGCatV3VL2zT2M0SpNiZKLZpH2tHfm0j_2dFcsLWN0a9MAooVZQ1Rlnq_7r0QrAPqcca_Y1Q7Jlzx2dgiEylYfFzNlNU2JTtinZg25gq3A7WayuWE5iBV5dhPijkcgEQbDETKg0eRa584q_cd68Rlm7qYeID3pc8gAbZ4zdqz6SfcQqoZS_EN43Z4Mc-t_HKN-9BwgXFNfvzbLoNekhoCiTrcEUikzXjVKqTbcuczAtH-uie_bfQkwfljFn7J8t7A3SeP961mvpx7iE-yJ4HXTeFhJI2TlBm4JB3OKMCoJSFdEiHjx82bX7TEPvq9g940TgPaooWUD2mEJ_f9ByY84L4EywrGFhtj-DxA1igkbWnCgWlxEquBcvmkRHkbTylkJz6kyz-_-5EPUEJLHqGsDHgotxYWXsxCalzDktH_GivrkeTYqhy1SikEJw93-X5SPMLD7EdQUS_K3XIe9p4T9lpn__zs_tCqssrun7ZQEpY9ULoYiMn2ENU9rK4IYpDoV0beXs4Xa24nj3qgrzbuzbLeKKbm8Y8RxNStogi4E4pK_difBVb_1oTIxfPrLnAJibQ8H-Tb9v20L2Zd3RWXtKi46-XJizKe9r-_JI2HmZ4QM2JOaBhHdybeBrwnu1Z36WhPk4m7YyK8-0K-kIPd-mW_ZF29tHBVhLifqPOq7D3HkJbnBH--KJum-F3v5LLqmeBN-3LWv6bk9-jqQNum9pm2WHtUkOMvH3zw0h8yiBjK3Qov7XHAP9dKHKs3B1eVqiVFGNbuB3Ss07ZzXQrSxgNFP2z64-HtdLJdsSXu3BGc7BqFrnF1tUVeu-KDXKXxJ0SFYaxnLqThuQ4b8CUXYWd8fnhCbhu3OE9Pd2aKWr-4bj73DTDcHLnYmy53mgNKtItsJBfA7m5Dzf6WKREmictNl5nMUWWlEay0nvE6so39zkRlc7wihRthJTEMDbMUdARJw7o1F8JBUPY3cIJchDnq0ZiGkrCA-OyPx-rkxbrQq9usJoTT7XUZNVZ5u7mXH8dY6uY4opcJmV02W2eJms-VtTxgkXuh_HLz_VPmCRMGfACFMwigpShdnr_j3T70ixy80FLcY6ILu1EbuZeLeqo4L8Z5fznYZ1', provider_name='openai', ), TextPart( content='Mexico City weather today (Tuesday, September 16, 2025): Cloudy. Current around 73°F; high near 74°F and low around 56°F. Showers return midweek. ', id='msg_00a60507bf41223d0068c9d326034881a0bb60d6d5d39347bd', ), ], usage=RequestUsage( input_tokens=9703, cache_read_tokens=8576, output_tokens=638, details={'reasoning_tokens': 576}, ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_00a60507bf41223d0068c9d31574d881a090c232646860a771', finish_reason='stop', ), ] ) def test_model_profile_strict_not_supported(): my_tool = ToolDefinition( name='my_tool', description='This is my tool', parameters_json_schema={'type': 'object', 'title': 'Result', 'properties': {'spam': {'type': 'number'}}}, strict=True, ) m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key='foobar')) tool_param = m._map_tool_definition(my_tool) # type: ignore[reportPrivateUsage] assert tool_param == snapshot( { 'name': 'my_tool', 'parameters': {'type': 'object', 'title': 'Result', 'properties': {'spam': {'type': 'number'}}}, 'type': 'function', 'description': 'This is my tool', 'strict': True, } ) # Some models don't support strict tool definitions m = OpenAIResponsesModel( 'gpt-4o', provider=OpenAIProvider(api_key='foobar'), profile=replace(openai_model_profile('gpt-4o'), openai_supports_strict_tool_definition=False), ) tool_param = m._map_tool_definition(my_tool) # type: ignore[reportPrivateUsage] assert tool_param == snapshot( { 'name': 'my_tool', 'parameters': {'type': 'object', 'title': 'Result', 'properties': {'spam': {'type': 'number'}}}, 'type': 'function', 'description': 'This is my tool', 'strict': False, } ) @pytest.mark.vcr() async def test_reasoning_model_with_temperature(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('o3-mini', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(m, model_settings=OpenAIResponsesModelSettings(temperature=0.5)) result = await agent.run('What is the capital of Mexico?') assert result.output == snapshot( 'The capital of Mexico is Mexico City. It serves as the political, cultural, and economic heart of the country and is one of the largest metropolitan areas in the world.' ) @pytest.mark.vcr() async def test_tool_output(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) class CityLocation(BaseModel): city: str country: str agent = Agent(m, output_type=ToolOutput(CityLocation)) @agent.tool_plain async def get_user_country() -> str: return 'Mexico' result = await agent.run('What is the largest city in the user country?') assert result.output == snapshot(CityLocation(city='Mexico City', country='Mexico')) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the largest city in the user country?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ToolCallPart( tool_name='get_user_country', args='{}', tool_call_id=IsStr(), id='fc_68477f0bb8e4819cba6d781e174d77f8001fd29e2d5573f7', ) ], usage=RequestUsage(input_tokens=62, output_tokens=12, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68477f0b40a8819cb8d55594bc2c232a001fd29e2d5573f7', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_user_country', content='Mexico', tool_call_id='call_ZWkVhdUjupo528U9dqgFeRkH', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ToolCallPart( tool_name='final_result', args='{"city":"Mexico City","country":"Mexico"}', tool_call_id='call_iFBd0zULhSZRR908DfH73VwN', id='fc_68477f0c91cc819e8024e7e633f0f09401dc81d4bc91f560', ) ], usage=RequestUsage(input_tokens=85, output_tokens=20, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68477f0bfda8819ea65458cd7cc389b801dc81d4bc91f560', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='final_result', content='Final result processed.', tool_call_id='call_iFBd0zULhSZRR908DfH73VwN', timestamp=IsDatetime(), ) ] ), ] ) @pytest.mark.vcr() async def test_text_output_function(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) def upcase(text: str) -> str: return text.upper() agent = Agent(m, output_type=TextOutput(upcase)) @agent.tool_plain async def get_user_country() -> str: return 'Mexico' result = await agent.run('What is the largest city in the user country?') assert result.output == snapshot('THE LARGEST CITY IN MEXICO IS MEXICO CITY.') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the largest city in the user country?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ToolCallPart( tool_name='get_user_country', args='{}', tool_call_id='call_aTJhYjzmixZaVGqwl5gn2Ncr', id='fc_68477f0dff5c819ea17a1ffbaea621e00356a60c98816d6a', ) ], usage=RequestUsage(input_tokens=36, output_tokens=12, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68477f0d9494819ea4f123bba707c9ee0356a60c98816d6a', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_user_country', content='Mexico', tool_call_id='call_aTJhYjzmixZaVGqwl5gn2Ncr', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ TextPart( content='The largest city in Mexico is Mexico City.', id='msg_68477f0ebf54819d88a44fa87aadaff503434b607c02582d', ) ], usage=RequestUsage(input_tokens=59, output_tokens=11, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68477f0e2b28819d9c828ef4ee526d6a03434b607c02582d', finish_reason='stop', ), ] ) @pytest.mark.vcr() async def test_native_output(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) class CityLocation(BaseModel): """A city and its country.""" city: str country: str agent = Agent(m, output_type=NativeOutput(CityLocation)) @agent.tool_plain async def get_user_country() -> str: return 'Mexico' result = await agent.run('What is the largest city in the user country?') assert result.output == snapshot(CityLocation(city='Mexico City', country='Mexico')) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the largest city in the user country?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ToolCallPart( tool_name='get_user_country', args='{}', tool_call_id=IsStr(), id='fc_68477f0fa7c081a19a525f7c6f180f310b8591d9001d2329', ) ], usage=RequestUsage(input_tokens=66, output_tokens=12, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68477f0f220081a1a621d6bcdc7f31a50b8591d9001d2329', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_user_country', content='Mexico', tool_call_id='call_tTAThu8l2S9hNky2krdwijGP', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ TextPart( content='{"city":"Mexico City","country":"Mexico"}', id='msg_68477f10846c81929f1e833b0785e6f3020197534e39cc1f', ) ], usage=RequestUsage(input_tokens=89, output_tokens=16, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68477f0fde708192989000a62809c6e5020197534e39cc1f', finish_reason='stop', ), ] ) @pytest.mark.vcr() async def test_native_output_multiple(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) class CityLocation(BaseModel): city: str country: str class CountryLanguage(BaseModel): country: str language: str agent = Agent(m, output_type=NativeOutput([CityLocation, CountryLanguage])) @agent.tool_plain async def get_user_country() -> str: return 'Mexico' result = await agent.run('What is the largest city in the user country?') assert result.output == snapshot(CityLocation(city='Mexico City', country='Mexico')) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the largest city in the user country?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ToolCallPart( tool_name='get_user_country', args='{}', tool_call_id=IsStr(), id='fc_68477f1168a081a3981e847cd94275080dd57d732903c563', ) ], usage=RequestUsage(input_tokens=153, output_tokens=12, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68477f10f2d081a39b3438f413b3bafc0dd57d732903c563', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_user_country', content='Mexico', tool_call_id='call_UaLahjOtaM2tTyYZLxTCbOaP', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ TextPart( content='{"result":{"kind":"CityLocation","data":{"city":"Mexico City","country":"Mexico"}}}', id='msg_68477f1235b8819d898adc64709c7ebf061ad97e2eef7871', ) ], usage=RequestUsage(input_tokens=176, output_tokens=26, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68477f119830819da162aa6e10552035061ad97e2eef7871', finish_reason='stop', ), ] ) @pytest.mark.vcr() async def test_prompted_output(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) class CityLocation(BaseModel): city: str country: str agent = Agent(m, output_type=PromptedOutput(CityLocation)) @agent.tool_plain async def get_user_country() -> str: return 'Mexico' result = await agent.run('What is the largest city in the user country?') assert result.output == snapshot(CityLocation(city='Mexico City', country='Mexico')) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the largest city in the user country?', timestamp=IsDatetime(), ) ], instructions="""\ Always respond with a JSON object that's compatible with this schema: {"properties": {"city": {"type": "string"}, "country": {"type": "string"}}, "required": ["city", "country"], "title": "CityLocation", "type": "object"} Don't include any text or Markdown fencing before or after.\ """, ), ModelResponse( parts=[ ToolCallPart( tool_name='get_user_country', args='{}', tool_call_id=IsStr(), id='fc_68482f1b0ff081a1b37b9170ee740d1e02f8ef7f2fb42b50', ) ], usage=RequestUsage(input_tokens=107, output_tokens=12, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68482f12d63881a1830201ed101ecfbf02f8ef7f2fb42b50', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_user_country', content='Mexico', tool_call_id='call_FrlL4M0CbAy8Dhv4VqF1Shom', timestamp=IsDatetime(), ) ], instructions="""\ Always respond with a JSON object that's compatible with this schema: {"properties": {"city": {"type": "string"}, "country": {"type": "string"}}, "required": ["city", "country"], "title": "CityLocation", "type": "object"} Don't include any text or Markdown fencing before or after.\ """, ), ModelResponse( parts=[ TextPart( content='{"city":"Mexico City","country":"Mexico"}', id='msg_68482f1c159081918a2405f458009a6a044fdb7d019d4115', ) ], usage=RequestUsage(input_tokens=130, output_tokens=12, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68482f1b556081918d64c9088a470bf0044fdb7d019d4115', finish_reason='stop', ), ] ) @pytest.mark.vcr() async def test_prompted_output_multiple(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(api_key=openai_api_key)) class CityLocation(BaseModel): city: str country: str class CountryLanguage(BaseModel): country: str language: str agent = Agent(m, output_type=PromptedOutput([CityLocation, CountryLanguage])) @agent.tool_plain async def get_user_country() -> str: return 'Mexico' result = await agent.run('What is the largest city in the user country?') assert result.output == snapshot(CityLocation(city='Mexico City', country='Mexico')) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the largest city in the user country?', timestamp=IsDatetime(), ) ], instructions="""\ Always respond with a JSON object that's compatible with this schema: {"type": "object", "properties": {"result": {"anyOf": [{"type": "object", "properties": {"kind": {"type": "string", "const": "CityLocation"}, "data": {"properties": {"city": {"type": "string"}, "country": {"type": "string"}}, "required": ["city", "country"], "type": "object"}}, "required": ["kind", "data"], "additionalProperties": false, "title": "CityLocation"}, {"type": "object", "properties": {"kind": {"type": "string", "const": "CountryLanguage"}, "data": {"properties": {"country": {"type": "string"}, "language": {"type": "string"}}, "required": ["country", "language"], "type": "object"}}, "required": ["kind", "data"], "additionalProperties": false, "title": "CountryLanguage"}]}}, "required": ["result"], "additionalProperties": false} Don't include any text or Markdown fencing before or after.\ """, ), ModelResponse( parts=[ ToolCallPart( tool_name='get_user_country', args='{}', tool_call_id=IsStr(), id='fc_68482f2889d481a199caa61de7ccb62c08e79646fe74d5ee', ) ], usage=RequestUsage(input_tokens=283, output_tokens=12, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68482f1d38e081a1ac828acda978aa6b08e79646fe74d5ee', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_user_country', content='Mexico', tool_call_id='call_my4OyoVXRT0m7bLWmsxcaCQI', timestamp=IsDatetime(), ) ], instructions="""\ Always respond with a JSON object that's compatible with this schema: {"type": "object", "properties": {"result": {"anyOf": [{"type": "object", "properties": {"kind": {"type": "string", "const": "CityLocation"}, "data": {"properties": {"city": {"type": "string"}, "country": {"type": "string"}}, "required": ["city", "country"], "type": "object"}}, "required": ["kind", "data"], "additionalProperties": false, "title": "CityLocation"}, {"type": "object", "properties": {"kind": {"type": "string", "const": "CountryLanguage"}, "data": {"properties": {"country": {"type": "string"}, "language": {"type": "string"}}, "required": ["country", "language"], "type": "object"}}, "required": ["kind", "data"], "additionalProperties": false, "title": "CountryLanguage"}]}}, "required": ["result"], "additionalProperties": false} Don't include any text or Markdown fencing before or after.\ """, ), ModelResponse( parts=[ TextPart( content='{"result":{"kind":"CityLocation","data":{"city":"Mexico City","country":"Mexico"}}}', id='msg_68482f296bfc81a18665547d4008ab2c06b4ab2d00d03024', ) ], usage=RequestUsage(input_tokens=306, output_tokens=22, details={'reasoning_tokens': 0}), model_name='gpt-4o-2024-08-06', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68482f28c1b081a1ae73cbbee012ee4906b4ab2d00d03024', finish_reason='stop', ), ] ) @pytest.mark.vcr() async def test_openai_responses_verbosity(allow_model_requests: None, openai_api_key: str): """Test that verbosity setting is properly passed to the OpenAI API""" # Following GPT-5 + verbosity documentation pattern provider = OpenAIProvider( api_key=openai_api_key, base_url='https://api.openai.com/v1', # Explicitly set base URL ) model = OpenAIResponsesModel('gpt-5', provider=provider) agent = Agent(model=model, model_settings=OpenAIResponsesModelSettings(openai_text_verbosity='low')) result = await agent.run('What is 2+2?') assert result.output == snapshot('4') @pytest.mark.vcr() async def test_openai_previous_response_id(allow_model_requests: None, openai_api_key: str): """Test if previous responses are detected via previous_response_id in settings""" model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model) result = await agent.run('The secret key is sesame') settings = OpenAIResponsesModelSettings(openai_previous_response_id=result.all_messages()[-1].provider_response_id) # type: ignore result = await agent.run('What is the secret code?', model_settings=settings) assert result.output == snapshot('sesame') @pytest.mark.vcr() async def test_openai_previous_response_id_auto_mode(allow_model_requests: None, openai_api_key: str): """Test if invalid previous response id is ignored when history contains non-OpenAI responses""" history = [ ModelRequest( parts=[ UserPromptPart( content='The first secret key is sesame', ), ], ), ModelResponse( parts=[ TextPart(content='Open sesame! What would you like to unlock?'), ], model_name='gpt-5', provider_name='openai', provider_response_id='resp_68b9bd97025c8195b443af591ca2345c08cb6072affe6099', ), ModelRequest( parts=[ UserPromptPart( content='The second secret key is olives', ), ], ), ModelResponse( parts=[ TextPart(content='Understood'), ], model_name='gpt-5', provider_name='openai', provider_response_id='resp_68b9bda81f5c8197a5a51a20a9f4150a000497db2a4c777b', ), ] model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model) settings = OpenAIResponsesModelSettings(openai_previous_response_id='auto') result = await agent.run('what is the first secret key', message_history=history, model_settings=settings) assert result.output == snapshot('sesame') async def test_openai_previous_response_id_mixed_model_history(allow_model_requests: None, openai_api_key: str): """Test if invalid previous response id is ignored when history contains non-OpenAI responses""" history = [ ModelRequest( parts=[ UserPromptPart( content='The first secret key is sesame', ), ], ), ModelResponse( parts=[ TextPart(content='Open sesame! What would you like to unlock?'), ], model_name='claude-sonnet-4-5', provider_name='anthropic', provider_response_id='msg_01XUQuedGz9gusk4xZm4gWJj', ), ModelRequest( parts=[ UserPromptPart( content='what is the first secret key?', ), ], ), ] model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) previous_response_id, messages = model._get_previous_response_id_and_new_messages(history) # type: ignore assert not previous_response_id assert messages == snapshot( [ ModelRequest(parts=[UserPromptPart(content='The first secret key is sesame', timestamp=IsDatetime())]), ModelResponse( parts=[TextPart(content='Open sesame! What would you like to unlock?')], usage=RequestUsage(), model_name='claude-sonnet-4-5', timestamp=IsDatetime(), provider_name='anthropic', provider_response_id='msg_01XUQuedGz9gusk4xZm4gWJj', ), ModelRequest(parts=[UserPromptPart(content='what is the first secret key?', timestamp=IsDatetime())]), ] ) async def test_openai_previous_response_id_same_model_history(allow_model_requests: None, openai_api_key: str): """Test if message history is trimmed when model responses are from same model""" history = [ ModelRequest( parts=[ UserPromptPart( content='The first secret key is sesame', ), ], ), ModelResponse( parts=[ TextPart(content='Open sesame! What would you like to unlock?'), ], model_name='gpt-5', provider_name='openai', provider_response_id='resp_68b9bd97025c8195b443af591ca2345c08cb6072affe6099', ), ModelRequest( parts=[ UserPromptPart( content='The second secret key is olives', ), ], ), ModelResponse( parts=[ TextPart(content='Understood'), ], model_name='gpt-5', provider_name='openai', provider_response_id='resp_68b9bda81f5c8197a5a51a20a9f4150a000497db2a4c777b', ), ModelRequest( parts=[ UserPromptPart( content='what is the first secret key?', ), ], ), ] model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) previous_response_id, messages = model._get_previous_response_id_and_new_messages(history) # type: ignore assert previous_response_id == 'resp_68b9bda81f5c8197a5a51a20a9f4150a000497db2a4c777b' assert messages == snapshot( [ ModelRequest(parts=[UserPromptPart(content='what is the first secret key?', timestamp=IsDatetime())]), ] ) async def test_openai_responses_usage_without_tokens_details(allow_model_requests: None): c = response_message( [ ResponseOutputMessage( id='123', content=cast(list[Content], [ResponseOutputText(text='4', type='output_text', annotations=[])]), role='assistant', status='completed', type='message', ) ], # Intentionally use model_construct so that input_tokens_details and output_tokens_details will not be set. usage=ResponseUsage.model_construct(input_tokens=14, output_tokens=1, total_tokens=15), ) mock_client = MockOpenAIResponses.create_mock(c) model = OpenAIResponsesModel('gpt-4o', provider=OpenAIProvider(openai_client=mock_client)) agent = Agent(model=model) result = await agent.run('What is 2+2?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is 2+2?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[TextPart(content='4', id='123')], usage=RequestUsage(input_tokens=14, output_tokens=1, details={'reasoning_tokens': 0}), model_name='gpt-4o-123', timestamp=IsDatetime(), provider_name='openai', provider_response_id='123', ), ] ) assert result.usage() == snapshot( RunUsage(input_tokens=14, output_tokens=1, details={'reasoning_tokens': 0}, requests=1) ) async def test_openai_responses_model_thinking_part(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) settings = OpenAIResponsesModelSettings(openai_reasoning_effort='high', openai_reasoning_summary='detailed') agent = Agent(m, model_settings=settings) result = await agent.run('How do I cross the street?') assert result.all_messages() == snapshot( [ ModelRequest(parts=[UserPromptPart(content='How do I cross the street?', timestamp=IsDatetime())]), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68c42c90b950819c9e32c46d4f8326ca07460311b0c8d3de', signature=IsStr(), provider_name='openai', ), ThinkingPart(content=IsStr(), id='rs_68c42c90b950819c9e32c46d4f8326ca07460311b0c8d3de'), ThinkingPart(content=IsStr(), id='rs_68c42c90b950819c9e32c46d4f8326ca07460311b0c8d3de'), ThinkingPart(content=IsStr(), id='rs_68c42c90b950819c9e32c46d4f8326ca07460311b0c8d3de'), ThinkingPart(content=IsStr(), id='rs_68c42c90b950819c9e32c46d4f8326ca07460311b0c8d3de'), ThinkingPart(content=IsStr(), id='rs_68c42c90b950819c9e32c46d4f8326ca07460311b0c8d3de'), TextPart( content=IsStr(), id='msg_68c42cb1aaec819cb992bd92a8c7766007460311b0c8d3de', ), ], usage=RequestUsage(input_tokens=13, output_tokens=2199, details={'reasoning_tokens': 1920}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68c42c902794819cb9335264c342f65407460311b0c8d3de', finish_reason='stop', ), ] ) result = await agent.run( 'Considering the way to cross the street, analogously, how do I cross the river?', message_history=result.all_messages(), ) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Considering the way to cross the street, analogously, how do I cross the river?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68c42cb43d3c819caf078978cc2514ea07460311b0c8d3de', signature=IsStr(), provider_name='openai', ), ThinkingPart(content=IsStr(), id='rs_68c42cb43d3c819caf078978cc2514ea07460311b0c8d3de'), ThinkingPart(content=IsStr(), id='rs_68c42cb43d3c819caf078978cc2514ea07460311b0c8d3de'), ThinkingPart(content=IsStr(), id='rs_68c42cb43d3c819caf078978cc2514ea07460311b0c8d3de'), ThinkingPart(content=IsStr(), id='rs_68c42cb43d3c819caf078978cc2514ea07460311b0c8d3de'), TextPart( content=IsStr(), id='msg_68c42cd36134819c800463490961f7df07460311b0c8d3de', ), ], usage=RequestUsage(input_tokens=314, output_tokens=2737, details={'reasoning_tokens': 2112}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68c42cb3d520819c9d28b07036e9059507460311b0c8d3de', finish_reason='stop', ), ] ) async def test_openai_responses_thinking_part_from_other_model( allow_model_requests: None, anthropic_api_key: str, openai_api_key: str ): m = AnthropicModel( 'claude-sonnet-4-0', provider=AnthropicProvider(api_key=anthropic_api_key), settings=AnthropicModelSettings(anthropic_thinking={'type': 'enabled', 'budget_tokens': 1024}), ) agent = Agent(m) result = await agent.run('How do I cross the street?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='How do I cross the street?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), signature=IsStr(), provider_name='anthropic', ), TextPart(content=IsStr()), ], usage=RequestUsage( input_tokens=42, output_tokens=291, details={ 'cache_creation_input_tokens': 0, 'cache_read_input_tokens': 0, 'input_tokens': 42, 'output_tokens': 291, }, ), model_name='claude-sonnet-4-20250514', timestamp=IsDatetime(), provider_name='anthropic', provider_details={'finish_reason': 'end_turn'}, provider_response_id='msg_0114iHK2ditgTf1N8FWomc4E', finish_reason='stop', ), ] ) result = await agent.run( 'Considering the way to cross the street, analogously, how do I cross the river?', model=OpenAIResponsesModel( 'gpt-5', provider=OpenAIProvider(api_key=openai_api_key), settings=OpenAIResponsesModelSettings(openai_reasoning_effort='high', openai_reasoning_summary='detailed'), ), message_history=result.all_messages(), ) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Considering the way to cross the street, analogously, how do I cross the river?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68c42ce323d48193bcf88db6278980cf0ad492c7955fc6fc', signature=IsStr(), provider_name='openai', ), ThinkingPart(content=IsStr(), id='rs_68c42ce323d48193bcf88db6278980cf0ad492c7955fc6fc'), ThinkingPart(content=IsStr(), id='rs_68c42ce323d48193bcf88db6278980cf0ad492c7955fc6fc'), ThinkingPart(content=IsStr(), id='rs_68c42ce323d48193bcf88db6278980cf0ad492c7955fc6fc'), ThinkingPart(content=IsStr(), id='rs_68c42ce323d48193bcf88db6278980cf0ad492c7955fc6fc'), ThinkingPart(content=IsStr(), id='rs_68c42ce323d48193bcf88db6278980cf0ad492c7955fc6fc'), TextPart(content=IsStr(), id='msg_68c42d0b5e5c819385352dde1f447d910ad492c7955fc6fc'), ], usage=RequestUsage(input_tokens=306, output_tokens=3134, details={'reasoning_tokens': 2496}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68c42ce277ac8193ba08881bcefabaf70ad492c7955fc6fc', finish_reason='stop', ), ] ) async def test_openai_responses_thinking_part_iter(allow_model_requests: None, openai_api_key: str): provider = OpenAIProvider(api_key=openai_api_key) responses_model = OpenAIResponsesModel('o3-mini', provider=provider) settings = OpenAIResponsesModelSettings(openai_reasoning_effort='high', openai_reasoning_summary='detailed') agent = Agent(responses_model, model_settings=settings) async with agent.iter(user_prompt='How do I cross the street?') as agent_run: async for node in agent_run: if Agent.is_model_request_node(node) or Agent.is_call_tools_node(node): async with node.stream(agent_run.ctx) as request_stream: async for _ in request_stream: pass assert agent_run.result is not None assert agent_run.result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='How do I cross the street?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68c42d1d0878819d8266007cd3d1402c08fbf9b1584184ff', signature='gAAAAABoxC0m_QWpOlSt8wyPk_gtnjiI4mNLOryYlNXO-6rrVeIqBYDDAyMVg2_ldboZvfhW8baVbpki29gkTAyNygTr7L8gF1XK0hFovoa23ZYJKvuOnyLIJF-rXCsbDG7YdMYhi3bm82pMFVQxNK4r5muWCQcHmyJ2S1YtBoJtF_D1Ah7GpW2ACvJWsGikb3neAOnI-RsmUxCRu-cew7rVWfSj8jFKs8RGNQRvDaUzVniaMXJxVW9T5C7Ytzi852MF1PfVq0U-aNBzZBtAdwQcbn5KZtGkYLYTChmCi2hMrh5-lg9CgS8pqqY9-jv2EQvKHIumdv6oLiW8K59Zvo8zGxYoqT--osfjfS0vPZhTHiSX4qCkK30YNJrWHKJ95Hpe23fnPBL0nEQE5l6XdhsyY7TwMom016P3dgWwgP5AtWmQ30zeXDs=', provider_name='openai', ), ThinkingPart( content=IsStr(), id='rs_68c42d1d0878819d8266007cd3d1402c08fbf9b1584184ff', ), ThinkingPart( content=IsStr(), id='rs_68c42d1d0878819d8266007cd3d1402c08fbf9b1584184ff', ), ThinkingPart( content=IsStr(), id='rs_68c42d1d0878819d8266007cd3d1402c08fbf9b1584184ff', ), TextPart( content=IsStr(), id='msg_68c42d26866c819da8d5c606621c911608fbf9b1584184ff', ), ], usage=RequestUsage(input_tokens=13, output_tokens=1680, details={'reasoning_tokens': 1408}), model_name='o3-mini-2025-01-31', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68c42d0fb418819dbfa579f69406b49508fbf9b1584184ff', finish_reason='stop', ), ] ) async def test_openai_responses_thinking_with_tool_calls(allow_model_requests: None, openai_api_key: str): provider = OpenAIProvider(api_key=openai_api_key) m = OpenAIResponsesModel( model_name='gpt-5', provider=provider, settings=OpenAIResponsesModelSettings(openai_reasoning_summary='detailed', openai_reasoning_effort='low'), ) agent = Agent(model=m) @agent.instructions def system_prompt(): return ( 'You are a helpful assistant that uses planning. You MUST use the update_plan tool and continually ' "update it as you make progress against the user's prompt" ) @agent.tool_plain def update_plan(plan: str) -> str: return 'plan updated' prompt = ( 'Compose a 12-line poem where the first letters of the odd-numbered lines form the name "SAMIRA" ' 'and the first letters of the even-numbered lines spell out "DAWOOD." Additionally, the first letter ' 'of each word in every line should create the capital of a country' ) result = await agent.run(prompt) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Compose a 12-line poem where the first letters of the odd-numbered lines form the name "SAMIRA" and the first letters of the even-numbered lines spell out "DAWOOD." Additionally, the first letter of each word in every line should create the capital of a country', timestamp=IsDatetime(), ) ], instructions="You are a helpful assistant that uses planning. You MUST use the update_plan tool and continually update it as you make progress against the user's prompt", ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68c42d29124881968e24c1ca8c1fc7860e8bc41441c948f6', signature=IsStr(), provider_name='openai', ), ThinkingPart(content=IsStr(), id='rs_68c42d29124881968e24c1ca8c1fc7860e8bc41441c948f6'), ThinkingPart(content=IsStr(), id='rs_68c42d29124881968e24c1ca8c1fc7860e8bc41441c948f6'), ThinkingPart(content=IsStr(), id='rs_68c42d29124881968e24c1ca8c1fc7860e8bc41441c948f6'), ThinkingPart(content=IsStr(), id='rs_68c42d29124881968e24c1ca8c1fc7860e8bc41441c948f6'), ToolCallPart( tool_name='update_plan', args=IsStr(), tool_call_id='call_gL7JE6GDeGGsFubqO2XGytyO', id='fc_68c42d3e9e4881968b15fbb8253f58540e8bc41441c948f6', ), ], usage=RequestUsage(input_tokens=124, output_tokens=1926, details={'reasoning_tokens': 1792}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68c42d28772c819684459966ee2201ed0e8bc41441c948f6', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='update_plan', content='plan updated', tool_call_id='call_gL7JE6GDeGGsFubqO2XGytyO', timestamp=IsDatetime(), ) ], instructions="You are a helpful assistant that uses planning. You MUST use the update_plan tool and continually update it as you make progress against the user's prompt", ), ModelResponse( parts=[TextPart(content=IsStr(), id='msg_68c42d408eec8196ae1c5883e07c093e0e8bc41441c948f6')], usage=RequestUsage( input_tokens=2087, cache_read_tokens=2048, output_tokens=124, details={'reasoning_tokens': 0} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68c42d3fd6a08196bce23d6be960ff8a0e8bc41441c948f6', finish_reason='stop', ), ] ) async def test_openai_responses_thinking_without_summary(allow_model_requests: None): c = response_message( [ ResponseReasoningItem( id='rs_123', summary=[], type='reasoning', encrypted_content='123', ), ResponseOutputMessage( id='msg_123', content=cast(list[Content], [ResponseOutputText(text='4', type='output_text', annotations=[])]), role='assistant', status='completed', type='message', ), ], ) mock_client = MockOpenAIResponses.create_mock(c) model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(openai_client=mock_client)) agent = Agent(model=model) result = await agent.run('What is 2+2?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is 2+2?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart(content='', id='rs_123', signature='123', provider_name='openai'), TextPart(content='4', id='msg_123'), ], model_name='gpt-4o-123', timestamp=IsDatetime(), provider_name='openai', provider_response_id='123', ), ] ) _, openai_messages = await model._map_messages(result.all_messages(), model_settings=model.settings or {}) # type: ignore[reportPrivateUsage] assert openai_messages == snapshot( [ {'role': 'user', 'content': 'What is 2+2?'}, {'id': 'rs_123', 'summary': [], 'encrypted_content': '123', 'type': 'reasoning'}, { 'role': 'assistant', 'id': 'msg_123', 'content': [{'text': '4', 'type': 'output_text', 'annotations': []}], 'type': 'message', 'status': 'completed', }, ] ) async def test_openai_responses_thinking_with_multiple_summaries(allow_model_requests: None): c = response_message( [ ResponseReasoningItem( id='rs_123', summary=[ Summary(text='1', type='summary_text'), Summary(text='2', type='summary_text'), Summary(text='3', type='summary_text'), Summary(text='4', type='summary_text'), ], type='reasoning', encrypted_content='123', ), ResponseOutputMessage( id='msg_123', content=cast(list[Content], [ResponseOutputText(text='4', type='output_text', annotations=[])]), role='assistant', status='completed', type='message', ), ], ) mock_client = MockOpenAIResponses.create_mock(c) model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(openai_client=mock_client)) agent = Agent(model=model) result = await agent.run('What is 2+2?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is 2+2?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart(content='1', id='rs_123', signature='123', provider_name='openai'), ThinkingPart(content='2', id='rs_123'), ThinkingPart(content='3', id='rs_123'), ThinkingPart(content='4', id='rs_123'), TextPart(content='4', id='msg_123'), ], model_name='gpt-4o-123', timestamp=IsDatetime(), provider_name='openai', provider_response_id='123', ), ] ) _, openai_messages = await model._map_messages(result.all_messages(), model_settings=model.settings or {}) # type: ignore[reportPrivateUsage] assert openai_messages == snapshot( [ {'role': 'user', 'content': 'What is 2+2?'}, { 'id': 'rs_123', 'summary': [ {'text': '1', 'type': 'summary_text'}, {'text': '2', 'type': 'summary_text'}, {'text': '3', 'type': 'summary_text'}, {'text': '4', 'type': 'summary_text'}, ], 'encrypted_content': '123', 'type': 'reasoning', }, { 'role': 'assistant', 'id': 'msg_123', 'content': [{'text': '4', 'type': 'output_text', 'annotations': []}], 'type': 'message', 'status': 'completed', }, ] ) async def test_openai_responses_thinking_with_modified_history(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) settings = OpenAIResponsesModelSettings(openai_reasoning_effort='low', openai_reasoning_summary='detailed') agent = Agent(m, model_settings=settings) result = await agent.run('What is the meaning of life?') messages = result.all_messages() assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the meaning of life?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68c42de022c881948db7ed1cc2529f2e0202c9ad459e0d23', signature=IsStr(), provider_name='openai', ), TextPart(content=IsStr(), id='msg_68c42de31d348194a251b43ad913ef140202c9ad459e0d23'), ], usage=RequestUsage(input_tokens=13, output_tokens=248, details={'reasoning_tokens': 64}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68c42ddf9bbc8194aa7b97304dd909cb0202c9ad459e0d23', finish_reason='stop', ), ] ) response = messages[-1] assert isinstance(response, ModelResponse) assert isinstance(response.parts, list) response.parts[1] = TextPart(content='The meaning of life is 42') with pytest.raises( ModelHTTPError, match=r"Item '.*' of type 'reasoning' was provided without its required following item\.", ): await agent.run('Anything to add?', message_history=messages) result = await agent.run( 'Anything to add?', message_history=messages, model_settings=OpenAIResponsesModelSettings( openai_reasoning_effort='low', openai_reasoning_summary='detailed', openai_send_reasoning_ids=False, ), ) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Anything to add?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68c42de4f63c819fb31b6019a4eaf67c051f82c608a83beb', signature=IsStr(), provider_name='openai', ), TextPart(content=IsStr(), id='msg_68c42de8a410819faf7a9cbebd2b4bc4051f82c608a83beb'), ], usage=RequestUsage(input_tokens=142, output_tokens=355, details={'reasoning_tokens': 128}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68c42de4afcc819f995a1c59fe87c9d5051f82c608a83beb', finish_reason='stop', ), ] ) async def test_openai_responses_thinking_with_code_execution_tool(allow_model_requests: None, openai_api_key: str): provider = OpenAIProvider(api_key=openai_api_key) m = OpenAIResponsesModel( model_name='gpt-5', provider=provider, settings=OpenAIResponsesModelSettings( openai_reasoning_summary='detailed', openai_reasoning_effort='low', openai_include_code_execution_outputs=True, ), ) agent = Agent(model=m, builtin_tools=[CodeExecutionTool()]) result = await agent.run(user_prompt='what is 65465-6544 * 65464-6+1.02255') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='what is 65465-6544 * 65464-6+1.02255', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68cdba57390881a3b7ef1d2de5c8499709b7445677780c8f', signature='gAAAAABozbpoKwjspVdWvC2skgCFSKx1Fiw9QGDrOxixFaC8O5gPVmC35FfE2jaedsn0zsHctrsl2LvPt7ELnOB3N20bvDGcDHkYzjSOLpf1jl2IAtQrkPWuLPOb6h8mIPL-Z1wNrngsmuoaKP0rrAcGwDwKzq8hxpLQbjvpRib-bbaVQ0SX7KHDpbOuEam3bIEiNSCNsA1Ot54R091vvwInnCCDMWVj-9u2fn7xtNzRGjHorkAt9mOhOBIVgZNZHnWb4RQ-PaYccgi44-gtwOK_2rhI9Qo0JiCBJ9PDdblms0EzBE7vfAWrCvnb_jKiEmKf2x9BBv3GMydsgnTCJdbBf6UVaMUnth1GvnDuJBdV12ecNT2LhOF2JNs3QjlbdDx661cnNoCDpNhXpdH3bL0Gncl7VApVY3iT2vRw4AJCU9U4xVdHeWb5GYz-sgkTgjbgEGg_RiU42taKsdm6B2gvc5_Pqf4g6WTdq-BNCwOjXQ4DatQBiJkgV5kyg4PqUqr35AD05wiSwz6reIsdnxDEqtWv4gBJWfGj4I96YqkL9YEuIBKORJ7ArZnjE5PSv6TIhqW-X9mmQTGkXl8emxpbdsNfow3QEd_l8rQEo4fHiFOGwU-uuPCikx7v6vDsE-w_fiZTFkM0X4iwFb6NXvOxKSdigfUgDfeCySwfmxtMx67QuoRA4xbfSHI9cctr-guZwMIIsMmKnTT-qGp-0F4UiyRQdgz2pF1bRUjkPml2rsleHQISztdSsiOGC2jozXNHwmf1b5z6KxymO8gvlImvLZ4tgseYpnAP8p_QZzMjIU7Y7Z2NQMDASr9hvv3tVjVCphqz1RH-h4gifjZJexwK9BR9O98u63X03f01NqgimS_dZHZUeC9voUb7_khNizA9-dS-fpYUduqvxZt-KZ7Q9gx7kFIH3wJvF-Gef55lwy4JNb8svu1wSna3EaQWTBeZOPHD3qbMXWVT5Yf5yrz7KvSemiWKqofYIInNaRLTtXLAOqq4VXP3dmgyEmAZIUfbh3IZtQ1uYwaV2hQoF-0YgM7JLPNDBwX8cRZtlyzFstnDsL_QLArf0bA8FMFNPuqPfyKFvXcGTgzquaUzngzNaoGo7k6kPHWLoSsWbvY3WvzYg4CO04sphuuSHh9TZRBy6LXCdxaMHIZDY_qVB1Cf-_dmDW6Eqr9_xodcTMBqs6RHlttLwFMMiul4aE_hUgNFlzOX7oVbisIS2Sm36GTuKE4zrbkvsA==', provider_name='openai', ), BuiltinToolCallPart( tool_name='code_execution', args={ 'container_id': 'cntr_68cdba56addc81918f656db25fd0a6800d6da575ea4fee9b', 'code': """\ # compute the value 65465 - 6544 * 65464 - 6 + 1.02255 """, }, tool_call_id='ci_68cdba5af39881a393a01eebb253854e09b7445677780c8f', provider_name='openai', ), BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed', 'logs': ['-428330955.97745']}, tool_call_id='ci_68cdba5af39881a393a01eebb253854e09b7445677780c8f', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content=IsStr(), id='rs_68cdba63843881a3a9c585d83e4df9f309b7445677780c8f', signature='gAAAAABozbpoJefk0Fp1xqQzY6ego00t7KnH2ohbIw-rR9ZgaEAQs3n0Fubka6xbgRxzb1og6Xup1BuT8hQKMS-NHFxYsYXw4b6KeSbCd5oySVO53bsITEVk0A6tgjGssDJc1xSct1ORo-nCNV24MCNZvL9MKFeGQHP-jRypOZ9Vhepje87kFWTpw9lP9j54fZJdRIBGA9G_goI9m1cPztFUufcUxtLsgorsM053oxh8yWiEccAbvBaGXRlPWSoZYktbKrWeBVwiRt2ul-jRV43Z3chB32bEM1l9sIWG1xnvLE3OY6HuAy5s3bB-bnk78dibx5yx_iA36zGOvRkfiF0okXZoYiMNzJz3U7rTSsKlYoMtCKgnYGFdrh0D8RPj4VtxnRr-zAMJSSZQCm7ZipNSMS0PpN1wri14KktSkIGZGLhPBJpzPf9AjzaBBi2ZcUM347BtOfEohPdLBn8R6Cz-WxmoA-jH9qsyO-bPzwtRkv28H5G6836IxU2a402Hl0ZQ0Q-kPb5iqhvNmyvEQr6sEY_FN6ogkxwS-UEdDs0QlvJmgGfOfhMpdxfi5hr-PtElPg7j5_OwA7pXtuEI8mADy2VEqicuZzIpo6d-P72-Wd8sapjo-bC3DLcJVudFF09bJA0UirrxwC-zJZlmOLZKG8OqXKBE4GLfiLn48bYa5FC8a_QznrX8iAV6qPoqyqXANXuBtBClmzTHQU5A3lUgwSgtJo6X_0wZqw0O4lQ1iQQrkt7ZLeT7Ef6QVLyh9ZVaMZqVGrmHbphZK5N1u8b4woZYJKe0J57SrNihO8Slu8jZ71dmXjB4NAPjm0ZN6pVaZNLUajSxolJfmkBuF1BCcMYMVJyvV7Kk9guTCtntLZjN4XVOJWRU8Db5BjL17ciWWHGPlQBMxMdYFZOinwCHLIRrtdVxz4Na2BODjl0-taYJHbKd-_5up5nysUPc4imgNawbN2mNwjhdc1Qv919Q9Cz-he9i3j6lKYnEkgJvKF2RDY6-XAI=', provider_name='openai', ), TextPart( content="""\ Using standard order of operations (multiplication before addition/subtraction): 65465 - 6544 * 65464 - 6 + 1.02255 = -428,330,955.97745 If you intended different grouping with parentheses, let me know.\ """, id='msg_68cdba6652ac81a3a58625883261465809b7445677780c8f', ), ], usage=RequestUsage( input_tokens=1493, cache_read_tokens=1280, output_tokens=125, details={'reasoning_tokens': 64} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68cdba511c7081a389e67b16621029c609b7445677780c8f', finish_reason='stop', ), ] ) messages = result.all_messages() result = await agent.run(user_prompt='how about 2 to the power of 8?', message_history=messages) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='how about 2 to the power of 8?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68cdba6c100481a394047de63f3e175009b7445677780c8f', signature='gAAAAABozbpuOXVfjIYw7Gw6uSeadpkyaqMU1Frav7mTaf9LP8p8YuC8CWR9fYa02yZ5oYr1mqmYraD8ViOE33zqO2HBCdiWpOkVdNX-s4SGuPPB7ewyM7bDD4XbaSzo-Q5I6MgZmvVGWDGodqa3MfSKKNcGyD4aEfryQRLi4ObvHE5yuOqRo8FzGXMqe_pFdnvJXXD7njyfUofhWNvQPsLVLQFA_g_e7WKXtJJf_2JY183oi7-jNQ6rD9wGhM81HWSv0sTSBIHMpcE44rvlVQMFuh_rOPVUHUhT7vED7fYtrMoaPl46yDBc148T3MfXTnS-zm163zBOa34Yy_VXjyXw04a8Ig32y72bJY7-PRpZdBaeqD3BLvXfMuY4C911Z7FSxVze36mUxVO62g0uqV4PRw9qFA9mG37KF2j0ZsRzfyAClK1tu5omrYpenVKuRlrOO6JFtgyyE9OtLJxqvRNRKgULe2-cOQlo5S74t9lSMgcSGQFqF4JKG0A4XbzlliIcvC3puEzObHz-jArn_2BVUL_OPqx9ohJ9ZxAkXYgf0IRNYiKF4fOwKufYa5scL1kx2VAmsmEv5Yp5YcWlriB9L9Mpg3IguNBmq9DeJPiEQBtlnuOpSNEaNMTZQl4jTHVLgA5eRoCSbDdqGtQWgQB5wa7eH085HktejdxFeG7g-Fc1neHocRoGARxwhwcTT0U-re2ooJp99c0ujZtym-LiflSQUICi59VMAO8dNBE3CqXhG6S_ZicUmAvguo1iGKaKElMBv1Tv5qWcs41eAQkhRPBXQXoBD6MtBLBK1M-7jhidVrco0uTFhHBUTqx3jTGzE15YUJAwR69WvIOuZOvJdcBNObYWF9k84j0bZjJfRRbJG0C7XbU=', provider_name='openai', ), TextPart(content='256', id='msg_68cdba6e02c881a3802ed88715e0be4709b7445677780c8f'), ], usage=RequestUsage(input_tokens=793, output_tokens=7, details={'reasoning_tokens': 0}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68cdba6a610481a3b4533f345bea8a7b09b7445677780c8f', finish_reason='stop', ), ] ) async def test_openai_responses_thinking_with_code_execution_tool_stream( allow_model_requests: None, openai_api_key: str ): provider = OpenAIProvider(api_key=openai_api_key) m = OpenAIResponsesModel( model_name='gpt-5', provider=provider, settings=OpenAIResponsesModelSettings(openai_reasoning_summary='detailed', openai_reasoning_effort='low'), ) agent = Agent(model=m, builtin_tools=[CodeExecutionTool()]) event_parts: list[Any] = [] async with agent.iter(user_prompt="what's 123456 to the power of 123?") as agent_run: async for node in agent_run: if Agent.is_model_request_node(node) or Agent.is_call_tools_node(node): async with node.stream(agent_run.ctx) as request_stream: async for event in request_stream: event_parts.append(event) assert agent_run.result is not None assert agent_run.result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content="what's 123456 to the power of 123?", timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content=IsStr(), id='rs_68c3509b2ee0819eba32735182d275ad0f2d670b80edc507', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='code_execution', args='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"n = pow(123456, 123)\\nlen(str(n))"}', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507', provider_name='openai', ), BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed'}, tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507', timestamp=IsDatetime(), provider_name='openai', ), BuiltinToolCallPart( tool_name='code_execution', args='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"str(n)[:100], str(n)[-100:]"}', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507', provider_name='openai', ), BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed'}, tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507', timestamp=IsDatetime(), provider_name='openai', ), BuiltinToolCallPart( tool_name='code_execution', args='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"n"}', tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507', provider_name='openai', ), BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed'}, tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507', timestamp=IsDatetime(), provider_name='openai', ), TextPart( content=IsStr(), id='msg_68c350a75ddc819ea5406470460be7850f2d670b80edc507', ), ], usage=RequestUsage( input_tokens=3727, cache_read_tokens=3200, output_tokens=347, details={'reasoning_tokens': 128} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68c35098e6fc819e80fb94b25b7d031b0f2d670b80edc507', finish_reason='stop', ), ] ) assert event_parts == snapshot( [ PartStartEvent( index=0, part=ThinkingPart(content='', id='rs_68c3509b2ee0819eba32735182d275ad0f2d670b80edc507') ), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta='**Calcul')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta='ating')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' a')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' large')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' integer')), PartDeltaEvent( index=0, delta=ThinkingPartDelta( content_delta="""\ ** I\ """ ), ), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' need')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' to')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' compute')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' 123')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta='456')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' raised')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' to')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' the')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' power')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' of')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' 123')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta='.')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' That')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=IsStr())), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' an')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' enormous')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' integer')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=',')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' and')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' the')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' user')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' probably')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' wants')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' the')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' exact')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' value')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta='.')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' I')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' can')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' use')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' Python')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta="'s")), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' ability')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' to')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' handle')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' big')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' integers')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=',')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' but')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' the')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' output')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' will')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' likely')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' be')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' extremely')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' long')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' —')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' potentially')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' hundreds')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' of')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' digits')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta='.')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' I')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' should')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' consider')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' that')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' and')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' prepare')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' to')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' return')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' the')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' result')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' as')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' plain')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' text')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=',')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' even')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' if')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' it')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' ends')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' up')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' being')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' around')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' 627')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' digits')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta='.')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' So')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=',')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' let')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=IsStr())), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' go')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' ahead')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' and')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' compute')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta=' that')), PartDeltaEvent(index=0, delta=ThinkingPartDelta(content_delta='!')), PartDeltaEvent( index=0, delta=ThinkingPartDelta( signature_delta=IsStr(), provider_name='openai', ), ), PartEndEvent( index=0, part=ThinkingPart( content=IsStr(), id='rs_68c3509b2ee0819eba32735182d275ad0f2d670b80edc507', signature='gAAAAABow1CfwMTF6GjgPzWVr8oKbF3qM2qnldMGM_sXMoJ2SSXHrcL4lsIK69rnKn43STNM_YZ3f5AcwxF4oThzCOPl1g9-u4GGFd5sISVWJYruCukTVDPaEEzdmJqCU1JMSIZvlvqo7b5PsUGyQU5ldX4KXDq8zs4NmRyLIJe-34SCmDG3BYVWR_O-CtcjH0tF9e3XnJ5T9TvxioDEGbASqXMKx5XB9P_b1ser8P9WIQk6hxZ8YX-FAmWSt-sad-zScdeTmyPcakDb7Z4NVcXmL_I-hoQYH_lu-HPFVwcXU8R7yeXU-7YF3vZBE84cmFuv25lftyojbdGq2A7uxGJZBPMCoUBDGBNG2_7mVvKyGz_ZZ6vXIO0GVDhHdW4Y012pkoDfLp6B-B9CGvANOH3ORlcbhB8aT9qN5bY773wW44JIxRU3umkmNzwF7lkbmuMCbGybHYSzqtkOrMIRgqxaXOx3bGbsreM4kGwgD3EXWqQ1PVye_K7gRkToVQpfpID5iuH4jJZDkvNjjJI09JR2yqlR6QkQayVg2x1y8VHXoMYjNdQdZeP62AguqYbgrlBRcjaUnw78KcWscQHaNsg0MfxL_5Q-pZR1OPVsFppHRTzrVK8458d05yEhDmun345oI9ScBrtXFRdHXPy0dQaayfjxM9H0grPrIogMw_zz4jAcFqWxE_C7GPMnNIJ_uEAhkPOetpNb-izd-iY4pGYKs8pmCB5czrAlKC1MXTnowrlWcwf5_kuD5SzWlzlWOoKWCeBDOZuKTDVJKXh_QCtQfftomQazDFCiCSgaQMuP7GaPcDuS1jdQoMQBcFfKuWoq-3eQBOCiEOAERH81zR4hz1x02T_910jGreSpfgxSqt4Td0pDDSmlEV6CwaUDQvrPc67d8_Wtx8YKv4eBH544_p1k9T8tHo3Q7xvgE37ZCdd_AVhC2ed1b5oUI95tM570HAVugFilcHJICa1RbFzIlRkNgI4k2JvsVWtD5_h3x6ZaEFTomwIXlochYgsegh8RJIRRCNKO9ebsvTrkdl8n1mb3hLrz7puwCkRFyUkxYBGT9zUjuKrjp_IjTvvov29v6pwYHg2Xd0nAfLP4WWWPBLNx3oV1-yOfXStRGHMZTB6iN9d0Bxi2QS7dk-rPPXml5HxrSo1TG06EdBXQ1VgrkWIxG1TF97-gK9oWWT9S5aaYKZAOdaqDvi7qO8I-4VwExtIq4Do3BHnWrgKNHfyuAobQK4H_CFMElYibJHwA9t-UGujMic07AxS-2XjXaCtjf7LnW_aXE2rQDqzHiTiLmTqT6jYHP0WHGSqFTOFkNmzqy6uVfU-TbdT91zDBeesc8XpzCXWBVKqxEzuQGdJrYk6ieZaxL76Kjs4jyo838LMJCXzhcF8enukz_llnoxAV59hTDAn0MUQvstGlDX0ToI7C8Oc0NZfZU5Pi4gs8u0He_Nw5UsoV7sA-jk4M45sFt6g3u00kJFP3gIcdvOzHcRK5z3Sfb9JF0bnvIYSbUFUidEJxSOAcRlxofOJPnkPtWCYiiv3zSVxZXX77-wtc8yrOYFzH1k_8P6CDpcfzOW7Yl1Tajgcm20nygmPlFtXF3RNFPztW1V5GwQHc99FvT4ZAex3fQ_UBDKyXnyGoySgpZbHQIvhzUhDEGm77EiYw5FoF6JgnHGGUCbfXr2EudtpbGW8MRHop2ytonb8Hq7w10yQSginBbH_w3bwtd7cwgDKcp6wIPotjpEC-N1YDsRqhPuqxVA==', provider_name='openai', ), next_part_kind='builtin-tool-call', ), PartStartEvent( index=1, part=BuiltinToolCallPart( tool_name='code_execution', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507', provider_name='openai', ), previous_part_kind='thinking', ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507', ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='n', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' =', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' pow', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='123', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='456', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' ', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='123', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=')\\n', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='len', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(str', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(n', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='))', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='"}', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507' ), ), PartEndEvent( index=1, part=BuiltinToolCallPart( tool_name='code_execution', args='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"n = pow(123456, 123)\\nlen(str(n))"}', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507', provider_name='openai', ), next_part_kind='builtin-tool-return', ), PartStartEvent( index=2, part=BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed'}, tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507', timestamp=IsDatetime(), provider_name='openai', ), previous_part_kind='builtin-tool-call', ), PartStartEvent( index=3, part=BuiltinToolCallPart( tool_name='code_execution', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507', provider_name='openai', ), previous_part_kind='builtin-tool-return', ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507', ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='str', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='(n', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta=')', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='[:', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='100', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='],', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta=' str', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='(n', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta=')[', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='-', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='100', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta=':]', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='"}', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507' ), ), PartEndEvent( index=3, part=BuiltinToolCallPart( tool_name='code_execution', args='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"str(n)[:100], str(n)[-100:]"}', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507', provider_name='openai', ), next_part_kind='builtin-tool-return', ), PartStartEvent( index=4, part=BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed'}, tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507', timestamp=IsDatetime(), provider_name='openai', ), previous_part_kind='builtin-tool-call', ), PartStartEvent( index=5, part=BuiltinToolCallPart( tool_name='code_execution', tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507', provider_name='openai', ), previous_part_kind='builtin-tool-return', ), PartDeltaEvent( index=5, delta=ToolCallPartDelta( args_delta='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"', tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507', ), ), PartDeltaEvent( index=5, delta=ToolCallPartDelta( args_delta='n', tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507' ), ), PartDeltaEvent( index=5, delta=ToolCallPartDelta( args_delta='"}', tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507' ), ), PartEndEvent( index=5, part=BuiltinToolCallPart( tool_name='code_execution', args='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"n"}', tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507', provider_name='openai', ), next_part_kind='builtin-tool-return', ), PartStartEvent( index=6, part=BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed'}, tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507', timestamp=IsDatetime(), provider_name='openai', ), previous_part_kind='builtin-tool-call', ), PartStartEvent( index=7, part=TextPart(content='123', id='msg_68c350a75ddc819ea5406470460be7850f2d670b80edc507'), previous_part_kind='builtin-tool-return', ), FinalResultEvent(tool_name=None, tool_call_id=None), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='456')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='^')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='123')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta=' equals')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta=':\n')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='180')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='302')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='106')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='304')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='044')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='807')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='508')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='140')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='927')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='865')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='938')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='572')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='807')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='342')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='688')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='638')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='559')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='680')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='488')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='440')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='159')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='857')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='958')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='502')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='360')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='813')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='732')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='502')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='197')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='826')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='969')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='863')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='225')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='730')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='871')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='630')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='436')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='419')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='794')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='758')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='932')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='074')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='350')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='380')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='367')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='697')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='649')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='814')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='626')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='542')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='926')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='602')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='664')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='707')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='275')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='874')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='269')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='201')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='777')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='743')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='912')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='313')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='197')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='516')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='323')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='690')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='221')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='274')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='713')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='845')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='895')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='457')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='748')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='735')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='309')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='484')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='337')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='191')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='373')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='255')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='527')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='928')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='271')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='785')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='206')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='382')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='967')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='998')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='984')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='330')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='482')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='105')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='350')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='942')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='229')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='970')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='677')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='054')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='940')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='838')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='210')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='936')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='952')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='303')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='939')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='401')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='656')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='756')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='127')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='607')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='778')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='599')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='667')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='243')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='702')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='814')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='072')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='746')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='219')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='431')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='942')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='293')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='005')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='416')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='411')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='635')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='076')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='021')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='296')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='045')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='493')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='305')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='133')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='645')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='615')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='566')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='590')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='735')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='965')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='652')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='587')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='934')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='290')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='425')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='473')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='827')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='719')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='935')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='012')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='870')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='093')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='575')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='987')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='789')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='431')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='818')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='047')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='013')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='404')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='691')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='795')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='773')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='170')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='405')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='764')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='614')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='646')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='054')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='949')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='298')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='846')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='184')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='678')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='296')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='813')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='625')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='595')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='333')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='311')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='611')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='385')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='251')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='735')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='244')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='505')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='448')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='443')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='050')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='050')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='547')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='161')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='779')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='229')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='749')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='134')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='489')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='643')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='622')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='579')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='100')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='908')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='331')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='839')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='817')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='426')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='366')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='854')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='332')), PartDeltaEvent(index=7, delta=TextPartDelta(content_delta='416')), PartEndEvent( index=7, part=TextPart( content="""\ 123456^123 equals: 180302106304044807508140927865938572807342688638559680488440159857958502360813732502197826969863225730871630436419794758932074350380367697649814626542926602664707275874269201777743912313197516323690221274713845895457748735309484337191373255527928271785206382967998984330482105350942229970677054940838210936952303939401656756127607778599667243702814072746219431942293005416411635076021296045493305133645615566590735965652587934290425473827719935012870093575987789431818047013404691795773170405764614646054949298846184678296813625595333311611385251735244505448443050050547161779229749134489643622579100908331839817426366854332416\ """, id='msg_68c350a75ddc819ea5406470460be7850f2d670b80edc507', ), ), BuiltinToolCallEvent( # pyright: ignore[reportDeprecated] part=BuiltinToolCallPart( tool_name='code_execution', args='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"n = pow(123456, 123)\\nlen(str(n))"}', tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507', provider_name='openai', ) ), BuiltinToolResultEvent( # pyright: ignore[reportDeprecated] result=BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed'}, tool_call_id='ci_68c3509faff0819e96f6d45e6faf78490f2d670b80edc507', timestamp=IsDatetime(), provider_name='openai', ) ), BuiltinToolCallEvent( # pyright: ignore[reportDeprecated] part=BuiltinToolCallPart( tool_name='code_execution', args='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"str(n)[:100], str(n)[-100:]"}', tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507', provider_name='openai', ) ), BuiltinToolResultEvent( # pyright: ignore[reportDeprecated] result=BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed'}, tool_call_id='ci_68c350a41d2c819ebb23bdfb9ff322770f2d670b80edc507', timestamp=IsDatetime(), provider_name='openai', ) ), BuiltinToolCallEvent( # pyright: ignore[reportDeprecated] part=BuiltinToolCallPart( tool_name='code_execution', args='{"container_id":"cntr_68c3509aa0348191ad0bfefe24878dbb0deaa35a4e39052e","code":"n"}', tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507', provider_name='openai', ) ), BuiltinToolResultEvent( # pyright: ignore[reportDeprecated] result=BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed'}, tool_call_id='ci_68c350a5e1f8819eb082eccb870199ec0f2d670b80edc507', timestamp=IsDatetime(), provider_name='openai', ) ), ] ) async def test_openai_responses_streaming_usage(allow_model_requests: None, openai_api_key: str): class Result(BaseModel): result: int agent = Agent( model=OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)), model_settings=OpenAIResponsesModelSettings( openai_reasoning_effort='low', openai_service_tier='flex', ), output_type=Result, ) async with agent.iter('Calculate 100 * 200 / 3') as run: async for node in run: if Agent.is_model_request_node(node): async with node.stream(run.ctx) as response_stream: async for _ in response_stream: pass assert response_stream.get().usage == snapshot( RequestUsage(input_tokens=53, output_tokens=469, details={'reasoning_tokens': 448}) ) assert response_stream.usage() == snapshot( RunUsage(input_tokens=53, output_tokens=469, details={'reasoning_tokens': 448}, requests=1) ) assert run.usage() == snapshot(RunUsage(requests=1)) assert run.usage() == snapshot( RunUsage(input_tokens=53, output_tokens=469, details={'reasoning_tokens': 448}, requests=1) ) assert run.usage() == snapshot( RunUsage(input_tokens=53, output_tokens=469, details={'reasoning_tokens': 448}, requests=1) ) async def test_openai_responses_non_reasoning_model_no_item_ids(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-4.1', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model) @agent.tool_plain def get_meaning_of_life() -> int: return 42 result = await agent.run('What is the meaning of life?') messages = result.all_messages() assert messages == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the meaning of life?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ToolCallPart( tool_name='get_meaning_of_life', args='{}', tool_call_id='call_3WCunBU7lCG1HHaLmnnRJn8I', id='fc_68cc4fa649ac8195b0c6c239cd2c14470548824120ffcf74', ) ], usage=RequestUsage(input_tokens=36, output_tokens=15, details={'reasoning_tokens': 0}), model_name='gpt-4.1-2025-04-14', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68cc4fa5603481958e2143685133fe530548824120ffcf74', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_meaning_of_life', content=42, tool_call_id='call_3WCunBU7lCG1HHaLmnnRJn8I', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ TextPart( content="""\ The meaning of life, according to popular culture and famously in Douglas Adams' "The Hitchhiker's Guide to the Galaxy," is 42! If you're looking for a deeper or philosophical answer, let me know your perspective or context, and I can elaborate further.\ """, id='msg_68cc4fa7693081a184ff6f32e5209ab00307c6d4d2ee5985', ) ], usage=RequestUsage(input_tokens=61, output_tokens=56, details={'reasoning_tokens': 0}), model_name='gpt-4.1-2025-04-14', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68cc4fa6a8a881a187b0fe1603057bff0307c6d4d2ee5985', finish_reason='stop', ), ] ) _, openai_messages = await model._map_messages(messages, model_settings=model.settings or {}) # type: ignore[reportPrivateUsage] assert openai_messages == snapshot( [ {'role': 'user', 'content': 'What is the meaning of life?'}, { 'name': 'get_meaning_of_life', 'arguments': '{}', 'call_id': 'call_3WCunBU7lCG1HHaLmnnRJn8I', 'type': 'function_call', }, {'type': 'function_call_output', 'call_id': 'call_3WCunBU7lCG1HHaLmnnRJn8I', 'output': '42'}, { 'role': 'assistant', 'content': """\ The meaning of life, according to popular culture and famously in Douglas Adams' "The Hitchhiker's Guide to the Galaxy," is 42! If you're looking for a deeper or philosophical answer, let me know your perspective or context, and I can elaborate further.\ """, }, ] ) async def test_openai_responses_code_execution_return_image(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel( 'gpt-5', provider=OpenAIProvider(api_key=openai_api_key), settings=OpenAIResponsesModelSettings(openai_include_code_execution_outputs=True), ) agent = Agent(model=model, builtin_tools=[CodeExecutionTool()], output_type=BinaryImage) result = await agent.run('Create a chart of y=x^2 for x=-5 to 5') assert result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='653a61', ) ) messages = result.all_messages() assert messages == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Create a chart of y=x^2 for x=-5 to 5', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_68cdc38812288190889becf32c2934990187028ba77f15f7', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='code_execution', args={ 'container_id': 'cntr_68cdc387531c81938b4bee78c36acb820dbd09bdba403548', 'code': """\ import numpy as np\r import matplotlib.pyplot as plt\r \r # Data\r x = np.arange(-5, 6, 1)\r y = x**2\r \r # Plot\r plt.figure(figsize=(6, 4))\r plt.plot(x, y, marker='o')\r plt.title('y = x^2 for x = -5 to 5')\r plt.xlabel('x')\r plt.ylabel('y')\r plt.grid(True, linestyle='--', alpha=0.6)\r plt.xticks(x)\r plt.tight_layout()\r \r # Save and show\r plt.savefig('/mnt/data/y_equals_x_squared.png', dpi=200)\r plt.show()\r \r '/mnt/data/y_equals_x_squared.png'\ """, }, tool_call_id='ci_68cdc39029a481909399d54b0a3637a10187028ba77f15f7', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='653a61', ), id='ci_68cdc39029a481909399d54b0a3637a10187028ba77f15f7', ), BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed', 'logs': ["'/mnt/data/y_equals_x_squared.png'"]}, tool_call_id='ci_68cdc39029a481909399d54b0a3637a10187028ba77f15f7', timestamp=IsDatetime(), provider_name='openai', ), TextPart( content=IsStr(), id='msg_68cdc398d3bc8190bbcf78c0293a4ca60187028ba77f15f7', ), ], usage=RequestUsage( input_tokens=2973, cache_read_tokens=1920, output_tokens=707, details={'reasoning_tokens': 512} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68cdc382bc98819083a5b47ec92e077b0187028ba77f15f7', finish_reason='stop', ), ] ) result = await agent.run('Style it more futuristically.', message_history=messages) assert result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='81863d', ) ) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Style it more futuristically.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_68cdc39f6aa48190b5aece25d55f80720187028ba77f15f7', signature='gAAAAABozcPV8NxzVAMDdbpqK7_ltYa5_uAVsbnSW9OMWGRwlnwasaLvuaC4XlgGmC2MHbiPrccJ8zYuu0QoQm7jB6KgimG9Ax3vwoFGqMnfVjMAzoy_oJVadn0Odh3sKGifc11yVMmIkvrl0OcPYwJFlxlt2JhPkKotUDHY0P2LziSsMnQB_KaVdyYQxfcVbwrJJnB9wm2QbA3zNZogWepoXGrHXL1mBRR3J7DLdKGfMF_7gQC5fgEtb3G4Xhvk8_XNgCCZel48bqgzWvNUyaVPb4TpbibAuZnKnCNsFll6a9htGu9Ljol004p_aboehEyIp6zAm_1xyTDiJdcmfPfUiNgDLzWSKf-TwGFd-jRoJ3Aiw1_QY-xi1ozFu2oIeXb2oaZJL4h3ENrrMgYod3Wiprr99FfZw9IRN4ApagGJBnWYqW0O75d-e8jUMJS8zFJH0jtCl0jvuuGmM5vBAV4EpRLTcNGOZyoRpfqHwWfZYIi_u_ajs_A6NdqhzYvxYE-FAE1aJ89HxhnQNjRqkQFQnB8sYeoPOLBKIKAWYi3RziNE8klgSPC250QotupFaskTgPVkzbYe9ZtRZ9IHPeWdEHikb2RP-o1LVVO_zFMJdC6l4TwEToqRG8LaZOgSfkxS8eylTw7ROI2p8IBSmMkbkjvEkpmIic0FSx23Ew_Q-Y6DPa9isxGZcMMS0kOPKSPSML2MGoVq5L3-zIVj6ZBcFOMSaV5ytTlH-tKqBP9fejMyujwQFl5iXawuSjVjpnd2VL83o-xKbm6lEgsyXY1vynlS2hT52OYUY3MMvGSCeW5d7xwsVReO0O1EJqKS0lLh8thEMpJvar9dMgg-9ZCgZ1wGkJlpANf2moQlOWXKPXcbBa2kU0OW2WEffr4ecqg1QwPoMFLmR4HDL-KknuWjutF5bo8FW0CAWmxObxiHeDWIJYpS4KIIwp9DoLdJDWlg8FpD6WbBjKQN6xYmewHaTLWbZQw8zMGBcnhAkkyVopjrbM_6rvrH4ew05mPjPRrq9ODdHBqDYEn1kWj9MBDR-nhhLrci_6GImd64HZXYo0OufgcbxNu5mcAOsN3ww13ui8CTQVsPJO20XHc4jfwZ2Yr4iEIYLGdp0Xgv8EjIkJNA1xPeWn9COgCRrRSVLoF6qsgZwt9IRRGGEbH6kvznO_Y7BTTqufsORG6WNKc_8DDlrczoZVy0d6rI1zgqjXSeMuEP9LBG-bJKAvoAGDPXod8ShlqGX3Eb9CmBTZtTOJZYdgAlsZHx9BZ6zHlrJDjSDhc8xvdUAn9G3JvTI3b5JWSNX0eEerZ4c0FVqlpR-mSG201qnFghtoGHTLJhlIf9Ir8Daio_AYxUTRarQbcKnJuyKHPOz1u0PX2zS0xegO-IZhFbzNaB8qwQgeBiHfP-1dP9mkttqIRMt-hMt9NMHXoGIvFxgQ-xUVw7GRWx-ffKY7nPAbZD8kwVP3i4jTVj8phhwQcDy9UmbaPjm4LBgJkfdwNfSpm3g_ePK4aLa_l7iF2WSSfy2wObb7VatDzYDcNRG0ZTMGsiHy8yzZAcec18rG7uE6QCKx32G8NI5YvcN1kbnrZEuoKTBuSb2B_ZAhvED9HxbG8mH4ZEHHioVuH3_-b2TesVUAbORab_-rG9CU6qyy_eAqP54FYiXXSWtBWNo4baVdqCzgSCiNxgpxx64WPw8y2M1bOMoV6KPGwDOjcNwbO9nQwztqTWPW0Ot_Llf0HV0p-RPC1Uy8uBB5flhJ3p5uqxCPV3kDRzXgjh28EaBEkaSw_6SZkJNvwbD_7VihlHGaO89TwlqSIYUT_gc72NZKRrj4f-Y-0NwxjaSVVGuWCoeG-TMjG6uXpSozo2J47_x_a0lr4KCT8NDYlksajyuPUbYhC7jhQ9uJakmAc7ay_VHn_LYlAWRdAA7wYvqw7aYIuSIYg2OfL6NlggCpBnhsUPEXmMRHcfj1Ctc1aeUjBcpLFVmTZ82lB0FdcKRe3bBsKRckbdKalehoK0NJtrWqNQQH7xPrS-r7or_oOWhA4EDIkRUOG9eZhdsvTXBUamxGwutJ97SdDkgppVC4M7DMK2ZGGBzQsE-JMilERvFQ8JqwVWPxExWmE_-H2-bYe-T-CguCin-mTqhLYswHVtXjtruoHBmDs2SdnkD3intwSpqxsltscCfRaoRYWTCTbchCdbctSEIc39ECpc5tL1Gnav0bwSkMYkxyaRVBiYBbmIG9JftkKIYtdZ_Ddjmq8k29QflqrcigahsVLZPye3dxVTuviqbQjRd2SPMv8RxgSebgm5RZZIpP4WposryghYZFvuA1WImRzsImnAJI9J-8dv6IhHpHsWOw9K-Neg8GlnDU1mGHUElMUbqHiLojmXqPGfhBI3iSR0Ugs7ErpeRUrSk3il2o3rysG1Fn7ePuP5qNJUt2NyBUxf3TExMOwG_zqvpIPr2V_ARr3PsfeD0IcY83Bh428S8KPzc7ASOjT9dGQtVVrdjSxHi8o5ANxGx6z3bHC5dJvDCXg8a7FIJHAd5CUqJxrBi-K4p21jf1BNqgO5JAJO1JrvtdTk4GOVe8YEfhxmGWW9oeuRg8crsIWCCCoxr2XJKgPCj2TTPkBDZ1O3Yw3_nuWaBU5sB09uEB5lTKMd0OfSHbPF4c50RWAFgQB-tHjIUss3oEcAUaZHC77r6sIYoAEBlU8Dgly983fFD0HCqtpIpKS_B_K1fTXYpWRM3uUZpPKEgbfw1Kiqp5cweKTeRKNvjlau6VxhPyVi66xPdHUCC_BcX1eeFe-zcxe6fczcJWqGZGtYyVS_S_GlWZcdA6AHvGU6c4KjG0oU_9q-pdHSRtpnrhqFu2L884m64A_HsFU71Dj34AxhmXO1Am-zSL3j9nEPPUe6lJSGyhHU9k8ApDadWagvlODdXYWaWiMCXGXcYtl_iUAm24IJozlLJ1IW9HW6RoTfKrxwQwND3pX9CLNewuPV776pVtRjvUMbLaYg8nzOu1eNT2IW9dUdzc7wqOjiT1gHuVd6RzJyTCWJb9yPwDTkB_NKkjfUPmJ9Id924xtxy6H0eDYRq-SqsSSEklr6KJc88PV35QqvaMUW1dt_tGynHgYy9PXlWXQLKw-Xphku3FS_R4BLUhJbXDsMOQq332yhizP3qQ7vjEmPm8KB4DMIWBNn_D9xFuDuTCMNPAA9AGYWgC39-L4wPbpBHpqWjDwMzijFpm0CEViPD9ghyyV8syT1uLscxJVVDlBx90u_qWLSzMnFrVWmZ60OyWa9EqG44ZU8ELLHlEDRO_yHuTVpSafCLeDe5baOG2mI6tZnDBmm_ysbYdaC2N_zNBK9rhx7g7BNLQPevl0vtZm7GVLYXiVaO5ZinHxeTyJ6dRU5b0HmSw8r7EpdgORfjUuMkUfWPwhXgTU8SbvjTZg1gJowyNDYCvacrgnmnpBG9BgNjsfWlGTwz19AcEP_GjCWRWoE-uE_5fIyq5eFEefCBUKU0Ejs0IB-Re5h8bbdc6bNV3Tnx4UfGDU6FbQrJmPzrw5wp_wCeVYjtNGRbO2MKr_m52km5xMpVMMHtthVbQ9Zsa9F9zB6Dkr-R4F7o0dITMhG3qaREHKc8mXIGoHND-WSGPZLntB43JmRIWwjlJNstv7VlVc-dU89oh6Z1biH9B88SENI1ao2wMQV-BB17E6cmfzm1JsSR-HkzSf3yoUJWwvIu4CaR4jeMZohuoNqfGvQWIJSfyyUNzq5uY5__04QUmNcRVspOTH4EOHAoXLfCV3VI7fodj4FppiIuIXKwS3N03-Qt4sQ__XQWuyDdORvhRJeCvYcK5kkyOQILcABxDItxLmk8AgdT0Hz0BAo_u1U71srS-T8a8O0-fXWsJAHxDg_rJn0LUm6zq2vXNl8zmOKwEayyb0YySbMRxI-LwLyOXGRDyAVvm_7KKJu1HHqMntLyY2G1xowFpwMVLYXlGxDbsSpE-g5kFnHWhj13FiekLxaFgMRNsMA-r5_rWbEjRa6H328FKsUJcYe9qsp2LlzdJmYZDTIMgzxupFwQ-R5F6QjWOudMBsRszb4YqnOPJ8P9YnY2WYd0B7srb5Gh7T6r6mcCl-HAb2z9QDeXOc2Lu7ujuSvGj7_Gk7PkZH-LzoAEaGG9Z-7IVJlV_hOBPif3GlJUSUhTlIwWxn75gOyoOFuMak-rQqkb0SaL5anfXS_NUTVgSh5G5JQIoykLxbVlGiyeq0M_oEvTw2wMZcWT2hhaudcQ6L912pntcD-WF2tfppgp6sN5-cq-D8Y39N5Txvs-wo-H7-vYKPozTNUKCfnzgXfvt5fOi3RBR4MZU3eHT8OZ7d1d3otho_4GVMNIFa6mxjW1BC_J42Hn27-vrNDLZI_BXdF1t2CCq9VeRwxIW1R9vadd04HzAXyhap95BAYacmbULR6BkX97TvY3hv5cMiaQFkzxg-tf-nGC_VCknvwKxu4ocoB14p9w5TPSKcJz4J26XvyQbi6AdaXbOk625ajB_clv3VJvXYz7DgvWZd408tMykYQLMEyv5lnS7qwQokeM4ilIXwM7EugiakhfefTM9ZdxaWVcvQdqGerx98wlhifCSv0FqFRpJdkqgHmV1qzrAjPDEKT5HJOjsvs5hb7gKBqHR-bYlgS94pvDUpPArQXYcGYGum6vFsCAJypefMTF3D7Zhu4hhWQQv-DzSmfcZOxSeVJFrgVeqJnIbZPtd59HCBXNIRXJa42wUYE4szNli8wKWX0rYSIhiX-ig2YYZz3ZoBE1KDOpzheuk9OMYg7tQG2UlmVq27ggaKJ2gEGuVv-GI7uD7vKxPQ97QwCf38gWKU95CjMEBm_EvmLs9eubNpSpz8Yoek8hWWgrCXUSwRsYnF-lGdG0nIkCClvzqqAGOjyPxG4qfrCXJ-4rVc4DQiJUj71_I0EAhOgxb5WYBt4a7C1aUxC__qeOTAecof-UjzNlUPTo91JgOh5xvZkRkgGFNsq1OFqOcRrrKV8U8brizYkIhDjzjwCIzScSYvEfY4S6st-oJBv5fwTqwICSs59hf6WR8GXsPFR4v3UtF0Rkt-Nrek-X6V7BCui1M5HeFRN7lcTYs1Qw2bIwu4Td5PIkZ16oHdCk9u5pEZce-n_MIwj2Yoq_Lq1BBY9f1rpG9IuaycwabFnd2MOj89-xdgC197DAij5WjZjXahooyAl0Mt3p9MrHCit7LYbxqd_dGBOmg9YRfGPhsoZ17oAmHyg_gvpooOsu21T_06ynhvySjOG0yUcphquvtHJWqQdcT6BBX0X-kGE4nA41VdMhepLhDRDXtR4HJ1m_dPFpkHeAAFIefjt5Kb782TDLFE3KuHFWqSU2K2UmlY12P21dpRvyUNz8ss_AA3rl5jFpcnC2IyJNDIZbqdJPd2z0SNlwNyBq7Vl6poenR-j2X3xzIGlCDQ9zRgs50wdWtZ3ZRWLVWMrVkhkddoVKuh1W9rlwsvxmlZbOeRk_Uh0BymAa0-4-n0jI4_-O8jqpL-YzL1Y191brY4ywLUrQXpln41UK76pxc34FojI1Nymw523SNYxAHSlpj01gNmcjPrBTFxQ9SDY7AlrSFwJia_KvWnsZ53qt6fiDHV7p62KzlG_rpz_dQSQoj-z1hZBoUxi4nqzeCIzPcB_3JqeqD6x1O-Vh3uk-6NxN_qCE8cRsizB5vV-Ur-4tqau6LIrdfIB3Db12vpgiCmD_BD4xCxOijDn-97edRZw__xYfhx9_MBEB6gYl1ZBtLJfxDN54N5UION2tiZ2U8THD_h4d8-c26H7NQv44kYppbaseMckhpVOBDh52P5gxWFwp4VGqAIkZ7KU10qAD6M3GTFx7vGth8cT8YS1s2gPDW-WcVQGlAF94gT-FE6vzAjxwRJ4m7B1rJZfYReDvMrAoLroayOVmfB8pOKVQLQEF5dUmlzAIIpeh1NAiTg4n3FXW7OXQhzhU8bmo0e2FuSEOUVimGw9Nk_Wor3kQFp-9kj_iazSC4p5VURnyY_lAirPfyw4nskpZzCjSg_EAU8Au5vvOqrdDEPjrbeT8ks0wi2rsB0AxQxhgf6jUWzp0apeZOIl9dJFH_OnyJfvwrV4YHpee3174WKYhOJIOy2-8FJbMw1MpQtVV49yWmZsIyjRNj2uLbqY7jWBo2UEeOVW5n1tdk5zAVF-RFPKyh9150MnJz_RQtgoNdUD4iLBwlHYHVGLyH4a3GJmOJP6ZC-A-8RiUjvhu5co0yC8M83aVFjLe-yob3sNgJQgdVJnEOfPz4-1DVORoDgIRrRBcZQZqvkZwADFUkyy9jy5oXdEJ5XzthnizbrOZkHk6sQsNXrP4Uadqo9w99uy7TUh62l5AMWBFcaaQhuAuFkUZCavIqoO-2k4oXIDoTeBYzbyo_HH6caMk0D0_zgEg_5i-NhT3EUPdoCBNmjbOKmN2wzf6kqEyc8-nunjfq6HOjC6B6SE6VgOVJgBrhB4cBto4CxO45eqeuCi_WCjRtSS43Bh0QFZi6xK8rRjItyQRIfBpomETElbng3mAmBLPNb_7CzfsBdhBhJQLKu9KZ__uL3YVGtrCaLcOsfwP7BXRNQJH0yN_JWfMZH3y3B8z1O__xGhR63ugExWJZyUn55KAEiODbX35_PcftWXjslq-wzsK4J2fO_HFNU8Pi4egk6ibvCUDFRUelukaAy_YHdb0VTSB6XCymTo96jK0HGjG8FaVwvQaesaUE-e0_JpdMXN3KstKFeTlDUx1o3Ny93-VxLB5rkOSd6cRjEnFRA7Q6HnturEjwPAeJjR2Ll5dsisVrdjqHMbSfSObkpd2dZ0T3LP4-_ug7qRJF60DJTjTPpx7YxeARzuwiu02TlVW0J0PrdXT8EpISHneKc1VWhtRcdD0R0spuAMzJLwELaOemihL1TJSIMBqFikbpulZCZ1k1kA_5D7I5c7pOF1g4uYBW-gJNTenfC9wYmDJAOCcnwk1W4=', provider_name='openai', ), BuiltinToolCallPart( tool_name='code_execution', args={ 'container_id': 'cntr_68cdc387531c81938b4bee78c36acb820dbd09bdba403548', 'code': """\ import numpy as np\r import matplotlib.pyplot as plt\r import matplotlib.patheffects as pe\r \r # Data\r x_smooth = np.linspace(-5, 5, 501)\r y_smooth = x_smooth**2\r x_int = np.arange(-5, 6, 1)\r y_int = x_int**2\r \r # Futuristic styling parameters\r bg_color = '#0b0f14' # deep space blue-black\r grid_color = '#00bcd4' # cyan\r neon_cyan = '#00e5ff'\r neon_magenta = '#ff2bd6'\r accent = '#8a2be2' # electric purple\r \r plt.style.use('dark_background')\r plt.rcParams.update({\r 'font.family': 'DejaVu Sans Mono',\r 'axes.edgecolor': neon_cyan,\r 'xtick.color': '#a7ffff',\r 'ytick.color': '#a7ffff',\r 'axes.labelcolor': '#a7ffff'\r })\r \r fig, ax = plt.subplots(figsize=(8, 5), dpi=200)\r fig.patch.set_facecolor(bg_color)\r ax.set_facecolor(bg_color)\r \r # Neon glow effect: draw the curve multiple times with increasing linewidth and decreasing alpha\r for lw, alpha in [(12, 0.06), (9, 0.09), (6, 0.14), (4, 0.22)]:\r ax.plot(x_smooth, y_smooth, color=neon_cyan, linewidth=lw, alpha=alpha, solid_capstyle='round')\r \r # Main crisp curve\r ax.plot(x_smooth, y_smooth, color=neon_cyan, linewidth=2.5)\r \r # Glowing integer markers\r ax.scatter(x_int, y_int, s=220, color=neon_magenta, alpha=0.10, zorder=3)\r ax.scatter(x_int, y_int, s=60, color=neon_magenta, edgecolor='white', linewidth=0.6, zorder=4)\r \r # Grid and spines\r ax.grid(True, which='major', linestyle=':', linewidth=0.8, color=grid_color, alpha=0.25)\r for spine in ax.spines.values():\r spine.set_linewidth(1.2)\r \r # Labels and title with subtle glow\r title_text = ax.set_title('y = x^2 • x ∈ [-5, 5]', fontsize=16, color=neon_cyan, pad=12)\r title_text.set_path_effects([pe.withStroke(linewidth=3, foreground=accent, alpha=0.35)])\r \r ax.set_xlabel('x', fontsize=12)\r ax.set_ylabel('y', fontsize=12)\r \r # Ticks\r ax.set_xticks(x_int)\r ax.set_yticks(range(0, 26, 5))\r \r # Subtle techy footer\r footer = ax.text(0.98, -0.15, 'generated • neon-grid',\r transform=ax.transAxes, ha='right', va='top',\r color='#7fdfff', fontsize=9, alpha=0.6)\r footer.set_path_effects([pe.withStroke(linewidth=2, foreground=bg_color, alpha=0.9)])\r \r plt.tight_layout()\r \r # Save and show\r out_path = '/mnt/data/y_equals_x_squared_futuristic.png'\r plt.savefig(out_path, facecolor=fig.get_facecolor(), dpi=200, bbox_inches='tight')\r plt.show()\r \r out_path\ """, }, tool_call_id='ci_68cdc3be6f3481908f64d8f0a71dc6bb0187028ba77f15f7', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='81863d', ), id='ci_68cdc3be6f3481908f64d8f0a71dc6bb0187028ba77f15f7', ), BuiltinToolReturnPart( tool_name='code_execution', content={ 'status': 'completed', 'logs': [ """\ /tmp/ipykernel_11/962152713.py:40: UserWarning: You passed a edgecolor/edgecolors ('white') for an unfilled marker ('x'). Matplotlib is ignoring the edgecolor in favor of the facecolor. This behavior may change in the future. ax.scatter(x_int, y_int, s=60, color=neon_magenta, edgecolor='white', linewidth=0.6, zorder=4) """, "'/mnt/data/y_equals_x_squared_futuristic.png'", ], }, tool_call_id='ci_68cdc3be6f3481908f64d8f0a71dc6bb0187028ba77f15f7', timestamp=IsDatetime(), provider_name='openai', ), TextPart( content="""\ I gave the chart a neon, futuristic look with a dark theme, glowing curve, and cyber-style markers and grid. Download the image: [y_equals_x_squared_futuristic.png](sandbox:/mnt/data/y_equals_x_squared_futuristic.png) If you want different colors or a holographic gradient background, tell me your preferred palette.\ """, id='msg_68cdc3d0303c8190b2a86413acbedbe60187028ba77f15f7', ), ], usage=RequestUsage( input_tokens=4614, cache_read_tokens=1792, output_tokens=1844, details={'reasoning_tokens': 1024} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68cdc39da72481909e0512fef9d646240187028ba77f15f7', finish_reason='stop', ), ] ) async def test_openai_responses_code_execution_return_image_stream(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel( 'gpt-5', provider=OpenAIProvider(api_key=openai_api_key), settings=OpenAIResponsesModelSettings(openai_include_code_execution_outputs=True), ) agent = Agent(model=model, builtin_tools=[CodeExecutionTool()], output_type=BinaryImage) event_parts: list[Any] = [] async with agent.iter(user_prompt='Create a chart of y=x^2 for x=-5 to 5') as agent_run: async for node in agent_run: if Agent.is_model_request_node(node) or Agent.is_call_tools_node(node): async with node.stream(agent_run.ctx) as request_stream: async for event in request_stream: event_parts.append(event) assert agent_run.result is not None assert agent_run.result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='df0d78', ) ) assert agent_run.result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Create a chart of y=x^2 for x=-5 to 5', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_06c1a26fd89d07f20068dd936ae09c8197b90141e9bf8c36b1', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='code_execution', args="{\"container_id\":\"cntr_68dd936a4cfc81908bdd4f2a2f542b5c0a0e691ad2bfd833\",\"code\":\"import numpy as np\\r\\nimport matplotlib.pyplot as plt\\r\\n\\r\\n# Data\\r\\nx = np.linspace(-5, 5, 1001)\\r\\ny = x**2\\r\\n\\r\\n# Plot\\r\\nfig, ax = plt.subplots(figsize=(6, 4))\\r\\nax.plot(x, y, label='y = x^2', color='#1f77b4')\\r\\nxi = np.arange(-5, 6)\\r\\nyi = xi**2\\r\\nax.scatter(xi, yi, color='#d62728', s=30, zorder=3, label='integer points')\\r\\n\\r\\nax.set_xlabel('x')\\r\\nax.set_ylabel('y')\\r\\nax.set_title('Parabola y = x^2 for x in [-5, 5]')\\r\\nax.grid(True, alpha=0.3)\\r\\nax.set_xlim(-5, 5)\\r\\nax.set_ylim(0, 26)\\r\\nax.legend()\\r\\n\\r\\nplt.tight_layout()\\r\\n\\r\\n# Save image\\r\\nout_path = '/mnt/data/y_eq_x_squared_plot.png'\\r\\nfig.savefig(out_path, dpi=200)\\r\\n\\r\\nout_path\"}", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='df0d78', ), id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', ), BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed', 'logs': ["'/mnt/data/y_eq_x_squared_plot.png'"]}, tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', timestamp=IsDatetime(), provider_name='openai', ), TextPart( content=IsStr(), id='msg_06c1a26fd89d07f20068dd937ecbd48197bd91dc501bd4a4d4', ), ], usage=RequestUsage(input_tokens=2772, output_tokens=1166, details={'reasoning_tokens': 896}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_06c1a26fd89d07f20068dd9367869c819788cb28e6f19eff9b', finish_reason='stop', ), ] ) assert event_parts == snapshot( [ PartStartEvent( index=0, part=ThinkingPart( content='', id='rs_06c1a26fd89d07f20068dd936ae09c8197b90141e9bf8c36b1', signature=IsStr(), provider_name='openai', ), ), PartEndEvent( index=0, part=ThinkingPart( content='', id='rs_06c1a26fd89d07f20068dd936ae09c8197b90141e9bf8c36b1', signature='gAAAAABo3ZN28TIB2hESP9n7FpWJJ4vj1KEPIVHYTNh64J3S9rOSRfmmTK_uSNB79wwlv3ur6X9Yl9sPe6moHK4nud8jgeScuOeCDq70JGXZ6xH_NBdiDWzeMis1WIDsyJrADdADGQRhjb8sXi6lz3nNvjeqXD-oZJkxTJ9FeJsCNNPBHX-ZYRIYZ7vGKLPfmi5qNS7V6VVGvwEWOBwW75ptObu5E8g2TqhPlUzsVoZsIZiczRXq6zQpDtMPAtv6Mz8puaq-o65P5-vZMywmEjyi0Dd2M9ozUfhWfhpEhCsAiItesA802-TSBQCKeP62riRAMJvfD3PEGLYL9d_7mUvJYSsiOADU0K6wfI6y8bRL-UaWUvn60KfPvqfBFm9-hwP1NS77OKoZABIuGz5sc3BuAh6ebKrJkfNHq7W0BA09S2gt3wLPzflpVl-wJ74L9UGnaKpmG3XRFogff_SNgDhO0_Cb4-1PYJi2NpqnCwTG2c8EFxXiP4trdynbpgRD5hKDj65FU46cBjR0g00bCShqwsseAzw_lAxbawcjF0zmAyz68Km2jCRKHRGgeMpbT-YQWs04IizKYsWfF-8pXX2vwSqk3Kb51OysuPN0K3gihF9v2tPnK2qFzkvNics__CDabCmafEKQlLp6TDRc5RY4ZcSHNwUM_dybJStzoH6qed1GQNt05wBhDZg39N7pJ8_dG7wXCSGHY5CRORZm19UGTd9DoZMzr8JmtxmRgJoKCHW_gavpt4__zifPVxqLUWj6GBaQRT8pR_Tym27HcsC0GbHLR1nel9hC6RzydTU5y7LWY_NoGUE4WZX5rHe5t73lFNSMwd9-6i9Qlj60_rBZ5z9oTAl_Ksywgo68AG7dFdSeI3VLnOyzhqeePn0ywaMp3HqO-FIXW3fjqtM2XMMMMn2Cje5rZhJ9JNmMqnxpltITkVdHMo7Yr1WFTkwLByEOb3M4LCq5B3dM1s1pVmqWAc9YNjpB7Fbi6fG90EAYFNEM4ubOE7y2d5E4hco0MbEKg-Fh0ubh1I2Y1kthZFEmPQLm6fFaljJKPtYojEZZ2cZ7sN3UaVg8Zpf3A7WS9kM2--lL5LuBnVDebf8Xrzv9dTmJvOtwWzJsY4RxWdnzfl_ZokHmg_HDNbeZpHsVI0gqHGr7YTlFJ0NUXW9mzZMx9e_VTrrf34XwRue3xVCqzsspRMjMIlAoDp0Rp0L2tJWAbKs_btqVpqjz8p-64CzSRq65BmSP6i86G0cJ9WLSD3gL3wR-Zt2HyvUvecHVmgKhXgY3F-RchYRO7TarJgyZY5bP2EEpHUwSWx4uWjYfzXMGYn8gNwgwl89qog-inK88qSG0DbqJQPwYNuRjS7Mu01O6eV39Zu7Njsn2io-kPc5HLRrbbhN7qCSki8yPWE_7yPtbIKlwWKOlEYx8_SGgE7waBFRem7ElsE9wvCX5KknilmN5_d9L4Sos0oT5NHAhApvVVDcygz9VGYBAmWfMOynDnOiTIpsAdjHmuZG7GJNAtUEYx7U7pNqbD2FJMIeN0L-3uqhxisRzeX64JZkVHWYL8HjeC1zHiUMZXKW1KXIvIU2_BCtqay22FtBskeMXZAReKhv3eX2oQlWL2Ps9VOk2imzjqBbFLzJgDq0iFoaHdOXGqo54GYZIxfWi10uo65s-3gOGmqPPE02FHEMjK7VHFjMh91FPhh8TmpWjOfa9QEcpEHSZJ6ipUMTVfRHHHshB6Sb74x-Jfr6Ioq2RnWd3E32GpE3kd1poqOssBi5jCqsA86tIMt0m8p_CDu_ANvMNKTiGTQdejm2rUhccpdbp8uLBPnqWxyGOCTlREglHPeh2EzjEMbtIaFp2NhHE6UlJ_nw40CDa5PA7C4lgUkn-4KtPy6rSaMu0mWM4vPO-5ksdtB3E5PkCdIB8j7htbhZH_MTv9RL7loDNkRVlJRSBiAC_qCGgVPyP4l1w4imdey-_HuVCKBD2vaXUz2l2efn-jLSlhty5vBOR-kr0EsU02_NYZtOKgBR1zIslAlnhM8lTxJWH4osSXHa4fIx9O9tyALjvxhooYww_Die_8iCH4u5cF53z3mvoK3Knzeada3jglwQyL3_uUQegcFKpvZwVAcguVMvrsbNgdR9VeKmYq8U7yBvziP-_vpj1UZcf3QxlNK_oOgDg9lxP3vsSKzxliW422svFDiyPkWPh1DWmry1xBD4Pldemf8OEvgSHSDAlegWoBnfOHljDcPf6kT0PaC-jHrKn8t1cQgWk1-1oxiW4zKIlKGoRvmo4lCcUfqGXb5EPuZM1qRFWxv4roAVoxdLV0Pz53L_Q-grQWvbKH_Rl6Dw1BysU55Klt8vn_XBL5Zw_UlbT9FrszDRjJ56F7zElzqVYunI5uJaPWTwQyO-4dvM94CqiUU59iFkfZqaSulYktZrgZeXe0lw59ecQnL_pR2xwkialTgDoqtPksIjTuWVzkiW9hIL5t9sHyCdJ9nqmwZRZU-JuTPXswmrJEJ23GhvtH9kWsswLd0qvmY5mV3cwr7hlFNWEf8_5e3LoCa9uHQgIa0uquekJ3St9dLOXpkcRv74nCpxkcjems_2ZC71DRU63NILFjKC5ffsUPOZ4NfevDMUDbYHdeyVV6E2f-_1yMYCWI_sws69fWQkWUIv33hk7Gm55NaNgLD4RYCUBTO7v1FtEZiVYAU5ab7NvvnTJ3FaEHo9G9eTzN1I_MmPzqlYX539YF_DDedh0ThnSoJl7PYD-7LhRRG1215KmsTWbqDGmtTsHePAVRSh464XHgiZ6cNPNogtMl4ym6r6nsMbzFP2krBR1f-u0tHfQFxAeLyBWij01Z1WBz4GBh3bpdLrB85AlvFeY7R46PPydAHxwwanYVyxpS0UmS7Y2S37EVRdFzai1izvoy3-wA05YKcnRiUKR-oMcLf-BmB3HHZnY77YOuqQBUZNI7OR8B6lvTARQuoJbK26ONmXEsH-VoBJR7C-hNiXMVh1jHfhuaBAj6Dg9g1Vs2kGxfoJUXB5dlFmR42mnyGcT96N8ZAIdIoQSrBzai6bQbuvOb3OAcG2lEhOZHZiwFRCzpHMfu5dctZ_wcTUhYZwgOcBNIo4WELyjv0Yx22AHSHcrUzFezOwibs-heUF_ciKWkGv9OaabaAGTaTVncfCnS7rOcD3Xum89EAVegpYiQzK0DZ_VKooPoddgHs6diYOEn4iJyvE54vaVi72NAy0Tf9poRlidKaM009FImefEtZqwD1MmaeVbjcClv5Xwyh-KCQ2hCZmrnJ2P_e0bWIsE0MAJOK8iU6Q3zxbntbZAQAKZHqqauT8kkRYxk6oBicV5BS-whqDN_GoNZrnRLTNkjk1a8mnqg_kucvC1mCQRbvP367DYqZGuAd2EQWVLSBQibHoVIUcYAFbsfRHfsQ-uiZVZsjZ-xGM-ZcTzCJ6p-hFi9IQXKqOioM_xzRl4TSY-AEbGja_RY0puxi8BeZXvSxx8eYsJ0TRtIIQwloZzKpbx1OwyK-Ibfj01PU5NIurJL10PKXcnc7ImXN-b_p8wfzEVN12lSbQ8m-Rs0tx32jfvviXyHtWYfHuNqP0eL3Xjuka6FGnuDOeOAIzy4xj1vqhXd8UN2tiFOObl4Rza5pKzF-0IcEsKX36v4iN8oYxOoCxCxLwvFw3znYiAKe6CVky4e46LxZOI3bGM6MSrypwblPMA2gC_ogfMiYViJe8gsgld9UvgQaFfj0EEgfc0BWfxVw2i6Yv3OcH3T1jaHnCVgvcDpTXI4-ZeeWKl6fhH9ukYAG4-Y2mGiJhxJ7cjSg8CwU0KDmNRwoXGB2FT0bKWovkcFYM5ueMbXFTZ4FFcgfWcOzXFZka82HFB_iqD1XvOYMFQNiz3jdtuOr8o66rtCVAjJnuoTQDmbSrWPU0-utUMJx-4QAlZM8hdtXGfNBp0JRxctMZdxR4BAzF7JH_ETYi3itZkgDLEs9JBdty6gUiM0NdR6F_7mxsHCik3rpb5bauJKP89gV03mnBQuSUQTauNxdzXqw55SPDAHMBWg8QwyffzWwmyTAjl_R1QiFsTOv31U-HditYAeYMhLAP0mIs97T0inLsTUri1s2b1s7j6-I-NLXuT4VKiBO8lqVicTbQdQwiXehHQsi18e0H6T9XM0xBQK2t1dd4Jz2oLUGroSB3XuNbcaaxsffqRQgk43KIMEw9VsUA3FOTEpdM_xYIYEFM_-ApjDQJ15JyMRspfmu7HDdd-ybcXZ-C8WASJUPV8tFEfP4xgUcZeu-mExkryebbdMExq78yj7GlwWaeqBYfEXsvG6FIOqL9iFVcc3iIelrly0oM_xJmLOB_CCkGylDmHLxZZydf5v0RDh0KOXd7J-QYepcALXYoXmToj2JPrJPkaznH-2tI5xwp_M-mktoYNOhWrOepFjceXDSF5G5ILomGd9mHLnkq514ayZJCeE437I2geH4s6upgSAaqc07IVvdU3WjorhBw9fvefI5NnYwMiUSk_LC-JiQZDJ0bMLttvwKDx0TmOnMDJqxDr06_MWXn3i0zLQlAjItS2foksr6EMeK2InZznVZtgjcbD0exqZuzjCAqKz4PLQl62xyuJx8trJe0uHbQk-NweJthN5xcj41kJTcDuXbA1bA9HerCBWMX0RW3RXAKTvltGaqyMyUsJ_uOb40D0m56SqOmxnyA-mauiV2R11KC5Hh7YSS587NxkWUx2t7G9uio6WgWyx-HvhXYVi8wejyZw51z70YEa-aUDS2G_N0e6BV2B6dMGyd3lzTkMY6Ncs127IwQmXkV4VGL0stfchFf7rhXc1CZmFm7NZOMQPgb3_Heb39gZfMa4EYUVLuvfSpuM8wHZcQa57_uj6wmGp7NBBVpcgTee9ADvJXxjlmAj6gm9TiCl_GYbBLCdoTRAgsgsy1r4WijYr2sA_zch6EbDpTjQy6ER5GINZ4zi0VDy9avZcxhGmOEHYvKzcLB5PANOAW-8FLFHGgDWvf0cEMCD0UpSLAJVIX6rMjMJC3N_cgWmmv_zbllaW-vDVNFPyZOW32zU-l7r46_5IuF9Vc5choUlWOGLADSnXReau9WC4rfGF05CAvLe5Q0dex4K14SHJTEJuBWhGTaaXzONQSGtU9LJexoI1ijcnz9X59VvXxFX0oHmLvgTAim6nN96X5kllHFvrdDjMOiZKQTXtodUI-3ZcjfA5booJk7tnFeni0H2L1sqvpGy8JDlfl0fds8hST0vtXscfD5jDC-i6btLnRgpOpRDQMebCkqRlisZScBXb0nxoHK7CHtnQy4aCQq4oCBgMXdbwHOnbBygBSAg-HCpK53YoT-R5NUdESGmGCX5uJ0qlmGaXSshFbNW_NpQItJIrD7NW3VmqfWvSB1VL-nyVLOmc_wPmUhY7dSGArYKYQFKL4cBOSfHHHuftrRXy356_mTcDeFsHzqH3RXPaXhiad_lmQ9Bcw0OD_BotHvYfvVCaETpweH3eHl3RPBiUHlc5Da4nprHbXrvQL675qwVLiwLwOvPULU4VdGU-jIfSMkRUbJhSt349C1poj4aM-aD3s5iJy-3YDRYzmqMmFFr9CoKMah6hmn6n0oKSwg0YpLOc9JRDhBfp87_NNsWdRkpNw_DC7OaIF6VNxc6o2t9jExqmAiAbyRSkW2x-UiZl6kbB3uqffgAYWNylgJDZ-UPQNki30zURQFl1anKa8xhIGOgH7piVerG2LO8X7pFxa3DlYxFm37HC6irFtBwsFbvNGicua6MfUD3dV2MhE9x-sOlG9O08DKObUwBTpTzfAe-P_jGWHnyOsLXbaiV_cwxgWkEw9rKuFpI1SPuPrdO8_iSYdH36TqIREPLVbRcSJvHrsWP2Bf-Bb04SIonHV4Olu9KEYWVCOltRx7JFjp3eVQZLAGwjtxG_vDlublMpybM6TZdg1UYaCU4ZqLKss3iWO3wBNwC2usITNSjaiiLSH96fOHpAyXMhhodFDS9X-frLB46hilqE3PwoIyiR5R1dAdM7oiWa5qD6KH_dISw5H-uO6ZrUFo6i14E4RcCtRBBKALvVnApLxA_lcpnFR9_TZkstK-6klIEiSttNhxhHhv36XJw_J6jUTHnxRBr4JyXLL3-NmDZy8mplsbS4OXl7gg0vuIOBBHarKFvCEdvZv8ikxbDeftTz2je9mrCNCAHKTeNQWKf7Q7HFfPcza_BwhSqrd64DndvGVkfLlYBrbVSZp5nxPF13qBWIw9bbXTU5z8Wna72Lh4HqL-cUDsKbKBpst1VuBgaA7Va', provider_name='openai', ), next_part_kind='builtin-tool-call', ), PartStartEvent( index=1, part=BuiltinToolCallPart( tool_name='code_execution', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', provider_name='openai', ), previous_part_kind='thinking', ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='{"container_id":"cntr_68dd936a4cfc81908bdd4f2a2f542b5c0a0e691ad2bfd833","code":"', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='import', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' numpy', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' as', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' np', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='import', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' matplotlib', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.pyplot', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' as', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' plt', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='\\r\\n\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='#', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' Data', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='x', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' =', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' np', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.linspace', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(-', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='5', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' ', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='5', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' ', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='100', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='1', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=')\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='y', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' =', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' x', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='**', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='2', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='\\r\\n\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='#', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' Plot', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='fig', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' =', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' plt', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.subplots', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(figsize', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='=(', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='6', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' ', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='4', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='))\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.plot', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(x', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' y', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' label', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="='", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='y', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' =', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' x', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='^', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='2', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="',", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' color', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="='#", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='1', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='f', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='77', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='b', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='4', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="')\\r\\n", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='xi', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' =', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' np', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.arange', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(-', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='5', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' ', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='6', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=')\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='yi', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' =', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' xi', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='**', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='2', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.scatter', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(x', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='i', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' yi', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' color', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="='#", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='d', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='627', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='28', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="',", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' s', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='=', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='30', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' z', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='order', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='=', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='3', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' label', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="='", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='integer', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' points', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="')\\r\\n\\r\\n", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.set', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_xlabel', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="('", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='x', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="')\\r\\n", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.set', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_ylabel', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="('", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='y', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="')\\r\\n", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.set', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_title', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="('", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='Par', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ab', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ola', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' y', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' =', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' x', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='^', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='2', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' for', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' x', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' in', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' [-', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='5', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' ', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='5', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=']', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="')\\r\\n", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.grid', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(True', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' alpha', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='=', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='0', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='3', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=')\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.set', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_xlim', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(-', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='5', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' ', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='5', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=')\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.set', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_ylim', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='0', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' ', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='26', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=')\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='ax', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.legend', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='()\\r\\n\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='plt', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.tight', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_layout', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='()\\r\\n\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='#', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' Save', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' image', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='out', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_path', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' =', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=" '/", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='mnt', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='/data', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='/y', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_eq', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_x', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_squared', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_plot', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.png', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta="'\\r\\n", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='fig', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='.savefig', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='(out', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_path', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=',', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=' dpi', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='=', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='200', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta=')\\r\\n\\r\\n', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='out', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='_path', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartDeltaEvent( index=1, delta=ToolCallPartDelta( args_delta='"}', tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7' ), ), PartEndEvent( index=1, part=BuiltinToolCallPart( tool_name='code_execution', args="{\"container_id\":\"cntr_68dd936a4cfc81908bdd4f2a2f542b5c0a0e691ad2bfd833\",\"code\":\"import numpy as np\\r\\nimport matplotlib.pyplot as plt\\r\\n\\r\\n# Data\\r\\nx = np.linspace(-5, 5, 1001)\\r\\ny = x**2\\r\\n\\r\\n# Plot\\r\\nfig, ax = plt.subplots(figsize=(6, 4))\\r\\nax.plot(x, y, label='y = x^2', color='#1f77b4')\\r\\nxi = np.arange(-5, 6)\\r\\nyi = xi**2\\r\\nax.scatter(xi, yi, color='#d62728', s=30, zorder=3, label='integer points')\\r\\n\\r\\nax.set_xlabel('x')\\r\\nax.set_ylabel('y')\\r\\nax.set_title('Parabola y = x^2 for x in [-5, 5]')\\r\\nax.grid(True, alpha=0.3)\\r\\nax.set_xlim(-5, 5)\\r\\nax.set_ylim(0, 26)\\r\\nax.legend()\\r\\n\\r\\nplt.tight_layout()\\r\\n\\r\\n# Save image\\r\\nout_path = '/mnt/data/y_eq_x_squared_plot.png'\\r\\nfig.savefig(out_path, dpi=200)\\r\\n\\r\\nout_path\"}", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', provider_name='openai', ), next_part_kind='file', ), PartStartEvent( index=2, part=FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', ), id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', ), previous_part_kind='builtin-tool-call', ), FinalResultEvent(tool_name=None, tool_call_id=None), PartStartEvent( index=3, part=BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed', 'logs': ["'/mnt/data/y_eq_x_squared_plot.png'"]}, tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', timestamp=IsDatetime(), provider_name='openai', ), previous_part_kind='file', ), PartStartEvent( index=4, part=TextPart(content='Here', id='msg_06c1a26fd89d07f20068dd937ecbd48197bd91dc501bd4a4d4'), previous_part_kind='builtin-tool-return', ), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=IsStr())), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' the')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' chart')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' of')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' y')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' =')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' x')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='^')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='2')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' for')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' x')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' from')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' -')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='5')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' to')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' ')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='5')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='.')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' \n')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='Download')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' the')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' image')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=':')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' [')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='Download')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' the')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=' chart')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='](')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='sandbox')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=':/')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='mnt')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='/data')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='/y')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='_eq')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='_x')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='_squared')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='_plot')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta='.png')), PartDeltaEvent(index=4, delta=TextPartDelta(content_delta=')')), PartEndEvent( index=4, part=TextPart( content=IsStr(), id='msg_06c1a26fd89d07f20068dd937ecbd48197bd91dc501bd4a4d4', ), ), BuiltinToolCallEvent( # pyright: ignore[reportDeprecated] part=BuiltinToolCallPart( tool_name='code_execution', args="{\"container_id\":\"cntr_68dd936a4cfc81908bdd4f2a2f542b5c0a0e691ad2bfd833\",\"code\":\"import numpy as np\\r\\nimport matplotlib.pyplot as plt\\r\\n\\r\\n# Data\\r\\nx = np.linspace(-5, 5, 1001)\\r\\ny = x**2\\r\\n\\r\\n# Plot\\r\\nfig, ax = plt.subplots(figsize=(6, 4))\\r\\nax.plot(x, y, label='y = x^2', color='#1f77b4')\\r\\nxi = np.arange(-5, 6)\\r\\nyi = xi**2\\r\\nax.scatter(xi, yi, color='#d62728', s=30, zorder=3, label='integer points')\\r\\n\\r\\nax.set_xlabel('x')\\r\\nax.set_ylabel('y')\\r\\nax.set_title('Parabola y = x^2 for x in [-5, 5]')\\r\\nax.grid(True, alpha=0.3)\\r\\nax.set_xlim(-5, 5)\\r\\nax.set_ylim(0, 26)\\r\\nax.legend()\\r\\n\\r\\nplt.tight_layout()\\r\\n\\r\\n# Save image\\r\\nout_path = '/mnt/data/y_eq_x_squared_plot.png'\\r\\nfig.savefig(out_path, dpi=200)\\r\\n\\r\\nout_path\"}", tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', provider_name='openai', ) ), BuiltinToolResultEvent( # pyright: ignore[reportDeprecated] result=BuiltinToolReturnPart( tool_name='code_execution', content={'status': 'completed', 'logs': ["'/mnt/data/y_eq_x_squared_plot.png'"]}, tool_call_id='ci_06c1a26fd89d07f20068dd937636948197b6c45865da36d8f7', timestamp=IsDatetime(), provider_name='openai', ) ), ] ) async def test_openai_responses_image_generation(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, output_type=BinaryImage) result = await agent.run('Generate an image of an axolotl.') messages = result.all_messages() assert result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='68b13f', ) ) assert messages == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Generate an image of an axolotl.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_68cdc3d72da88191a5af3bc08ac54aad08537600f5445fc6', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_68cdc3ed36dc8191b543d16151961f8e08537600f5445fc6', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='68b13f', ), id='ig_68cdc3ed36dc8191b543d16151961f8e08537600f5445fc6', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1536x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_68cdc3ed36dc8191b543d16151961f8e08537600f5445fc6', timestamp=IsDatetime(), provider_name='openai', ), TextPart(content='', id='msg_68cdc42eae2c81918eeacdbceb60d7fa08537600f5445fc6'), ], usage=RequestUsage( input_tokens=2746, cache_read_tokens=1664, output_tokens=1106, details={'reasoning_tokens': 960}, ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id=IsStr(), finish_reason='stop', ), ] ) result = await agent.run('Now give it a sombrero.', message_history=messages) assert result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='2b4fea', ) ) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Now give it a sombrero.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_68cdc4311c948191a7fb4cb3e04f12f508537600f5445fc6', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_68cdc46a3bc881919771488b1795a68908537600f5445fc6', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='2b4fea', ), id='ig_68cdc46a3bc881919771488b1795a68908537600f5445fc6', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1536x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_68cdc46a3bc881919771488b1795a68908537600f5445fc6', timestamp=IsDatetime(), provider_name='openai', ), TextPart(content='', id='msg_68cdc4c5951c8191ace8044f1e89571508537600f5445fc6'), ], usage=RequestUsage( input_tokens=2804, cache_read_tokens=1280, output_tokens=792, details={'reasoning_tokens': 576}, ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id=IsStr(), finish_reason='stop', ), ] ) async def test_openai_responses_image_generation_stream(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model, output_type=BinaryImage) async with agent.run_stream('Generate an image of an axolotl') as result: assert await result.get_output() == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='be46a2', ) ) event_parts: list[Any] = [] async with agent.iter(user_prompt='Generate an image of an axolotl.') as agent_run: async for node in agent_run: if Agent.is_model_request_node(node) or Agent.is_call_tools_node(node): async with node.stream(agent_run.ctx) as request_stream: async for event in request_stream: event_parts.append(event) assert agent_run.result is not None assert agent_run.result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='69eaa4', ) ) assert agent_run.result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Generate an image of an axolotl.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_00d13c4dbac420df0068dd91a321d8819faab4a11031f79355', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='69eaa4', ), id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1536', 'revised_prompt': IsStr(), }, tool_call_id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', timestamp=IsDatetime(), provider_name='openai', ), ], usage=RequestUsage( input_tokens=1588, output_tokens=1114, details={'reasoning_tokens': 960}, ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id=IsStr(), finish_reason='stop', ), ] ) assert event_parts == snapshot( [ PartStartEvent( index=0, part=ThinkingPart( content='', id='rs_00d13c4dbac420df0068dd91a321d8819faab4a11031f79355', signature=IsStr(), provider_name='openai', ), ), PartEndEvent( index=0, part=ThinkingPart( content='', id='rs_00d13c4dbac420df0068dd91a321d8819faab4a11031f79355', signature='gAAAAABo3ZGveBi351h31WQM2aG_dbN1N74J4X3Lf1SbUrUhElKaT5odbh4N1liwG5Hjip3Ci1illQSsd4n035fOOIV3sZzAMvV3ypncux4WDBpQ9NbeuFMNSyNOPTxJLg4j66UbW2ptw3u1VP3j0vCHvV5MoDhErheYZsWKhYVtkUNkKSVLWkS_yK0pOltSwHfRy3tbrkxnqD99BuVbCjV1nWSzTAmJLicBtjDaH0NjjD_vMyFiUe83-eZRs-Q_6njWasZNCmTcOq4zlpFoJ_AGeaTbaLIC1OwDV3sNT7pXvo7YI7jmsYEhHAKa8BjZmMjzBPLDRu9TMWtXMnO6nyVYqMxsyQPdNmP-BDNfr_8Rmo_uI5egfE0qRKgAc5MrOGd1fSgtUqeKah3kbLMyCD0_-jWmVInb2Y4LfPcX0iOeTGum2IRKwy6G1tdY8C_gEOnIGAUKOT2sEF98Ythy9auV27BCbcjfCBJlH0rOir_OiQjUIXZqqY0My1kVENBbXj2-VIFIqG-CcxCldFG2Mq0NGo86h1igQIFmLItXLPTS_QnaWADSD9La8JWpg8CuWg-yB3UqYaG5_f2Cl5jRDQdIYavTBvD-lp54y8aEnGA6HksQaCtB7jHX0ZM0pqYu7LvLjeHxAJWsnF4NN0HPz3d307muS0TtrXUxqeZFdTNoqdBOxfuJ2-Ym_LmeubnEzh5wHAguJKZ6S_jcEFM3Jdb1R8Gk9dv2y7BUz1hKSFF7peXc9Ear00JjPHAlR1x0ECqONTSD9Kda80pQlDSh05ITKQ2viOy1jmCsWeSsll6EJPcGEMfAcZ1UMgHYX3sBa5Oz3DS28Ur8yk-I62nUWbcj8n7IsZmZL0CWc2qgCtj2TzFZaVEx8iumUKpU0hmML_kF3JPH2Ie8nB1ko18HZV7A_-n9XGDZzwsfPD9pu4P-fb68KNqU_qQBfe8msYvuFuljC-0kyGrQIQH2X6stwEkyme1TuJfxIZ2t2q2l02gEUVN8LN8qX98hp7DBxXepgdKvqWVOM7icvtW0mPACf1b4izSDqEgqhqx4tNsjixoHcM9M8awzss_y2_jZ3V7gY3pbPgwWKHyyTUzA1ogPfMkjxxUrVLNyHRPmnklUeQdV-vytip3BzNOq4yTUz7jVFrudSDcr_KM6Ie806OkgKF81l-W-40qzx6bGg2DAcZf5hfbTzk-ho51sRBwDp7RJrx2SXSBGXA3ArYzgq-2iat368uDLiQhhbunzKm3_6CFWggpbUO8Kp3FP7-k4Z4CRbHkg8WVT0HhH6w0ysoi-P6_ZH-IKI7XG-GT1kq4yje3qlfRUT0-0_LPsr8LyM6AbOYj4NiWHP3XJ2qa978VVOLJQtY-qG3VX9kMq13C-uU8PDOsOEidYZl2gqFtXhxkXivwACbLMnvzJayXJRev1QkoNxIg1Stl9II4D_ndHfNYeAvMvOnSNafoCOmMzCBp1klovMP_31YvR2B3af1TYanbbHoJt2UR1GRR_Aqr7G6RukNkXAl63LPlDQSYm5BB6zD9iNX9hJ8MSZ1IFIcbM0L32tAWsyKKAEWyr9MGckicDa_hES9adeXuunqqKhUctd94J1dsXLiWCGIet57YIUj5WoF_FQ6D6FY9rB00KhCDlHr1Ot5NCMmn6y-u6TYJUhpl7elEErYGXaGPhUtKUSbAIzOXzBIAKb_MiMVvo6a2VYwsxwZV14X8TYkKw_Y7w5Wt6JA_wTOoen7Cc0eFyc7FZA4NjIMkIUOXymtjzOSkFJz1eMBqp9diET9VYKGsn6GxviD8jWM6-RCWcFurewcn4d6TeTclAt7G_LZrJ9bZtMVlieSJT-3vWr9qVt8OGBUJEJRVOzpr5FBnEceqK8s7D_s8EZwTaGwyAuuaZThy2PNWJhpE4c0UeKgh0ec36Q0ZRN8DF8Khne8Epe1rehOrsfeyFFRuQ5CDGdHimhtOAIbDyg_5PPCp8fgiU4R9xqtizCVTR4ej1VPIClmebUErOl3TN-IyoSc8rv--Vi0ATn69Q8tSPweI07KVEzRJpDtxbnGcbbilPN5_liJcQrLMf5ikaWBoq42s6FXDjr-ASD0h7IlNGHxnN8q__iO6jA9-2PTywI2bbBJsie2L7OaGGehO5zv_rWv_6rbk4HLVcQafi2nC5w1GNeDaXWSz0RjiTfXxjBh98302CQxiM-e1Lvt1Pe6Mqv-pAgXlFrSHDrqw8s4NSS2YpLDTUIOcOx8UutAJOgVpyZm2sQcvtOsGsSUBIyNI_4huseO9EuXF4TUQ-yzQRsimtXaDa6VId0y6qG7dWxTP30SWZkft2iW2_Nz_56MiioY7xACIjzo4s2aGLM352ufd4nEeU-K3UQd5hvhdIWUZn6KTyCUnqgChyIlB0Sto24VwIIj74DYisSiu-d8EYsVr5gZaQ_NaW4T7M_ZB0TJ0ptlU0X_h8uLu0ro2Vc_s7D8nkIKSzhGuuHO4lOjvZ-qLsPxG-pBa6jGvv1hOyng_x99icZ0oM7G7FmDl7SjP1pdLiZAA1hMPPU9b8Uk0j8hb4AFtfoXSfwZBQ8sYlT0_QmcSBgGxfZKXv4RcFSnAEGDNUn1V-P2uNoj06MOwzroZVjTuzVy284Hqe-08Gtt_bvZDmfsHonbEw5DrthsP9SzoC62hc6pcVs_ApQE5LwHgODxT-oejDppixNCr--hJ1IYVj4rRsHsmBv33H5kJP0rwmkdJ-I8rLj66jLf_Qu_OEh02dJqf3XSYsG7io3XCVjA-d-jUhLJSqcPS_3y5thCtWUcG_ucT64ADWdtOH0EkmzN0o7HmOJ48pkGhttNScjXlQUmOdkeBV55dTdXAzAyjKZsxP5ZK1F9m_1TMWDJX6nT4rRFrzv3PQByEyc3Rje7ZUdGa3Qky1-T5uhu1dk4ty_I92CbMDCM-jGZorhg5MX10B_zZ03DFrYTrdcDILS5i_BSOlGT8Du4aSMvwvUC5FLOYQFQdM_ZNIRIGhOSWsvObmVYh0j70YKqitDudSIm1V_Yw6qsW3ZPpLDgBju176FVDJJBn1Wx-DeQ6FrYtOjFHctqJN-2mjWQi_7lAzKbTLsB-9c4iZ4_efWXsHncmAeqvt0gvglQHDhY6cM4yZurpHkrE-lb5-vDLYamv-Du7Cs0pAaynEcbT-f3_F_WOgoXFy2WYOTt2KkSQZnW6ZPHzl3gfVOsHfAkWalMJ6vXa8FuoYfMmgZJpqtee5J6AxJaUea8xQ0VlVwuXmcK8EOPcwF1pWg8w5_SweA9jZ0fh5PaFW-BNlzGDmhRR-8Up0TCUTsdnZN7bABJBlxeQ5GEcwOjgT0UBF0_zXZo5fbk34TSDoEgfdQydVLlOGda8McmvsnNzDSq77a-Vj_8BeVacM1PPG9rp9F_-PQgpM7_7YsNoWMXha4b4_H58q7vPOvMK1zxRzNrq-sm9QhQ1LkzPgt158Gf2IPq8D3rh9YCmJvg1Ju7roShfnVdV_UO73MLnDhoqaUZEdq10723KFpescGNTRpsuWDE8qBiu58rbOzjmpy7nJfuOtfrv_qSjaFRTkShLV5PW2neHjNLlvQlWy-q3yjJXq-2zM-iRehbFIxI3ATcCq-SgThDeQ1qnTg9G0Jtsx3qBNZtCIi8x1oVsyavVJcqvo36UC-IXaXA1vpjuwER1dcZ999sP9MUnXcMTO9ba-GM3dslKvDtuZ5b8x_u7eCJfawzUPItU8iwISYKDWW8wTNOS8Iukujq3-IDOEFqmCOAlkdv6-AWNc7ZVOmyvvgDCpSN5nSkjpJhWI5kP13FJtJNHkNtP4RQkhRhwRh2ei308TvNgT8YSaa4E_BJ-QWQ_9PMNBsfAYSGIl1VaQinZF0qdvNhRIlonuZMV58aEEzsLk6hS7CGlbFwBMwAzZ5Q6PANavXDFiPGeIadxTE4r-iZLQ3CdvJWUiUv3AL3lzYraXX8BGDpEVAAIqoRYZEpR2QgIUui5b3gkCSlG-YdKqJ4HZ_6VCFqpywKsgPCX_c8pVD_6eJhgt9o5Vc0ARsfc1IG_XC-nFWOV4caiARMobX0y4qXDFulrAZInqBZ9Pq5MmbbhBmLLdT-y5fdPpB5UxsIHGqb3pip4ZaKS80IqAt8t7HPXSNza7zb1TwrjNlYcO_KhbLQBB0hMmKULnEJPWLDPKf_9NeAsN3U9AWyj1WpAKjSfpjjbXn37qpTMdgd-Js9-_FDaXDFH_aOYXI0GY1AMpvSSQzx_f6Erq4qyS5TAuAtXbvUm-iVJcHaZTIy7buGJqOUBb7BC1L33KpeQEZuCg6QyAdzn4bZUKvwjXuxNykpZA9LZWaFVdx2QfwCV_yqN2TTvLFmSj5SjldGwbBndjmtHs5kkDcV2mDlm3huEfbEJqf9sdxXaYhIfmUIkFDtYTpE1C0qSol-A6Yagtx_aNfWTL7F2lFI0OusuBwnDfkNow5mPsKqGMIqx5eJA2InLcpV7GTyCxT3BjVsggtSb1-4Zz2TYzBz7iYe8NPe-rxF6XWyHf1N0nyyCY8Y0_CqJS9OPFpsd53a6qY7xlhh1kwBOM8nJWb3OEJjMVspTUfwF90O8D9fDNS293vnG8SArU6d-1L4u0LalQbKXDRzcze8W8R3KWv1N0LXrWwfArPrO1WnpdEkJnbFfc1eUHqThJ39c7RAInK66VtNe5xtUVzuNZDfPKsIfD4Ms5xqMKEOWQt8RIciRapDo9aoWv5l-YCkuTrWp4pWP4b7eu9fizM5ZuzmRCj3Ecc7ZT2uvxe9sP045dqTH6lSeBNW1eW-pmb3oQ-g_mYL6SU60NmDp_mMa5HFuTdGSAAI9jP11k8KQUX6oGGGhx24w9seLaY98N_0v-cWsiNMQSnwR_SsGs6tPYqltHguz_azu0qsQuuXTQK9B06oEDR8tyb6CTqfX8pcumXIXC_DMFYfQ3pBK5R37G_oXTtX9srpw9vSulg4z52GhuvfT09ukMmdNGoIAS0551PjpZRz7-sI_nNTJQKpGgbhiH_zvA3U5hxue7fpAnQYXd6DYxR_y7QXSleoqQhZ2iVQW90Lwqp5MIDJaAx14bn27WBmQSLcuMpgnwpothMYFMmmNMdWYnGcQ0MIjhlOoykau7DRBFsLOKZ88y_9Pke7k9ISeTmArge2IdC1Ma7-GiJ90YVwwXDBSs9ssae8F1kWgyYV9rFxNbpF4uiWdQkVvASmW-QUNWzsHAtfuvrt-TR1SQ1Z-mMP_zF8mVjC14pAP5Z4pYkolLBinwy9V7DjcN0kymIM6fwpLt2h0LgfC1eLK3sutJcJJP9fFd8tTLIskEvUly-TeEct-syQebPxjxpxae7UPmqeDrOtvPi8-JWiHeIoJrUQnnw3ik2ULXvX1VFSnzDcKBAs_xZzdtjRlCGZWD-hgPPRTmG-YWeyovXZDp5Wv06AEL-hJlk4z1ZEt3yA0H6Ni7zE8jQ0_c6zJCWk6YtPhFk0ARZfjjdYSOFwJvx6rIrteH39b5W1yE8X0bm_cdeA1Q6TluBBkwv-9liCSOGT4ctzwaK3-cb0b4ko_apEEtpYkevu2ulqZoFi1S9g1joFZ5ooBLpxYGntuXXbALvq-zZniOJOtTdbpgsFQPS6Ae9kWXddWChNeyv_CEdkwXCkM__ua4GiH_Ce9WlqCzDCEoCYFpr7PyJP3gNg9Q_vkiLQa9V9bc3VtA5z4cjWB3rU5X9fLDZ0xzwO9krtGmsK9r2gkENMMu5Yy5BxGo94n6wRef0eMY6_GTzi7QsRuQSqNQLa98UdN4QGDa2c_-uDpENkMya7_hgM1z_RyUGtqVgpCHrld-jfSIGLPUI6kKWUDZ3USldXuep47KNuO3-BEOP2QEAKgHVlS9g2viG5r6wdeMl7Njs6iMsjs1KnHaqHlfZww8egAuOxAJjFxUYPy5djKn8n5lgPdk9ISeMZfxW5LcP80kPQekLohUbHcJ_JC2rTI76ckZvwuEGDUQTwGHR0B7YonoiTVzrhOWeqndwk3EBp0cr2mIc8vsWANK1WechMxunFVn7RuwV926PZhqFrnoep4ytDP8h4nJ4Z5zr9cXQCDv624H3JdPUYBBoxJ_7-QDM0fpuFXuRArtuezy6PV0a21CHLFtNq3DCWp56o4xgGm8x_8r2NtKTXxSwUY4_5cBHWd80aXF84Z42ldtGkAXayyFsv5er4VvWTzjwfEc39qkUGDQ5feVJb3YhfsT2qFyUnhb167hdJIPkI8rud4vLu3e9eu6xNLcw-LEjHptgEtfxOqiAPrBZLfWgkhfpU-encYtxg9cing8f_bAkf4-sP1tEaczGkdkMD-0orT-aN46m-8Dyn82fQgQdvov6n7KIuQipYomIQ3mJh5mSl2BAGMFlvLY297s3dCkBD3pGbRb6AAqu-5l8yCCVtg7FvzUWoQ3gL8FcP2cK_fYoJf7Z2YbgTNI_5SHiaAb-qxWuIP8ICEsxCHJJWIOfL6UnBXXctp8B_TiSbOFfGFrQPTJDUvKPyN9_mzO4mzXlOXLXu2VRG9J4NMSYTJT6-Q269vzse4SGqnULEUnpm2zQz9b9W97ahoMFYfV8xaVeFZK5ZU8LpyaN6v4mOJuuHm_vZuVircckh7UVVEK67jvRMi5JcKv-hDQhy1EmSRNCiZ4WHmGi7wcLEcJaUVFBRi84nU50Gjjs2kTslgVAnR9MyGqL2N4xvTAjoi4o-SCvDIvgWDnRCHXSD6ghfQagEUVGldGzk3EKEQF7VO5KTdheZ9FDiSXaaJJKit9NnohzmxM651VFC-AW0Ghklj52C5yvHScmJrIpMv4IjFAKj7erMRDjvYJ0v0PZDE0guTvoUFHrZd6umnB68QFINJogoy5GeT1hUs87OjZVQzPrxZqO6rzJK9m3meI2dFvdbgyAdbUx7fJRAu4yf2LC4dh0QaS5z24wuND3y-jHEsOvjUyIklRGeoH8EdGTBI8ZJIYKXJ8Ow797VYFI3FBzKNiPxJH-VFjpw0aqTLXVrAvCxwVK3awVAoWpwWMHN5yT57TOn3kpAbnBdAXG80kwTuOAAagePIVGrzENRGWVPGhvBFi55TDrQFXyymCP6c5q01KY04VU0udmOSe2Bwd-jMk2pjT3CLHb95G4PUVgy-l-occtk0mNRX4k3P9ETjeyOuA05c2rzMDthoHcFUnMqofePnvVK3eliJjh1uoNOrbx1rJuGsDZFEGxUfkjc5z5BW9zVw5YS7mlXjACPSDgMgreTTygsKTL0xhvSPsmu18K-cGz19v8ho7ix5B1WmPDsL75qXEqKsiO0ry1Ka23z8c4omngareIMqyM6OANeslUhQ7M_4o-OSaHUKQ3kAmJ3c_iPpedZUCo8GALcrgifqgd_ckfBRBpYssZhFQkxPNKJZhncuoRkdjxeAzANinaBUCxZ-Bg5DRQI6GCHgzUiUFMIWEqi21FF5UEiq0G2PM7PTE-RRO7wu8qg==', provider_name='openai', ), next_part_kind='builtin-tool-call', ), PartStartEvent( index=1, part=BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', provider_name='openai', ), previous_part_kind='thinking', ), PartEndEvent( index=1, part=BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', provider_name='openai', ), next_part_kind='file', ), PartStartEvent( index=2, part=FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', ), id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', ), previous_part_kind='builtin-tool-call', ), FinalResultEvent(tool_name=None, tool_call_id=None), PartStartEvent( index=2, part=FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='69eaa4', ), id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', ), previous_part_kind='file', ), PartStartEvent( index=3, part=BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1536', 'revised_prompt': IsStr(), }, tool_call_id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', timestamp=IsDatetime(), provider_name='openai', ), previous_part_kind='file', ), BuiltinToolCallEvent( # pyright: ignore[reportDeprecated] part=BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', provider_name='openai', ) ), BuiltinToolResultEvent( # pyright: ignore[reportDeprecated] result=BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1536', 'revised_prompt': IsStr(), }, tool_call_id='ig_00d13c4dbac420df0068dd91af3070819f86da82a11b9239c2', timestamp=IsDatetime(), provider_name='openai', ) ), ] ) async def test_openai_responses_image_generation_tool_without_image_output( allow_model_requests: None, openai_api_key: str ): model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, builtin_tools=[ImageGenerationTool()]) with capture_run_messages() as messages: with pytest.raises( UnexpectedModelBehavior, match=re.escape('Exceeded maximum retries (1) for output validation') ): await agent.run('Generate an image of an axolotl.') assert messages == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Generate an image of an axolotl.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_68cdec207364819f94cc61029ed4e1d2079003437d26d0c0', signature='gAAAAABozexg98F3au1443vbazt85gDycVpBeC63gC3bUrFg_jpx3BYCksfaKwRkdFirkKpRHBYG1go0Kbzl_1w7ZqwT-BcPYX1Q7a--X9S-5OvU43ikr2kPbJgGhjWv1W37aLPKfIFOvt0VspdWlN3Diq6u67ktR0R0BXOFuSSv7WQmRAIl2JxiDzquSCb12Uc6i61LxNLpzalYk9lyW4Nm5c4czAsbUNv22AeTsB-nwWzO9NJyPfe6cVybz5gdShl8lKIvBsjHMonyiZqqzuSZakXSlbteA8yvZmOYO9XT1ruXNhCoFnq4pNuMHiZuOyCSIvASPUebLO9Q9uMv-t2aKku_4Xg4VsNUuQQpJfZ_gqYJyZFmANBTAcbMGBVotJS0V0ZkO9kyM9W99udKPuS-IzAkPCiHuBsjMaQzhM9xA2-uNm169O4P6TfqD65iCYAMLvwZbXauC6etI17If_731Oo0k4qcR5G7vruSd_Om-vwAGmb0u3_FNcI73bNw4WkhfGdUucfquaGIBkSm2_H63SOfLHOiLsnLIZT1QkEm2k2LP6O57WHAE3H1Rd1nKkw7GQcY-oQlF9_AGi_okM_nCNf7RXzfEocRYXlkSwoJT67TGV_rp1aSzhxKgzOzntDlcOT4FdyVY_0MMtxnBANZL2mBM8nvmqogWOnrJui-7qmFYP6DJj-GkoqPhi_gXlb9gTHtus_lQtLvJSXFhDlQDT40dPbU6T716Bp1TRQSAtj5s4aIhEupcAyoza4Vzko9WF0lrwyTKeU0Yh2nkrieKNqL9XbhknW9bp8dRMRM5-cG4WZHWgD5nLV4EP-8xcZc0ApwBLebiUhkX3MZ7phpS_ZpwnHxO8GDnvuPNT6pXbvvrUL-Vitwe-qWoodziaUetUcopfpGlBYnZb6_cJOVFUoJDxPxgOkLiUW0WSSe-NsU0XllTG75sVx6cciU7LbDJjkPU3yLOrJcwpE81Khsefm-yyk4BOMzPbhJKg9Lrs9pZmuhXa0-GdMP6fHks4UKYeR5pX7zTU36t4BUYFssq-p8QqSuXah64S50W644yvaJR52PzkjDhNtl_lBbLRsVvlimUz2vGuJfFrATSnw-pkuGEDznc5BfdjqNDxncVWpwu0u2HnfAXbzBBtgNFVvWUegjRhBAwqrlWdjhvTcfzp2xUAoaXcQdRmZUh9Cw1Ib3pvejHk8l56i2Gf5X0VrDVxj2av3LugJ0sDgahri96q_EfYVD6TEF5D1lz-GBFTWJ3CZgdICN1HM2ny8yNg60U7EWFNqN3Rn9wx1LnntWcKxmwLRfTWFr3k3-TTHGam9Nw41T8hSkpGmpDYM2LsOcqdGa6ZYlFEBstzvf8JmPtBxIlD-nFIAVLo0Y4lFmt29x8hi56Ybu3_xdwY63SMj0rydOF0bX1K1QXcIJrSY4joCesFCJ05vB9F39HNByztFA3cBvyZkwzpmif9juYOpM2qfZVtG8oCnaBU90u7lkIvfgRd2H8lH0pnVTLjSq885mjhxRad1pnD-0rIoPY7ppz-quELsMOVqNTZWW8mkCy6uKiWna-3m0THLNz0CNFCnIz5ZTmchoj0x1WewlSamGL6n_SnB0H_lIXq9RUZlwrd1ASQtiOnI94pBRHPXfQ3a4PfNyeZv9GOKHr4pR0uHATkCd-rldmWQ5kG6MbNjNMJChaCMuSwrJiBondTeGIZswsMwOfV5eHgoZwfzkTxD3xo91CLGsE77IDjp05mNYc_KMbEqSmnDWpPJzsHWAX5vahfVXsRFx1Jjw-D4d5PIU_Mx4mwjPLjTrWkd5Hl2uKWvjw0Hb55lHT8D3cGlvIjRnTGM6ndLGndeKjXobs0NBcmgDQNLpHMccHAbb2UVIdvx8cF3zhkc6FdKJ17TZGJQbzWSqkkKwNUCYuRrf6CeHoEZh2ErArmcj57QVdXeDREoSzHhu1XRBfgc-ey4WF2RMzJ47Y0LNxFHpLxEk4Tpg4jcMvfRRKv-8tIu5kZeVSBqZTac90ly9qDeb32mv131YXy9G1A4RCLhjCoxM9M5r8a3AnDIvoMCusPxAM5mHpLEdv8A_5mliza9hztzmDKIQq7sQAow_XafhRJfX0dOeOft6aLkLTaq3KHN1HE0xy9Fupg5ut_AUd8tIvst7Av6vHPiK7gR-rxgWNx2FmKKXhvcWqMeeqFwSyq_18Y4w3ibPc-l-oYXD5gEMAaXGa6WgyaeNBSHNup7HDYlm_WLK3UdH-5IuIMxkhLFgDFED7g9lFl5V0I4bmW8Vqg0AqmNC2hkADsr7mNjuYr3NOzGCTsE2Ed992VG_e3k2PqtHVegZ41jxZTbfqYRM_HYg2rOdnzNN_NV3w0hpKmV-F6UIrb8Sfpscdwa2kz9Zz2huG_QGzI6AyjoepNgOYYZ_Phq4JMtrjge8HcOGRR3z8_hV21N61o5Z9yBfwx5kSnAvPXuAgeuh2MIfB_koOrwbEryE4HJTSA9b2IAs3BS9cvAu36VHVYP7Cj-U3EZxaxRIqusjNHb3WIzswa4AXFfjK65aaCCizHwxTSdn53nlSe_f7y9pMnOV3o467Vtt-oR9dqz92pauT1MxXYdBD8o0q7iOgHsqdcHBDvQmWOlpag9W1sF5uEyzA9bxDGlKLA9xtvfwnC2Y3nv9i-haFaoknx8eQGsM_bzWC54o6VlhJiNeeRUuTNEAsoTXv13usbK6MtSXoGvWPNDkj0CJ4sluSWmOidGG6DW0bEj58HYCedg71EKyNcrxcN7JJFklv1ju6IVY4k6pLMPu6kbYdKzXaxFWkOmB27Qz0dgBbK7hHhHagJWjOKrHWNiOphce9SHf9xQP2U0uJRNKqNnqmKRZLBQ-QcwRUxzaFrDByG7nRV0ybRHpJvrRfCjq-FVF0b8JXudNY3D2gI4p7WJeBqk84bt5a00DzmTZap1cEYi8VYs6zwFRa-LTemxgq8jOaeR33x8I8tDBbnqJdOV_o88Mek2E0mXkKfl_3ZzPzajcjyNHYdfhNHfcB0Oeyk6w_TXnVxOJVHuoYUsXuB4gDDMENk2yubSUFjOUzuZhXXZ4CdE4bymK54tzj9qATV0c7k-YsRlfUk5fX0JRQF6iMMWl0VtVgi3HolN7S5K4Tbs9tB0ByOS5H5N0D2BjlDl-kmd9Yrn6-B7Dxz2rxCtj_TQneCyMzfb6edt8X17c-iLsOV-fZOP3mFTCcnI6HyMxaLQDENgPF12gW3mDZyX2gAd7iRFXCHzmTnVkUEBhlCoIbq5Dc5s0niA3Jq9MHvhtgcXaUusGqCxOtQ22_CWixDntwS3hQx1KxEUzYZxThNSv-f5ji56iiWOB9uVzv6XLPdGYkN5CgdKzqPsim6VWfz52q2TTSZFRuaMGZsJuEpprdcWpHcHiBZsk3Qa-giYazywLHxj3Ph_Kf7kByYuzspVpGX3bct_unkM8jQzg8AWkn0LuFIY8ScyzXAVECJbFiOv4HipzyoyYcpDiPmadV-qAG8ghpw90xwcvgrGnHm5pzHQaqZVPKWXrHnkaJFgQ7OyEpmX-U52R5t4PZCeWJA90zAnvmL7s5MFEDLzSlzXPFjzUo3T8XWz6p6tUksLsGdUUqILT7hYdWwCdDnUJYZvjysEVIkNPNx3lAGW_e82KYUZUjQqiQqsbu1meJkdZdvMPmOlVEGx9oFvTW8cZrZZfJ1EKNOPR_1eyGdh5ZOfxGU2sogpOST3U6dxdeUwpEdhl1dTaZA_chepczFdHI7aMoKSISbpNC7nNhKNfQIpBcwPLtAhlgCOQKuBRMJUPK7VcOpl_nhz3FKexgJ0X_hFqN5qygPtKITZ_Et5ME9k5tzelHVAiosKhWOLngFJzKZkYFavSYUOHemVmUo7licjeUTPAb0d6kKbqqrJ44ZP22gL-Rw0YZa7t0VM7LrD4jD_taPhqmZ28CCchPAfP6Umo6txaiXDusvPG7v-zUGh4XWQlV_5SBSQwvPHUfQHlogHH69jxfJYRD3F-lDIfKR9ta8RuCuCdd2VsBUUAWFaRuulGcLiQ1BFWZ2Fx7W6rXgW8QkufqX9sp0zgTK9fCPN0rPLLU27BUwn0EB3EZe4bDBYrm9xAxYCgoOOE28GMpZsznXXIVaAXvUGVTBnXks9ycNghOw35fsAniH64H8u7Yp45JH8BMb7sk4zHcW_An1TzmUxjq3_JdOo9kkzNEu_qs0Y9btf4M6NajoVWlttXT2RD8XPxIrASjFMv8fxYJG0OsVHJoKTnGFlHqy13dIDMtfOkT658EuGe_pHwp8B1zI1jjpPmMW2MG3TAlumFgy9T0iyw0V3dp6qCZCjavMPIJ2HD9V9TJYueufIptuN1_hZF-xESc1ENH6z_NtMBJmW0hwCU9a6UqZ-K3_ZsJ7EK7q06V53KOSzzaJUY7SgUAFgwfbqFpvqi8emyHMxxIFylw_E1iauYGssBb_tzY1fTWwk9n4h4A9bdKesz_JBNRuKmKyOeYOS2LdJGhp9VOsbTvJtJ3MvwXuiH9rgFTXzXbDgIHxSUnUkMo4mJhnWXiqENnfqc_oOgx6zkicwwX05Bjn_k4nj800fT4RkJTY81dXy54TbvqBgPR--nTkq-WJD0e8_9hjOrtD7c7_p08FhVGWl_d499ylunVccNQ51zfeP0uGt8uYK-S9fNN8ED5PJ5iBycLRU0uvyFdsZFS0DJ4N96xSrdkdPAZ5CjfIn4bawnCs8MrHg47sCgONAqrZ1WZTgyL8j8J0kdfVJTZoLRud4oFmM4t8nQsL1sxH322EWVaXsy9aWAMVWGcc2fesk4jVODZ4mfGtnvm-Q8ifjV7wqRa7s5uXv_-JFUawxNvHqMw2AvG1M0RJTIEnRkCKB_8CXNb4K-GRw12XtZs1KRED6j1yPzLwabcWNl2BpR9JCBmogxFFuPPLdevD2JWptQ3YwTQSIMridFriwY8g31iFMFrNub9Z356Vc9zyMvZ0sRBB4oK6iSy8Y39nU3512YdGpDmMTH-T5Cxy3pi1dphlbYHcar1Yl-n5gSS0_dezGILZbxfvGbxOAIL-AGwSE4JJpUFn6N0xRclaNTPDk9VkKpVktgJeWqkWFI1xdBUp0K9BQdNs6XsJsfMCaIE-ed9SbQpJRdc1S7m6lFKFZFvHujK1zplJemcpOrYIpsuTD8wzWJAxzWwtUoo0DXi0YQOrnFdo9PbcTscUGyNArCcGjOYiL5_oMwhJh5kg5L_OPLH3UhiLI_aHs4gT7nX__HHm_3GVOov7-kK_Rs5lGsZtFQ-yoau74FnzVn8N3YWMqWzCVbwGRBhvAm_fdI53h77CZeJm9yWZkWTzrc0Ua2HqA7KB-eZgCNx9Ox9n0Ilh42hdGLFSwOEF1oEHw63x4ZTENyAP7j7mHWnyVbqRVSZOlP6w8JquYAtS9hUJQb8GZs2MFuFcwTO8SX8gMWWVM3tGtpnz7UwqhcFMZHrJ0ehues8kdtrlqR2BWPYAquFhOQebvqhlYxieuLggwAIxudJr3PFYJrAgAxivKZlhKRSoa1HCFSp_4k_kuVp5AvfBMViLJ39pi_xHX8PnokEmi3_GZiz31hGjj1GgNg8HZCkQtQJcOjMA3YPE3kQHy76YIdxzL59EdWsfuHj9IhJ4J_PoHTg5k683yXkvcXsz_sOYj9j6eMNn3Krp-ZFmWbtmqpWuvKS7vmE2Wtq9RmzvkGPC0jeY6J_ndbyCCljLpFGbvSYC50ejEulcMSUw1ypHhHzoDzO1jFo1xBDfta1H_hAsLkmYKOseTZce6hHIZR5xUwWStmu0y3OoOeVT3cZXEErr7qPLxEzB6nTlSgzLRX-ncRCnnUy0f_pXWwBE9dE6w1Nq4Y9BuS2Ip9oZZvj-gRCxTmmJLL8RYd-G9EeiBSlf09kezq4plUsJwvvPqVlj5CVLk6DkEsTvAM5r8DK3FYnLUgf7hQI_EZ8P9VN_rrPTPa25y19MR1-XIsVGLrVPmyXcj_w6XLBxEc1J8qQ37NZCw_DRfS0_ZUUqSDNlIy-y-DsdLIVtXE-BzpUkgqx5ADmbsiFFj87rS7wE5Yi2-btSpkWdTjaBbsWBgN3sOvcZgFt-AQrCK8BMLENwFrkFicExianGcwm55IlO2iUvCNjz84ogzU0IYhzDbHGCZBzYaLNX4JIVeonOoQuKA6QGueCffX1MKQ8fDKVZQc11Pr9rwjPNR3xxAs0G4ykW0c3809YE60dLbP-AZ8Qm6vxvAmTzd3XlMFaC-KbBxskXtMJRJqxUd5jYx-YQMQiOA8wLytP8INXSHi2_lgMI8QivRHoKx4oAl-qTx_qz0Ut4iw192OVWoJqTjhwIE_NB1Um9GawsbM9gb8VgI69RTPmQi9obao9kkQEUU-NrNtDkumrltR9Q9fXFyRbKn5Hs0PHzC2yiRFa_IqGEqJeqz2CSBkdC5GauukZj2XumrXKKCIYV2vJ-42D6MUqD138clb-prSiOe4dA2-wrKPjaaWdpaMeAbLXbLkHuH4K5h6HOpYIVMu_JWdnzzDnvye0o8A8vrxFZsOSDeiHPcoDyN6-6KYQwOlKpjiswFVdoD_e3Aw9ge6YHDOggsKeyERzv46Hc2GwW_GWrwaWgXSv-lePsj94L1b17WG_y4oEKbNMAmE4A4EBH1aJI6_wEeySONFKhbyOIwUBcRKCoKT40dbGie7kW23rrzSTQHpjdd4NbAbNAGEtbAJbVwZbFC2RMwMWQbz8mmnMSdVw0VN6UVaCdUatYzATx-gk-lg_8ikyOhMwA_lXFI9pfnHIIqGmKHDJdrE4pdDBK5wVLB1H_CYqzUneygueeTUc_rHiMj7QdekTGh4KnA2lurqXemNemePYl621G_FqimReuPlTPmn88h-DvnmcVhTJEMCT2O6huU2_6yOlyulJw-mq6KMS_b3PSB3bgYmJEH7EM7ljv7lu0ZIqZm9xbpVTntP2s9jDBPMb95q8AnllIwH6uZEYdyiIDU9NQj9RIlR4RZ8Oi5b6n2IuKojvP6aK47npwKMvC4IOAMmGaE3_S2X0vFnpT1djiFPAjvklOEA8o0k91YV_z-QbWwVTd5fdRgaqXcqb3dLAuvnFq0bOpJMchlL9lrC02JW07Xi9Lw4EIoDsPBRr5s5DWLG8kLfpEv-YNZatryAbjbwMtJX0O9aNxLzG1bzyXVFwBb_HUgkotdbmlT7cXMMX8D4_xIQcDyjwo925uAVU3va121ddHt2JasKJc1vMyuOKXuDg5F3dYByqEQQH8zywgBi_IRtUx8aXNoNXobUf3LGaLc-3HqVTZby9Xv_Axm-s5jSqcEPL4WJX60rY28qx_lmajcmcVLY7irKovGmfEIlVeHYdMxDxZue2nHHHc7NmF7dGORg870x5iGUcqtmjvOx-NIqVShVQlalGOdIF3_u6r8xlvOL8xWJ6WLXKNaAFVtaoDdObEoR3stpG8iaaaGNcrRqIH7J86ntBUmQ8chIgOOvPz81W0Op5jbSc4d2e_qAAuvt6j_qElh9qsGNMVPoY9DlxqqrlJ3ojG_6yqlX_jP6NGSx31vxc-IgggbyeEm2BVt1v3dJv_Z1Kmt8PGa3--atQsH3cemYMbWcwX2mAdMCHLY7xQJs_X9OgDaPd25bGPHFJQVNM4cypyPSWXEDiR-xIqkB7NzTrSEGf82wSgIPRAo7k-CBpbBVvsuLre4zof8K5u7QH2jYFQA0-9YtDa_Uyc_JcErLU7AroB5ZZr7s_s9qx5w_wJxMNW1NLZJdOKUVryP6DJPqTNmly3PT88GaPUDdrcQa7NplSF1FcqFmzOlZc1Se_fSkgEcFKrX9M7_65bTgLbAvj-8bCTIxZp0-PcmoQO4mrkNkW2Vr1rfSuOH5_vqJCT7s9A-H77RjLseMxJ27YF_dEXOHjsEV0DPM_zfno9_Lb6gL0rqffxhKdM_xRhSsLg47PJlCgoZkL2xVTJfahwydAzbr4ZWbZ84WwprOimGLJBdcQgjHEhxx0_cT9tFpUKkUbpAlUYqm1e23JGUXKrS9kBqM68RjcBAiaAgeKMx_5pNU4RzuJqCARPYgqhsy50LxkN6DgIMiDglLxho4wUYHVVkez3XXPHmO8FJcRuuk85Z-7qDeExR-Dp8vHkAvSGuyuUKHdyaQdhigMm18qFzu5-L_m3-C7xEblO7KJBDtK9mDdaviyLU9bQA4i7lLgUUdkCClPjm7yDt3SgjDZKXpBeD_HEb134vjhc6EVJN0IK0bf-lSswaAPJYcGc9ArU_mch_F1w0X1ISwvFHWKLYBM1bUSCr7vLyX-j-sbwroVSJ53bTedlaUpoVhEjKxcksjSgnndvAeeHAwHV-HCkOH_zqhxp5aTO1vNXeNESG7WoSRLE1_6vF7ZzTGmpG3GIbuBexi0BUe95UwrAJpdtzWMrAiRNQ3LlB8JkPIqX_ZXmHsu1bo84_x1u-VWQZFNTOitRXyLdA9GtDqg2q7RUJLj1Axq6CzjcewoW380K7r95Kimr6RDUUkvi85SjekZuV8NNd328heZWNSdov9lzmJlCokX6N5VDpg-NIPvjJyaQtf6YZfYtOk7pp_koGxatbsxZTSVh_DwXz7K8VfC2mEhr_xdDPe9nKAPrU4r_J9zdtAkkzdJssMWhSCMTj8z3l1bbIzMt05ivwEGLZYqZ5Sy2-duQVd1wA0NfKB2HjfgSyYhX5wN4aDW15copsEtPTrxCLidwc75rLdoi5Ch1Jt74v5UzKh8mxDaGqjdWeHkDrHbVy5hDVk00n1TZ5UAzWCq3lge3717y0ECZX992BrkqjffUYe0dZUUJr_3GWKSS0AZHg5uI-1Tka_DGqF7mWwdz7XpafzU4siolRkGa3QYmB8LWqdbAnpvte-uSwxAiQm2LiFF9h4dOO8U_2gNsniQViwLkD0KTHnuk1_N94P6QsypEL2bcPWCvCw1SgMmgKBaXYpP8FIN1trlpqyk_0abqnq9GoeCI2AjAOkHI0LnNsM8lTwWNqh1b8YVco3or8J4dOPeVQ=', provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_68cdec307db4819fbc6af5c42bc6f373079003437d26d0c0', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='c51b7b', ), id='ig_68cdec307db4819fbc6af5c42bc6f373079003437d26d0c0', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_68cdec307db4819fbc6af5c42bc6f373079003437d26d0c0', timestamp=IsDatetime(), provider_name='openai', ), TextPart(content='', id='msg_68cdec605234819fab332bfc0ba35a5d079003437d26d0c0'), ], usage=RequestUsage( input_tokens=2799, cache_read_tokens=2048, output_tokens=1390, details={'reasoning_tokens': 1216} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68cdec1f3290819f99d9caba8703b251079003437d26d0c0', finish_reason='stop', ), ModelRequest( parts=[ RetryPromptPart( content='Please return text or call a tool.', tool_call_id=IsStr(), timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_68cdec62725c819f92668a905ed1738d079003437d26d0c0', signature='gAAAAABozey1vHMbs_Q2Ou1f-stI__3zJS-qTasRefyc_eyOxqogM8UGbPpL8D6PLFHcypshJpa9SQli-qZRIyG4ioUDLsKpBwFbfjdIhps667-8st03DRTRP0ms2izupS0ae6QqY9qrsPSchrSF2o2PlJOWKZAFJ609S0hGX8VDtrU8nESfp78NQ5HgpgXksXQTxk3_xRmXES2AThlUD0LYykoVKRX-xOyPQsOK7aDEs1CIk3lG1meiXdtJxP1Jm9JQGLWk6kePWUgwnAs818LMVvjcj8GWzFjxKUQlI3S855vYngivkMqYqh4gOcDRGRWej4NRzRmhOK-2yrATl26qnpRwNA1YXkFtn1ojxEkXD99P8RIXNItH4KW19ALs7ZizQmQlKzd96eyPT16OSLqEIfHAXWEKwoB2vTM2ExvHK4il76X9XmgRDy_CI3HAPI-7M3787MJBEY3z9cBe2sIS_GtSk12_GXRBUREhu8wcc4920FxkufYegHd3FzKxBRjyxGpR-jLyI24ahOZRKvoXi4-n1v4umoD5OSMjYpMtr0ykwIBQyyqldi9KqHBpJCzB0wA3JyAn-4JvQsXwIeeAtq3bNSJFaaf9aLJ5OwMO9I6IIWGxoQ1mzqmCs5cVwwjeJLzEc0T5g2qWJdXxdYmjesvMj3pJtgIq3iR2105LydhUiKE-0VLVAQGg-lnjkCtj-muEqlko2_FCHQ7b_hA0VkOUIKOYUDHRtwgtaeNnUpiWk8L7GnBNHtVQ7_kHEGj00UIVC4CKiJqESXS1om73Xt1K1-bglZLfSKfjrAd6E3W51cKQXM7KOfmpRwP-9DThdeOBgjlmMFveru6NYl2ntiu7GF8JJAvjebF3Q6SR4AtFSp8zrZVjlduW3hzQtKaROHLBVgH1KaMST-Nfnkn4AHCbhYNGSZxg4J8M3hh-BLba-lM7o9d0cHsHSORXeuAg40qioVCZNCtIooo6fAdWSAULw-uGdAbRbrJq5nE-w_Lilyeb2mWnMwMbKBHjQO7Kwe92UHvve46vMkiSSX-wZYwthfbO9BM6_ha5BJOtwNggKuBXxqMVizL8WKdvdTVwzP1guDvuVgVoCYKl340jB_EE2V-L-YzbSdaxHi09Gi6E10MgdaSGhNqUJMZWXrezkT6pyRYYRIWhaaImIuQf6JybMUH5hHH8DDEKvofLnQmgPVccU6womuYosIgLOLPOetK6OEFlMsQPBn95hb6jY5vETMyhiVYAVxaeXgk5WA-NdYQ-F2q4kQQS6Ku858AaO9rXMYpkaJ0nIubIbdgQMaXzq6ha5Z0BaxrJhxCDqmHXA5-INBBqWDw0AgJcAlMM_a5ShZA4zVWu4ydzikq8PlnATLbFzOkL8WBhJGRyveKaSyknPfPCBvXu_1l-hwAyvFv2dWWBloD_IIJ3ID_qtjgT7epwC88qmQd5ICPMMdx4DjEu72hU-rTIz30ks970qi_dKVbgpsLAJbHeCCWXBJzJ3UKrC6sc7Kj3rhtelPNEJqFyuB_EJOVX4o7R0AZvkk3wWs3IZ2nE9TeuYckw-hHg35YsC43QSrbIZUbfonaN57ZbwyrnEwnhH3oYXaMiPqqywH0CsZYrO0QLuAeGJTknlpWHgLEVmz39-e3UZFb6WIGIfSFaZHAFpmQBiPjae-qudcbvvfmAgBHqt-Aq4D_06ySnELOtDWlFusZcmHQwG9b0OCDXt6KRTR_-49uuoPCoXlv2nKb2eFhXp1gp6m6WsH21XNaeLU4RF4PR6oRUh-TCLzyBtwCscukF_3gBvcTdwJ4io0Fu6YVtEJux_Ec1vCaQHlUVGtZR7JDVyE5lu1y-aZx0u4s6HheF0bHLYaFgqgOmaNNWwK_jldqp99ZhU7Qat8GcG8YLLEJ04WDIp6_i_Ri7OUf5xgTEkAxS9gOxeJ1EMKR2oB0pf7YJ18XkNqeA7zxXmufJNIbEmXOC3XQKiDY9-2UzTyqjzdZ4V2naUggs7DjAAntcHhVFLGOZgGeQ5FLJ9jfzFlpE8mAg95ZtVvPzYBNFaPoTynqUlukCH4eje_62w_u2TruBMSU3cOV5IqVTLMHu2uwxHWdA1zrVi32LMv8FEYZ8nPyyk_BdapV-SRGQKn1yjGml__I5ksVlqNWVC3BX4hkIxH9K1bO6HjWP2-cdRtTYtRNcOOGOZZv5RtKfpvzjIK5o6d45KDK-jp39_cY9Veyawzc4XwT7jkyL8U0YNsRTEjafcPONK7yWasrOIzNuUppBFdMyER_R8Q1bTMQp1sE-NoAN-0MqupZe1jltzga6i6KLWuOXtMm1_DeHHH3OPNq-kfVs19gbQD13R9kMNjgu8FbAWdoVreG24tKUVSf2nWKReXwxc3WiiODaYTew2ynZ3BUchm3eKebybh4lKoYCw6lLoclnD7smFkP4-72RfaTylVe_npaWU_kWIhxItYosjWGc_ScJhLFdwAOUaNijGNX0TmeMb3uaESw23E3Y0M2pAC_wVkaHvJEYv_nYebwYc6yON5oMFAnOmqaJ14d-LfhuATtTrqD8fGXTPi73rpN5IpA3fVklkyUuu0GWqvsRujNnEcN2nL43LPRwFvwYSeL_tXJoTpTxdgkwjEg4dJr6hImPIwk6Yu_a159LyNKIeZOSZbHi0gao7OeDiSM2_1zb_srjUXgiVPJ26r3GCz07dhcwqUS8lU6nx5q1ncCt9mjTgUG0qmVPzDjfRmeqOU1gPZhh2XQeiXp2AWB-_9M9vu2EiSeOO2gfYKeaFjVhBLbjOeKs9r0xt5JXpdx5IDB1JOfK_MSlKwjl2kOlNo7p3e7RIVB38MQoih95hSz5E6EyOoH2O6KAXLM3qhgcmXe-XJwQKOkA8rPRclgvN-hLSopl6mDGqg7dNKXZB6SQspQPiB4mx91Wwt62aMqWa7Ve-thQ6-oCq9IQTLT34xpCOpHWz4b8kSfr-WDg9cTDdvYIGEDGj_XlE6CK5PuxzezWGYvYggwVJC_65zkGHFBURkBCRHc7otAyxMTKMCTKZnYWUdUEGpTCBonYFPOlh_ApDPnh1h3feF1x8AEIoVkq_ADRKhKbs28y44LQGp9pe49LdsgKN7YT8_azHknz5frvCUQJu8aiP_TaFCAiZhUc0JSATHPv3q6ZsNoUzF8ZfeSWuI3ZpQyoyMq4wxcyH1sFNqtIHd_iS2U9AkEACp6q6FAohK_O7GaDr_T7VfeO3JuRL9icg82WtPOtgJ1o7oqZxa1lfypGkWAgX_KF5aytblSoxlwn-Zk84Mf_YlbJEBO2mUa0Me5uLhM183akeG4y06FR-ANXrsYxrGmhpIWfl90WAKEG4ExdaexgzQOKXedTLOKnIwDW0ZSAu6O-Eiddn2w5GBO93OGEGQwkXDddA9PB9--mdyHgJM1OvXFYIWtziDLZ5qHAUrUFpYUth9B9mV4TXXLeLqx25TO7DL9czT6cGPeYNSOR3HpNdw93Pbro_kDIk-4zrmhlLd-I6w1tSisK7veJE0Y9Svvf6VLky34iV0RlIw-Z976oPP3rVJpSIujNbuFm84V2EvHFkG1oaHoViDxp4QesbToOdhl8GfnHHuwPaT78C1rwucflil_XkLAi0PBv0uGYLWaaAVlhm_lNZc4CYd7qHcdgma8dL27kHwVUJctIzphtV4yAhL-06SY-kwR9snNogfzDSuuNTVHPofu0_B7qA9vjwf3jeE8WJUbq0HxPSIGMSvJ57uh2YzRPWnMJ2PmARWgHAYoWUsZknHyr7DlKqzV1kxrLmr40xk98D9-Qkkq3enbEazhNWXRTIGMuWQbM1FQB3VL8GX3Xa1TjujWQS8_nC9LTId1XzNWsSCNOg8gHXqvt5hAeJVZ9GMTFJREPCBk5ts9odm3N3bjK5KgA3pNahnOS0u_c2auAc1t9C_5xqxEnIRxE6R1lVHz7hDTebYMcpldFI8IEuToExCjUUpoW6FmpeJrv16hwzTqbX69oToXJ2YA4WYCerDob0BAMHKWDC0nqPJTp9wjq2OnC5YKmMKfJ7lKhVprYG14RKnJfOJdChRpWQH2iK1Hc12sCJBJT2Lvm138cQeRApo2uUTs1dpJ-faoPvb6H_Wg-9ys5JsZtrzUXVpj4ttC84M7dZnbdyEh64iOoUINTSG4yryVDfN7PokiuN3DHuuXlWG8hkWAP4uyZg6sXdeSBGfVOjmG7Tc0zNqxZFkCMo9XEaLk_Zz6X7fQPM-MQVkSrb_0-S7tNwcufe3Y0nEnKpM1WohnyojInkRUzPWLUcBukzYpwuXg3MxxayDLwfjfybNb3hO_aNF_5mLz8s40IotW2Oxa1eKfZO5igty32jA5ipXwPjJjBj5yVgmTESDPmYrPkJCdFUtJJpGRTRX30BbLAybWkhJWBGilR-f5wp7yHp1pAcLl8YIKi-Di35kCCG0qtTimMeyb6E9hQww06pdDKAuVuDmC-RhgG9-x6MlmeJgKeNu2VeANq5lIiAKuDEXz4cs-TBrC_PC4j7dnaIbvchVdxx9Regcqfa2XTeXsKJB8uGwHDBQ_qu6zyKJ2ANyqk8x7Vmmz3YNREGNgiiRQK-zDjU2ZRJN0DJnHxdFMYcmywKz0QOab4orE01eqaG_Zy3vr7fDLOMJOl_puAjLnF7xiVmj1UWC2FwoWngvCrGO-2wsHB7fnvJapv-NpIoW146QuSVwhMROuZ-5SmzQz4MlF-ARtdkEvCAO45BZTM-AnTlOiMqMXspKrHGCiwE_S4FStVdHT4D7m6Ha4q_BRD9nBYp9r0vP4QdsfsK0pegYawDfZ3U9Vuk0dRZp3Z2QBXDLuIs0-0ol7_liDeC64KCdL2zrDSQCXeSQGtDpBdbSDf5xkzQ1N_IStAz6dI_FLbLqRPfE9tf3AfA9k7j3BwN_K6eeVfRueVnf0VOXukHURPwMTVE9C8IdPA8OnwLBD-k1YT2aV3Aow6eC4Dwl7cW2FtQ_BuHcpjMfWuJFiUuw9L8bLCWSlJ3rYdX_MYv-9mY--9d3r49p5FHAoK-bJS5yxHg2Q6Eg6DrSC4dORU5p_fKxrPklgOJKbZoQyb96_dp2qkCVgPjN1naoHfhgqHp49MxalqSx9n-vd86NTSXNw22lnboj4qAsLg54P4RSayO-U6jvj09ZuGtLGrCvKPAgHl_xP4dtpdbOC8OJ3nwHNfxAgZr2P5JEaFHN3RuIQGH5gkwNEA2otd40YptNJvD6r4gasyBPNY15jeYYL18yFQobK60gnXQweT_JXTlnGgbvgoGw6rJ2nifXw_o6Q_uBDQE9MOCJiN0FoivBdcwk-NHU-nNg93U30q4zbGbJ96O0E2X2qRyoOaEhBKAqkHrQM-NGjX7aj1YJFCxIFtQ00OQjT0vhGng6-3cB01l44mGdDFV47PZLzcFrGx7iDaR1Oy2Na5rOLphgT1_zvVF2mCw10HYxOYwSDnm6uqo_kADX_HQAGxQx1xDZ9iaZZGD00hdoZp55kRPGt6uZ9ZEEXPWUpAV8mPUlu0DcK6rr948_btFuMWo9KrVneCiF4qxkk_Q56aFoRa_HQwEEuh3sp9PSCT9wIfBYSR3661Ox7C-25rHNkrdv7XC8ArnQ7xT04y9JYOF_XLxtOLlAzscUryz56Qk7lexv7Qqe80fTTSRNFseDNFCxLjWm6wAo_kpaTOOvFiPUxlYwcmW4hy-hW8zH_JRVPaBCCKR_s68yEEAVve-8q0ePzqcElS4Bt8cFyU2kqodDmzzh2HAFcrA_ScDciNbwKWeJublK97rkWmLCuPZwJcvKNT_FfgYU5OxtF6G2TVVhUcbVAhPQFFegVn_8hYkZ3mJFkZa8FYYNMSGn8nssR8F9RInU9PFLfBiI2_sDJKwfhgLZ9Lb4x2Idx1-XNh9pAFkCv4eRKCoQNrfxZ4VgD7L2UeLTiTBOsH117rSSF3Aq5kaLLV9yqXc7bB8ZVdvsQ64ET6Z3sNM6xk78phFYy-Dnl9sM73dX2qpUefxdItLtql4E_jwm-D2qRdGtdkm3FpQhYhTKgfm--H3hj64AfDQP-7WVykl508pb7Ultl6j9ne28UqtsV6LHaXX3Raq78sZZl7pmkgp3dSZlZXuo0zwyh0eR8aDp201EdOqbG6a8Vs7cHo2pjy_31ZrIGA_rZhFRN5uVohUvtPWCwwV3D6qq9XQRFK6GsiIMgO8oH8v2AB_qopEXWkStyn9HgA-UntHqncuVnnVrprWFYfWVuTDkJhTC1-i9ZgdA1eUvZVxl-I4SfmDG540HUVVRw-Kt15vS7K2vc1FDiQA91Iya8eMjVKOs96Cr--cngQ_zZw062ZqKp7avO0EOTamvz8Zi2a0XzdIH5dH0_9_kXE_T4U43Ud_29QMElOxJfxt-9p9lBNBjfEkUvBayPX2XWlePtoQL89QLg-Xwe7RaGu0hvUiROaArk47B_703dSKDll2V5eUKc5f0H7icWyqp8u5rnjQsafBu6RCWHr7YJ1Pk5TBaw1qQCvNA2Z_FVZWN18No61fV16DHyjoiHBBjTROCS7m7_3snv4SDkoiFvIswpEt7pbYtbXLp5t0EQOQkWQOITojrGYIUi9c23kdiXr3EoPsvSMKlJcDyag25wzVNfA-bfiMCkdHPqaaTFBqYqlwA0SI6bwHKhqFKdGkrJ5YIxgaFLsLwwiNMSBR2wWXSFRXz-HCMewHkVV4LpGxkzeihWXJUO3gXeJuVY1EGxB8U15BUtQQcAAe2Om9KZtOsS2kRtO7vZq62E8jl7bUbTmw0XTZ4eh3xg-IRiK1ynur6XqtZH1kNQFq7k60X-6cFwDS7eDGdzrgl-Kbl6VSzxpwxu5Lz-KIjV5gGBUcOjnIpRuwY_s', provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_68cdec701280819fab216c216ff58efe079003437d26d0c0', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='c9d559', ), id='ig_68cdec701280819fab216c216ff58efe079003437d26d0c0', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_68cdec701280819fab216c216ff58efe079003437d26d0c0', timestamp=IsDatetime(), provider_name='openai', ), TextPart(content='', id='msg_68cdecb54530819f9e25118291f5d1fe079003437d26d0c0'), ], usage=RequestUsage( input_tokens=2858, cache_read_tokens=1920, output_tokens=1071, details={'reasoning_tokens': 896} ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_68cdec61d0a0819fac14ed057a9946a1079003437d26d0c0', finish_reason='stop', ), ] ) async def test_openai_responses_image_or_text_output(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, output_type=str | BinaryImage) result = await agent.run('Tell me a two-sentence story about an axolotl.') assert result.output == snapshot(IsStr()) result = await agent.run('Generate an image of an axolotl.') assert result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='f77253', ) ) async def test_openai_responses_image_and_text_output(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, builtin_tools=[ImageGenerationTool()]) result = await agent.run('Tell me a two-sentence story about an axolotl with an illustration.') assert result.output == snapshot(IsStr()) assert result.response.files == snapshot( [ BinaryImage( data=IsBytes(), media_type='image/png', identifier='fbb409', ) ] ) async def test_openai_responses_image_generation_with_tool_output(allow_model_requests: None, openai_api_key: str): class Animal(BaseModel): species: str name: str model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, builtin_tools=[ImageGenerationTool()], output_type=Animal) result = await agent.run('Generate an image of an axolotl.') assert result.output == snapshot(Animal(species='Axolotl', name='Axie')) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Generate an image of an axolotl.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_0360827931d9421b0068dd832972fc81a0a1d7b8703a3f8f9c', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_0360827931d9421b0068dd833f660c81a09fc92cfc19fb9b13', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='918a98', ), id='ig_0360827931d9421b0068dd833f660c81a09fc92cfc19fb9b13', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_0360827931d9421b0068dd833f660c81a09fc92cfc19fb9b13', timestamp=IsDatetime(), provider_name='openai', ), TextPart(content='', id='msg_0360827931d9421b0068dd836f4de881a0ae6d58054d203eb2'), ], usage=RequestUsage(input_tokens=2253, output_tokens=1755, details={'reasoning_tokens': 1600}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0360827931d9421b0068dd8328c08c81a0ba854f245883906f', finish_reason='stop', ), ModelRequest( parts=[ RetryPromptPart( content='Please include your response in a tool call.', tool_call_id=IsStr(), timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_0360827931d9421b0068dd8371573081a09265815c4896c60f', signature=IsStr(), provider_name='openai', ), ToolCallPart( tool_name='final_result', args='{"species":"Axolotl","name":"Axie"}', tool_call_id='call_eE7MHM5WMJnMt5srV69NmBJk', id='fc_0360827931d9421b0068dd83918a8c81a08a765e558fd5e071', ), ], usage=RequestUsage(input_tokens=587, output_tokens=2587, details={'reasoning_tokens': 2560}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0360827931d9421b0068dd8370a70081a09d6de822ee43bbc4', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='final_result', content='Final result processed.', tool_call_id='call_eE7MHM5WMJnMt5srV69NmBJk', timestamp=IsDatetime(), ) ] ), ] ) async def test_openai_responses_image_generation_with_native_output(allow_model_requests: None, openai_api_key: str): class Animal(BaseModel): species: str name: str model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, builtin_tools=[ImageGenerationTool()], output_type=NativeOutput(Animal)) result = await agent.run('Generate an image of an axolotl.') assert result.output == snapshot(Animal(species='Ambystoma mexicanum', name='Axolotl')) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Generate an image of an axolotl.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_09b7ce6df817433c0068dd840825f481a08746132be64b7dbc', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_09b7ce6df817433c0068dd8418e65881a09a80011c41848b07', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='4ed317', ), id='ig_09b7ce6df817433c0068dd8418e65881a09a80011c41848b07', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_09b7ce6df817433c0068dd8418e65881a09a80011c41848b07', timestamp=IsDatetime(), provider_name='openai', ), TextPart( content='{"species":"Ambystoma mexicanum","name":"Axolotl"}', id='msg_09b7ce6df817433c0068dd8455d66481a0a265a59089859b56', ), ], usage=RequestUsage(input_tokens=1789, output_tokens=1312, details={'reasoning_tokens': 1152}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_09b7ce6df817433c0068dd8407c37881a0ad817ef3cc3a3600', finish_reason='stop', ), ] ) async def test_openai_responses_image_generation_with_prompted_output(allow_model_requests: None, openai_api_key: str): class Animal(BaseModel): species: str name: str model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, builtin_tools=[ImageGenerationTool()], output_type=PromptedOutput(Animal)) result = await agent.run('Generate an image of an axolotl.') assert result.output == snapshot(Animal(species='axolotl', name='Axel')) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Generate an image of an axolotl.', timestamp=IsDatetime(), ) ], instructions="""\ Always respond with a JSON object that's compatible with this schema: {"properties": {"species": {"type": "string"}, "name": {"type": "string"}}, "required": ["species", "name"], "title": "Animal", "type": "object"} Don't include any text or Markdown fencing before or after.\ """, ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_0d14a5e3c26c21180068dd8721f7e08190964fcca3611acaa8', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_0d14a5e3c26c21180068dd87309a608190ab2d8c7af59983ed', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='958792', ), id='ig_0d14a5e3c26c21180068dd87309a608190ab2d8c7af59983ed', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_0d14a5e3c26c21180068dd87309a608190ab2d8c7af59983ed', timestamp=IsDatetime(), provider_name='openai', ), TextPart( content='{"species":"axolotl","name":"Axel"}', id='msg_0d14a5e3c26c21180068dd8763b4508190bb7487109f73e1f4', ), ], usage=RequestUsage(input_tokens=1812, output_tokens=1313, details={'reasoning_tokens': 1152}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0d14a5e3c26c21180068dd871d439081908dc36e63fab0cedf', finish_reason='stop', ), ] ) async def test_openai_responses_image_generation_with_tools(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, output_type=BinaryImage) @agent.tool_plain async def get_animal() -> str: return 'axolotl' result = await agent.run('Generate an image of the animal returned by the get_animal tool.') assert result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='160d47', ) ) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Generate an image of the animal returned by the get_animal tool.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_0481074da98340df0068dd88e41588819180570a0cf50d0e6e', signature=IsStr(), provider_name='openai', ), ToolCallPart( tool_name='get_animal', args='{}', tool_call_id='call_t76xO1K2zqrJkawkU3tur8vj', id='fc_0481074da98340df0068dd88f000688191afaf54f799b1dfaf', ), ], usage=RequestUsage(input_tokens=389, output_tokens=721, details={'reasoning_tokens': 704}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0481074da98340df0068dd88dceb1481918b1d167d99bc51cd', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_animal', content='axolotl', tool_call_id='call_t76xO1K2zqrJkawkU3tur8vj', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_0481074da98340df0068dd88fb39c0819182d36f882ee0904f', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='160d47', ), id='ig_0481074da98340df0068dd88fb39c0819182d36f882ee0904f', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_0481074da98340df0068dd88fb39c0819182d36f882ee0904f', timestamp=IsDatetime(), provider_name='openai', ), TextPart(content='', id='msg_0481074da98340df0068dd8934b3f48191920fd2feb9de2332'), ], usage=RequestUsage(input_tokens=1294, output_tokens=65, details={'reasoning_tokens': 0}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0481074da98340df0068dd88f0ba04819185a168065ef28040', finish_reason='stop', ), ] ) async def test_openai_responses_multiple_images(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, output_type=BinaryImage) result = await agent.run('Generate two separate images of axolotls.') # The first image is used as output assert result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/png', identifier='2a8c51', ) ) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Generate two separate images of axolotls.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_0b6169df6e16e9690068dd80d6daec8191ba71651890c0e1e1', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_0b6169df6e16e9690068dd80f7b070819189831dcc01b98a2a', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='2a8c51', ), id='ig_0b6169df6e16e9690068dd80f7b070819189831dcc01b98a2a', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1024x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_0b6169df6e16e9690068dd80f7b070819189831dcc01b98a2a', timestamp=IsDatetime(), provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_0b6169df6e16e9690068dd8125f4448191bac6818b54114209', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/png', identifier='dd7c41', ), id='ig_0b6169df6e16e9690068dd8125f4448191bac6818b54114209', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1536x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_0b6169df6e16e9690068dd8125f4448191bac6818b54114209', timestamp=IsDatetime(), provider_name='openai', ), TextPart(content='', id='msg_0b6169df6e16e9690068dd8163a99c8191ae96a95eaa8e6365'), ], usage=RequestUsage( input_tokens=2675, output_tokens=2157, details={'reasoning_tokens': 1984}, ), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0b6169df6e16e9690068dd80d64aec81919c65f238307673bb', finish_reason='stop', ), ] ) async def test_openai_responses_image_generation_jpeg(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent(model=model, builtin_tools=[ImageGenerationTool(output_format='jpeg')], output_type=BinaryImage) result = await agent.run('Generate an image of axolotl.') assert result.output == snapshot( BinaryImage( data=IsBytes(), media_type='image/jpeg', identifier='df8cd2', ) ) assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Generate an image of axolotl.', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_08acbdf1ae54befc0068dd9cee0698819791dc1b2461291dbe', signature=IsStr(), provider_name='openai', ), BuiltinToolCallPart( tool_name='image_generation', tool_call_id='ig_08acbdf1ae54befc0068dd9d0347bc8197ad70005495e64e62', provider_name='openai', ), FilePart( content=BinaryImage( data=IsBytes(), media_type='image/jpeg', identifier='df8cd2', ), id='ig_08acbdf1ae54befc0068dd9d0347bc8197ad70005495e64e62', ), BuiltinToolReturnPart( tool_name='image_generation', content={ 'status': 'completed', 'background': 'opaque', 'quality': 'high', 'size': '1536x1024', 'revised_prompt': IsStr(), }, tool_call_id='ig_08acbdf1ae54befc0068dd9d0347bc8197ad70005495e64e62', timestamp=IsDatetime(), provider_name='openai', ), TextPart(content='', id='msg_08acbdf1ae54befc0068dd9d468248819786f55b61db3a9a60'), ], usage=RequestUsage(input_tokens=1889, output_tokens=1434, details={'reasoning_tokens': 1280}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_08acbdf1ae54befc0068dd9ced226c8197a2e974b29c565407', finish_reason='stop', ), ] ) async def test_openai_responses_history_with_combined_tool_call_id(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('gpt-5', provider=OpenAIProvider(api_key=openai_api_key)) class CityLocation(BaseModel): city: str country: str agent = Agent(m, output_type=ToolOutput(CityLocation)) messages = [ ModelRequest( parts=[ UserPromptPart( content='What is the largest city in the user country?', ) ] ), ModelResponse( parts=[ ToolCallPart( tool_name='get_user_country', args='{}', tool_call_id='call_ZWkVhdUjupo528U9dqgFeRkH|fc_68477f0bb8e4819cba6d781e174d77f8001fd29e2d5573f7', ) ], model_name='gpt-4o-2024-08-06', provider_name='openai', provider_response_id='resp_68477f0b40a8819cb8d55594bc2c232a001fd29e2d5573f7', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='get_user_country', content='Mexico', tool_call_id='call_ZWkVhdUjupo528U9dqgFeRkH|fc_68477f0bb8e4819cba6d781e174d77f8001fd29e2d5573f7', ) ] ), ] result = await agent.run('What is the largest city in the user country?', message_history=messages) assert result.output == snapshot(CityLocation(city='Mexico City', country='Mexico')) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What is the largest city in the user country?', timestamp=IsDatetime(), ) ] ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_001fd29e2d5573f70068ece2e816fc819c82755f049c987ea4', signature='gAAAAABo7OLt_-yMcMz15n_JkwU0selGH2vqiwJDNU86YIjY_jQLXid4usIFjjCppiyOnJjtU_C6e7jUIKnfZRBt1DHVFMGpAVvTBZBVdJhXl0ypGjkAj3Wv_3ecAG9oU3DoUMKrbwEMqL0LaSfNSN1qgCTt-RL2sgeEDgFeiOpX40BWgS8tVMfR4_qBxJcp8KeYvw5niPgwcMF3UPIEjHlaVpglJH2SzZtTOdxeFDfYbnvdWTMvwYFIc0jKOREG_-hZE4AznhHdSLV2-I5nGlxuxqaI4GQCk-Fp8Cvcy15_NYYP62ii50VlR6HPp_gQZEetwgC5pThsiuuG7-n1hGOnsj8gZyjSKsMe2KpzlYzhT7ighmArDVEx8Utvp1FXikqGkEzt4RTqqPInp9kuvqQTSyd8JZ6BEetRl1EuZXT7zXrzLwFN7Vm_gqixmf6mLXZUw6vg6LqGkhSh5fo6C7akPTwwJXjVJ37Dzfejo6RiVKOT-_9sdYCHW2kZ9XfQAmRQfB97UpSZ8QrVfaKy_uRIHLexs8QrQvKuw-uHDQBAL3OEmSTzHzCQ-q7b0FHr514Z29l9etavHNVdpeleWGo6VEtLWGQyblIdIBtf946YnQvr6NYIR8uATn9Z91rr8FsFJTpJh_v5iGA2f8rfPRu27nmw-q8XnPVc_FYCZDk08r_YhdEJZn1INBi8wYSWmpib8VxNpkFO7FFRuK-F8rh3MTpYgIOqPQYbf3LCRvKukTwv1b3mjSKVpHQSm_s6s7djdD-rLuc22-3_MLd0ii4_oOT8w51TQIM61LtonGvxUqf4oKHSUFCVnrWWiT-0ttdpwpJ_iB5frnEeY2mWyU1u7sd38BI3dOzoM82IFaIm98g9fa99bmoA7Z7gI60tzyF8YbJmWF-PCwyKHJ7B1MbCBonO36NmeEM-SplrR54fGykxTmwvtbYGhd5f0cdYzD0zulRDj-AhOd96rrUB_fIgoQGTXey8L_w0whcnVTWdG6is-rx8373Sz8ZRoE5RiLWW1mfHzVXxwslphx4BedRVF0tL-1YO7sg5MXhHCf6hpw8dOht-21NMrb1F1DQadFE_fhySFl-TgOD5BlhAuupLMsqcCIa4lcXP_loyA4ERP6WSdz2Bybz7_1eOiflfVodRrNqvr_DnL0NEXD_JkYTeIn84ziarFV7U7ZnkMvRiA_p1fWdbHTsE_8lu1rsf8fcJ1e76_6ycPkOc4TrOZw8gVRb7gIbMMVrv72BT_sFhW7GkXrzCQpQaeybmRw-bjFhkMMjMDYGXkA_H0q2Zfyh3zCOoa40hl2cqRWp7n1XuafmtKG_F8e9hyWox0q7AhZr5HOOaHz8r3O3-dmNl1KP52bqA8S72rLDslAOQlDupmAQgAmkm5ApYeYcEBredN78jHQ1pviUEI2-3qr4ClXZFHPa54AJ_q4HQ-EcKXEcYQglG21mSUy_tFQF-m4X46Qu8yYWcBVW4E0CG3wbvYx0BCdbc5RhIDkJo1elxLK8XS64lpFkCWy62xLVeMuVuCj8q84-Kk7tZ7gtMtLV9PHQCdbl3s2pAzMfuNIBJog6-HPmwha2n9T0Md5qF7OqCtnYWOWUfIMmQVcdW-ECGsQy9uIUmpsOjdtH31hrX3MUEhIOUB5xErLwfp-_s22ciAY_ap3JlYAiTKGlMCxKxTzK7wWEG_nYhDXC1Afj2z-tgvYhtn9MyDf2v0aIpDM9BoTOLEO-ButzylJ06pJlrJhpdvklvwJxUiuhlwy0bHNilb4Zv4QwnUv3DCrIeKe1ne90vEXe6YlDwSMeWJcz1DZIQBvVcNlN8q2y8Rae3lMWzsvD0YXrcXp02ckYoLSOQZgNYviGYLsgRgPGiIkncjSDt7WWV6td3l-zTrP6MT_hKigmg5F5_F6tS1bKb0jlQBZd0NP-_L_TPqMGRjCYG8johd6VyMiagslDjxG39Dh2wyTI19ZW7h_AOuOpnfkt2armqiq6iGfevA3malqkNakb6mFAS04J9O0butWVAw4yiPCEcLuDNAzzi_qrqLee4gkjh0NplvfGCaE6qqYms61GJbJC4wge6vjyTakurbqWEV3YoR3y_dn-0pjQ7TOx9kkruDwg0nZIV5O6yYxaulmbuvo3fs5CZb9ptZPD0MzGZj7CZU2MDCa4a4gr0McOx2MricxSzIu6emuRUzZuC6C1JxPRC00M0TrZNMIe_WVa9fXDLV1ULEAIMwMXzNT9zV6yiYQCwhkp30Wqde3W0LlIRpSbDuJXcvT8OCbXkdPNIScccdT9LvUQQ--hU2P45kisOev3TYn7yv-pdxM3u1KFNwuFxedSArMBPg7GDz1BOxDQRzv0mfwbf_CcoFbuyj7Tf4zWO46HVdHeRNbvIE--bnaSYD-UFaKknp8ZsBQQhBU_2TEca3fKwmg81-g7Vdb28QUZEuPzgE4ekxZejkKpiKqlLC5nJYgvXrqk2H35D51mYdzPs0ST05Mc41x9MFm_YOLxSFyA0yGAKVINmD5wT6kvRflPkgoksd2ryIvo4KMw3oZQKodv5By0mSJ8iX2vhTGylxiM8wj-ICyNuOsaRFrcMSpX7tZbXcDyysApdmx217BSADoQiNZBLngF7ptxc2QGyo3CwuDjaljwmSgL9KeGthd1RJFd826M287IPpCjLM4WRquCL_E0pQryNqOMn-ZEOCAlBjE37290EhkjKbhiGBEnHUvSbhoH4nL47AmunP_Q5aqh5173VfyoyaybuS3fXjQ5WO0kyFjMdD-a7C6PVdwToCTP-TljoF2YnQKCiqUGs9gNHS9mYhQSXzY4uuGlTHLfKB4JKS5_MQHvwI9zCbTvVG854fPuo_2mzSh-y8TSzBWPokhYWI_q095Sh6tOqDIJNMGyjI2GDFRSyKpKhIFCLyU2JEo9B6l91jPlir0XI8ZOQfBd9J0I4JIqnyoj40_1bF1zUDGc014bdGfxazxwlGph_ysKAP39wV7X9DBFS3ZmeSIn-r3s-sci0HmwnJUb2r03m40rFuNTV1cJMAFP7ZY7PQQQ0TtlO_al0uedaOWylLauap_eoRqc6xGJ2rSz1e7cOevksUlAqzK5xknYKHlsW970xuDGHKOZnKPg8O9nb2PKrcjwEQF5RFPc3l8TtOUXPhhvTERZFGoEuGuSuSp1cJhzba06yPnL-wE3CstYUm3jvkaUme6kKqM4tWBCQDg-_2PYf24xXYlmkIklylskqId826Y3pVVUd7e0vQO0POPeVYU1qwtTp7Ln-MhYEWexxptdNkVQ-kWx63w6HXF6_kefSxaf0UcvL8tOV73u7w_udle9MC_TXgwJZpoW2tSi5HETjQ_i28FAP2iJmclWOm3gP08cMiXvgpTpjzh6meBdvKepnifl_ivPzRnyjz3mYCZH-UJ4LmOHIonv-8arnckhCwHoFIpaIX7eSZyY0JcbBETKImtUwrlTSlbD8l02KDtqw2FJURtEWI5dC1sTS8c2HcyjXyQDA9A25a0M1yIgZyaadODGQ1zoa9xXB', provider_name='openai', ), ToolCallPart( tool_name='final_result', args='{"city":"Mexico City","country":"Mexico"}', tool_call_id='call_LIXPi261Xx3dGYzlDsOoyHGk', id='fc_001fd29e2d5573f70068ece2ecc140819c97ca83bd4647a717', ), ], usage=RequestUsage(input_tokens=103, output_tokens=409, details={'reasoning_tokens': 384}), model_name='gpt-5-2025-08-07', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_001fd29e2d5573f70068ece2e6dfbc819c96557f0de72802be', finish_reason='stop', ), ModelRequest( parts=[ ToolReturnPart( tool_name='final_result', content='Final result processed.', tool_call_id='call_LIXPi261Xx3dGYzlDsOoyHGk', timestamp=IsDatetime(), ) ] ), ] ) async def test_openai_responses_model_mcp_server_tool(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel( 'o4-mini', provider=OpenAIProvider(api_key=openai_api_key), ) agent = Agent( m, instructions='You are a helpful assistant.', builtin_tools=[ MCPServerTool( id='deepwiki', url='https://mcp.deepwiki.com/mcp', description='DeepWiki MCP server', allowed_tools=['ask_question'], headers={'custom-header-key': 'custom-header-value'}, ), ], ) result = await agent.run('Can you tell me more about the pydantic/pydantic-ai repo? Keep your answer short') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Can you tell me more about the pydantic/pydantic-ai repo? Keep your answer short', timestamp=IsDatetime(), ) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ BuiltinToolCallPart( tool_name='mcp_server:deepwiki', args={'action': 'list_tools'}, tool_call_id='mcpl_0083938b3a28070e0068fabd81d51081a09d4b183ced693273', provider_name='openai', ), BuiltinToolReturnPart( tool_name='mcp_server:deepwiki', content={ 'tools': [ { 'input_schema': { 'type': 'object', 'properties': { 'repoName': { 'type': 'string', 'description': 'GitHub repository: owner/repo (e.g. "facebook/react")', }, 'question': { 'type': 'string', 'description': 'The question to ask about the repository', }, }, 'required': ['repoName', 'question'], 'additionalProperties': False, '$schema': 'http://json-schema.org/draft-07/schema#', }, 'name': 'ask_question', 'annotations': {'read_only': False}, 'description': 'Ask any question about a GitHub repository', } ], 'error': None, }, tool_call_id='mcpl_0083938b3a28070e0068fabd81d51081a09d4b183ced693273', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0083938b3a28070e0068fabd84727c81a0a52c171d2568a947', signature='gAAAAABo-r2bs6ChS2NtAXH6S8ZWRHzygQvAZrQGsb5ziJKg6dINF9TQnq4llBquiZh-3Ngx2Ha4S-2_TLSbgcsglradULI8c8N2CnilghcqlLE90MXgHWzGfMDbmnRVpTW9iJsOnBn4ferQtNLIsXzfGWq4Ov0Bbvlw_fCm9pQsqOavcJ5Kop2lJ9Xqb__boYMcBCPq3FcNlfC3aia2wZkacS4qKZGqytqQP13EX3q6LwFVnAMIFuwn5XLrh4lFf-S5u8UIw3C6wvVIXEUatY6-awgHHJKXxWUxqRQPJegatMb8KE-QtuKQUfdvEE0ykdHtWqT7nnC3qTY67UaSCCvJ9SdXj-t806GVei9McSUe8riU3viHnfY0R0u9GIXsVnfVthIDRnX7KzpF5ot_CpCrgbCmD9Rj2AAos5pCdSzpc08G5auUuuMZfoiWANADTHHhO2OvflSEpmO8pb-QAYfMoK9exYVQ8Oig-Nj35unupcYy7A2bDCViXzqy32aw9QHmH7rErI4v72beWQxRVdX15Z7VS2c6L1dD7cU18K35CWqlSz9hEX5AcGqEEtIDVu1TdF3m1m2u4ooc4TjYpRecjYoG8Ib-vVKoX5C65a7G1cTbCo8dO0DYKGgM8jM7ZDubxbCcZ22Sxk58f8cer7WxHyp7WRo5-6zvMwMCk8uEY44RJmg-m0Oxl_6qxdr4Md80xZah_6tCCB62agQmYwCrR75_r93xOckQAK0R_37khvQD5gWVlE5Rg-01eUTboiPGqYmIsqWvOkziMGnxgKVw_yUf8swHU1ciWr7O1EdVPHLG7YXlVQTHTE_CX3uOsE2FoZnpS_MgpxGfjb76majV50h7mJ6ySVPF_3NF3RQXx64W08SW4eVFD8JJf0yChqXDmlwu2CDZN1n99xdaE9QbMODNEOmfTQOPhQ9g-4LhstNTKCCxWDh0qiv_dq2qAd0I9Gupoit33xGpb66mndc0nuuNFe8-16iC_KzQtHBNzgasgYK-r83KFVmiYK3Jxvz_2dfdwe0M1q7NLBvbnWc6k9LIf8iDUF6Q1J-cfC7SsncCbROtzIPlKpQwxhP-M09Xy3RVxlH9dcvuk3_qqEAartUQC8ZbuLRbhiq66eE1RvQzdNd2tsoBQ85cdNs57Penio7w9zILUf1JP5O8-zCe5GPC3W3EXTIEvHR-kiuxJvhcsySijpldGmuygRx05ARNOIT7VDCZvF23RfmnRduY1X1FAqb_i_aMStK7iyHr_2ohwOWLuklpyuoG0Y1ulvq1A9-hyCZ0mpvTEF6om2tAZ9_7h8W9ksiOkey0yA-6ze17MCjfnK2XcbqmSMgOngW1PrD81oKoheMnIeJdcWgF2mk8VDqmAwaDTxMxdnXkzK74rA43a4rWk3d2bUts8dAUkuYXTwJwKQw4LfXtu-mwwgJ6BkT_GiBcBJ6ulBuPsNZfpwPuxox6PS6KpzVTQ94cKNqSIIyFCD4xZsEvPALud09-gmAEDHxdnPjqLSi2U8xd0j-6XYKN0JtZ45kwEIRsOrFu-SYLz1OcYFKI5A5P-vYlzGx1WhEnoeUlyooJBhNj6ZBfj9f63SByxm7sgh260vf1t-4OGzVTIUKFluxkI4ubigLZ-g4q4dSwiEWXn50JFPrtuPs5VxsIIz_lXbh1SrKeQ647KdDSAQZFgEfzOOt3el5K97V1x7V7gEWCCgmqDIz3yZPpwD6qmUQKqlj_p8-OQrniamGULkXrmrgbNQVfV-Qw7Hg6ELw4aHF_IZME9Qnyn7peFhH6ai_YapuNF7FK-MBtPYoMaqBf05U2-uJAVUas3VuT_-pTyHvhtFmB7vc0-qgf_CtVNIXSPq2_vXdQdEwwCVPPwW6xWm-invrzhyQR_mf3OQqZT6_zOHIMPBJUaXcQKT0KTdoBZUDamAR-ECZl8r6wdLCn0HjAEwj3ifUCNMzQ7CZHUQG46rj61YyasNWO__4Ef4kTcApKgljosuABqP4HAdmkP5eEnX-6nutrL50iv-Mms_R-T7SKtmEEf9wihTu4Meb441cU9DI4WwSyiBSnsYdGy9FJKmHwP7HD0FmpmWkOrtROkQVMlMVKQFlKK8OBtxafHYsZkWDawbA1eetzMBzQ3PP8PSvva6SJWjbgURHVm5RjXV8Hk6toIBEDx9r9vAIczSp49eDCkQbzPkGAVilO3KLQpNx2itBbZzgE36uV0neZZsVs7aqafI4qCTQOLzYA8YFDKz92yhgdIzl5VPFLFNHqRS4duPRQImQ7vb6yKSxjDThiyQQUTPBX_EXUAAR7JHwJI1i8la3V', provider_name='openai', ), BuiltinToolCallPart( tool_name='mcp_server:deepwiki', args={ 'action': 'call_tool', 'tool_name': 'ask_question', 'tool_args': { 'repoName': 'pydantic/pydantic-ai', 'question': 'Provide a brief summary of the repository, including purpose, main features, and status.', }, }, tool_call_id='mcp_0083938b3a28070e0068fabd88db5c81a08e56f163bbc6088b', provider_name='openai', ), BuiltinToolReturnPart( tool_name='mcp_server:deepwiki', content={ 'output': """\ Pydantic AI is a Python agent framework designed to build production-grade applications using Generative AI, emphasizing an ergonomic developer experience and type-safety . It provides type-safe agents, a model-agnostic design supporting over 15 LLM providers, structured outputs with Pydantic validation, comprehensive observability, and production-ready tooling . The project is structured as a UV workspace monorepo, including core framework components, an evaluation system, a graph execution engine, examples, and a CLI tool . ## Purpose <cite/> The primary purpose of Pydantic AI is to simplify the development of reliable AI applications by offering a robust framework that integrates type-safety and an intuitive developer experience . It aims to provide a unified approach to interacting with various LLM providers and managing complex agent workflows . ## Main Features <cite/> ### Type-Safe Agents <cite/> Pydantic AI agents are generic `Agent[Deps, Output]` for compile-time validation, utilizing `RunContext[Deps]` for dependency injection and Pydantic `output_type` for output validation . This ensures that the inputs and outputs of agents are strictly typed and validated . ### Model-Agnostic Design <cite/> The framework supports over 15 LLM providers through a unified `Model` interface, allowing developers to switch between different models without significant code changes . Implementations for providers like OpenAI, Anthropic, and Google are available . ### Structured Outputs <cite/> Pydantic AI leverages Pydantic for automatic validation and self-correction of structured outputs from LLMs . This is crucial for ensuring data integrity and reliability in AI applications . ### Comprehensive Observability <cite/> The framework includes comprehensive observability features via OpenTelemetry and native Logfire integration . This allows for tracing agent runs, model requests, tool executions, and monitoring token usage and costs . ### Production-Ready Tooling <cite/> Pydantic AI offers an evaluation framework, durable execution capabilities, and protocol integrations . * **Tool System**: Tools can be registered using the `@agent.tool` decorator, with automatic JSON schema generation from function signatures and docstrings . * **Graph Execution**: The `pydantic_graph.Graph` module provides a graph-based state machine for orchestrating agent execution, using nodes like `UserPromptNode`, `ModelRequestNode`, and `CallToolsNode` . * **Evaluation Framework**: The `pydantic-evals` package provides tools for creating datasets, running evaluators (e.g., `ExactMatch`, `LLMEvaluator`), and generating reports . * **Integrations**: It integrates with various protocols and environments, including Model Context Protocol (MCP) for external tool servers, AG-UI for interactive frontends, and Temporal/DBOS for durable execution . ## Status <cite/> The project is actively maintained and considered "Production/Stable" . It supports Python versions 3.10 through 3.13 . The documentation is built using MkDocs and includes API references and examples . ## Notes <cite/> The repository is organized as a monorepo using `uv` for package management . Key packages include `pydantic-ai-slim` (core framework), `pydantic-evals` (evaluation system), `pydantic-graph` (graph execution engine), `examples` (example applications), and `clai` (CLI tool) . Wiki pages you might want to explore: - [Overview (pydantic/pydantic-ai)](/wiki/pydantic/pydantic-ai#1) View this search on DeepWiki: https://deepwiki.com/search/provide-a-brief-summary-of-the_a5712f6e-e928-4886-bcea-b9b75761aac5 """, 'error': None, }, tool_call_id='mcp_0083938b3a28070e0068fabd88db5c81a08e56f163bbc6088b', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0083938b3a28070e0068fabd97008081a0ad1b2362bcb153c9', signature='gAAAAABo-r2bD-v0Y3pAlyAEK1Sb8qJJcJRKSRtYwymHwLNXY-SKCqd_Q5RbN0DLCclspuPCAasGLm1WM1Q2Y_3szaEEr_OJalXTVEfRvhCJE1iTgoz2Uyf7KttZ4W92hlYjE8cjgdo5tKtSVkNyzTs4JUHKRHoDMutL2KivjZKuK_4n-lo9paJC_jmz6RWO8wUoXo3_fGxjliOGnWyRXwEPmgAcEWNOSVgCgAEO3vXerXRPLie02HegWcLMtK6WORDHd02Kr86QSK3W30bnvU7glAFX6VhSSnR8G0ceAM-ImoomQ8obEDyedX1-pYDKPOa4pZ5iTjD24ABYOwz-0L7SNziQJLycwwsr11Fj0_Au9yJph8YkNb2nAyFeiNVCRjKul51B7dZgz-UZ9juWO2ffeI0GNtQTYzf46_Y1t0qykGW6w59xjmBHTKf5SiSe0pqWxZ6LOLoPx01rX2gLaKgNZZiERSbO0iwbA4tpxb9ur-qeFVv5tS7xy8KFYOa8SPrypvFWDoY6CjSwTS3ir0vyfpbJy-n6bcYP_pTwDZxy_1aVkciim8Tmm_9wYgI0uY5kcA9VYJuyc4cg7S7ykTUxMZz7xiLMf8FoXl1gHbVJrYriyZzh2poYTWlcCuSCiUaXhQKxcxMRrt_P7WANx0n68ENQ40HkoJ6rThvWUuwtmEYqZ0ldh3XSFtyNrqha4PQ5eg_DudlU_5CxyykuzWmi_o5MEW4_XW4b9vdXg1laqx4189_jEuV_JPGNeL3Ke4EbMbKHzsiaGePRZGgNutnlERagmU4VFTeoE5bN3oHlR_Au4PeQxdb7BuBmZRDDCnnIRd2NfSWb7bgfUozkA4S6rm_089OlRBeRVoLtA8zZZinNGtOZl7MtkLnoJVIWpF1rr7D_47eWSyyegUIIS2e5UKLJfCLkNgSlWPU9VquHEzSfqeHfzoN5ccoVwrvrHmeveTjI-wIJygdfuyti5cMgOOkAtLzjWmbs4CjmlWcbZKeidtDj5YpCSmYAGFuZze-cSbNjMv4th639dCu_jmRMze-l2Y5npbRwMqEJr7VLXghmLc1vhOsaQM3gxoF0CJJlmvtR4jxPqhE3694YRva6LS1WjR4oueM6zfpVeB2kC0hQgqaL6MiwtTRYFfuCzEHi18TwA5bqqkfgrDXedmjAzlEGSZFe2EBRlF_ZtagrVVTCagHQArnH3DkVQMEDCHCqDxA_PINR_997IxeNgGPsvazVdOOBef7sO4rvAWrC94nIlt7d4aViqbTNMW-W8rqjGFOqj1swrM0yoX5y6LY5oXPc3Mu35xeitn_paqtGPkvuH6WeGzAiNZFDoQkUdLkZ4SIH2lr4ZXmMI3nuTzCrwyshwcEu-hhVtGAEQEqVrIn8J75IzYTs1UGLBvhmcpHxCfG04MFNoVf-EPI4SgjNEgV61861TYshxCRrydVhaJmbLqYh8yzLYBHK6oIymv-BrIJ0LX222LwoGbSc0gMTMaudtthlFXrHdnswKf81ubhF7viiD3Y=', provider_name='openai', ), TextPart( content=IsStr(), id='msg_0083938b3a28070e0068fabd989bb481a08c61416ab343ef49', ), ], usage=RequestUsage(input_tokens=1207, output_tokens=535, details={'reasoning_tokens': 320}), model_name='o4-mini-2025-04-16', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0083938b3a28070e0068fabd81970881a0a1195f2cab45bd04', finish_reason='stop', ), ] ) messages = result.all_messages() result = await agent.run('What packages does the repo contain?', message_history=messages) assert result.new_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='What packages does the repo contain?', timestamp=IsDatetime(), ) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ ThinkingPart( content='', id='rs_0083938b3a28070e0068fabd9de42881a08fbb49a65d0f9b06', signature='gAAAAABo-r2izZacxe_jVh_p3URhewxBJuyLNqkJOd0owsDPt9uCE7MXn06WHhO_mp6gLDAqcF1uhMhXCqwztJ1Nbpc0cEDAxUpUCUn2bKSgG6r8Snc_FPtKGgQWDsByvW_Nigx55CyPuNeDO_MiDgYee_WeUw7ASLPfiGOx_9YNc_BFYo1ngsb8CKZcJn3AoponMheLoxkVAPgOjMgteRVaQTr13MljTDUlBIZLIOhVbtIu_dI23saXPigbgwR4RhGn5mCHG_a9ILNkXDJUmGy5TKklIEi2HuJM3ZJ3gfoGYS3OONvzmU4AgMP2UrU17YKZAYKxUBKSpyAqigd4RJSYWzxBCoYzCTmiITwdZ6Cpsw1X9Wox_TQSGt5G2Xu0UY2TQZGRNNH8knJpWs-UQxBBV4L3alMwJuIeV-uzqeKr5fKO5rL_c9as-qQIW_EGQItjvR5z80Hi-S9VXthWCmtqZFIJkgLB5JfTYuFL86valsFVLzSavUIWJAG5qOcxag2mbZMwMRRNfvR__BBtoqBoeGIqveQAbIeZbG0ymw30PH1a2v1mmSrpkK6PB3AHYRDdpkezXLkbyGYgidyV2DAAtPaFplsubWCh_74UxmOuk4BH-9cWkE15mRUBrvtnbTb793RsPzOe7nPmkMpdgqa3nqc6RcQZ_M30lFLUViAbfpEpMVrCzz2cv1RklT1JUzpuVXBTKqQ4FxVCfnvzSgQ2INQ8K50E1X5w_7TAWhrHbNg6LetCa-4KWe9ps0GH6r1x9FWvGyVxSwa7SIdPq3sGpxjOydluPECbBOnHWFUB-3rI2DcUl4rGWYbv2FEFNeCH9Zr67uUvMc4Doi8nVMoeb1lJxFCrfziGhbEXY0FepH3zIzlj-_dXqLAL1qqhfCznT_xkDMVYg-D5gMu-_p3r2SirjJbeaz5UFmP-Dihd9v7jWgD6hx_Mq1uIdzIPE8ImGiDPR7PK64svkvwYg1Czdrc_7GmrKRuzsBL0720UXe19NQqCZfYvUJAjgbEqr3tuS_RkhuEQeeVORn88xkhkrGCEgBS0LHFpe4tcnUEXKnaYYRnoYtk5xo4EyOGVKR2yhF9ht2zrMTo83YuRAPcNT38Jk4gMtVhBaJw_GOfee-IWN_F258rpmU4p8sRV-1iSuQI3Arm4JBU66QuyjoY-KJmTcE9ft3Bfm9If3yG5W0RFRJrsVb--GjHmiiXDGWiR5Q8L1of_RnSD5QDEbXXxhn4dsDejtCXUaQXE9Ty-NvkvA7G6Ru8cMvIKqP2fXS9SmiW6ePJ2Znrlyafxx6L58pT26RF42h90BVrSldf6SjxQApK3AKZW6q8AkuJnYWTtkR9-qfIDl7W94BsgOFoEd-SDQGxWzGJV9YqAu6_SQKiNDQoZZHrJkRSOPEW_b3-BAdrpwL700I92Rye4-BdhlgeK1RwhT3w1Z-z1tvGZXJtPwdpPa3iIw2TIlesMbC1ZJ22iT3CB_r0lnlZhMtIH6o50l50UGfSDuv8HZ_RNgGnYEPqP3FW-o_VD_Yu_KBqGSA0Eb5xAJjl0vpin2vFGO1P4RdgI17eZXRsCp1KvkpWjbEQTWAvJz39yr7wFQ4BrPfgxUqMP0-ZI_h1DkdPBzWs1uKqHw-4qC77sZXgxgHGEIU1tfKosTy_fK4c-WAbdqIHNTh9VdlM1EdrUJQ4rs2rsUG8o9WXwnGTFchI9Ao64LiCFTFTiFL_dvKI4ZraNNXXprfPhxsdLBaNfgj2CIfUwBMJ9xMGmHKQKLtwZdHpQNVqi8DNm1qjvs3CxbSXGKtkl5K8UhJtI1g4OnEnbq3jDO8DGIyDl0NH-0bcCDqS2yAkh8I3IobzxTg16mqU3roXLQ4pGXnWbx26A_9zb4Y1jV7rzCq24VIfNJzMUtW4fVMYzlrp3X1l32I5hF3YP-tU2paD98xobgc2Cn2RWXd3OirrdjKAE088KhXYLZZY59y4LYRLC6MDMHSX0cbEXbBvl6mKmbaFig2_7ICiSa7rR_Ij6PpQRxIW7NfS7ZMu5w7TnhLJyg5nuwMI8A5pVxfy3gYg2L60wepuX7UUV0USaHNKi8qxbp4RJj4nO-GdE8TbLJtvPw-OzrH9Qiv7iDHVMHOe1CDPLD5IeGqmVB0tuLqlyASuIe3oPxTU7QdctyxHa1z-sO8nN6kpPnzmVmS6XK8bY-h5do28dkZvefomSquXwKeiVg9VAMWVziKLPWWg5iWp2x-spLkWcQsQle2T7xizyETaF1t6YbecXtSoVFmu90_o6ns07etU3RVK1YpQLgqUIJwwF3ZwP65MaWPwqDuWCuoQErlApdhRptxId67KE3UC4j8cAaGSoG0kXnws-jzpPyAg1GU8c-Gu_K0F-h-KFbHPMiWCrrQqzVfvoA2wLaQz3NPAqpq-kbFmrXRGkzLIeIvRVxck-sKkxQIcg3amSV5Dykl-lRCXGxlWNiFG_1SFrTSfp5VKyg7l1KjJzXUXHtqAErsPtMyhxaMmlh4An5a8NIaM9W6tafJrBXpUh85DfwZ8W92OAi1WOgoJIwWXSSeSuo6ECDstjVWW3OQQh9183jliwS7Bis3eu9jgAF3q8sYILBdwjrJRa6aAna2GirNwqZMEIg60kIlvmf1U6S2PgYaPm9UDzvMxjpzwjhXhzxHJitfU1tfl0vo-ATaTV8CxmKerNzy2AjlIZnjknG3xLyonCHbGbAe33QQTclb98y_vr5nA4WKlrls413o0a0f8GL8GjINCOd1RHVMjV', provider_name='openai', ), TextPart( content="""\ The monorepo is organized into these main packages: \n\ • pydantic-ai-slim\u2003– core agent framework (type-safe agents, model interface, tooling) \n\ • pydantic-evals\u2003\u2003– evaluation system (datasets, metrics, evaluators, reports) \n\ • pydantic-graph\u2003\u2003– graph-based execution engine (state-machine orchestration) \n\ • clai\u2003\u2003\u2003\u2003\u2003\u2003\u2003– CLI for scaffolding and running agents \n\ • examples\u2003\u2003\u2003\u2003– sample apps & demos showing real-world usage\ """, id='msg_0083938b3a28070e0068fabda04de881a089010e6710637ab3', ), ], usage=RequestUsage(input_tokens=1109, output_tokens=444, details={'reasoning_tokens': 320}), model_name='o4-mini-2025-04-16', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0083938b3a28070e0068fabd9d414881a089cf24784f80e021', finish_reason='stop', ), ] ) async def test_openai_responses_model_mcp_server_tool_stream(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel('o4-mini', provider=OpenAIProvider(api_key=openai_api_key)) agent = Agent( m, instructions='You are a helpful assistant.', builtin_tools=[ MCPServerTool( id='deepwiki', url='https://mcp.deepwiki.com/mcp', allowed_tools=['ask_question', 'read_wiki_structure'], ), ], ) event_parts: list[Any] = [] async with agent.iter( user_prompt='Can you tell me more about the pydantic/pydantic-ai repo? Keep your answer short' ) as agent_run: async for node in agent_run: if Agent.is_model_request_node(node) or Agent.is_call_tools_node(node): async with node.stream(agent_run.ctx) as request_stream: async for event in request_stream: if ( isinstance(event, PartStartEvent) and isinstance(event.part, BuiltinToolCallPart | BuiltinToolReturnPart) ) or (isinstance(event, PartDeltaEvent) and isinstance(event.delta, ToolCallPartDelta)): event_parts.append(event) assert agent_run.result is not None messages = agent_run.result.all_messages() assert messages == snapshot( [ ModelRequest( parts=[ UserPromptPart( content='Can you tell me more about the pydantic/pydantic-ai repo? Keep your answer short', timestamp=IsDatetime(), ) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ BuiltinToolCallPart( tool_name='mcp_server:deepwiki', args={'action': 'list_tools'}, tool_call_id='mcpl_00b9cc7a23d047270068faa0e29804819fb060cec0408ffbcd', provider_name='openai', ), BuiltinToolReturnPart( tool_name='mcp_server:deepwiki', content={ 'tools': [ { 'input_schema': { 'type': 'object', 'properties': { 'repoName': { 'type': 'string', 'description': 'GitHub repository: owner/repo (e.g. "facebook/react")', } }, 'required': ['repoName'], 'additionalProperties': False, '$schema': 'http://json-schema.org/draft-07/schema#', }, 'name': 'read_wiki_structure', 'annotations': {'read_only': False}, 'description': 'Get a list of documentation topics for a GitHub repository', }, { 'input_schema': { 'type': 'object', 'properties': { 'repoName': { 'type': 'string', 'description': 'GitHub repository: owner/repo (e.g. "facebook/react")', }, 'question': { 'type': 'string', 'description': 'The question to ask about the repository', }, }, 'required': ['repoName', 'question'], 'additionalProperties': False, '$schema': 'http://json-schema.org/draft-07/schema#', }, 'name': 'ask_question', 'annotations': {'read_only': False}, 'description': 'Ask any question about a GitHub repository', }, ], 'error': None, }, tool_call_id='mcpl_00b9cc7a23d047270068faa0e29804819fb060cec0408ffbcd', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_00b9cc7a23d047270068faa0e4cd5c819f8855c183ff0fe957', signature='gAAAAABo-qDma-ZMjX6meVDoCLYMqgkbQoEVzx_VFnmBFRLqsq37MiF7LP1HrMpqXqtrZ0R2Knb6lUiGSKhsOjOUAn9IFNUCuJx23cPLObF2CKt86wGLb7vccbCrp8bx-I6-kUtZASjlJx7_eJnvwyr24FLZlaDyGDuqRecGA8H4tXnQSAQTT9fJqy8h8dXvxvYzNj5rgOUWgRGn1NBph164KpiEzVWHADzZ_K0l4fX-DFHgtNFssPDYqOKLs_nU0XO8xaIZOgJ8QTf0XmHYF02GA_KciV6sIlSzVricQkwmu1XfJbjpME8XmRMIzlnLRqC8SAJs2kiaYnA8ObfI-s0RbRd3ztIUrzmAsdeo13ualD3tqC1w1_H6S5F47BB47IufTTbpwe_P6f5dLGpOzcrDPbtfHXv-aAW5YEsGyusXqxk51Wp7EONtADmPmVLJffFbRgnwfvPslbxxpNGfxNkN2pIs3U1FW7g1VvmxUfrF84LJpPKvs3xOaWXGorrPBY5nUyeRckhDFt6hGdS59VICmVy8lT4dL_LNswq7dVRS74HrrkfraXDDm2EhL2rtkwhiMqZtuYFsyIK2ys0lZuhNAkhtfgIoV8IwY6O4Y7iXbODxXUr48oZyvLdgV2J2TCcyqIbWClh3-q8MXMmP5wUJdrqajJ8lMVyhQt0UtMJKyk6EWY1DayGpSEW6t8vkqmuYdhyXQOstluONd31LqnEq58Sh8aHCzrypjcLfjDRo5Om1RlxIa-y8S-6rEIXahcJCX_juSg8uYHzDNJffYdBbcLSVQ5mAVl6OM9hE8gHs7SYqw-k-MCeoYsZwt3MqSV7piAu91SMZqB0gXrRDD67bdhmcLBYKmZYKNmLce60WkLH0eZMPSls-n2yyvmwflJA---IZQZOvYXpNUuS7FgMrh3c7n9oDVp15bUgJ8jDx6Mok4pq9E-MHxboblGUpMlFCJDH3NK_7_iHetcqC6Mp2Vc5KJ0OMpDFhCfT3Bvohsee5dUYZezxAkM67qg0BUFyQykulYLHoayemGxzi1YhiX1Of_PEfijmwV2qkUJodq5-LeBVIv8Nj0WgRO-1Y_QW3AWNfQ80Iy6AVa8j9YfsvQU1vwwE9qiAhzSIEeN1Pm2ub8PaRhVIFRgyMOLPVW7cDoNN8ibcOpX-k9p_SfKA9WSzSXuorAs80CTC9OwJibfcPzFVugnnBjBENExTQRfn4l7nWq-tUQNrT4UNGx-xdNeiSeEFCNZlH50Vr5dMaz5sjQQEw_lcTrvxKAV5Zs1mtDf6Kf29LkqhuUEdlMLEJwnAdz2IHLIy41zWLQctSnzBl9HB3mkw8eHZ1LdaRBQRFH4o7Rumhb3D1HdIqDLWeE3jkA6ZBAh2KadGx1u3AIIh4g3dHUS6UREkmzyRIuImbdTsoin1DrQbuYbaqZwIqU4TTIEmA8VeohMfff0rIL5yyFy7cfgGYurgAyMhARPGAAMAoTrR8ldWwymzPkGOJ_SQlzfNGV8weHOEYUl2BgQe57EDX4n1Uk294GIbvGR7eLRL_TLBUyHQErCaOCi8TkBNlLXIobw4ScN_jqqtURmC0mjRDVZeBi6hfrVShWChpQR8A2HxxHrcuHi2hi_2akgUea3zz6_zbUYVoIRdOa9DvZuN015E8ZSL-v_1_vOzUGvt0MuWPazjiRDWgpgcISYzT8N-Xzu_EbwO1OsaOFIeUqrD8mZ6MKOuBQts68og0DWo8KQaHmCaWi4O-c8-5fbB2q3H6oiIoZtSJIoowAmFGOwyWxn_OPS9svDgEaeFYEYhXZ5wZDphxoHkjJ703opxrWoEfQw==', provider_name='openai', ), BuiltinToolCallPart( tool_name='mcp_server:deepwiki', args='{"action":"call_tool","tool_name":"ask_question","tool_args":{"repoName":"pydantic/pydantic-ai","question":"What is the pydantic/pydantic-ai repository about?"}}', tool_call_id='mcp_00b9cc7a23d047270068faa0e67fb0819fa9e21302c398e9ac', provider_name='openai', ), BuiltinToolReturnPart( tool_name='mcp_server:deepwiki', content={ 'error': None, 'output': """\ The `pydantic/pydantic-ai` repository is a Python agent framework designed to simplify the development of production-grade applications using Generative AI . It aims to bring the ergonomic developer experience and type-safety philosophy of Pydantic and FastAPI to AI agent development . ## Core Purpose and Features The framework focuses on providing a robust and type-safe environment for building AI agents . Key features include: * **Type-safe Agents**: Agents are generic `Agent[Deps, Output]` for compile-time validation, leveraging Pydantic for output validation and dependency injection . * **Model-agnostic Design**: It supports over 15 LLM providers through a unified `Model` interface, allowing for easy switching between different models and providers . * **Structured Outputs**: Automatic Pydantic validation and reflection/self-correction ensure structured and reliable outputs from LLMs . * **Comprehensive Observability**: Integration with OpenTelemetry and native Logfire provides real-time debugging, performance monitoring, and cost tracking . * **Production-ready Tooling**: This includes an evaluation framework (`pydantic-evals`), durable execution capabilities, and various protocol integrations like MCP, A2A, and AG-UI . * **Graph Support**: It provides a way to define graphs using type hints for complex applications . ## Framework Architecture The framework is structured as a UV workspace monorepo, containing several packages . ### Core Packages * `pydantic-ai-slim`: Contains the core framework components such as `Agent`, `Model`, and tools . * `pydantic-ai`: A meta-package that includes all optional extras . ### Supporting Packages * `pydantic-graph`: Provides the graph execution engine with `Graph` and `BaseNode` . * `pydantic-evals`: An evaluation framework for datasets and evaluators . * `examples`: Contains example applications . * `clai`: Provides a CLI interface . ## Agent Execution Flow The `Agent` class serves as the primary orchestrator . Agent execution is graph-based, utilizing a state machine from `pydantic_graph.Graph` . The execution involves three core node types: * `UserPromptNode`: Processes user input and creates initial `ModelRequest` . * `ModelRequestNode`: Calls `model.request()` or `model.request_stream()` and handles retries . * `CallToolsNode`: Executes tool functions via `RunContext[Deps]` . The `Agent` provides methods like `run()`, `run_sync()`, and `run_stream()` for different execution scenarios . ## Model Provider Support The framework offers a unified `Model` abstract base class for various LLM providers . This includes native support for providers like OpenAI, Anthropic, Google, Groq, Mistral, Cohere, and Bedrock . Additionally, many OpenAI-compatible providers can be used with `OpenAIChatModel` . ## Tool System Tools are registered using the `@agent.tool` decorator . The system automatically generates JSON schemas from function signatures and docstrings, validates tool call arguments, and provides context injection via `RunContext[Deps]` . ## Observability Integration Pydantic AI integrates with OpenTelemetry, allowing for instrumentation of agent runs, model requests, and tool executions . It has native integration with Pydantic Logfire for enhanced monitoring and visualization . ## Evaluation Framework The `pydantic-evals` package provides a framework for systematically testing and evaluating AI systems . It supports defining datasets with `Case` objects and using various evaluators, including built-in and custom ones . ## Integration Ecosystem Pydantic AI supports various integrations for development and production: * **Model Context Protocol (MCP)**: For external tool server access . * **AG-UI Protocol**: For interactive application frontends . * **Agent2Agent (A2A)**: For multi-agent communication and workflows . * **Temporal**: For durable workflow execution . * **DBOS**: For database-backed execution and state persistence . ## Notes The `CLAUDE.md` file provides guidance for Claude Code when working with the repository, including development commands and an overview of core components and design patterns . The `mkdocs.yml` file defines the structure and content of the project's documentation, including navigation, plugins, and watch directories for various packages . The `docs/install.md` file details how to install the `pydantic-ai` package and its optional components, including a "slim" installation option for specific model dependencies . Wiki pages you might want to explore: - [Overview (pydantic/pydantic-ai)](/wiki/pydantic/pydantic-ai#1) View this search on DeepWiki: https://deepwiki.com/search/what-is-the-pydanticpydanticai_e234e9cf-d4aa-4c67-a257-56034816dd56 """, }, tool_call_id='mcp_00b9cc7a23d047270068faa0e67fb0819fa9e21302c398e9ac', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_00b9cc7a23d047270068faa0f4ff54819f9fb9ff25bebe7f5f', signature='gAAAAABo-qD2WTMmhASwWVtFPlo7ILZP_OxHfRvHhda5gZeKL20cUyt0Np6wAHsJ6pyAsXCkLlKBVz3Vwm52JrJuUbqmw-zlXL19rbpvTPRMkiv_GdSfvmxKKNJvSm417OznBDVjsIAqmes2bMq03nRf6Pq2C0oUJnIbpbMwtWzs3jMQqUb0IwyopqXGhn3MWKctLPKZS89nyL4E9kJAx_TyWTQvME8bf8UrV8y2yrNz9odjSQQyZq5YXrlHzpOJjDTfLofVFjsEzM8J29SdLcWnqlv4djJ8xeMpP2ByXuHRnTEyNNuxpYJB7uQbYT0T_eLhwcLv2ZzDZ_hf2Msv7ZdyuPc7Yxc5YWlChB0iaHqQ_8UuMjIVurfgSIjSq2lTvJwdaA365-ZoBMpo4mG04jQDP3XM-0xEM6JTFWc4jZ1OjIXVpkjaXxdOOkYq3t3j8cqBQH69shFCEQr5tnM8jOEl3WHnkvaBg4xEMcd61hiLOKnWbQiYisbFucA8z5ZNbdohUZd-4ww0R8kSjIE5veiyT66gpIte0ItUnTyhIWy8SZYF9bnZGeS-2InDhv5UgjF2iXzgl6dmUrS-_ITgJkwu4Rdf9SBDJhji3_GUO9Za0sBKW8WohP142qY0Tbq4I6-7W1wJ3_gHJqiXVwDLcY90ODSyyC5_I3MgaALRC1wt55sHSeSsDjmNGmiH-m0snaqsI0JnAZwycnWCK17NamjQ9SxVM5tTqJgemkGFQNH1XhZPWvVj56mlj74KKbCJALQpdXD27C8LfdrlBd0v_zEmF1dh7e12I95fYeAlO51xOglBaMCgcMWSDHMGHsJBbJ04eVQSwYTl72rmkASTMaybD-aAm1m8qZnKU-f3xQradhs9l1x9eOfQDIsfWMr1aVMiZi59--VsrgYCbqBj7AGf8n6VNbQWkhO2etozwYZcdGIyiu4TaULX1Xp89Gb28M-tVkIrkQoHO_Z7wzKU1HRBViES1wRKUJ-Sa6wc8UP5orDxeOTFPUr7JL-qaj49cpKzvdlfuoIdbYwpsNvAg69sNbFI3w4jLxOT4yxS6thra1Bit6SY5wAEfrrjtzofLeg49aFqFVGIHeJ8kE3spc1rctpETkdHNyP9fEjZaM3mxR4yz0tPmEgUsd-sdw5BbOKDAVzwconmbeGBmf9KLXMEpRRH7-qSIWUscCi5qIdHXGYoQkStsNGrnhucn_hwqZCSti3Kbzfosud3zQPjW6NyuJCdeTxbDbsnrV7Lkge5j92pyxCHw9j0iuzofRW55_KToBtIvRoPr_37G_6d6TxK42mKqdbgk9GHrcXf27mXszCEzX-VfRVTxyc6JLfEy1iikdo-J2AzXPd4m3zE-zazBU3Z5ey596g8gxwXMkHakLrvwp4_-fQfcvs7sIH34xkEhz7BRdNok3Aqbu_zCt2np69jjHqfPQWZzAy1C-bmMuhAaItPYkkw-LgSu-YP6L89zNofK9Q_S3JwVsLN-fq-9OwhSjy_rQu22Gn4KD6saAu61QMXBPa6z0QJSFUZHJQ_megq1tENfB6wRVtQ0DdAvUwhUsMwx6yE9CT20bma4CloGW__aZuD9gikdQrQ1DCHOvTrfEpvHkl6-wuCImeNjsCvbRFAkx6Xgpc6fdbq4j6WyEVW_4VePNknFWYZ1cw795ka5uJMLc3hVughVlGwDbw60Q3utsjHPbu03pxPle5pdcVEYSQWa0WbFDCrF4ysK0lpmlF7', provider_name='openai', ), TextPart( content=IsStr(), id='msg_00b9cc7a23d047270068faa0f63798819f83c5348ca838d252', ), ], usage=RequestUsage(input_tokens=1401, output_tokens=480, details={'reasoning_tokens': 256}), model_name='o4-mini-2025-04-16', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_00b9cc7a23d047270068faa0e25934819f9c3bfdec80065bc4', finish_reason='stop', ), ] ) assert event_parts == snapshot( [ PartStartEvent( index=0, part=BuiltinToolCallPart( tool_name='mcp_server:deepwiki', args={'action': 'list_tools'}, tool_call_id='mcpl_00b9cc7a23d047270068faa0e29804819fb060cec0408ffbcd', provider_name='openai', ), ), PartStartEvent( index=1, part=BuiltinToolReturnPart( tool_name='mcp_server:deepwiki', content={ 'tools': [ { 'input_schema': { 'type': 'object', 'properties': { 'repoName': { 'type': 'string', 'description': 'GitHub repository: owner/repo (e.g. "facebook/react")', } }, 'required': ['repoName'], 'additionalProperties': False, '$schema': 'http://json-schema.org/draft-07/schema#', }, 'name': 'read_wiki_structure', 'annotations': {'read_only': False}, 'description': 'Get a list of documentation topics for a GitHub repository', }, { 'input_schema': { 'type': 'object', 'properties': { 'repoName': { 'type': 'string', 'description': 'GitHub repository: owner/repo (e.g. "facebook/react")', }, 'question': { 'type': 'string', 'description': 'The question to ask about the repository', }, }, 'required': ['repoName', 'question'], 'additionalProperties': False, '$schema': 'http://json-schema.org/draft-07/schema#', }, 'name': 'ask_question', 'annotations': {'read_only': False}, 'description': 'Ask any question about a GitHub repository', }, ], 'error': None, }, tool_call_id='mcpl_00b9cc7a23d047270068faa0e29804819fb060cec0408ffbcd', timestamp=IsDatetime(), provider_name='openai', ), previous_part_kind='builtin-tool-call', ), PartStartEvent( index=3, part=BuiltinToolCallPart( tool_name='mcp_server:deepwiki', tool_call_id='mcp_00b9cc7a23d047270068faa0e67fb0819fa9e21302c398e9ac', provider_name='openai', ), previous_part_kind='thinking', ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='{"action":"call_tool","tool_name":"ask_question","tool_args":', tool_call_id='mcp_00b9cc7a23d047270068faa0e67fb0819fa9e21302c398e9ac', ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='{"repoName":"pydantic/pydantic-ai","question":"What is the pydantic/pydantic-ai repository about?"}', tool_call_id='mcp_00b9cc7a23d047270068faa0e67fb0819fa9e21302c398e9ac', ), ), PartDeltaEvent( index=3, delta=ToolCallPartDelta( args_delta='}', tool_call_id='mcp_00b9cc7a23d047270068faa0e67fb0819fa9e21302c398e9ac' ), ), PartStartEvent( index=4, part=BuiltinToolReturnPart( tool_name='mcp_server:deepwiki', content={ 'error': None, 'output': """\ The `pydantic/pydantic-ai` repository is a Python agent framework designed to simplify the development of production-grade applications using Generative AI . It aims to bring the ergonomic developer experience and type-safety philosophy of Pydantic and FastAPI to AI agent development . ## Core Purpose and Features The framework focuses on providing a robust and type-safe environment for building AI agents . Key features include: * **Type-safe Agents**: Agents are generic `Agent[Deps, Output]` for compile-time validation, leveraging Pydantic for output validation and dependency injection . * **Model-agnostic Design**: It supports over 15 LLM providers through a unified `Model` interface, allowing for easy switching between different models and providers . * **Structured Outputs**: Automatic Pydantic validation and reflection/self-correction ensure structured and reliable outputs from LLMs . * **Comprehensive Observability**: Integration with OpenTelemetry and native Logfire provides real-time debugging, performance monitoring, and cost tracking . * **Production-ready Tooling**: This includes an evaluation framework (`pydantic-evals`), durable execution capabilities, and various protocol integrations like MCP, A2A, and AG-UI . * **Graph Support**: It provides a way to define graphs using type hints for complex applications . ## Framework Architecture The framework is structured as a UV workspace monorepo, containing several packages . ### Core Packages * `pydantic-ai-slim`: Contains the core framework components such as `Agent`, `Model`, and tools . * `pydantic-ai`: A meta-package that includes all optional extras . ### Supporting Packages * `pydantic-graph`: Provides the graph execution engine with `Graph` and `BaseNode` . * `pydantic-evals`: An evaluation framework for datasets and evaluators . * `examples`: Contains example applications . * `clai`: Provides a CLI interface . ## Agent Execution Flow The `Agent` class serves as the primary orchestrator . Agent execution is graph-based, utilizing a state machine from `pydantic_graph.Graph` . The execution involves three core node types: * `UserPromptNode`: Processes user input and creates initial `ModelRequest` . * `ModelRequestNode`: Calls `model.request()` or `model.request_stream()` and handles retries . * `CallToolsNode`: Executes tool functions via `RunContext[Deps]` . The `Agent` provides methods like `run()`, `run_sync()`, and `run_stream()` for different execution scenarios . ## Model Provider Support The framework offers a unified `Model` abstract base class for various LLM providers . This includes native support for providers like OpenAI, Anthropic, Google, Groq, Mistral, Cohere, and Bedrock . Additionally, many OpenAI-compatible providers can be used with `OpenAIChatModel` . ## Tool System Tools are registered using the `@agent.tool` decorator . The system automatically generates JSON schemas from function signatures and docstrings, validates tool call arguments, and provides context injection via `RunContext[Deps]` . ## Observability Integration Pydantic AI integrates with OpenTelemetry, allowing for instrumentation of agent runs, model requests, and tool executions . It has native integration with Pydantic Logfire for enhanced monitoring and visualization . ## Evaluation Framework The `pydantic-evals` package provides a framework for systematically testing and evaluating AI systems . It supports defining datasets with `Case` objects and using various evaluators, including built-in and custom ones . ## Integration Ecosystem Pydantic AI supports various integrations for development and production: * **Model Context Protocol (MCP)**: For external tool server access . * **AG-UI Protocol**: For interactive application frontends . * **Agent2Agent (A2A)**: For multi-agent communication and workflows . * **Temporal**: For durable workflow execution . * **DBOS**: For database-backed execution and state persistence . ## Notes The `CLAUDE.md` file provides guidance for Claude Code when working with the repository, including development commands and an overview of core components and design patterns . The `mkdocs.yml` file defines the structure and content of the project's documentation, including navigation, plugins, and watch directories for various packages . The `docs/install.md` file details how to install the `pydantic-ai` package and its optional components, including a "slim" installation option for specific model dependencies . Wiki pages you might want to explore: - [Overview (pydantic/pydantic-ai)](/wiki/pydantic/pydantic-ai#1) View this search on DeepWiki: https://deepwiki.com/search/what-is-the-pydanticpydanticai_e234e9cf-d4aa-4c67-a257-56034816dd56 """, }, tool_call_id='mcp_00b9cc7a23d047270068faa0e67fb0819fa9e21302c398e9ac', timestamp=IsDatetime(), provider_name='openai', ), previous_part_kind='builtin-tool-call', ), ] ) async def test_openai_responses_model_mcp_server_tool_with_connector(allow_model_requests: None, openai_api_key: str): m = OpenAIResponsesModel( 'o4-mini', provider=OpenAIProvider(api_key=openai_api_key), ) agent = Agent( m, instructions='You are a helpful assistant.', builtin_tools=[ MCPServerTool( id='google_calendar', url='x-openai-connector:connector_googlecalendar', authorization_token='fake', description='Google Calendar', allowed_tools=['search_events'], ), ], ) result = await agent.run('What do I have on my Google Calendar for today?') assert result.all_messages() == snapshot( [ ModelRequest( parts=[ UserPromptPart(content='What do I have on my Google Calendar for today?', timestamp=IsDatetime()) ], instructions='You are a helpful assistant.', ), ModelResponse( parts=[ BuiltinToolCallPart( tool_name='mcp_server:google_calendar', args={'action': 'list_tools'}, tool_call_id='mcpl_0558010cf1416a490068faa0f9679481a082dc4ac08889f104', provider_name='openai', ), BuiltinToolReturnPart( tool_name='mcp_server:google_calendar', content={ 'tools': [ { 'input_schema': { 'properties': { 'calendar_id': { 'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'description': "The ID of the calendar to search. Default one is 'primary'", 'title': 'Calendar Id', }, 'max_results': {'default': 50, 'title': 'Max Results', 'type': 'integer'}, 'next_page_token': { 'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'title': 'Next Page Token', }, 'query': { 'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'title': 'Query', }, 'time_max': { 'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'description': "Time in the ISO-8601 format. You can also use 'now' or leave null.", 'title': 'Time Max', }, 'time_min': { 'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'description': "Time in the ISO-8601 format. You can also use 'now' or leave null.", 'title': 'Time Min', }, 'timezone_str': { 'anyOf': [{'type': 'string'}, {'type': 'null'}], 'default': None, 'description': "Timezone of the event. Default is 'America/Los_Angeles'", 'title': 'Timezone Str', }, }, 'title': 'search_events_input', 'type': 'object', }, 'name': 'search_events', 'annotations': {'read_only': True}, 'description': 'Look up Google Calendar events using various filters.', } ], 'error': None, }, tool_call_id='mcpl_0558010cf1416a490068faa0f9679481a082dc4ac08889f104', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0558010cf1416a490068faa0fb684081a0a0b70f55d8194bb5', signature='gAAAAABo-qEE669V-_c3vkQAeRtSj9pi72OLJweRJe4IRZkLcFfnuwdxSeJM5DVDLzb3LbfzU0ee6a4KAae0XsETU3hELT1hn3LZPwfFku5zl7CVgsc1DmYBf41Qki1EPHFyIlMj937K8TbppAAqMknfLHHwV1FLb8TapccSEhJbzGutqD3c2519P9f6XHKcuDa8d-sjyUejF0QuSjINFcjifJ8DiU40cL_-K6OJotlx6e0FqOivz6Nlj13QZxQ0I3FiiSi03mYKy240jYMpOpjXr7yPmEXLdCJdP5ycmTiJLxf4Bugww6u4F2uxy22978ACyFGSLHBiQyjczj_can7qKXAkMwYJKcGNjaNi8jG5iTIwsGswRjD1hvY-AGUotMFbPCszX3HW1M_ar-livaheiZauCfKV-Uc1ZeI3gijWEwtWQ0jye29FyQPCCpOBvT6RbUvFEpfqpwcMQuUhOyEfgzli2dpuOAgkSjCPE6ctoxjbYa62YzE-yrXAGc5_ptQy_2vw7t0k3jUzSo2Tv0aKnqvvKcj9SIilkZV4Nf-TL_d2E7d48bBJDlqbAv7fkhhd2YlkLqwdR1MqZtygcR1Jh8p2Y1pFAa4mSj7hh4M-zfSu--6dij2iKIbnKQ4DbXyGpMZXBAqTHMe9PPOwGxWKShlN5a5T89B04d_GwJYBDJx2ctecqZxDMjkTn3wVGl_5wuDnrEgd0I91vmAoYuWldR_h8M_FjDFiHefdbZjw1TxVKjkp6wk6zQiXCvvCZYJa9XkhytcllWvUI4C0gbxHrEzZRy9Vii3buqnbiIM9Qj0VPx-Q-FKM_usZBBmlvmk9PMQ8rH9vVT8dRFNQEj-aqudB5yUcTx8XaUFwYAts04OObGBqXoazYtxh6WvHwrf09pb_g0dwzE_rlcQdYxcFLOpYD-AentRAjOuIr4bLRM9BMERBxPvvPCxZ2Mva8YqV2TIOtxzMY08freim6du1IuYprO6CoejPaBdULhct-nsPubOdjLBikZt_bwumvmqGXnxI_uu51b9HtzPeDpWIjF6pi88bcsOk0qglA9GAu3wwX-iIdaV19VdVCO4KJjxiVrbTY1IVgWSdz98Alb_HzpXsoS6i2PRAjjsYOe4RBX3etxjsY07XXLlmXAM_vuYXc8Y6STxvBk4ST4OkaCvUk9DoZbVL5KmVcT6TaFpbVCOB_eHkHIvMjXc35kzxCdqEMG3FpRzL_UkY8pPridvq2z1Xw0al2KEBvdKPlInB8-zX5ANGeRkMGZ6ZfyX1zCIdYLe3wrC8xqr5nUZ-ueWmtqYLavSg8mQKphp4QyVaiwtbxEt5GEiVG7_LR754mGQYPdr9Shh3ECAp8wmSfDVO8MHaLmzgo3RXeqlqFldRjQzDHtCaGhjD9bHKF3yWF2LtH4gUN-Sf--86lcq7iwHDSDm656P_FBfYmE7rA0svH-m3hQoBhza4CKJ7s7f7ZymEhcHAfH7SPImZ3Y-kT_Sy1mbCCf3Yg8uitrpX7ukO6_bIANS_R4oiOPcuLixbWY0ZSyq8ERB5fa5EsIUm7PpGxbO96nmk5rPkewyB4gCtslwJI0Ye7zHtqrDBz1j1nsjIKsRCfFWlUdRF8J1JPiiBSvP8SraQ_94cnKBCsl34BGsVm-R1_ULbuyahBzSHq2Kwr0XQuNLdGChyLKS_FZVT58kbRFsvjZnbalAZ-k9alMeZ-pdWX5f9nSn3w7fz675zOxnBaqiZmoWHXFNOBVGH7gkz05ynJ2B8j_RpdRNJKXUN8pAvf595HGl2IPdaDhqoeS2_3jixO5mmxZuPEdzopoBFRarWud99mxH-mYxWJzKiA1pLNqj7SO93p2-jB-jtsCfZfk6bVEWpRRkIEz0XvxffFTVuGUCqpGS7FiFZc4pQU24pCrdpg2w3xeDSrmfHDAx2vUvv0iRBnQxTTWx2-de2TQQTpR5tjFNyOhYGVn1OXqkbkNtIUHdnNGA1QBCU0Qs0471Ss1CrxXIeeNVSTd00jiu4_ELk6nJYgSpmS8G_crrDza8mRLV5Yk0ItRrZj6pwKUOEaYeyM-RHyhrjf09yaf7Qc3sAozQF0aXFCQjSYiVb98DuGH28HLUxW9ulmSKKR4pYKlCOLNGm0h_gWCpSa0H1HXCgEoPn68HyaJogv_xH3k4ERYyJnxu8zVbVPMGoa9q9nNRQQ9Ks2AvxYRQeGFSCTACBmuookvHsO1zjYfHNuSCD7pCLRFE76KlmSiAX6l9LNOq_xe9Oos-1AvcZHkmVsuh-mjTVkBOjG6zmnHiNJirBpORs_UWL5lmlQBeaXgdHxcb4tHIn8XYXFkQiC4b4pw==', provider_name='openai', ), BuiltinToolCallPart( tool_name='mcp_server:google_calendar', args={ 'action': 'call_tool', 'tool_name': 'search_events', 'tool_args': { 'time_min': '2025-10-23T00:00:00', 'time_max': '2025-10-23T23:59:59', 'timezone_str': 'America/Los_Angeles', 'max_results': 50, 'query': None, 'calendar_id': 'primary', 'next_page_token': None, }, }, tool_call_id='mcp_0558010cf1416a490068faa0fdf64481a085a3e5b8f7d6559a', provider_name='openai', ), BuiltinToolReturnPart( tool_name='mcp_server:google_calendar', content={ 'output': None, 'error': { 'code': 500, 'message': 'An unknown error occurred while executing the tool.', 'type': 'http_error', }, }, tool_call_id='mcp_0558010cf1416a490068faa0fdf64481a085a3e5b8f7d6559a', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0558010cf1416a490068faa0ff5c9081a0b156a84d46e5d787', signature='gAAAAABo-qEE72KCH4RlulMdH6cOTaOQwFy4of4dPd8YlZ-zF9MIsPbumWO2qYlZdGjIIXDJTrlRh_5FJv2LtTmMbdbbECA20AzFMwE4pfNd2aNLC5RhcHKa4M9acC1wYKAddqEOPP7ETVNBj-GMx-tMT_CY8XnBLWvSwPpcfde9E--kSrfsgvRn1umqDsao4sLlAtV-9Gc6hmW1P9CSJDQbHWkdTKMV-cjQ-wZHFCly5kSdIW4OKluFuFRPkrXs7kVmlGnMr8-Q5Zuu1ZOFR9mPvpu2JdxAFohjioM-ftjeBuBWVJvOrIF4nV-yIVHVT-_psAZaPUUB5cyPAtqpoxxIV3iPKPU8DHctP03g_0R6pSWWHhggvO5PBw3zyPwtBwOrHBipc4nQEWEMxZxLH5SYJauTKwHNOx9NyCq8JUjZXM_v4xsGxNa4cAp7GuXqR2YyW2sx7syRUiDwtebh0xk_YOQtkv8tAjzCofmaz3n8FJ2nGSXkilaV5Q8LUNO-9-D2tsAaScDVMuLMMAHFNp_GPplWrmGES4mTCNtTXWyF1GLcQBw8dYYctV66Ocy2_zxyDoB7SsR5htlV77nJ6u1Hbp3tk26LutDrhAhe55xcki8iblHbXNY9MRzR1SS5Zk3-dv0ex4QOzC663NvS9aK3olQbKYko5TvM7Pq4MFYfaxwFTVFVEdaskoDJieVyikz0ZzBjTsItIwL-Q2BVN2F_P_wgCV5hyDclNMPEGTMxajxfIFv-oEunmHY1_RJavl47iXWS8H3JWAvp-9YYQdTS4Aa6m5zPndvHOvEV355UawLHRPctHFUS7rE7rYmcU6KQaqC96JRM0KRfXNIgYtNfw6cxgnyqGxzTF7qeeVzObOqoQmz59Rh0U9ti37vqHb8Ca43-q2Gx2KaVZFj7MBQK8UodfaDRIEuyMB3XNfckxCefwHs7FeAj5NuNDBrm0uDcwJjs2JfY2i54gAES8kAPLGJgRpq_qdjVXqpO6W0H9E1vBdRem7zLPYbA8OOo-KCkRW4AFCVbgCpgIvo4GDNvFOMksl-d8zgQU2qroUWJRu58j1bdaar7Zlfxk0UR33nROmJpXGb_R-RCNAN1ZxJTdEU_dVfyLCeuIXPsnO-FlfO8J6Un3WWPNLuN_bDS5RocniI_ms71qLsisJQiPTs-JDFl-eMM2Hk3QqSCC6OT0CLG9XMmI_zva9yp2joQ8HdGMddE3FDCbLejRrx8fV-9Nd0tZ7SYjFG78_fre8IfL0L67CK1JIPYzhgRZgCb-FFwUy-stR_BstIn0sRr_tDCoHdxuoVCh0dZfTY1p27xbKQ50svHxp1caNp3uze0wLXP9STNouFjFpdIHMsDRaGfO9R9mMmUsFcmBMK3aikuHTpebyL1CeZsIzH2cbZLPRx3pN2IqJ-5h6-cORHuMqf3ysEEFCjXnqmzvWPuBjYDsxnxA1awaGkYKsKhqchgakrfplOjdG5tSkklggBJA93iRaUWIR-4oV6HkkrnpdK1w7BL_VT8upqZmkpHZtZCDSgINk5S5hoYPLBTtS3dcCmQIbLvPXPuGzdAZxl0bhD4Rm3GPDFszaDoFK0Jszcjlaf4SJqyZABKEf71dDbi1as-2Qwr4fxBiQIOsF8ChbYo6Z2iFtUpBnbruFUIwB5QyKfWnwEZbOgf4UbIvIqNMkTzMc8tJgz6Ddqfih8VeNH3v8_84J6vHU0SVm_gvkgQ6P6N_6r5LwNdlAEff0hFwn-aTHWZ3s8MICckUZj97lKoZxAl91WlsKa0yrLw24dxvJ6bhZf0FsOitUJGd7vFPx0TxSobUkzE2RrbQ3hziPxw2Gins4aI6YG3M1gfumd3MgdH-fYBvZulJ9vmw0ZC1Dqh6BkCWHOFKsnpQvHmYuyTzUmnYuJf8N5j_b9XNw0krmxouOCPQClFmIOBLw8XPbe3xf0F5JP7BC0PpjlPT33A5Z6Za5zlA5O-DE_Wp0WG885-GaKtZI-zBZW3R0lc9A4s0HbxqA3lqH8leXOCe6WO46Z_iTQlALpTR-7oaHqzTegq0KSmEjCFO-jLSrVZnBOQ4ddTvLj4ASsQbj-o6TFUFVZAKSLI3FtWovHw02Gc_D0luFz9TbfaXM-EapEQYajkG0_b_nSCoPq0T9HSyvU4oCxXyQvhwIgzbijR-BheN6a_l6hiqZCw9L1c8MdPRtjpbHtEwWkpQ62s8XdydeJnV5vJYp9ezBbS_vWQ7Nz1siai6epJTdzDkRm-dudVhKzdohwg-FOQ-5gSrvoPS_MF4lZvah3iXY1g4uePO4eNDWGJ74YPybiy', provider_name='openai', ), BuiltinToolCallPart( tool_name='mcp_server:google_calendar', args={ 'action': 'call_tool', 'tool_name': 'search_events', 'tool_args': { 'time_min': '2025-10-23T00:00:00Z', 'time_max': '2025-10-23T23:59:59Z', 'timezone_str': None, 'max_results': 50, 'query': None, 'calendar_id': 'primary', 'next_page_token': None, }, }, tool_call_id='mcp_0558010cf1416a490068faa102400481a09fa35e84bc26c170', provider_name='openai', ), BuiltinToolReturnPart( tool_name='mcp_server:google_calendar', content={ 'output': None, 'error': { 'code': 500, 'message': 'An unknown error occurred while executing the tool.', 'type': 'http_error', }, }, tool_call_id='mcp_0558010cf1416a490068faa102400481a09fa35e84bc26c170', timestamp=IsDatetime(), provider_name='openai', ), ThinkingPart( content='', id='rs_0558010cf1416a490068faa102d89481a0b74cca04bcb8f127', signature='gAAAAABo-qEECuiSxfvrR92v1hkqyCTCWyfmpHSaW-vVouk5mOTIFDvaBZdVTFH8-dJfpwEG3MCejRKh9V-I8mrYAjhudVr1ayHo8UYOOU1cfVc6w3wsrkL8hXljjE-amiJhBSjvRc2nwwGtgYpDxOfWTqJkaUvFnMD6MrS4CwMrCBbDOLYZgM1cQbidtrrtpP7D5u42tR6coC_PCOqwPzDN4f0RggrxVxh0038p81VUmlkUeA2jWzRyFpeDGRjXFk84Og73rXAp7EWQv7TmzgVXBjCVwwzJNU8HCZ_gkwh5dvL94QxBx32lEmfOOKcqA3hN3FLwDqXlZ8f7jEqYInnpILQgX5XMdM9OrCyXmDCr_eIy00cjvxnTcXhCnZBOaKCKmTP74yUpGNdLbQcr4BalTiviNYEeCAhJyRo4KnhUZbBoT7MB5NULf-kqhRo1gEGKjWiLdV47PhR7Z8i4BK7zBceganMKpLtzIMW5a6JAujC4Z9FYxcpJZI_CD9NHsPr4SjKgIwv89d6BYo89-xfflF6ZUZBkuDUnL2-Nc9CKgGuKlcDunvYLr38pzA278OFYzh9T42u4SbS8KkSXKjGU3H8LfpMnBEZigriixLt5vj7qnWmZvCFarzxT4U4qqR1ITp5rkO6G9kYvBEfS7wu768mteDBgAajUaeOMQEfjJRErC4wfzbB89YCsXPJz0JE90QZ5LeiP5ZlVezTTaddG9JmiGsBCPckqUb1LWdpvekCfPkePF_uDMVWyJpQ4ZBzQsZx8sHf5spygsiQjlzTiriqwhoTcPuXoONoCr9HeFX1Qy8SGOm87siRPAD7FHJdDxbJwq8tOlMpx8MH1dqEY07lwoxZB0GQ9XbB7QJXfQR_27nkpqBYFkrbqChNJLO2x8gNFClbB0mgYQE1CRy64y6yOrG3CtS53RK5VGrF1GnqwuWdZ452VgShT5nAmPFRlRk1S9px4eMUTAozT0QAYrlHQC7b6I6K3m_Qe3kXGpnn_87i2eGG8mHmXG2FvFChkgf2OU7-LRy_Wl_u-ataICeoBwfngBFMppvUW6tJP009HK7mUE8P1KJntN3ExKLIBhmKhV6ziBpIi1bSTmd8leYqfSaf648c7-sVuDRx7DzxTp19l3fwVFa67GdiagZFs7xaU1HxMnMc3uy5VKWAH_qcv-Mga3VCTtTPpMTjvB95nsLeOFjS2FtpPvaP0N6o5kkkzW7cteWpOHhSX0z7AQA7CqgOCQLfLUc7ltVxnOH4WdHoeZFah_q_Ue6caf0kNo4YsTfbRDdzsW70o8P5Agr-Pgttg19vTDA_eBFur9GDKIRT0vYMWPpykwJBDTgJKOFW6uyNkqNWk_RAAvleE9pAyOoSmgomyrMcnnpdeYHNxeNxvTWFC3mcKSjJIB316wypPvaGTJyaK_pxJScD7CtLrIPkgwPpOsJnDySF6wGe-fGsUMt3zxJrc-S6fp24mYVfTRZbjUsP0fJgLmCohJiAtEg_xvlQ8sPyuLoLdOdossTQ7ufl0CwVn4f_ol4q__gpTvYVaoGsWl3QmHul5zj7OUAn7of6iBfCSlXbrauJvMyNYt4x_dLM8SXTRNPe-ZMDmER9DOw0KJXcUrpl6uw4TphKmUOK6KrxqshujXdN9VDgOwD7eKqIHpvC_6a2R6sS6ZHcebmh2o3bic-Hctomrbv03OQ==', provider_name='openai', ), TextPart( content=IsStr(), id='msg_0558010cf1416a490068faa103e6c481a0930eda4f04bb3f2a', ), ], usage=RequestUsage(input_tokens=1065, output_tokens=760, details={'reasoning_tokens': 576}), model_name='o4-mini-2025-04-16', timestamp=IsDatetime(), provider_name='openai', provider_details={'finish_reason': 'completed'}, provider_response_id='resp_0558010cf1416a490068faa0f945bc81a0b6a6dfb7391030d5', finish_reason='stop', ), ] ) async def test_openai_responses_requires_function_call_status_none(allow_model_requests: None, openai_api_key: str): model = OpenAIResponsesModel( 'gpt-5', provider=OpenAIProvider(api_key=openai_api_key), profile=replace(openai_model_profile('gpt-5'), openai_responses_requires_function_call_status_none=True), ) agent = Agent(model) @agent.tool_plain def get_meaning_of_life() -> int: return 42 result = await agent.run('What is the meaning of life?') messages = result.all_messages() _, openai_messages = await model._map_messages(messages, model_settings=model.settings or {}) # type: ignore[reportPrivateUsage] assert openai_messages == snapshot( [ {'role': 'user', 'content': 'What is the meaning of life?'}, { 'id': 'rs_01d311e2633707df0068fbac0050ec81a2ad76fd9256abcaf7', 'summary': [], 'encrypted_content': 'gAAAAABo-6wE6H4S9A886ZkwXcvvHqZ6Vx5BtpYvvNAJV5Ijq7pz-mTBJxfdjilNSzBj0ruy7NOsMRMhWzNahRf-n3KDQ2x1p-PjVCHM5IAGqHqae8A-aAUn_FDRiTbAT5N5FXTrZ80DAtdDv17z2HlODmTTYRvBU2-rX7opysjc4rf7-rvy6j4cUcNbM0ntT5DH8UHxC9LCM_s7Cb2unEV0jaDt7NzFxgfWN2u24Avs2EnjPoxOjd6BR-PWHJk_7kGGkVBub8NU7ZOyHsci3T8DAq_eX38DgkHJBJCPT4EqvlNP-VjPdecYEFUCw5G_Pye6h55-77g8LjkrFO43f8p6wscQ0iM601i1Ugmqbzxyv1ogPIN-YuSk2tkCw-D7xBD7I4fum2AmvyN-fR58lWcn-Z0WTqACA4baTJiCtW5b7uVeAp8vm8-gWzFR5BdDHVdQqu1TAKVWl_1P8NauDtd5M24MjVZd6WC0WrbTDPY9i2gieMMjFek2M8aoQFO0CG7r3JHn2zxfFB3THWCpl4VqZAQp6Ok7rymeY0Oayj--OLpNMBXIYUWc51eyYeurwQ943BSkf-m6PPVKO8T5U__Bx-biCNCePSlFKp7V0Du6h7UgYoqqonH2S3Jrg87c6dk7VJ7ca2i8sZqhy0rG6Kb7ENDVvwkMOdpnaFgdWd3VINp6P8j69kBQg-qwWP-YHPC9LnsjT2j1ktMowVO97eOpV4j2BhiThxunmu_SOIAEbghmjJEkLuRxLxBUPFRIajke2CvvFeIuReJr53isPKOxOjVzsc6oG5ZeykDlfz_mfEap7AByPNY0987zwG58tGueNxXjdpd7NQFcn_6DKj60SvUg0sk49V_QrDY3cAhSRvZoEeqA8XR97pEe7CByYMl80b9fzgyahc4NCdUwK8es2ll-lsJwEx1ZGdC8cB45QOrTnw8tJAUsSM44rLKwAQY-KsuN4UygO99d1CQZEm2YWtnPAvA9I-EhY87UIDx0CpPsEyxxFu2GZCTy7ceSnpcmQbAFWXzfBSpM7k42xVV8G8IK_bHpoF1enF5Vbc37_L_aWd4AgzuAwF_RVyd8exVh3NVJtO3BqPv72kTukr2Fok3KEaSeU0whP_dxr-thP2exS0F2Jdn13ZtB_pqxwKVWEsvzdbN92Q9qs10BAgYs2SA4cq66semwRl-1n-dr7XJyZzPOEiA9TQYgUCw0ueIc0ciMOZ0Waaj094bKIylw_TD5Bu1diXpzbTma_AVO-NZn7INhAZN3guSme-zIUEMrh66w0VJP-DbDA-ecSD41eMRSadyV4g86wLL4NOBE5NwSiSkwd2xJ9NqG7YohFM8BlPdEV4zhmqHcIKpVwAitFItqnAaUSU42Aebdritt9oNVnpKCeeA4QQv_8W7rOXJlLfGXRJUBCrh3Rv7KCVC3yncAOIU8FWu3jyaAqhLrWHLW958wjF8ka7lw80YZbToPjIuiii0UXu2w3Tv5EGVdkhf05A3Yj6M_LXStns8iBMzcU4-mJ1649FnnImLnW5AeohoWPBB6WYhW9gfwjuxejTI3Q5R0mo9jUSP3_tFiawlC2zFgvkNFufC6Kry8-Burjf8l6rpAX7_sjtCu1AlAbI6PEFtxcKhNWHfQp4mUATR6P4k68jk_Kl-FpRBtNOf8YOlLGrKE-WbwCoIV7VAgK2CTZJOxaslxVZRCLObNrA3XuEtc3jo8pMzqx8GJWshIgmF4XiQcmgh65U_kjB07adlgnbCZvGUXdIIQiA2vqIWC6Qu8SSO20nOOR65hGXyIgf4aOolU0Ljbi4slXnJKjbcPaX5O3cXvKHbkVFwXmHK2Ymaqb6fZcap78_On8jLK_GRlw3jV18SLeOcJiG2LqtHzcUawY4K7bPDNY2QX89yL5d4qxRF577QgzalmdQDsKyC_N-wk', 'type': 'reasoning', }, { 'name': 'get_meaning_of_life', 'arguments': '{}', 'call_id': 'call_cp3x6W9eeyMIryJUNhgMaP5w', 'type': 'function_call', 'status': None, 'id': 'fc_01d311e2633707df0068fbac038f1c81a29847e80d6a1a3f60', }, {'type': 'function_call_output', 'call_id': 'call_cp3x6W9eeyMIryJUNhgMaP5w', 'output': '42'}, { 'role': 'assistant', 'id': 'msg_01d311e2633707df0068fbac094ff481a297b1f4fdafb6ebd9', 'content': [{'text': '42', 'type': 'output_text', 'annotations': []}], 'type': 'message', 'status': 'completed', }, ] )

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pydantic/pydantic-ai'

If you have feedback or need assistance with the MCP directory API, please join our Discord server