diff --git a/tutorials/50_Using_Pre_Built_Agents_from_Agent_Pack.ipynb b/tutorials/50_Using_Pre_Built_Agents_from_Agent_Pack.ipynb index 20f3ab7e..3603c04a 100644 --- a/tutorials/50_Using_Pre_Built_Agents_from_Agent_Pack.ipynb +++ b/tutorials/50_Using_Pre_Built_Agents_from_Agent_Pack.ipynb @@ -28,7 +28,7 @@ "There are three ways to use an agent from the pack:\n", "\n", "- **Run it as is.** Call the `create_*` function, pass a question, and get an answer. The defaults are chosen to work out of the box.\n", - "- **Customize it.** Each entry point exposes keyword arguments for swapping models, adding tools, and tuning behavior.\n", + "- **Customize it.** Each entry point exposes keyword arguments for the choices specific to that agent, such as which models to use. For everything else, such as adding tools or hooks, use [`clone()`](https://docs.haystack.deepset.ai/docs/agent#cloning-and-modifying-an-agent) on the returned agent.\n", "- **Copy it.** Read the implementation and adapt it as a blueprint for your own architecture.\n", "\n", "### Why these two agents?\n", @@ -242,12 +242,11 @@ "source": [ "### Customizing the agent\n", "\n", - "Everything is configured through keyword arguments. Only `document_store` and `retriever` are required. A few useful ones:\n", + "Everything is configured through keyword arguments. Only `document_store` and `retriever` are required. The other keyword arguments cover the choices specific to this agent: models, the prompt, and limits. A few useful ones:\n", "\n", "- `llm`: the chat generator that drives the agent loop. Defaults to `OpenAIResponsesChatGenerator(\"gpt-5.4\")` with low reasoning effort. Swap in any tool-calling generator, from OpenAI or another provider.\n", "- `max_agent_steps`: caps the loop (default `20`). If the loop is cut off before an answer is written, a built-in `BackupAnswerHook` makes one extra call to produce a best-effort answer, so `last_message` always carries text.\n", "- `max_fetched_docs`: how many documents `fetch_documents_by_filter` shows per call (default `10`).\n", - "- `extra_tools`, `state_schema`, `hooks`: extend the agent with your own tools, state, and hooks.\n", "\n", "Here we swap the LLM for a smaller, widely available model and tighten the step budget:" ] @@ -277,6 +276,15 @@ "id": "41b3360b", "metadata": {}, "source": [ + "**Extending the agent.** To change anything else, such as adding tools, [hooks](https://docs.haystack.deepset.ai/docs/hooks), or [`State`](https://docs.haystack.deepset.ai/docs/state) entries, use [`clone()`](https://docs.haystack.deepset.ai/docs/agent#cloning-and-modifying-an-agent) on the returned agent. Unpack the existing values so you keep the built-in tools and the `BackupAnswerHook`:\n", + "\n", + "```python\n", + "customized = rag_agent.clone(\n", + " tools=[*rag_agent.tools, my_tool],\n", + " hooks={**rag_agent.hooks, \"before_llm\": [my_hook]},\n", + ")\n", + "```\n", + "\n", "**Using a retrieval pipeline.** To use a multi-component retrieval flow (for example hybrid retrieval), pass a `Pipeline` as `retriever` and supply `retrieval_pipeline_input_mapping` (mapping the tool's `query` and `filters` to your pipeline's input sockets) and, optionally, `retrieval_pipeline_output_mapping`. See the [Advanced RAG Agent docs](https://docs.haystack.deepset.ai/docs/advanced-rag-agent) for a full hybrid-retrieval example.\n", "\n", "**Using the tools on their own.** The four document-store-backed tools are exported individually and bundled as `DocumentStoreToolset`, so you can drop them into your own `Agent` with your own prompt, treating the pack as a toolbox rather than a finished agent:\n", @@ -320,12 +328,13 @@ "outputs": [], "source": [ "from haystack_integrations.agent_pack import create_deep_research_agent\n", + "from haystack_integrations.tools.tavily import TavilyWebSearchTool\n", "\n", "research_agent = create_deep_research_agent(\n", " max_subtopics=2, # delegate at most 2 sub-questions (breadth)\n", " max_concurrent_researchers=2, # run at most 2 sub-researchers at once\n", " max_researcher_steps=6, # cap each sub-researcher's search/read/think loop\n", - " max_search_results=5, # results per web_search call\n", + " search_tool=TavilyWebSearchTool(top_k=5), # results per web_search call (default: top_k=10)\n", ")" ] }, @@ -392,10 +401,12 @@ "\n", "Each phase takes its own `ChatGenerator`, so you can mix models by cost and capability, or swap in a different provider entirely:\n", "\n", - "- `scope_llm`, `orchestrator_llm`, `writer_llm`: default to `OpenAIResponsesChatGenerator(\"gpt-5.4\")` (the heavier reasoning steps).\n", - "- `researcher_llm`, `summarizer_llm`: default to `OpenAIResponsesChatGenerator(\"gpt-5.4-mini\")` (run many times, so a cheaper model keeps cost down).\n", + "- `llm`, `brief_llm`, `report_llm`: default to `OpenAIResponsesChatGenerator(\"gpt-5.4\")` (the heavier reasoning steps).\n", + "- `researcher_llm`, `page_summary_llm`: default to `OpenAIResponsesChatGenerator(\"gpt-5.4-mini\")` (run many times, so a cheaper model keeps cost down).\n", + "\n", + "The breadth/depth of the investigation is fully tunable: `max_subtopics`, `max_concurrent_researchers`, `max_agent_steps`, `max_researcher_steps`, and `max_page_chars`. The orchestrator's `system_prompt` can also be overridden (the `{{ max_subtopics }}` placeholder is substituted).\n", "\n", - "And the breadth/depth of the investigation is fully tunable: `max_subtopics`, `max_concurrent_researchers`, `max_orchestrator_steps`, `max_researcher_steps`, `max_search_results`, and `max_content_length`.\n", + "The sub-researchers' web search is a `search_tool` you can replace, as we did above to limit results. It defaults to `TavilyWebSearchTool(top_k=10)`, and the researcher prompt refers to it as `web_search`, so a custom tool should keep that name.\n", "\n", "For example, to make the whole run cheaper you might point every phase at a smaller model:\n", "\n", @@ -404,13 +415,22 @@ "from haystack_integrations.agent_pack import create_deep_research_agent\n", "\n", "cheap_agent = create_deep_research_agent(\n", - " scope_llm=OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", - " orchestrator_llm=OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", + " llm=OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", + " brief_llm=OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", " researcher_llm=OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", - " summarizer_llm=OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", - " writer_llm=OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", + " page_summary_llm=OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", + " report_llm=OpenAIChatGenerator(model=\"gpt-4o-mini\"),\n", " max_subtopics=3,\n", ")\n", + "```\n", + "\n", + "As with the Advanced RAG Agent, to change anything else, such as adding tools or hooks to the orchestrator, use [`clone()`](https://docs.haystack.deepset.ai/docs/agent#cloning-and-modifying-an-agent) on the returned agent, unpacking the existing values to keep the built-in tools and the Scope and Write hooks:\n", + "\n", + "```python\n", + "customized = research_agent.clone(\n", + " tools=[*research_agent.tools, my_tool],\n", + " hooks={**research_agent.hooks, \"before_llm\": [my_hook]},\n", + ")\n", "```" ] },