Support fully qualified type path in component trace output
Is your feature request related to a problem? Please describe.
In Haystack’s tracing system, each component emits metadata such as haystack.component.name, type, and input/output specs. However, haystack.component.type currently only includes the bare class name (e.g. "OpenAIChatGenerator"), without the fully qualified module path.
This creates friction for tools or devs that want to dynamically resolve or load a component by type — they’re forced to scan the codebase or maintain a manual mapping of known modules. This is especially problematic in modular or plugin-heavy environments.
Describe the solution you'd like Add a new trace field:
"haystack.component.type_fqn": "haystack.components.generators.chat.openai.OpenAIChatGenerator"
This gives the full dotted path to the class, enabling dynamic loading and better tooling. It also aligns with how all other trace metadata already uses fully qualified paths (e.g. in input_spec types).
Describe alternatives you've considered
- Manually resolving the class by searching across all known modules
- Overloading
typefield to include module path (not backward compatible)
Additional context Example for consistency:
"haystack.component.type": "OpenAIChatGenerator",
"haystack.component.type_fqn": "haystack.components.generators.chat.openai.OpenAIChatGenerator"
All other type fields already expose fully qualified paths (e.g. typing.List[haystack.dataclasses.chat_message.ChatMessage]), so this would bring the type field in line and remove ambiguity.
Here is the current tracing output structure with this field added:
{
"haystack.component.name": "chat_generator",
"haystack.component.type": "OpenAIChatGenerator",
"haystack.component.type_fqn": "haystack.components.generators.chat.openai.OpenAIChatGenerator",
"haystack.component.input_types": {
"messages": "list",
"tools": "list"
},
"haystack.component.input_spec": {
"messages": {
"type": "typing.List[haystack.dataclasses.chat_message.ChatMessage]",
"senders": []
},
"streaming_callback": {
"type": "typing.Union[typing.Callable[[haystack.dataclasses.streaming_chunk.StreamingChunk], NoneType], typing.Callable[[haystack.dataclasses.streaming_chunk.StreamingChunk], typing.Awaitable[NoneType]], NoneType]",
"senders": []
},
"generation_kwargs": {
"type": "typing.Optional[typing.Dict[str, typing.Any]]",
"senders": []
},
"tools": {
"type": "typing.Union[typing.List[haystack.tools.tool.Tool], haystack.tools.toolset.Toolset, NoneType]",
"senders": []
},
"tools_strict": {
"type": "typing.Optional[bool]",
"senders": []
}
},
"haystack.component.output_spec": {
"replies": {
"type": "typing.List[haystack.dataclasses.chat_message.ChatMessage]",
"receivers": []
}
},
"haystack.component.visits": 1
}
It is hard to properly fix https://github.com/deepset-ai/haystack-core-integrations/issues/2050 without resolving this issue. And we might likely need this fix anyway. It's a straightforward improvement/fix without any risk, only benefits.
Perhaps we could rename the field to haystack.component.type_qualified_name or haystack.component.fully_qualified_type?
Otherwise I agree we should be providing the fully qualified type for the component so they are easy/straightforward to inspect and not just the class name.
Alternatively @vblagoje to be more consistent with how we normally provide fully qualified types in our other type fields we could change the "haystack.component.type" to have the fully qualified type via our normal breaking change process. So add a Deprecation Warning in 2.16.0 and make the change in 2.17.0
Simultaneously, we could add a new field called "haystack.component.class_name" which would just have the name of the class in case users find it helpful to have just the last item of the fully qualified type. What do you think?
Alternatively @vblagoje to be more consistent with how we normally provide fully qualified types in our other type fields we could change the
"haystack.component.type"to have the fully qualified type via our normal breaking change process. So add a Deprecation Warning in 2.16.0 and make the change in 2.17.0
You’re more brave than I am - to me this looks that’s like unplugging a random cable in a data center, smiling, thinking everything is fine... and then 🤯
Yeah both are good but fully_qualified_type is more precise and explicit while class_name could again mean just the class name without module path
Yeah both are good but fully_qualified_type is more precise and explicit
Okay let's go for that then!