Repository navigation
feat: add StructuredOutputHook to parse an Agent's final reply into structured output - #13240
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Coverage reportClick to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||||||||||||||||||||
|
Thanks @sjrl, I tried the hook with a mock generator and live against OpenAI ( Works as described: the 18 unit tests pass. Both docs examples run unchanged. I also checked plain JSON, retries, retry exhaustion ( One thing I'd flag: replies wrapped in a markdown fence ( Happy to test anything else. |
|
@rautaditya2606 Thanks for testing this! We've added support for replies wrapped in a markdown code fence, which is now removed before parsing. |
julian-risch
left a comment
There was a problem hiding this comment.
Looks quite good to me already in general.
Two edge cases I found with AI code review and we should talk about them:
- When the run ends through max_agent_steps or a stop_run hook, the on_exit hook does not run and therefore in those cases result["structured_output"] raises KeyError. What about some fallback? For example running for
on_run_endtoo? Or alternatively at least document that behavior more explicitly? - The hook parses messages[-1] but if another on_exit hook runs before it and adds a user message, the hook parses that message instead of the model's reply. I'd say we can live with that limitation for now but at least documenting this would be good or maybe you have an idea for a simple fix.
|
@julian-risch Thanks! For 1, For 2, the hook now skips parsing when an earlier |
Related Issues
Proposed Changes:
StructuredOutputHook(haystack.hooks.structured_output), anon_exithook that parses the Agent's final text reply as JSON, validates it against a Pydantic model or JSON schema, and stores a dict under aStatekey (structured_outputby default). Declaring the key instate_schemamakes it an Agent output.max_retries: on invalid JSON or a schema mismatch the hook adds a user message with the error and schema and keeps the Agent running. Retries are counted from tagged correction messages in the current turn and stay bounded bymax_agent_steps.lengthcutoffs) and exhausted retries storeNoneand log a warning.How did you test it?
Unit tests with
MockChatGenerator(sync and async); ran the docs examples againstgpt-5.4-nano.Notes for the reviewer
exit_reasonstays"text"and only the output isNone.Checklist
fix:,feat:,build:,chore:,ci:,docs:,style:,refactor:,perf:,test:and added!in case the PR includes breaking changes.