deepset-ai / deepset-ai/haystack

OpenAI and Azure Responses Chat Generators fail to deserialize ComponentTool

Open
#12,484 1 comment 0 reactions 1 assignee View on GitHub

@julian-risch is already working on this.

Since Aug 27, 2026.

Dominant language
Python
Stars
26.6k
Forks
3.2k
Avg merge
1d 3h
Merged PRs (30d)
194

Description

Describe the bug

OpenAIResponsesChatGenerator.from_dict() and AzureOpenAIResponsesChatGenerator.from_dict() fail to deserialize ComponentTool objects.

Because from_dict() hardcodes a check for "haystack.tools.tool.Tool", ComponentTool (which serializes with "type": "haystack.tools.component_tool.ComponentTool") is skipped and left as an un-deserialized dictionary ({'type': '...', 'data': ...}).


To Reproduce
from haystack.components.builders import PromptBuilder
from haystack.components.generators.chat.openai_responses import OpenAIResponsesChatGenerator
from haystack.tools import ComponentTool

tool = ComponentTool(
    name="prompt",
    description="Builds prompt",
    component=PromptBuilder(template="hi"),
)

generator = OpenAIResponsesChatGenerator(tools=[tool])
data = generator.to_dict()

restored = OpenAIResponsesChatGenerator.from_dict(data)

# Fails: restored.tools[0] is <class 'dict'>, not ComponentTool
assert isinstance(restored.tools[0], ComponentTool)

Expected behavior

from_dict() should deserialize ComponentTool back into a ComponentTool instance, matching the behavior of OpenAIChatGenerator.from_dict().


Root Cause

In haystack/components/generators/chat/openai_responses.py (lines 367–374) and haystack/components/generators/chat/azure_responses.py (lines 259–266):

tools = data["init_parameters"].get("tools")
if tools and (
    isinstance(tools, dict)
    and tools.get("type") == "haystack.tools.toolset.Toolset"
    or isinstance(tools, list)
    and tools[0].get("type") == "haystack.tools.tool.Tool"
):
    deserialize_tools_or_toolset_inplace(data["init_parameters"], key="tools")

The check tools[0].get("type") == "haystack.tools.tool.Tool" fails for ComponentTool, skipping deserialize_tools_or_toolset_inplace().


Fix

Check for the presence of "data" to identify serialized Haystack tools:

tools = data.get("init_parameters", {}).get("tools")
if tools and (
    isinstance(tools, dict)
    and "type" in tools
    and "data" in tools
    or isinstance(tools, list)
    and isinstance(tools[0], dict)
    and "type" in tools[0]
    and "data" in tools[0]
):
    deserialize_tools_or_toolset_inplace(data["init_parameters"], key="tools")

Additional context
  • OS: Any
  • Haystack version: 2.31.0 (main)
  • Components: OpenAIResponsesChatGenerator and AzureOpenAIResponsesChatGenerator

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.