Calling verify() with no guards configured fails closed. ResponseVerifier() without default_guards (or VerifiedOpenAI without guards) returns verified=False with the reason “No guards configured”, and blocks the response in strict mode. Earlier versions returned verified=True in this case. Constructing VerifiedOpenAI without guards also emits a UserWarning, because fail-closed verification would block every response. Always configure at least one guard.
verify_structured_output requires a schema or at least one guard. Calling it with neither raises ValueError, because the call would verify nothing. An explicitly supplied empty schema {} is honored as a valid JSON Schema that matches anything.
The OpenResponsesMiddleware intercepts streaming events from the Open Responses protocol, verifying tool_call and function_call items through your guard stack before they are yielded to the consumer.
from qwed_open_responses.middleware.streaming_interceptor import OpenResponsesMiddlewarefrom qwed_open_responses.guards import ToolGuard, SafetyGuardmiddleware = OpenResponsesMiddleware( guards=[ToolGuard(), SafetyGuard()], block_on_failure=True, # Replace blocked items with system_intervention on_blocked=my_callback, # Optional callback when an item is blocked)# Wrap any async stream of Open Responses itemsasync for item in middleware.verify_stream(response_stream): process(item)# Check runtime statsprint(middleware.get_stats())# {"total": 12, "verified": 10, "blocked": 2}
Non-tool items (text, metadata) pass through unchanged
Items with type of tool_call or function_call are verified against all guards in their original shape, before the middleware yields them. The type match ignores case and surrounding whitespace, so " Function_Call " is verified as a function_call
Tool-shaped items that can’t be verified unambiguously are blocked. This covers items with an unknown type, ambiguous envelopes, and tool calls nested inside other items
tool_result and function_call_output items pass through; the middleware does not validate their correlation metadata. Results that hide a nested tool call are blocked
If verification passes, the original item is yielded
If verification fails and block_on_failure is True, a system_intervention item is yielded instead:
Pass a context to verify_stream to enforce SafetyGuard budget limits for the whole stream:
middleware = OpenResponsesMiddleware( guards=[ToolGuard(), SafetyGuard(max_cost=5.0, max_tokens=20_000)],)async for item in middleware.verify_stream( response_stream, context={"total_cost": 1.25, "total_tokens": 4_000},): process(item)
The middleware copies the context and adds each item’s reported usage.cost and usage.total_tokens to the running total_cost and total_tokens. Later tool calls are verified against those totals, so a call that arrives after the budget is spent is blocked. Your original context dictionary is not modified.