Pydantic AIPydantic AI 2.43 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
23 small wins to finish your pathNext lesson

Function tools: letting the model look things up

A tool is a Python function the model can call. Pydantic AI builds its description from your type hints and docstring and runs it when the model asks.

Example
ORDERS = {
    "A-1001": "shipped on 12 March",
    "A-1002": "waiting for stock",
}
Example
@agent.tool_plain
def lookup_order(order_id: str) -> str:
    """Look up the status of an order.

    Args:
        order_id: The order id, like A-1001.
    """
    return ORDERS.get(order_id, "not found")
Example
result = agent.run_sync("Where is my order A-1001?")
print(result.output)
print(result.usage)

@agent.tool_plain adds the function to the agent. The stand-in saw the order id and a tool, called lookup_order, and wrote its answer from the result: two requests and one tool call, the loop from lesson 2 with a real value.

What the model reads about a tool

Example
def peek(messages, info):
    tool = info.function_tools[0]
    print(tool.name)
    print(tool.description)
    print(json.dumps(tool.parameters_json_schema, indent=2))
    return ModelResponse(parts=[TextPart("ok")])


agent = Agent(FunctionModel(peek))
agent.tool_plain(lookup_order)
agent.run_sync("hi")

The name is the function's name. The description is the docstring's first part, and the Args: section became the description of order_id in the schema. Pydantic AI reads Google, NumPy and Sphinx docstring styles. The model chooses tools from these words alone, so they are worth writing well.

agent.tool_plain(lookup_order) without the @ does the same as the decorator, which is handy for functions defined elsewhere. Agent(..., tools=[lookup_order]) is a third way.

Arguments are validated

When the model calls a tool, Pydantic checks the arguments against the type hints before your function runs. A wrong type goes back to the model as a retry prompt, as in lesson 7, so a function with order_id: str can rely on getting a string.

Try it yourself
  • Add refund_order(order_id: str, amount: float) -> str and print both tools' schemas.
  • Ask about A-1002, then about A-5555.
  • Remove the docstring and print the description again.

Every expert started right here.