Skip to content

fix: replace structured output list state after validation - #13400

Open
emme1t wants to merge 2 commits into
deepset-ai:mainfrom
emme1t:fix/structured-output-list-state-20261022
Open

emme1t wants to merge 2 commits into
deepset-ai:mainfrom
emme1t:fix/structured-output-list-state-20261022

Conversation

@emme1t

@emme1t emme1t commented Oct 22, 2026

Copy link
Copy Markdown

Related Issues

Follow-up bug fix for the structured output hook introduced in #13240.

Proposed Changes:

When an Agent declares structured_output as list[str], the default state handler concatenates each write. An invalid reply followed by ["Paris"] therefore returns [None, "Paris"]; exhausted retries return a list of None values. Initial state values also remain in the result.

Use replacement semantics for all three structured output writes. The final state now contains the exact validated result, or None when parsing fails or the reply is truncated. Update the documentation and add a release note covering custom state handlers.

Minimal reproduction:

from haystack.components.agents import Agent
from haystack.components.generators.chat import MockChatGenerator
from haystack.dataclasses import ChatMessage
from haystack.hooks.structured_output import StructuredOutputHook

agent = Agent(
    chat_generator=MockChatGenerator(responses=["invalid", '["Paris"]']),
    state_schema={"structured_output": {"type": list[str]}},
    hooks={"on_exit": [StructuredOutputHook(
        schema={"type": "array", "items": {"type": "string"}},
        max_retries=1,
    )]},
)
result = agent.run(messages=[ChatMessage.from_user("List cities")])
assert result["structured_output"] == ["Paris"]

How did you test it?

  • All 9 added regression cases failed against the original implementation at 17a0e39.
  • hatch run test:unit test/hooks/structured_output test/components/agents/test_agent_hooks.py test/components/agents/test_state_class.py -q --no-cov: 149 passed on Python 3.14.5.
  • hatch run test:types haystack/hooks/structured_output/hooks.py test/hooks/structured_output/test_hooks.py: passed.
  • Ruff checks/formatting and all applicable pre-commit hooks passed for the four changed files.
  • Regression coverage includes JSON Schema and Pydantic RootModel, retries, exhausted retries, truncated replies, existing state, and async execution.

Notes for the reviewer

The hook overrides the output field's handler so its value retains the validated shape. Applications that collect multiple structured responses can accumulate the returned Agent outputs separately.

Checklist

  • Read the contributor guidelines and code of conduct.
  • Included the reproduction and findings above.
  • Added unit tests and updated docstrings and documentation.
  • Used a conventional commit PR title.
  • Added a Reno release note.
  • Ran pre-commit hooks and resolved reported issues.

This contribution was generated with AI assistance and validated with the checks listed above.

Astra辅助

@emme1t
emme1t requested a review from a team as a code owner October 22, 2026 15:59
@emme1t
emme1t requested review from davidsbatista and removed request for a team October 22, 2026 15:59
@vercel

vercel Bot commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

@emme1t is attempting to deploy a commit to the deepset Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant

CLAassistant commented Oct 22, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@HaystackBot

Copy link
Copy Markdown
Contributor

Hi @emme1t, thanks a lot for your contribution! 🙏

We noticed that the Contributor License Agreement (CLA) check (license/cla) hasn't passed yet, so we've temporarily moved this PR to draft and paused the review assignment.

To get your PR reviewed, please sign the CLA via the link in the license/cla check below (or in the CLA bot comment). As soon as the check turns green, this PR will automatically be marked ready for review again and a reviewer will be re-assigned.

@HaystackBot
HaystackBot removed the request for review from davidsbatista October 22, 2026 17:27
@HaystackBot HaystackBot added the cla-pending PR is in draft until the contributor signs the CLA label Oct 22, 2026
@HaystackBot
HaystackBot marked this pull request as draft October 22, 2026 17:27
@HaystackBot
HaystackBot marked this pull request as ready for review October 22, 2026 18:12
@HaystackBot HaystackBot removed the cla-pending PR is in draft until the contributor signs the CLA label Oct 22, 2026
@HaystackBot

Copy link
Copy Markdown
Contributor

Thanks for signing the CLA, @emme1t! 🎉 This PR is now ready for review again and the reviewer has been re-assigned.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants