Skip to main content
Version: 2.31

Agent Pack

haystack_integrations.agent_pack.advanced_rag.agent

create_advanced_rag_agent

python
create_advanced_rag_agent(
*,
document_store: DocumentStore,
retriever: TextRetriever | Pipeline | None = None,
retrieval_pipeline_input_mapping: dict[str, list[str]] | None = None,
retrieval_pipeline_output_mapping: dict[str, str] | None = None,
llm: ChatGenerator | None = None,
backup_answer_llm: ChatGenerator | None = None,
system_prompt: str | None = None,
max_agent_steps: int = 20,
max_fetched_docs: int = 10,
extra_tools: ToolsType | None = None,
state_schema: dict[str, Any] | None = None,
hooks: dict[HookPoint, list[Hook]] | None = None,
raise_on_tool_invocation_failure: bool = False,
tool_concurrency_limit: int = 4
) -> Agent

Create the advanced RAG agent.

The agent answers questions from documents it retrieves out of the document store. Instead of guessing which metadata fields exist, it can inspect the store (fields, values, ranges) and construct a Haystack filter to narrow its retrieval when metadata helps — plain, unfiltered retrieval remains available when it doesn't. The answer cites the retrieved documents.

The required retriever becomes the search_documents tool; document_store additionally feeds the three metadata inspection tools and must implement the metadata introspection methods (get_metadata_fields_info, get_metadata_field_unique_values, get_metadata_field_min_max).

Parameters:

  • document_store (DocumentStore) – The document store the metadata inspection tools and the fetch_documents_by_filter tool run against.
  • retriever (TextRetriever | Pipeline | None) – What retrieves for the search_documents tool (required). Either a standalone retriever component following the TextRetriever protocol, i.e. its run method accepts query and filters (e.g. InMemoryBM25Retriever, or an embedding retriever wrapped in TextEmbeddingRetriever), or a custom retrieval Pipeline (e.g. embedder -> retriever, or hybrid retrieval) — a pipeline additionally requires retrieval_pipeline_input_mapping. It should retrieve by relevance scoring (keyword or embedding-based) — direct, unscored fetching is already covered by the built-in fetch_documents_by_filter tool.
  • retrieval_pipeline_input_mapping (dict[str, list[str]] | None) – Required when retriever is a Pipeline: maps the tool inputs to pipeline input sockets; must have exactly the keys "query" and "filters", e.g. {"query": ["embedder.text"], "filters": ["retriever.filters"]}.
  • retrieval_pipeline_output_mapping (dict[str, str] | None) – Optional when retriever is a Pipeline: maps pipeline output sockets to tool outputs, e.g. {"retriever.documents": "documents"}.
  • llm (ChatGenerator | None) – LLM that drives the agent loop. Defaults to OpenAIResponsesChatGenerator("gpt-5.4") with low reasoning effort.
  • backup_answer_llm (ChatGenerator | None) – LLM the built-in BackupAnswerHook uses to write a best-effort answer when the run is cut off by max_agent_steps. Defaults to a separate OpenAIResponsesChatGenerator("gpt-5.4") with low reasoning effort.
  • system_prompt (str | None) – Overrides the pre-made system prompt.
  • max_agent_steps (int) – Maximum steps for the agent loop. If the loop is cut off by this limit before writing an answer, an after_run hook (BackupAnswerHook) makes one extra LLM call to produce a best-effort answer from the evidence gathered so far, so last_message always carries a text answer.
  • max_fetched_docs (int) – Maximum number of documents fetch_documents_by_filter shows per fetch. A filter fetch is not bounded by a retriever's top_k, so this caps the tool result instead; the scored search_documents tool is bounded by the top_k configured on your retrieval components.
  • extra_tools (ToolsType | None) – Additional tools (or toolsets) for the agent, appended after the built-in document-store toolset and the retrieval tool.
  • state_schema (dict[str, Any] | None) – Additional entries merged into the agent's state schema. The built-in documents entry (the accumulated retrieved documents) always takes precedence.
  • hooks (dict[HookPoint, list[Hook]] | None) – Additional hooks per hook point, merged with the built-in hooks. For after_run, the built-in backup-answer hook runs first, so custom hooks see the final answer.
  • raise_on_tool_invocation_failure (bool) – If True, a failing tool call raises instead of being returned to the LLM as an error message it can recover from (the default).
  • tool_concurrency_limit (int) – Maximum number of tool calls executed in parallel within one agent step.

Returns:

  • Agent – The advanced RAG Agent. Call it with the question as a user message, agent.run(messages=[ChatMessage.from_user(question)]); the answer is in last_message (a ChatMessage) and documents carries every document the agent retrieved during the run (deduplicated by id, in first-retrieved order) — the answer cites them by the first 8 characters of their id, e.g. [doc a1b2c3d4]. The standard Agent outputs messages, step_count, token_usage and tool_call_counts are also returned.

