Python: Fix structured_output propagation in ClaudeAgent (#4137)

* Fix structured_output propagation in ClaudeAgent

Capture structured_output from ResultMessage in _get_stream() and
propagate it to AgentResponse.value via a custom finalizer. Previously
structured_output was silently discarded, making output_format unusable.

Fixes #4095

* Address review feedback: use value parameter instead of private properties

- Extend AgentResponse.from_updates() to accept optional value parameter
- Remove structured_output yield from _get_stream()
- Update _finalize_response() to pass value via public API
- Update streaming test to use get_final_response()

* Fix mypy errors: add value parameter to from_updates overloads

Add value parameter to both @overload signatures of
AgentResponse.from_updates() so mypy recognizes the argument.

---------

Co-authored-by: Amit Mukherjee <amimukherjee@microsoft.com>
Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
This commit is contained in:
Amit Mukherjee
2026-02-23 12:45:02 -06:00
committed by GitHub
Unverified
parent 69eabcd1fc
commit 11628c3166
3 changed files with 183 additions and 2 deletions
@@ -2256,6 +2256,7 @@ class AgentResponse(SerializationMixin, Generic[ResponseModelT]):
updates: Sequence[AgentResponseUpdate],
*,
output_format_type: type[ResponseModelBoundT],
value: Any | None = None,
) -> AgentResponse[ResponseModelBoundT]: ...
@overload
@@ -2265,6 +2266,7 @@ class AgentResponse(SerializationMixin, Generic[ResponseModelT]):
updates: Sequence[AgentResponseUpdate],
*,
output_format_type: None = None,
value: Any | None = None,
) -> AgentResponse[Any]: ...
@classmethod
@@ -2273,6 +2275,7 @@ class AgentResponse(SerializationMixin, Generic[ResponseModelT]):
updates: Sequence[AgentResponseUpdate],
*,
output_format_type: type[BaseModel] | None = None,
value: Any | None = None,
) -> AgentResponseT:
"""Joins multiple updates into a single AgentResponse.
@@ -2281,8 +2284,9 @@ class AgentResponse(SerializationMixin, Generic[ResponseModelT]):
Keyword Args:
output_format_type: Optional Pydantic model type to parse the response text into structured data.
value: Optional pre-parsed structured output value to set directly on the response.
"""
msg = cls(messages=[], response_format=output_format_type)
msg = cls(messages=[], response_format=output_format_type, value=value)
for update in updates:
_process_update(msg, update)
_finalize_response(msg)