From 74da3d1c8abf71ce77bff1df4e4e9d1348dcbe3d Mon Sep 17 00:00:00 2001 From: tstadel <60758086+tstadel@users.noreply.github.com> Date: Fri, 31 Oct 2025 08:12:27 +0100 Subject: [PATCH] fix: Agent deserialization when `state_schema=None` (#9984) * fix: agent deserialization when state_schema None * add reno --- haystack/components/agents/agent.py | 2 +- ...none-deserialization-23e967b51a5a56ee.yaml | 4 ++ test/components/agents/test_agent.py | 70 +++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/fix-state-schema-none-deserialization-23e967b51a5a56ee.yaml diff --git a/haystack/components/agents/agent.py b/haystack/components/agents/agent.py index b8b7739ee..9b870cec5 100644 --- a/haystack/components/agents/agent.py +++ b/haystack/components/agents/agent.py @@ -239,7 +239,7 @@ class Agent: deserialize_chatgenerator_inplace(init_params, key="chat_generator") - if "state_schema" in init_params: + if init_params.get("state_schema") is not None: init_params["state_schema"] = _schema_from_dict(init_params["state_schema"]) if init_params.get("streaming_callback") is not None: diff --git a/releasenotes/notes/fix-state-schema-none-deserialization-23e967b51a5a56ee.yaml b/releasenotes/notes/fix-state-schema-none-deserialization-23e967b51a5a56ee.yaml new file mode 100644 index 000000000..64821c556 --- /dev/null +++ b/releasenotes/notes/fix-state-schema-none-deserialization-23e967b51a5a56ee.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - | + Fix deserialization of state schema when it is None in Agent.from_dict. diff --git a/test/components/agents/test_agent.py b/test/components/agents/test_agent.py index 24b977304..1cc0e94e0 100644 --- a/test/components/agents/test_agent.py +++ b/test/components/agents/test_agent.py @@ -464,6 +464,76 @@ class TestAgent: assert agent.tools[0].function is weather_function assert agent.exit_conditions == ["text"] + def test_from_dict_state_schema_none(self, monkeypatch): + monkeypatch.setenv("OPENAI_API_KEY", "fake-key") + data = { + "type": "haystack.components.agents.agent.Agent", + "init_parameters": { + "chat_generator": { + "type": "haystack.components.generators.chat.openai.OpenAIChatGenerator", + "init_parameters": { + "model": "gpt-4o-mini", + "streaming_callback": None, + "api_base_url": None, + "organization": None, + "generation_kwargs": {}, + "api_key": {"type": "env_var", "env_vars": ["OPENAI_API_KEY"], "strict": True}, + "timeout": None, + "max_retries": None, + "tools": None, + "tools_strict": False, + "http_client_kwargs": None, + }, + }, + "tools": [ + { + "type": "haystack.tools.tool.Tool", + "data": { + "name": "weather_tool", + "description": "Provides weather information for a given location.", + "parameters": { + "type": "object", + "properties": {"location": {"type": "string"}}, + "required": ["location"], + }, + "function": "test_agent.weather_function", + "outputs_to_string": None, + "inputs_from_state": None, + "outputs_to_state": None, + }, + }, + { + "type": "haystack.tools.component_tool.ComponentTool", + "data": { + "component": { + "type": "haystack.components.builders.prompt_builder.PromptBuilder", + "init_parameters": { + "template": "{{parrot}}", + "variables": None, + "required_variables": None, + }, + }, + "name": "parrot", + "description": "This is a parrot.", + "parameters": None, + "outputs_to_string": None, + "inputs_from_state": None, + "outputs_to_state": None, + }, + }, + ], + "system_prompt": None, + "exit_conditions": ["text", "weather_tool"], + "state_schema": None, + "max_agent_steps": 100, + "raise_on_tool_invocation_failure": False, + "streaming_callback": None, + "tool_invoker_kwargs": {"max_workers": 5, "enable_streaming_callback_passthrough": True}, + }, + } + agent = Agent.from_dict(data) + assert agent.state_schema == {"messages": {"type": list[ChatMessage], "handler": merge_lists}} + def test_serde(self, weather_tool, component_tool, monkeypatch): monkeypatch.setenv("FAKE_OPENAI_KEY", "fake-key") generator = OpenAIChatGenerator(api_key=Secret.from_env_var("FAKE_OPENAI_KEY"))