Python: [BREAKING] Make response_format validation errors visible to users (#3274)

* Make response_format validation errors visible to users

* Small fix

* Addressed comments
This commit is contained in:
Dmytro Struk
2026-01-19 09:20:46 -08:00
committed by GitHub
Unverified
parent 3c1be2a713
commit 83e8965c8e
12 changed files with 298 additions and 62 deletions
@@ -12,7 +12,7 @@ Functions host."""
import json
import logging
from collections.abc import Mapping
from typing import Any, cast
from typing import Any
import azure.functions as func
from agent_framework.azure import AgentFunctionApp, AzureOpenAIChatClient
@@ -102,7 +102,9 @@ def spam_detection_orchestration(context: DurableOrchestrationContext):
options={"response_format": SpamDetectionResult},
)
spam_result = cast(SpamDetectionResult, spam_result_raw.value)
spam_result = spam_result_raw.try_parse_value(SpamDetectionResult)
if spam_result is None:
raise ValueError("Failed to parse spam detection result")
if spam_result.is_spam:
result = yield context.call_activity("handle_spam_email", spam_result.reason)
@@ -123,7 +125,9 @@ def spam_detection_orchestration(context: DurableOrchestrationContext):
options={"response_format": EmailResponse},
)
email_result = cast(EmailResponse, email_result_raw.value)
email_result = email_result_raw.try_parse_value(EmailResponse)
if email_result is None:
raise ValueError("Failed to parse email response")
result = yield context.call_activity("send_email", email_result.response)
return result
@@ -101,10 +101,10 @@ def content_generation_hitl_orchestration(context: DurableOrchestrationContext):
options={"response_format": GeneratedContent},
)
content = initial_raw.value
content = initial_raw.try_parse_value(GeneratedContent)
logger.info("Type of content after extraction: %s", type(content))
if content is None or not isinstance(content, GeneratedContent):
if content is None:
raise ValueError("Agent returned no content after extraction.")
attempt = 0
@@ -146,11 +146,9 @@ def content_generation_hitl_orchestration(context: DurableOrchestrationContext):
options={"response_format": GeneratedContent},
)
rewritten_value = rewritten_raw.value
if rewritten_value is None or not isinstance(rewritten_value, GeneratedContent):
content = rewritten_raw.try_parse_value(GeneratedContent)
if content is None:
raise ValueError("Agent returned no content after rewrite.")
content = rewritten_value
else:
context.set_custom_status(
f"Human approval timed out after {payload.approval_timeout_hours} hour(s). Treating as rejection."