haystack_integrations.agent_pack.advanced_rag.hooks

BackupAnswerHook

Produce a final answer when the agent run ends without one. Runs as an after_run hook.

When the agent exhausts max_agent_steps mid-investigation, the run ends on a tool call or tool result instead of an assistant text answer (and only after_run hooks run in this situation). This hook detects that case and makes one LLM call over the conversation so far to produce a best-effort answer from the already-gathered evidence.

init

python
__init__(chat_generator: ChatGenerator) -> None

Create the hook.

Parameters:

  • chat_generator (ChatGenerator) – LLM that writes the backup answer from the gathered evidence.

warm_up

python
warm_up() -> None

Prepare the hook's generator for use; called from the Agent's warm_up.

close

python
close() -> None

Release the hook's generator resources; called from the Agent's close.

to_dict

python
to_dict() -> dict

Serialize the hook to a dictionary.

Returns:

  • dict – Dictionary with serialized data.

from_dict

python
from_dict(data: dict) -> BackupAnswerHook

Deserialize the hook from a dictionary.

Parameters:

  • data (dict) – Dictionary to deserialize from.

Returns:

  • BackupAnswerHook – Deserialized hook.

run

python
run(state: State) -> None

Append a best-effort final answer when the run ended without one (e.g. step exhaustion).

Parameters:

  • state (State) – The agent run's state.

haystack_integrations.agent_pack.advanced_rag.tools

ListMetadataFieldsTool

Bases: Tool

Tool that lists all metadata fields and their types from a document store.

init

python
__init__(document_store: DocumentStore) -> None

Create the tool.

Parameters:

  • document_store (DocumentStore) – The document store to inspect. Must implement get_metadata_fields_info.

Raises:

  • ValueError – If the store does not implement get_metadata_fields_info.

to_dict

python
to_dict() -> dict[str, Any]

Serialize the tool to a dictionary.

from_dict

python
from_dict(data: dict[str, Any]) -> ListMetadataFieldsTool

Deserialize the tool from a dictionary.

Parameters:

  • data (dict[str, Any]) – The dictionary produced by to_dict.

Returns:

  • ListMetadataFieldsTool – The deserialized tool.

GetMetadataFieldValuesTool

Bases: Tool

Tool that returns the distinct values of a metadata field from a document store.

init

python
__init__(document_store: DocumentStore) -> None

Create the tool.

Parameters:

  • document_store (DocumentStore) – The document store to inspect. Must implement get_metadata_field_unique_values.

Raises:

  • ValueError – If the store does not implement get_metadata_field_unique_values.

to_dict

python
to_dict() -> dict[str, Any]

Serialize the tool to a dictionary.

from_dict

python
from_dict(data: dict[str, Any]) -> GetMetadataFieldValuesTool

Deserialize the tool from a dictionary.

Parameters:

  • data (dict[str, Any]) – The dictionary produced by to_dict.

Returns:

  • GetMetadataFieldValuesTool – The deserialized tool.

GetMetadataFieldRangeTool

Bases: Tool

Tool that returns the minimum and maximum values of a metadata field from a document store.

init

python
__init__(document_store: DocumentStore) -> None

Create the tool.

Parameters:

  • document_store (DocumentStore) – The document store to inspect. Must implement get_metadata_field_min_max.

Raises:

  • ValueError – If the store does not implement get_metadata_field_min_max.

to_dict

python
to_dict() -> dict[str, Any]

Serialize the tool to a dictionary.

from_dict

python
from_dict(data: dict[str, Any]) -> GetMetadataFieldRangeTool

Deserialize the tool from a dictionary.

Parameters:

  • data (dict[str, Any]) – The dictionary produced by to_dict.

Returns:

  • GetMetadataFieldRangeTool – The deserialized tool.

FetchDocumentsByFilterTool

Bases: Tool

Tool that fetches documents directly from a document store by metadata filter.

Unlike a scored retrieval tool, this fetches without any relevance ranking, so an agent can grab specific documents (e.g. a known title or source file) without going through a relevance search. The fetched documents are put into reading order first: grouped by their parent file (file_name/file_path/source_id) and sorted by their position within it (split_id/split_idx_start/page_number), using whichever of those metadata fields the documents carry. Match sets larger than max_docs are paged: each call returns one page plus the total match count, and the tool's offset input continues where the previous page ended.

init

python
__init__(
document_store: DocumentStore,
max_docs: int = 10,
max_fetch_factor: int = 10,
) -> None

Create the tool.

Parameters:

  • document_store (DocumentStore) – The document store to fetch documents from.
  • max_docs (int) – Ceiling on the number of documents shown to the agent per fetch. Unlike scored retrieval, a filter fetch is not bounded by a retriever's top_k, so this caps the tool result instead. The LLM can request fewer via the tool's optional max_docs input, but never more.
  • max_fetch_factor (int) – How many times the max_docs ceiling a filter may match before the fetch is refused outright (when the store supports count_documents_by_filter) — the refusal is surfaced to the LLM as an error it can recover from by narrowing the filter.

to_dict

python
to_dict() -> dict[str, Any]

Serialize the tool to a dictionary.

from_dict

python
from_dict(data: dict[str, Any]) -> FetchDocumentsByFilterTool

Deserialize the tool from a dictionary.

Parameters:

  • data (dict[str, Any]) – The dictionary produced by to_dict.

Returns:

  • FetchDocumentsByFilterTool – The deserialized tool.

DocumentStoreToolset

Bases: Toolset

All document-store-backed tools as one unit.

Bundles the three metadata inspection tools (ListMetadataFieldsTool, GetMetadataFieldValuesTool, GetMetadataFieldRangeTool) and the direct FetchDocumentsByFilterTool, so they can be handed to an Agent (or combined with a retrieval tool) as a single object.

init

python
__init__(document_store: DocumentStore, max_fetched_docs: int = 10) -> None

Create the toolset.

Parameters:

  • document_store (DocumentStore) – The document store all tools run against. Must implement the metadata introspection methods (get_metadata_fields_info, get_metadata_field_unique_values, get_metadata_field_min_max).
  • max_fetched_docs (int) – Maximum number of documents fetch_documents_by_filter shows per fetch (see FetchDocumentsByFilterTool.max_docs).

to_dict

python
to_dict() -> dict[str, Any]

Serialize the toolset to a dictionary.

from_dict

python
from_dict(data: dict[str, Any]) -> DocumentStoreToolset

Deserialize the toolset from a dictionary.

Parameters:

  • data (dict[str, Any]) – The dictionary produced by to_dict.

Returns:

  • DocumentStoreToolset – The deserialized toolset.

haystack_integrations.agent_pack.deep_research.agent

create_deep_research_agent

python
create_deep_research_agent(
*,
scope_llm: ChatGenerator | None = None,
orchestrator_llm: ChatGenerator | None = None,
researcher_llm: ChatGenerator | None = None,
summarizer_llm: ChatGenerator | None = None,
writer_llm: ChatGenerator | None = None,
max_subtopics: int = 5,
max_concurrent_researchers: int = 5,
max_orchestrator_steps: int = 8,
max_researcher_steps: int = 20,
max_search_results: int = 10,
max_content_length: int = 50000
) -> Agent

Create the deep research agent.

Parameters:

  • scope_llm (ChatGenerator | None) – LLM that rewrites the user query into a focused research brief. Defaults to OpenAIResponsesChatGenerator("gpt-5.4").
  • orchestrator_llm (ChatGenerator | None) – LLM that plans the investigation and delegates the sub-questions. Defaults to OpenAIResponsesChatGenerator("gpt-5.4").
  • researcher_llm (ChatGenerator | None) – LLM that drives each sub-researcher's search/read/think loop. Defaults to OpenAIResponsesChatGenerator("gpt-5.4-mini").
  • summarizer_llm (ChatGenerator | None) – LLM used inside the read_url tool to summarize a fetched page toward the question. Defaults to OpenAIResponsesChatGenerator("gpt-5.4-mini").
  • writer_llm (ChatGenerator | None) – LLM that turns the brief plus collected notes into the final report. Defaults to OpenAIResponsesChatGenerator("gpt-5.4").
  • max_subtopics (int) – Maximum number of sub-questions the orchestrator may delegate (breadth).
  • max_concurrent_researchers (int) – Maximum number of sub-researchers that run at the same time.
  • max_orchestrator_steps (int) – Maximum steps for the orchestrator's agent loop (reflect -> delegate rounds).
  • max_researcher_steps (int) – Maximum steps for each sub-researcher's agent loop.
  • max_search_results (int) – Number of results returned per web_search call.
  • max_content_length (int) – Maximum raw page characters fed to the summarizer, before summarization.

Returns:

  • Agent – The deep research Agent. Call it with the question as a user message, agent.run(messages=[ChatMessage.from_user(question)]); it returns a dict whose main output is report (the final markdown report, a str). The dict also carries the intermediate brief (str) and notes (list[str]), plus the standard Agent outputs messages, last_message, step_count, token_usage and tool_call_counts.