Haystack Agent Pack 集成实战指南:Advanced RAG Agent 与 Deep Research Agent 架构详解
【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack
本文以 Haystack 开源仓库中 Agent Pack 集成(agent-pack-haystack)的 API 参考文档为核心,系统讲解create_advanced_rag_agent与create_deep_research_agent两个工厂函数、背后四大文档存储工具与DocumentStoreToolset、BackupAnswerHook钩子,并结合仓库源码与用户指南,让读者掌握如何开箱即用地运行、按参数定制、并用Agent.clone深度改造这两个开箱即用的复杂 Agent 架构。
Agent Pack 是什么
Agent Pack 是 Haystack 生态中一组开箱即用的复杂 Agent集合,其代码独立于主仓库的haystack包,通过agent-pack-haystack单独分发(源码位于haystack-core-integrations仓库)。每个 Agent 都是一套由 Haystack 原生构件——Agent、Tool、hooks、State与 Pipeline——组合而成的完整架构,对外只暴露一个create_*工厂入口。
它的设计哲学决定了三种使用方式(详见 agent-pack.mdx):
- 直接运行:工厂函数以合理的默认值构建出可立即使用的 Agent,例如
create_deep_research_agent()返回一个"输入问题、输出报告"的 Agent。 - 参数化定制:每个入口暴露该 Agent 特有的一组关键字参数(如选用哪些 LLM);其余一切改动(加工具、加 hooks)通过返回对象的
clone()完成。 - 抄作业式参考:这些 Agent 本身就是为"可阅读、可改编"设计的,各部分易于拆解复用,可作为自定义 Agent 架构的蓝图。
当前 Agent Pack 提供两个成员(见 agent-pack.mdx):
| Agent | 定位 |
|---|---|
| Advanced RAG Agent | 检查文档存储的元数据,构造 Haystack 过滤器做精准检索,再带引用作答 |
| Deep Research Agent | 针对问题在 Web 上展开研究,产出带引用的结构化 Markdown 报告 |
实验性警告:Agent Pack 目前处于实验阶段(experimental),其 API 与 Agent 架构可在任何版本中变更,且不遵循常规的弃用策略。面向生产使用时请锁定版本并自行评估风险。
安装与前置条件
安装基础包:
pip install agent-pack-haystack两个 Agent 各有额外的运行时依赖与 API Key 要求:
- Advanced RAG Agent:
pip install agent-pack-haystack arrow。其中arrow是默认系统提示词渲染"今天日期"所必需的——Agent 需要据此构造类似"最近 5 年"的相对日期过滤器。同时需在环境中设置OPENAI_API_KEY。 - Deep Research Agent:
pip install agent-pack-haystack tavily-haystack trafilatura pypdf arrow。trafilatura(HTML 解析)、pypdf(PDF 解析)与arrow(日期渲染)是运行时依赖;tavily-haystack仅为默认的search_tool所需。需设置OPENAI_API_KEY与TAVILY_API_KEY。
Advanced RAG Agent:元数据感知的 RAG
核心思路
create_advanced_rag_agent创建一个元数据感知的 RAG Agent:它不靠猜测元数据字段是否存在,而是直接检查文档存储(字段、取值、范围),在元数据有助于缩小检索范围时构造 Haystack 过滤器;当元数据无法帮助缩小问题时,仍然退回到普通的无过滤检索。最终答案会引用检索到的文档。
适合使用的场景(见 advanced-rag-agent.mdx):
- 语料大而异构(主题、来源、文档类型混杂)且元数据结构良好——元数据能显著提升检索精度;
- 需要按元数据精确或完整地取出某个子集(如"某个文件的全部页面""来源 X 的全部文档"),而不只是最相关的 top-k 结果。
不适用的情况:元数据缺失或对缩小检索无帮助;语料小而均匀,普通 top-k 检索已足够。
工厂函数签名
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 ) -> Agent所有参数均为keyword-only,其中只有document_store与retriever是必填项,其余全部可选。
参数详解
检索相关
document_store(DocumentStore)— 元数据检查工具与fetch_documents_by_filter工具所运行于其上的文档存储。它必须实现元数据内省方法:get_metadata_fields_info、get_metadata_field_unique_values、get_metadata_field_min_max。retriever(TextRetriever | Pipeline | None)— 驱动search_documents工具的检索器(必填)。可以是:- 遵循
TextRetriever协议的独立组件,即run方法接受query与filters,例如InMemoryBM25Retriever,或包装在TextEmbeddingRetriever中的 embedding 检索器; - 一条自定义检索
Pipeline(例如 embedder → retriever,或混合检索),此时还必须提供retrieval_pipeline_input_mapping。
它应基于相关性打分(关键词或向量)检索——直接的、不打分的按元数据抓取已由内置的
fetch_documents_by_filter工具覆盖。- 遵循
retrieval_pipeline_input_mapping(dict[str, list[str]] | None)— 当retriever是Pipeline时必填:把工具输入映射到 Pipeline 输入 socket,必须恰好包含"query"与"filters"两个键,例如{"query": ["embedder.text"], "filters": ["retriever.filters"]}。retrieval_pipeline_output_mapping(dict[str, str] | None)— 当retriever是Pipeline时可选:把 Pipeline 输出 socket 映射为工具输出,例如{"retriever.documents": "documents"}。
模型与提示词
llm(ChatGenerator | None)— 驱动 Agent 主循环的 LLM。默认OpenAIResponsesChatGenerator("gpt-5.4")且使用低 reasoning effort。backup_answer_llm(ChatGenerator | None)— 内置BackupAnswerHook在运行被max_agent_steps截断时用来撰写尽力而为(best-effort)答案的 LLM。默认是独立的另一个OpenAIResponsesChatGenerator("gpt-5.4")(低 reasoning effort)。system_prompt(str | None)— 覆盖预置系统提示词。
限制参数
max_agent_steps(int,默认20)— Agent 循环的最大步数。若循环在写出答案前被该上限截断,after_run钩子BackupAnswerHook会额外发起一次 LLM 调用,基于已收集的证据产出尽力而为的答案,从而保证last_message始终携带文本答案。max_fetched_docs(int,默认10)—fetch_documents_by_filter每次抓取最多展示的文档数。过滤抓取不受检索器top_k约束,因此该参数充当工具结果上限;而带打分的search_documents工具则受你配置在检索组件上的top_k约束。
返回值:Agent对象。调用方式为agent.run(messages=[ChatMessage.from_user(question)]);答案在last_message(一个ChatMessage)中,documents携带运行期间检索到的全部文档(按 id 去重、按首次检索顺序排列)——答案以文档 id 前 8 个字符引用它们,例如[doc a1b2c3d4]。标准 Agent 输出messages、step_count、token_usage、tool_call_counts同样会被返回。
最小可用示例
以下示例来自 advanced-rag-agent.mdx:索引一份带多样元数据的语料,提出一个只有通过检查元数据、构造过滤器并据此检索才能回答好的问题:
from haystack import Document from haystack.components.retrievers.in_memory import InMemoryBM25Retriever from haystack.dataclasses import ChatMessage from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack_integrations.agent_pack import create_advanced_rag_agent document_store = InMemoryDocumentStore() document_store.write_documents( [ Document( content="CRISPR gene editing corrected a hereditary blindness mutation in a clinical trial.", meta={"category": "science", "year": 2021, "rating": 4.6}, ), Document( content="A quantum computer demonstrated error-corrected logical qubits.", meta={"category": "science", "year": 2023, "rating": 4.8}, ), Document( content="Dolly the sheep became the first mammal cloned from an adult somatic cell.", meta={"category": "science", "year": 1996, "rating": 4.2}, ), Document( content="The Berlin Wall fell, a decisive moment in the end of the Cold War.", meta={"category": "history", "year": 1989, "rating": 4.7}, ), Document( content="Argentina won the FIFA World Cup final against France on penalties.", meta={"category": "sports", "year": 2022, "rating": 4.9}, ), ], ) agent = create_advanced_rag_agent( document_store=document_store, retriever=InMemoryBM25Retriever(document_store=document_store, top_k=5), ) result = agent.run( messages=[ChatMessage.from_user("What science advances happened after 2015?")], ) print(result["last_message"].text) # 答案,引用文档形如 [doc <short-id>] for doc in result["documents"]: # 运行期间检索到的全部文档,已去重 print(f"[doc {doc.id[:8]}] {doc.meta} :: {doc.content[:60]}")Agent 的执行轨迹是:先列出元数据字段 → 校验category的取值与year的范围 → 构造形如{"operator": "AND", "conditions": [{"field": "meta.category", "operator": "==", "value": "science"}, {"field": "meta.year", "operator": ">", "value": 2015}]}的过滤器 → 带过滤器检索 → 引用 CRISPR 与量子计算机两篇文档作答。过滤是可选的:当元数据无法缩小问题时,Agent 会直接无过滤器检索。
用检索 Pipeline 替代单检索器
要使用多组件的检索流程,将retriever传为Pipeline并提供 query / filters / documents 的映射。例如带倒数排名融合(reciprocal rank fusion)的混合检索(示例同样来自 advanced-rag-agent.mdx):
from haystack import Pipeline from haystack.components.embedders import OpenAITextEmbedder from haystack.components.joiners import DocumentJoiner from haystack.components.retrievers.in_memory import ( InMemoryBM25Retriever, InMemoryEmbeddingRetriever, ) pipeline = Pipeline() pipeline.add_component( "bm25_retriever", InMemoryBM25Retriever(document_store=document_store), ) pipeline.add_component("text_embedder", OpenAITextEmbedder()) pipeline.add_component( "embedding_retriever", InMemoryEmbeddingRetriever(document_store=document_store), ) pipeline.add_component("joiner", DocumentJoiner(join_mode="reciprocal_rank_fusion")) pipeline.connect("text_embedder.embedding", "embedding_retriever.query_embedding") pipeline.connect("bm25_retriever.documents", "joiner.documents") pipeline.connect("embedding_retriever.documents", "joiner.documents") agent = create_advanced_rag_agent( document_store=document_store, retriever=pipeline, retrieval_pipeline_input_mapping={ "query": ["bm25_retriever.query", "text_embedder.text"], "filters": ["bm25_retriever.filters", "embedding_retriever.filters"], }, retrieval_pipeline_output_mapping={"joiner.documents": "documents"}, )注意输入映射的两个键要精确覆盖"query"与"filters",分别落到两个检索分支的对应输入 socket 上。
单独使用文档存储工具
四个文档存储工具既随 Agent 捆绑,也被单独导出,并打包为DocumentStoreToolset,可以放进你自己的Agent与自定义提示词中:
from haystack_integrations.agent_pack.advanced_rag import DocumentStoreToolset agent = Agent( chat_generator=..., tools=[DocumentStoreToolset(document_store), my_retrieval_tool], )支持的文档存储
元数据工具依赖的get_metadata_fields_info、get_metadata_field_unique_values、get_metadata_field_min_max三个方法不属于基础DocumentStore协议,而是各存储实现的增强能力。InMemoryDocumentStore与绝大多数存储集成(OpenSearch、Elasticsearch、Weaviate、Chroma、pgvector、Qdrant、Pinecone、MongoDB Atlas、Astra 等)都已实现。
以仓库中的InMemoryDocumentStore为例(见 document_store.py),get_metadata_fields_info遍历存储中的所有文档,根据值的运行时类型推断字段类型(boolean、int、float,其余归为keyword),返回{字段名: {"type": 类型}}的映射。get_metadata_field_min_max(同文件 L672 起)则返回指定字段在所有文档上的最小/最大值。
每个工具在构造时快速失败:若存储缺少其所需方法,立刻抛出清晰的ValueError。因此只实现了部分方法的存储仍可使用与之匹配的那部分工具子集。
工作原理:三阶段五工具
Advanced RAG Agent 的架构是单个 HaystackAgent,借助五个工具走完三个逻辑阶段(详见 advanced-rag-agent.mdx):
- 检查元数据:发现有哪些元数据字段,再检查它们的取值或范围;
- 检索文档:执行基于相关性的检索(可选地以元数据过滤器收窄),或在元数据能唯一标识文档时直接抓取;
- 作答:只依据检索到的文档作答,并以
[doc <short-id>]形式引用。
五个工具一览:
| 工具名 | 类 | 作用 |
|---|---|---|
list_metadata_fields | ListMetadataFieldsTool | 列出全部元数据字段及其类型。系统提示词要求 Agent 首先调用它 |
get_metadata_field_values | GetMetadataFieldValuesTool | 返回某字段的互异取值,确保过滤器使用真实存在的值;高基数字段的列举会被封顶,存储可提供总数时一并报告 |
get_metadata_field_range | GetMetadataFieldRangeTool | 返回可排序字段(如年份、评分、ISO 日期)的最小值与最大值 |
fetch_documents_by_filter | FetchDocumentsByFilterTool | 当无需相关性打分时(如已知标题或文件),直接按元数据过滤器抓取文档 |
search_documents | 基于你的检索器的ComponentTool,或基于检索 Pipeline 的PipelineTool | 按相关性为查询检索文档,可用元数据过滤器收窄;受检索组件top_k约束;空结果会提示 Agent 放宽过滤器 |
fetch_documents_by_filter的读取顺序:抓取结果先按父文件(file_name/file_path/source_id)分组,再按其在文件内的位置(split_id/split_idx_start/page_number)排序(使用文档实际携带的元数据字段),以"阅读顺序"呈现。单次调用最多展示max_docs条并报告总匹配数,更大的匹配集可用工具的offset输入分页续取。在支持count_documents_by_filter的存储上,过宽的过滤器会在抓取前被直接拒绝,拒绝信息以错误形式返回给 LLM,LLM 会通过收窄过滤器来恢复。
过滤器语法
为了让 LLM 稳定地构造合法的 Haystack 过滤器,过滤器语法被写进search_documents与fetch_documents_by_filter的filters参数描述中(而非全部塞进系统提示词),使模型在使用工具处按上下文接收到它:
- 单条件:
{"field": "meta.category", "operator": "==", "value": "science"} - 比较运算符:
==, !=, >, >=, <, <=, in, not in - 逻辑分组:
{"operator": "AND"|"OR"|"NOT", "conditions": [...]}(可嵌套) - 字段名必须以
meta.为前缀
系统提示词则补充工作流规则:先检查字段、过滤前先校验取值、搜索为空时放宽过滤器。
BackupAnswerHook:兜底答案钩子
BackupAnswerHook是一个after_run钩子,负责在 Agent 运行结束时仍未产生答案的情况下生成最终答案(详见关联文档haystack_integrations.agent_pack.advanced_rag.hooks一节)。
为什么需要它:当 Agent 在调查中途耗尽max_agent_steps时,运行会结束在工具调用或工具结果上,而不是助手文本答案上——而这种情形下只有after_run钩子会执行。该钩子检测到这种情况后,会对迄今为止的对话发起一次 LLM 调用,从已收集的证据中尽力生成答案。
API 形态:
__init__(chat_generator: ChatGenerator) -> None # 用于撰写兜底答案的 LLM warm_up() -> None # 由 Agent 的 warm_up 调用,预热钩子生成器 close() -> None # 由 Agent 的 close 调用,释放生成器资源 to_dict() -> dict # 序列化钩子 from_dict(data: dict) -> BackupAnswerHook # 反序列化钩子 run(state: State) -> None # 运行结束时无答案则追加尽力而为的最终答案钩子机制本身是 Haystack Agent 的一等公民:HookPoint定义了before_run、before_llm、before_tool、after_tool、on_exit、after_run六个挂载点(见 protocol.py),每个Hook通过就地修改State来影响运行(见 protocol.py),并可选实现warm_up/close生命周期方法——这与BackupAnswerHook实现warm_up/close的行为完全吻合。
Deep Research Agent:多智能体深度研究
核心思路
create_deep_research_agent创建一个"给一个问题,产出结构化、带引用的 Markdown 报告"的深度研究 Agent。它适用于需要从大量 Web 来源收集信息、评估并产出带引用的结构化报告的场景,例如:跨多来源调研宽泛主题、产品/公司/技术/科学发现对比、文献综述或市场概览、需要并行研究多个子主题的复杂问题。
它不适用的情况:单次搜索或一次 RAG 查询即可解决(多智能体工作流会带来额外延迟与成本);信息位于私有知识库而非公开 Web(此时应使用 Advanced RAG Agent)。
工厂函数签名
create_deep_research_agent( *, llm: ChatGenerator | None = None, system_prompt: str | None = None, max_agent_steps: int = 8, brief_llm: ChatGenerator | None = None, researcher_llm: ChatGenerator | None = None, search_tool: Tool | None = None, page_summary_llm: ChatGenerator | None = None, report_llm: ChatGenerator | None = None, max_researcher_steps: int = 20, max_concurrent_researchers: int = 5, max_subtopics: int = 5, max_page_chars: int = 50000 ) -> Agent所有参数均为keyword-only 且全部可选。
参数详解
主 Agent(编排器)
llm(ChatGenerator | None)— 驱动编排器循环、规划调查并派发子问题的 LLM。默认OpenAIResponsesChatGenerator("gpt-5.4")。system_prompt(str | None)— 覆盖预置编排器提示词;其中的{{ max_subtopics }}占位符会被替换为max_subtopics的实际值。max_agent_steps(int,默认8)— 编排器 Agent 循环(反思/派发轮)的最大步数。max_subtopics(int,默认5)— 编排器最多可派发的子问题数量(广度)。max_concurrent_researchers(int,默认5)— 同时运行的最大子研究员数量。
子研究员
researcher_llm(ChatGenerator | None)— 驱动每个子研究员"搜索/阅读/思考"循环的 LLM。默认OpenAIResponsesChatGenerator("gpt-5.4-mini")。search_tool(Tool | None)— 每个子研究员使用的 Web 搜索工具。默认TavilyWebSearchTool(top_k=10),需要tavily-haystack。预置的研究员提示词以web_search指代该工具——自定义工具时请同名命名或改写提示词。page_summary_llm(ChatGenerator | None)—read_url工具内部用于把抓取的页面朝问题方向总结的 LLM。默认OpenAIResponsesChatGenerator("gpt-5.4-mini")。max_researcher_steps(int,默认20)— 每个子研究员 Agent 循环的最大步数。max_page_chars(int,默认50000)— 在总结之前,喂给总结 LLM 的原始页面最大字符数。
Brief 与报告
brief_llm(ChatGenerator | None)— 把用户查询改写为聚焦研究简报(brief)的 LLM。默认OpenAIResponsesChatGenerator("gpt-5.4")。report_llm(ChatGenerator | None)— 把简报加收集到的笔记整合为最终报告的 LLM。默认OpenAIResponsesChatGenerator("gpt-5.4")。
Scope 与 Write 两个阶段各自是独立的单次 LLM 调用、各有独立的ChatGenerator,因此可以按成本与能力混搭模型,或整体换成其他提供商。
返回值:Agent对象。调用agent.run(messages=[ChatMessage.from_user(question)])后返回字典,主输出是report(最终 Markdown 报告,str);同时携带中间产物brief(str)与notes(list[str]),以及标准 Agent 输出messages、last_message、step_count、token_usage、tool_call_counts。
最小可用示例
from haystack.dataclasses import ChatMessage from haystack_integrations.agent_pack import create_deep_research_agent agent = create_deep_research_agent() result = agent.run(messages=[ChatMessage.from_user("your research question")]) print(result["report"])架构:Scope / Research / Write 三阶段
整体架构围绕**一个顶层 HaystackAgent(编排器)**构建,两个钩子分别在主循环前后运行,形成三个逻辑阶段(详见 deep-research-agent.mdx):
- Scope(定界):把用户问题改写为聚焦的研究简报。这是一个纯 LLM 调用,由
before_run钩子ScopeHook在编排器循环开始前执行,简报存入State。 - Research(研究):编排器把简报拆分为聚焦的子问题,逐个派发给子研究员,并收集它们的总结。子研究员之间相互隔离,各自是独立的
Agent。 - Write(写作):由
after_run钩子WriteHook在编排器循环结束后执行,把简报与收集到的notes整合为最终报告——带内联text引用的 Markdown。
brief、notes、report都声明在 Agent 的state_schema中,因此一次agent.run(...)调用即可取回全部三个输出。
Scope 与 Write 均为"ChatPromptBuilder + OpenAIResponsesChatGenerator"的纯 LLM 调用,被包装为可序列化的钩子类(ScopeHook、WriteHook)。
两个嵌套 Agent
编排器(Orchestrator)
- 职责:把简报拆成少量互不重叠的子问题,逐个派发,检查覆盖度,证据足够即停止。
- 并行:单轮可发出多次派发调用,它们并发执行(受
max_concurrent_researchers限制)。 - 记忆:子研究员返回的总结被追加到共享的
notes列表(Agent 的State),供写作者整合为报告。 - 停止条件:输出纯文本(研究完成)或达到
max_agent_steps。
编排器的两个工具:
| 工具 | 是什么 | 作用 |
|---|---|---|
research_subtopic | 以AgentTool暴露的子研究员 Agent | 在隔离上下文中研究单个子问题,返回压缩的、带引用的总结;只有该总结对编排器可见,同时也会追加到notes |
think_tool | 无操作的反思工具 | 让编排器在各轮之间暂停,规划子问题、评估覆盖度 |
子研究员(Sub-researcher)
子研究员是可复用的、回答单个子问题的 Agent。编排器会以隔离上下文并行运行它多次——这是本架构的关键思想:每个子研究员在私有上下文中处理原始搜索结果,只返回一份精炼总结,从而保证编排器的上下文保持小巧、最终报告保持连贯。
- 职责:搜索 Web,可选阅读有希望的页面,反思,然后写出带精确源 URL 内联引用的压缩总结。
- 返回:其最终文本消息本身就是总结(一旦写出纯文本即退出)。
- 约束:
max_researcher_steps。
子研究员的三个工具:
| 工具 | 是什么 | 作用 |
|---|---|---|
web_search | 默认TavilyWebSearchTool,或你传入的search_tool | 执行 Web 搜索,返回标题、精确 URL 与摘要的 top 结果 |
read_url | 基于"抓取-路由-转文本-总结" Pipeline 的PipelineTool | 抓取页面(LinkContentFetcher),按 MIME 类型路由(FileTypeRouter)到HTMLToDocument(Trafilatura)或PyPDFToDocument(PDF 也能解析),并按 Agent 传入的问题方向对页面做总结——只有相关文本进入 Agent 上下文,而非整页。仅在搜索摘要过浅时使用 |
think_tool | 无操作反思工具 | 在搜索之间自问:"我学到了什么?还缺什么?继续还是停止?" |
上下文管理:隔离与压缩
深度研究 Agent 的核心挑战是让每个上下文窗口保持小巧聚焦。原始 Web 内容(搜索结果、整页、PDF)体量大且噪音多,若全部堆积进单一上下文,模型输出质量会下降。解决方案是隔离 + 压缩:
- 每个子研究员作为独立 Agent 运行,拥有自己的
State——所有杂乱的中间内容(每条搜索结果、每个抓取页面)都留在它私有的上下文里; - 它最终只写出一份简短总结(其最终消息)。只有这份总结离开子研究员——原始内容永远不会到达编排器或写作者。
AgentTool的默认输出处理与research_subtopic上的一个设置共同决定总结去向:
| 行为/设置 | 控制什么 | 效果 |
|---|---|---|
AgentTool默认输出处理 | 编排器 LLM 看到的工具结果 | 默认返回子研究员最终回复的文本,而非完整消息历史,保持编排器上下文干净 |
outputs_to_state={"notes": {...}} | 为写作者保存什么 | 同一份总结以文本形式追加到共享notes列表,成为写作者的输入 |
数据流如下:总结以两种方式流转——进入编排器的推理(以便决定是否深挖)与进入notes累加器(供写作者使用),而体量庞大的原始研究内容则被隔离,不会传播出子研究员:
sub-researcher (私有上下文:搜索、页面、反思) │ 写出一份简短总结 ├─ AgentTool 默认输出 → 编排器的 LLM (决策:完成,还是继续深挖?) └─ outputs_to_state → notes → 写作者 (最终报告)进一步定制:clone 模式
两个工厂函数返回的都是标准Agent。要改动其余任何内容(添加工具、hooks、State条目),都应在返回对象上使用clone(),并通过解包已有值来保留内置工具与钩子:
agent = create_advanced_rag_agent(document_store=document_store, retriever=retriever) customized = agent.clone( tools=[*agent.tools, my_tool], hooks={**agent.hooks, "before_llm": [my_hook]}, )clone的底层语义可在仓库源码中直接确认(见 agent.py):它用inspect.signature反射__init__的参数名,取出当前实例的全部初始化参数,再以{**params, **overrides}合并覆盖项,构造一个新的同类实例——因此clone返回的是配置相同但独立的新 Agent,对它的任何修改不会影响原对象。
可观测输出与运行语义
两个 Agent 的运行结果都遵循 HaystackAgent的统一输出约定:
- Advanced RAG Agent:
last_message(带[doc <short-id>]引用的答案)+documents(去重后的全部检索文档),解析引用可用doc.id.startswith(...)对照返回列表; - Deep Research Agent:
report(最终 Markdown 报告)+brief+notes; - 两者都附带标准输出
messages、step_count、token_usage、tool_call_counts,且都支持通过warm_up/close(含异步变体)管理资源生命周期。
总结
Agent Pack 把"元数据感知 RAG"与"多智能体深度研究"两种复杂架构做成了可立即运行的成品,同时保留了充分的定制空间:参数层(create_*工厂的关键字参数)覆盖模型选择、检索拓扑、并行度与各类上限;结构层(clone()+ hooks +State)允许深度改造而不触碰内置逻辑;工具层(四个文档存储工具与DocumentStoreToolset、search_tool、research_subtopic等)可被单独取出,融入你自己的 Agent 设计。由于 Agent Pack 仍处于实验阶段,接入生产环境时务必锁定版本、验证行为,并关注后续 API 演进。
延伸阅读
- Agent Pack 总览:设计哲学、三种使用方式与安装
- Advanced RAG Agent 指南:完整示例、混合检索 Pipeline、过滤器语法与工作原理
- Deep Research Agent 指南:三阶段架构、子研究员隔离与上下文管理细节
- Agent 核心实现:
clone、warm_up/close、to_dict/from_dict等生命周期与序列化语义 - Hook 协议:六个钩子挂载点与
Hook协议定义 - InMemoryDocumentStore 元数据内省:
get_metadata_fields_info与get_metadata_field_min_max的实现参考
【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考