agents.mdx
1 --- 2 title: "Agents" 3 id: agents 4 slug: "/agents" 5 description: "This page explains how to create an AI agent in Haystack capable of retrieving information, generating responses, and taking actions using various Haystack components." 6 --- 7 8 # Agents 9 10 This page explains how to create an AI agent in Haystack capable of retrieving information, generating responses, and taking actions using various Haystack components. 11 12 ## What’s an AI Agent? 13 14 An AI agent is a system that can: 15 16 - Understand user input (text, image, audio, and other queries), 17 - Retrieve relevant information (documents or structured data), 18 - Generate intelligent responses (using LLMs like OpenAI or Hugging Face models), 19 - Perform actions (calling APIs, fetching live data, executing functions). 20 21 ### Understanding AI Agents 22 23 AI agents are autonomous systems that use large language models (LLMs) to make decisions and solve complex tasks. They interact with their environment using tools, memory, and reasoning. 24 25 ### What Makes an AI Agent 26 27 An AI agent is more than a chatbot. It actively plans, chooses the right tools and executes tasks to achieve a goal. Unlike traditional software, it adapts to new information and refines its process as needed. 28 29 1. **LLM as the Brain**: The agent's core is an LLM, which understands context, processes natural language and serves as the central intelligence system. 30 2. **Tools for Interaction**: Agents connect to external tools, APIs, and databases to gather information and take action. 31 3. **Memory for Context**: Short-term memory helps track conversations, while long-term memory stores knowledge for future interactions. 32 4. **Reasoning and Planning**: Agents break down complex problems, come up with step-by-step action plans, and adapt based on new data and feedback. 33 34 ### How AI Agents Work 35 36 An AI agent starts with a prompt that defines its role and objectives. It decides when to use tools, gathers data, and refines its approach through loops of reasoning and action. It evaluates progress and adjusts its strategy to improve results. 37 38 For example, a customer service agent answers queries using a database. If it lacks an answer, it fetches real-time data, summarizes it, and provides a response. A coding assistant understands project requirements, suggests solutions, and even writes code. 39 40 ## Key Components 41 42 ### Agents 43 44 Haystack has a universal [Agent](../pipeline-components/agents-1/agent.mdx) component that interacts with chat-based LLMs and tools to solve complex queries. It requires a Chat Generator that supports tools to work and can be customizable according to your needs. Check out the [Agent](../pipeline-components/agents-1/agent.mdx) documentation, or the [example](#tool-calling-agent) below to see how it works. 45 46 ### Additional Components 47 48 You can build an AI agent in Haystack yourself, using the three main elements in a pipeline: 49 50 - [Chat Generators](../pipeline-components/generators.mdx) to generate tool calls (with tool name and arguments) or assistant responses with an LLM, 51 - [`Tool`](../tools/tool.mdx) class that allows the LLM to perform actions such as running a pipeline or calling an external API, connecting to the external world, 52 - [`ToolInvoker`](../pipeline-components/tools/toolinvoker.mdx) component to execute tool calls generated by an LLM. It parses the LLM's tool-calling responses and invokes the appropriate tool with the correct arguments from the pipeline. 53 54 There are three ways of creating a tool in Haystack: 55 56 - [`Tool`](../tools/tool.mdx) class – Creates a tool representation for a consistent tool-calling experience across all Generators. It allows for most customization, as you can define its own name and description. 57 - [`ComponentTool`](../tools/componenttool.mdx) class – Wraps a Haystack component as a callable tool. 58 - [`@tool`](../tools/tool.mdx#tool-decorator) decorator – Creates tools from Python functions and automatically uses their function name and docstring. 59 - [Toolset](../tools/toolset.mdx) – A container for grouping multiple tools that can be passed directly to Agents or Generators. 60 61 ## Example Agents 62 63 ### Tool-Calling Agent 64 65 You can create a similar tool-calling agent with the `Agent` component: 66 67 ```python 68 from haystack.components.agents import Agent 69 from haystack.components.generators.chat import OpenAIChatGenerator 70 from haystack.components.websearch import SerperDevWebSearch 71 from haystack.dataclasses import Document, ChatMessage 72 from haystack.tools.component_tool import ComponentTool 73 74 from typing import List 75 76 ## Create the web search component 77 web_search = SerperDevWebSearch(top_k=3) 78 79 ## Create the ComponentTool with simpler parameters 80 web_tool = ComponentTool( 81 component=web_search, 82 name="web_search", 83 description="Search the web for current information like weather, news, or facts.", 84 ) 85 86 ## Create the agent with the web tool 87 tool_calling_agent = Agent( 88 chat_generator=OpenAIChatGenerator(model="gpt-4o-mini"), 89 system_prompt="""You're a helpful agent. When asked about current information like weather, news, or facts, 90 use the web_search tool to find the information and then summarize the findings. 91 When you get web search results, extract the relevant information and present it in a clear, 92 concise manner.""", 93 tools=[web_tool], 94 ) 95 96 ## Run the agent with the user message 97 user_message = ChatMessage.from_user("How is the weather in Berlin?") 98 result = tool_calling_agent.run(messages=[user_message]) 99 100 ## Print the result - using .text instead of .content 101 print(result["messages"][-1].text) 102 ``` 103 104 Resulting in: 105 106 ```python 107 108 - **Morning**: 49°F 109 - **Afternoon**: 57°F 110 - **Evening**: 47°F 111 - **Overnight**: 39°F 112 113 For more details, you can check the full forecasts on [AccuWeather](https://www.accuweather.com/en/de/berlin/10178/current-weather/178087) or [Weather.com](https://weather.com/weather/today/l/5ca23443513a0fdc1d37ae2ffaf5586162c6fe592a66acc9320a0d0536be1bb9). 114 ``` 115 116 ### Pipeline With Tools 117 118 Here’s an example of how you would build a tool-calling agent with the help of `ToolInvoker`. 119 120 This is what’s happening in this code example: 121 122 1. `OpenAIChatGenerator` uses an LLM to analyze the user's message and determines whether to provide an assistant response or initiate a tool call. 123 2. `ConditionalRouter` directs the output from the `OpenAIChatGenerator` to `there_are_tool_calls` branch if it’s a tool call or to `final_replies` to return to the user directly. 124 3. `ToolInvoker` executes the tool call generated by the LLM. `ComponentTool` wraps the `SerperDevWebSearch` component that fetches real-time search results, making it accessible for `ToolInvoker` to execute it as a tool. 125 4. After the tool provides its output, the `ToolInvoker` sends this information back to the `OpenAIChatGenerator`, along with the original user question stored by the `MessageCollector`. 126 127 ```python 128 from haystack import component, Pipeline 129 from haystack.components.tools import ToolInvoker 130 from haystack.components.generators.chat import OpenAIChatGenerator 131 from haystack.components.routers import ConditionalRouter 132 from haystack.components.websearch import SerperDevWebSearch 133 from haystack.core.component.types import Variadic 134 from haystack.dataclasses import ChatMessage 135 from haystack.tools import ComponentTool 136 137 from typing import Any, Dict, List 138 139 140 ## helper component to temporarily store last user query before the tool call 141 @component() 142 class MessageCollector: 143 def __init__(self): 144 self._messages = [] 145 146 @component.output_types(messages=List[ChatMessage]) 147 def run(self, messages: Variadic[List[ChatMessage]]) -> Dict[str, Any]: 148 149 self._messages.extend([msg for inner in messages for msg in inner]) 150 return {"messages": self._messages} 151 152 def clear(self): 153 self._messages = [] 154 155 156 ## Create a tool from a component 157 web_tool = ComponentTool(component=SerperDevWebSearch(top_k=3)) 158 159 ## Define routing conditions 160 routes = [ 161 { 162 "condition": "{{replies[0].tool_calls | length > 0}}", 163 "output": "{{replies}}", 164 "output_name": "there_are_tool_calls", 165 "output_type": List[ChatMessage], 166 }, 167 { 168 "condition": "{{replies[0].tool_calls | length == 0}}", 169 "output": "{{replies}}", 170 "output_name": "final_replies", 171 "output_type": List[ChatMessage], 172 }, 173 ] 174 175 ## Create the pipeline 176 tool_agent = Pipeline() 177 tool_agent.add_component("message_collector", MessageCollector()) 178 tool_agent.add_component( 179 "generator", 180 OpenAIChatGenerator(model="gpt-4o-mini", tools=[web_tool]), 181 ) 182 tool_agent.add_component("router", ConditionalRouter(routes, unsafe=True)) 183 tool_agent.add_component("tool_invoker", ToolInvoker(tools=[web_tool])) 184 185 tool_agent.connect("generator.replies", "router") 186 tool_agent.connect("router.there_are_tool_calls", "tool_invoker") 187 tool_agent.connect("router.there_are_tool_calls", "message_collector") 188 tool_agent.connect("tool_invoker.tool_messages", "message_collector") 189 tool_agent.connect("message_collector", "generator.messages") 190 191 messages = [ 192 ChatMessage.from_system( 193 "You're a helpful agent choosing the right tool when necessary", 194 ), 195 ChatMessage.from_user("How is the weather in Berlin?"), 196 ] 197 result = tool_agent.run({"messages": messages}) 198 199 print(result["router"]["final_replies"][0].text) 200 ``` 201 202 Resulting in: 203 204 ```python 205 206 For more detailed weather updates, you can check the following links: 207 - [AccuWeather](https://www.accuweather.com/en/de/berlin/10178/weather-forecast/178087) 208 - [Weather.com](https://weather.com/weather/today/l/5ca23443513a0fdc1d37ae2ffaf5586162c6fe592a66acc9320a0d0536be1bb9) 209 ```