Agents and tools
Agent runs a chat generator in a loop with tools: when the model asks for a tool, the agent runs it and sends the result back, until the model answers.
from haystack.components.agents import Agent
from haystack.dataclasses import ChatMessage
from haystack.tools import tool
from shop_chat import ShopChat
ORDERS = {"A-1001": "shipped on 12 March", "A-1002": "waiting for stock"}
@tool
def lookup_order(order_id: str) -> str:
"""Look up the status of an order by its id, like A-1001."""
return ORDERS.get(order_id, "no such order")The agent gets the stand-in generator from lesson 11 and the tool:
agent = Agent(chat_generator=ShopChat(), tools=[lookup_order])result = agent.run(messages=[ChatMessage.from_user("Where is my order A-1001?")])
for message in result["messages"]:
detail = message.text or message.tool_call or message.tool_call_result.result
print(f"{message.role.value:9} {detail}")@tool turns a function into a Tool: its name, docstring and type hints become what the model sees. Agent checked that ShopChat.run accepts tools, then looped: the generator returned a tool call, the agent ran lookup_order and added a tool message with the result, and the generator answered from it.
print(lookup_order.name)
print(lookup_order.description)
print(lookup_order.parameters)This is the tool definition a real model receives. Write the docstring for the model: what the tool does and what its arguments look like.
Pipelines as tools
ComponentTool wraps any component, and PipelineTool a whole pipeline, as a tool. The RAG pipeline from lesson 12 could become a search_policies tool, so the agent decides when to search the policies and when to look up an order.
- Ask about
A-9999. - Ask a question with no order id and count the messages.
- Pass
max_agent_steps=1toAgentand ask about A-1001.
Slow is fine. Stopping is the only problem.