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  ```