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

Dependencies: giving tools your data

Dependencies are the objects a run needs, like the customer and a database connection. You pass them to run_sync and tools read them from RunContext.

Example
from dataclasses import dataclass

from pydantic_ai import Agent, RunContext

from shop_model import shop_model


@dataclass
class Desk:
    customer: str
    orders: dict[str, str]


agent = Agent(shop_model, deps_type=Desk)
Example
@agent.tool
def lookup_order(ctx: RunContext[Desk], order_id: str) -> str:
    """Look up the status of one of this customer's orders."""
    return ctx.deps.orders.get(order_id, "not one of this customer's orders")

deps_type=Desk tells the agent, and your type checker, what the dependencies will be. @agent.tool, not tool_plain, passes a RunContext as the first argument, and ctx.deps is the object given to this run. ctx is not part of the tool's schema; the model never sees it.

Example
asha = Desk(customer="Asha", orders={"A-1001": "shipped on 12 March"})
ravi = Desk(customer="Ravi", orders={"A-1002": "waiting for stock"})

print(agent.run_sync("Where is A-1001?", deps=asha).output)
print(agent.run_sync("Where is A-1001?", deps=ravi).output)

One agent, two customers. Each run looks only at the orders it was given, so Ravi cannot read Asha's order even by quoting its number. With a global dictionary instead, every run would see every order.

Instructions from dependencies

Example
def spy(messages, info):
    return ModelResponse(parts=[TextPart(info.instructions)])


agent = Agent(FunctionModel(spy), deps_type=Desk, instructions="You answer support tickets.")


@agent.instructions
def customer(ctx: RunContext[Desk]) -> str:
    return f"The customer is {ctx.deps.customer}. Orders on file: {len(ctx.deps.orders)}."


print(agent.run_sync("hi", deps=Desk("Asha", {"A-1001": "shipped"})).output)

Instruction functions, output validators and output functions can take RunContext too. Besides deps, it has the run's usage, messages and retry count.

Why not a global
In tests, lesson 20, you pass a Desk with made-up orders and nothing else changes. In a web app, each request builds its own dependencies, so one customer's data never leaks into another's run.
Try it yourself
  • Run without deps= and read what the tool gets.
  • Add refund_limit: float to Desk and mention it in the instructions.
  • Print ctx.usage.requests inside lookup_order.

Little by little, you're building something great.