From 32bb59553646bf960ca67cb19e8254d6aa47c4e0 Mon Sep 17 00:00:00 2001 From: Giles Odigwe Date: Fri, 16 Jan 2026 18:04:09 -0800 Subject: [PATCH 1/5] azureai image gen sample fix --- .../azure-ai/agent_framework_azure_ai/_shared.py | 12 ++++++++++++ .../azure_ai/azure_ai_with_image_generation.py | 14 +++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_shared.py b/python/packages/azure-ai/agent_framework_azure_ai/_shared.py index b99a3b5f66..511ff9508a 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_shared.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_shared.py @@ -10,6 +10,7 @@ HostedCodeInterpreterTool, HostedFileContent, HostedFileSearchTool, + HostedImageGenerationTool, HostedMCPTool, HostedVectorStoreContent, HostedWebSearchTool, @@ -31,6 +32,7 @@ CodeInterpreterTool, CodeInterpreterToolAuto, FunctionTool, + ImageGenTool, MCPTool, ResponseTextFormatConfigurationJsonObject, ResponseTextFormatConfigurationJsonSchema, @@ -442,6 +444,16 @@ def to_azure_ai_tools( timezone=location.get("timezone"), ) azure_tools.append(ws_tool) + case HostedImageGenerationTool(): + opts = tool.options or {} + azure_tools.append( + ImageGenTool( + model=opts.get("model_id", "gpt-image-1"), + size=opts.get("image_size"), + output_format=opts.get("media_type"), + partial_images=opts.get("streaming_count"), + ) + ) case _: logger.debug("Unsupported tool passed (type: %s)", type(tool)) else: diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py b/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py index 21166911ac..e5aad9c966 100644 --- a/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py +++ b/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py @@ -1,9 +1,10 @@ # Copyright (c) Microsoft. All rights reserved. import asyncio +import tempfile from pathlib import Path import aiofiles -from agent_framework import DataContent, HostedImageGenerationTool +from agent_framework import HostedImageGenerationTool, ImageGenerationToolResultContent from agent_framework.azure import AzureAIProjectAgentProvider from azure.identity.aio import AzureCliCredential @@ -32,7 +33,7 @@ async def main() -> None: tools=[ HostedImageGenerationTool( options={ - "model": "gpt-image-1-mini", + "model": "gpt-image-1", "quality": "low", "size": "1024x1024", } @@ -54,15 +55,14 @@ async def main() -> None: # Save the image to a file print("Downloading generated image...") image_data = [ - content + content.outputs for content in result.messages[0].contents - if isinstance(content, DataContent) and content.media_type == "image/png" + if isinstance(content, ImageGenerationToolResultContent) and content.outputs is not None ] if image_data and image_data[0]: - # Save to the same directory as this script + # Save to the OS temporary directory filename = "microsoft.png" - current_dir = Path(__file__).parent.resolve() - file_path = current_dir / filename + file_path = Path(tempfile.gettempdir()) / filename async with aiofiles.open(file_path, "wb") as f: await f.write(image_data[0].get_data_bytes()) From f8958c951b90f483a6685db22ee73bdf798a08fa Mon Sep 17 00:00:00 2001 From: Giles Odigwe Date: Sat, 17 Jan 2026 10:12:01 -0800 Subject: [PATCH 2/5] mypy fixes --- .../azure-ai/agent_framework_azure_ai/_shared.py | 10 +++++++--- .../agents/azure_ai/azure_ai_with_image_generation.py | 1 - 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_shared.py b/python/packages/azure-ai/agent_framework_azure_ai/_shared.py index 511ff9508a..e170c4a461 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_shared.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_shared.py @@ -446,11 +446,15 @@ def to_azure_ai_tools( azure_tools.append(ws_tool) case HostedImageGenerationTool(): opts = tool.options or {} + # Azure ImageGenTool requires the constant model "gpt-image-1" + # Cast optional fields to expected Literal unions for mypy compliance azure_tools.append( ImageGenTool( - model=opts.get("model_id", "gpt-image-1"), - size=opts.get("image_size"), - output_format=opts.get("media_type"), + model="gpt-image-1", + size=cast( + Literal["1024x1024", "1024x1536", "1536x1024", "auto"] | None, opts.get("image_size") + ), + output_format=cast(Literal["png", "webp", "jpeg"] | None, opts.get("media_type")), partial_images=opts.get("streaming_count"), ) ) diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py b/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py index e5aad9c966..947bb95781 100644 --- a/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py +++ b/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py @@ -34,7 +34,6 @@ async def main() -> None: HostedImageGenerationTool( options={ "model": "gpt-image-1", - "quality": "low", "size": "1024x1024", } ) From 2b295e82e516358b31f7618dc34036aae38f0651 Mon Sep 17 00:00:00 2001 From: Giles Odigwe Date: Tue, 20 Jan 2026 11:22:30 -0800 Subject: [PATCH 3/5] addressed comments + mapping updates --- .../agent_framework_azure_ai/_shared.py | 32 +++++++++++++------ .../azure_ai_with_image_generation.py | 11 +++++-- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_shared.py b/python/packages/azure-ai/agent_framework_azure_ai/_shared.py index e170c4a461..ca79f78db3 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_shared.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_shared.py @@ -33,6 +33,7 @@ CodeInterpreterToolAuto, FunctionTool, ImageGenTool, + ImageGenToolInputImageMask, MCPTool, ResponseTextFormatConfigurationJsonObject, ResponseTextFormatConfigurationJsonSchema, @@ -446,18 +447,29 @@ def to_azure_ai_tools( azure_tools.append(ws_tool) case HostedImageGenerationTool(): opts = tool.options or {} + addl = tool.additional_properties or {} # Azure ImageGenTool requires the constant model "gpt-image-1" - # Cast optional fields to expected Literal unions for mypy compliance - azure_tools.append( - ImageGenTool( - model="gpt-image-1", - size=cast( - Literal["1024x1024", "1024x1536", "1536x1024", "auto"] | None, opts.get("image_size") - ), - output_format=cast(Literal["png", "webp", "jpeg"] | None, opts.get("media_type")), - partial_images=opts.get("streaming_count"), - ) + ig_tool: ImageGenTool = ImageGenTool( + model="gpt-image-1", + size=cast( + Literal["1024x1024", "1024x1536", "1536x1024", "auto"] | None, opts.get("image_size") + ), + output_format=cast(Literal["png", "webp", "jpeg"] | None, opts.get("media_type")), + input_image_mask=( + ImageGenToolInputImageMask( + image_url=addl.get("input_image_mask", {}).get("image_url"), + file_id=addl.get("input_image_mask", {}).get("file_id"), + ) + if isinstance(addl.get("input_image_mask"), dict) + else None + ), + quality=cast(Literal["low", "medium", "high", "auto"] | None, addl.get("quality")), + background=cast(Literal["transparent", "opaque", "auto"] | None, addl.get("background")), + output_compression=cast(int | None, addl.get("output_compression")), + moderation=cast(Literal["auto", "low"] | None, addl.get("moderation")), + partial_images=opts.get("streaming_count"), ) + azure_tools.append(ig_tool) case _: logger.debug("Unsupported tool passed (type: %s)", type(tool)) else: diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py b/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py index 947bb95781..b894997fbb 100644 --- a/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py +++ b/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py @@ -33,9 +33,14 @@ async def main() -> None: tools=[ HostedImageGenerationTool( options={ - "model": "gpt-image-1", - "size": "1024x1024", - } + "model_id": "gpt-image-1", + "image_size": "1024x1024", + "media_type": "png", + }, + additional_properties={ + "quality": "low", + "background": "opaque", + }, ) ], ) From 91df80e4180a994869f49718179822f88e012ff6 Mon Sep 17 00:00:00 2001 From: Giles Odigwe Date: Wed, 21 Jan 2026 10:05:53 -0800 Subject: [PATCH 4/5] image model fix --- python/packages/azure-ai/agent_framework_azure_ai/_shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_shared.py b/python/packages/azure-ai/agent_framework_azure_ai/_shared.py index ca79f78db3..1f42eb82eb 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_shared.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_shared.py @@ -450,7 +450,7 @@ def to_azure_ai_tools( addl = tool.additional_properties or {} # Azure ImageGenTool requires the constant model "gpt-image-1" ig_tool: ImageGenTool = ImageGenTool( - model="gpt-image-1", + model=opts.get("model_id", "gpt-image-1"), # type: ignore size=cast( Literal["1024x1024", "1024x1536", "1536x1024", "auto"] | None, opts.get("image_size") ), From 4b85fa5d6eb7da974f11350d87f427ed5d395427 Mon Sep 17 00:00:00 2001 From: Giles Odigwe Date: Thu, 22 Jan 2026 08:35:13 -0800 Subject: [PATCH 5/5] content type fix --- .../azure_ai_with_image_generation.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py b/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py index b894997fbb..707a71f05c 100644 --- a/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py +++ b/python/samples/getting_started/agents/azure_ai/azure_ai_with_image_generation.py @@ -1,10 +1,12 @@ # Copyright (c) Microsoft. All rights reserved. import asyncio +import base64 import tempfile from pathlib import Path +from urllib import request as urllib_request import aiofiles -from agent_framework import HostedImageGenerationTool, ImageGenerationToolResultContent +from agent_framework import HostedImageGenerationTool from agent_framework.azure import AzureAIProjectAgentProvider from azure.identity.aio import AzureCliCredential @@ -61,14 +63,34 @@ async def main() -> None: image_data = [ content.outputs for content in result.messages[0].contents - if isinstance(content, ImageGenerationToolResultContent) and content.outputs is not None + if content.type == "image_generation_tool_result" and content.outputs is not None ] if image_data and image_data[0]: # Save to the OS temporary directory filename = "microsoft.png" file_path = Path(tempfile.gettempdir()) / filename + # outputs can be a list of Content items (data/uri) or a single item + out = image_data[0][0] if isinstance(image_data[0], list) else image_data[0] + data_bytes: bytes | None = None + uri = getattr(out, "uri", None) + if isinstance(uri, str): + if ";base64," in uri: + try: + b64 = uri.split(";base64,", 1)[1] + data_bytes = base64.b64decode(b64) + except Exception: + data_bytes = None + else: + try: + data_bytes = await asyncio.to_thread(lambda: urllib_request.urlopen(uri).read()) + except Exception: + data_bytes = None + + if data_bytes is None: + raise RuntimeError("Image output present but could not retrieve bytes.") + async with aiofiles.open(file_path, "wb") as f: - await f.write(image_data[0].get_data_bytes()) + await f.write(data_bytes) print(f"Image downloaded and saved to: {file_path}") else: