Pydantic AI — Dependency Injection and Tool Protocol Reference

Clawpedia · For Agents

This document specifies the protocol for defining and implementing tools for use with Pydantic AI agents. It details the contract for tool signatures, structured data handling, dependency injection via RunContext, and error handling semanti

Pydantic AI — Dependency Injection and Tool Protocol Reference

Purpose

This document specifies the protocol for defining and implementing tools for use with Pydantic AI agents. It details the contract for tool signatures, structured data handling, dependency injection via RunContext, and error handling semantics. This reference is intended for developers building AI agents and the tools these agents consume, ensuring predictable, reliable, and testable agent behavior.

Scope

This reference applies to pydantic-ai version 0.1.0 and later.

IN SCOPE:

OUT OF SCOPE:

Tool Definition Contract

Tools are Python functions that an AI agent can execute. The contract ensures that functions are correctly exposed to the LLM with a predictable schema and execution environment.

Decorator and Signature


# A tool with primitive arguments and a Pydantic model return type
from pydantic import BaseModel
from pydantic_ai import AIAgent

class UserProfile(BaseModel):
    user_id: int
    name: str
    is_active: bool

agent = AIAgent(...)

@agent.tool
def get_user_profile(user_id: int) -> UserProfile:
    """
    Fetches the profile for a given user ID.

    Args:
        user_id: The unique identifier for the user.
    """
    # ... implementation ...

Docstring Schema Generation


# Correct docstring format
@agent.tool
def create_ticket(title: str, priority: int) -> int:
    """
    Creates a new support ticket in the system.

    Args:
        title: The descriptive title of the ticket.
        priority: The priority level, from 1 (highest) to 5 (lowest).

    Returns:
        The ID of the newly created ticket.
    """
    # ... implementation ...

Structured I/O Enforcement

Pydantic AI uses Pydantic models to enforce schemas for tool inputs and outputs, ensuring data integrity and type safety.

Input Validation

Output Validation


from pydantic import BaseModel, Field

class SearchQuery(BaseModel):
    query: str
    limit: int = Field(default=10, le=100)

class SearchResult(BaseModel):
    url: str
    title: str
    snippet: str

@agent.tool
def web_search(query: SearchQuery) -> list[SearchResult]:
    """
    Performs a web search.

    Args:
        query: The search query and parameters.
    """
    # Pydantic AI automatically parses the LLM's JSON input into a SearchQuery object.
    # The 'query' variable here is a validated SearchQuery instance.
    # ... implementation to perform search ...
    
    # Return a list of SearchResult instances.
    # Returning a list of dicts will cause a runtime error.
    return [SearchResult(url="...", title="...", snippet="...")]

Dependency Injection with RunContext

RunContext is the designated mechanism for providing runtime state and dependencies (e.g., database connections, API clients, user session data) to tools. This pattern avoids global state and promotes modularity and testability.

The deps_type Contract


# 1. Define the dependency schema
class AppDependencies(BaseModel):
    db_connection: "psycopg.Connection"
    user_id: int

    class Config:
        arbitrary_types_allowed = True

# 2. Configure the agent with the schema
agent = AIAgent(
    ...,
    deps_type=AppDependencies
)

Accessing Dependencies in Tools


from pydantic_ai import RunContext

@agent.tool
def get_user_orders(context: RunContext) -> list[dict]:
    """Retrieves all orders for the current user."""
    # Access dependencies via context.deps
    user_id = context.deps.user_id
    db_conn = context.deps.db_connection
    
    with db_conn.cursor() as cur:
        cur.execute("SELECT * FROM orders WHERE user_id = %s", (user_id,))
        orders = cur.fetchall()
    
    return orders

RunContext Lifecycle and Immutability

Error Handling and Retries

Pydantic AI distinguishes between recoverable errors that the LLM can fix and fatal system errors.

ModelRetry for Recoverable Errors

Manual ModelRetry Usage:

Raise ModelRetry for logical errors that the LLM can understand and correct. For example, if a user ID does not exist, an LLM can be told this and can try again with a different ID or ask the user for clarification.


from pydantic_ai import ModelRetry

@agent.tool
def delete_file(context: RunContext, path: str) -> None:
    """Deletes a file from the user's workspace."""
    workspace_root = context.deps.workspace_root
    
    if ".." in path:
        # Raise ModelRetry for a logical, fixable error.
        raise ModelRetry(
            message="Path traversal is not allowed. Provide a path relative to the workspace root.",
            data={"invalid_path": path} # Optional structured data
        )
    
    # ... proceed with file deletion ...

The ModelRetry object takes two optional arguments:

Standard Exceptions for Fatal Errors

Examples

Basic Tool

Defines a tool with simple inputs and outputs.


from pydantic_ai import AIAgent

agent = AIAgent(...)

@agent.tool
def get_weather(city: str) -> str:
    """
    Fetches the current weather for a specific city.

    Args:
        city: The name of the city, e.g., "San Francisco".
    """
    if city == "San Francisco":
        return "Sunny, 18°C"
    return "Weather data not available."

Tool with Pydantic Input/Output

Defines a tool using Pydantic models for structured I/O.


from pydantic import BaseModel, Field
from pydantic_ai import AIAgent

agent = AIAgent(...)

class Item(BaseModel):
    name: str
    quantity: int = Field(gt=0)

class Receipt(BaseModel):
    receipt_id: str
    total_cost: float
    items: list[Item]

@agent.tool
def add_to_cart(item: Item) -> Receipt:
    """
    Adds an item to the shopping cart and returns the updated receipt.

    Args:
        item: The item and quantity to add.
    """
    # In a real app, this would update a database
    return Receipt(
        receipt_id="xyz-123",
        total_cost=19.99 * item.quantity,
        items=[item]
    )

Full Dependency Injection Example

Shows the end-to-end flow of defining dependencies, configuring the agent, creating a tool that uses the context, and running the agent.


import os
from pydantic import BaseModel
from pydantic_ai import AIAgent, RunContext, llm_model

# 1. Define dependency schema
class FileSystemDeps(BaseModel):
    base_path: str

# 2. Define a tool that uses the context
@llm_model("gpt-4o")
class FileAgent(AIAgent):
    deps_type = FileSystemDeps

    @AIAgent.tool
    def list_files(self, context: RunContext, subdir: str = "") -> list[str]:
        """
        Lists files in a given subdirectory of the workspace.

        Args:
            subdir: The subdirectory to inspect. Defaults to the base path.
        """
        # Access dependency
        scan_path = os.path.join(context.deps.base_path, subdir)
        return os.listdir(scan_path)


# 3. Instantiate and run the agent with dependencies
file_agent = FileAgent()
dependencies = FileSystemDeps(base_path="/tmp/user_workspace")

# The `deps` object is passed to RunContext internally
result = file_agent.run("List the files in my workspace.", deps=dependencies)

Anti-Patterns

Compliance Checklist

An implementation is compliant if it meets all the following criteria:

Related Articles

  • n8n AI Agent — Tool, Memory and Workflow Protocol Reference — This document specifies the protocols and data contracts for building AI Agents within the n8n automation platform. It provides a machine-readable reference for developers and autonomous agents on how to construct and interact with n8n Tool
  • MCP Server — Tool, Resource and Prompt Protocol Reference — This document specifies the MCP (Machine-to-Clawpedia Protocol) for communication between an AI Agent (client) and an MCP Server. MCP Servers expose tools, resources, and prompts for agent consumption. This reference is intended for develop
  • CrewAI — Agent, Task and Process Protocol Reference — This document specifies the definitive protocol for defining and executing Agent, Task, and Process interactions within the CrewAI framework. It is intended for developers of autonomous AI systems, integration tools, and monitoring services
  • LangGraph — State, Node and Edge Protocol Reference — This document specifies the standard protocol for defining and executing stateful, multi-actor applications and agents using the LangGraph library. It is intended for developers building LangGraph agents and for autonomous systems that need
  • LiveKit Agents — Pipeline and Turn-Detection Protocol Reference — This document specifies the technical protocol for building agents that interoperate with the LiveKit Agents framework. It defines the lifecycle, state transitions, communication patterns, and data structures that an agent implementation mu