Pydantic Ai Tool System

v1.0.1

Register and implement PydanticAI tools with proper context handling, type annotations, and docstrings. Use when adding tool capabilities to agents, implemen...

0· 187·2 current·2 all-time
byKevin Anderson@anderskev

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for anderskev/pydantic-ai-tool-system.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Pydantic Ai Tool System" (anderskev/pydantic-ai-tool-system) from ClawHub.
Skill page: https://clawhub.ai/anderskev/pydantic-ai-tool-system
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install pydantic-ai-tool-system

ClawHub CLI

Package manager switcher

npx clawhub@latest install pydantic-ai-tool-system
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name, description, and runtime instructions all describe registering and implementing PydanticAI tools. The skill asks for no binaries, env vars, or installs, which is proportionate for an instruction-only developer guide.
Instruction Scope
SKILL.md instructs the agent to validate source-file signatures, docstrings, and use RunContext to access deps/usage/messages. That is appropriate for a tool-registration guide, but it implies the agent will read code and operate on per-request context (which may include dependencies and tokens provided at runtime). The skill does not instruct reading arbitrary system files or environment variables beyond the RunContext API.
Install Mechanism
No install spec and no code files — instruction-only. No downloads or package installs are requested, minimizing installation risk.
Credentials
The skill itself requests no environment variables or credentials. However, the documented usage of RunContext shows access to ctx.deps, tokens_used, messages, and model info. That is expected for tools but means runtime dependencies provided to the agent (not this skill) could expose sensitive data; the skill does not request unrelated credentials.
Persistence & Privilege
Flags show default autonomy settings (not always:true). The skill does not request persistent installation or modify other skills; no elevated persistence privileges are requested.
Assessment
This skill is a usage guide for registering tools and appears coherent. Before installing/using: (1) Confirm the agent runtime's RunContext only supplies the dependencies and secrets you intend (ctx.deps may expose DB clients, API clients, or tokens). (2) Review any tool functions you register for unintended access to secrets or network calls. (3) Use least-privilege for dependencies injected into RunContext (limit DB/API clients and roles). If you want extra assurance, test the guidance in a sandboxed environment first.

Like a lobster shell, security has layers — review code before you run it.

latestvk971wy7cbbqf0qzqfkmn72dx5185bgw0
187downloads
0stars
2versions
Updated 6d ago
v1.0.1
MIT-0

PydanticAI Tool System

Tool Registration

Two decorators based on whether you need context:

from pydantic_ai import Agent, RunContext

agent = Agent('openai:gpt-4o')

# @agent.tool - First param MUST be RunContext
@agent.tool
async def get_user_data(ctx: RunContext[MyDeps], user_id: int) -> str:
    """Get user data from database.

    Args:
        ctx: The run context with dependencies.
        user_id: The user's ID.
    """
    return await ctx.deps.db.get_user(user_id)

# @agent.tool_plain - NO context parameter allowed
@agent.tool_plain
def calculate_total(prices: list[float]) -> float:
    """Calculate total price.

    Args:
        prices: List of prices to sum.
    """
    return sum(prices)

Critical Rules

  1. @agent.tool: First parameter MUST be RunContext[DepsType]
  2. @agent.tool_plain: MUST NOT have RunContext parameter
  3. Docstrings: Required for LLM to understand tool purpose
  4. Google-style docstrings: Used for parameter descriptions

Gates (verify in the file, not from memory)

  1. Decorator matches signature — If the first parameter is RunContext[...], the decorator must be @agent.tool (not @agent.tool_plain). Pass: the same def line’s decorator stack includes @agent.tool, and the first parameter is typed RunContext[...].
  2. Plain tools — With @agent.tool_plain, the parameter list must not include RunContext. Pass: a quick scan of the signature shows no RunContext.
  3. Docstring for the model — Non-empty docstring; if the tool has parameters, describe them (Google Args: or Sphinx :param when using docstring_format='sphinx'). Pass: each parameter in the signature is mentioned in the docstring body.

Docstring Formats

Google style (default):

@agent.tool_plain
async def search(query: str, limit: int = 10) -> list[str]:
    """Search for items.

    Args:
        query: The search query.
        limit: Maximum results to return.
    """

Sphinx style:

@agent.tool_plain(docstring_format='sphinx')
async def search(query: str) -> list[str]:
    """Search for items.

    :param query: The search query.
    """

Tool Return Types

Tools can return various types:

# String (direct)
@agent.tool_plain
def get_info() -> str:
    return "Some information"

# Pydantic model (serialized to JSON)
@agent.tool_plain
def get_user() -> User:
    return User(name="John", age=30)

# Dict (serialized to JSON)
@agent.tool_plain
def get_data() -> dict[str, Any]:
    return {"key": "value"}

# ToolReturn for custom content types
from pydantic_ai import ToolReturn, ImageUrl

@agent.tool_plain
def get_image() -> ToolReturn:
    return ToolReturn(content=[ImageUrl(url="https://...")])

Accessing Context

RunContext provides:

@agent.tool
async def my_tool(ctx: RunContext[MyDeps]) -> str:
    # Dependencies
    db = ctx.deps.db
    api = ctx.deps.api_client

    # Model info
    model_name = ctx.model.model_name

    # Usage tracking
    tokens_used = ctx.usage.total_tokens

    # Retry info
    attempt = ctx.retry  # Current retry attempt (0-based)
    max_retries = ctx.max_retries

    # Message history
    messages = ctx.messages

    return "result"

Tool Prepare Functions

Dynamically modify tools per-request:

from pydantic_ai.tools import ToolDefinition

async def prepare_tools(
    ctx: RunContext[MyDeps],
    tool_defs: list[ToolDefinition]
) -> list[ToolDefinition]:
    """Filter or modify tools based on context."""
    if ctx.deps.user_role != 'admin':
        # Hide admin tools from non-admins
        return [t for t in tool_defs if not t.name.startswith('admin_')]
    return tool_defs

agent = Agent('openai:gpt-4o', prepare_tools=prepare_tools)

Toolsets

Group and compose tools:

from pydantic_ai import FunctionToolset, CombinedToolset

# Create a toolset
db_tools = FunctionToolset()

@db_tools.tool
def query_users(name: str) -> list[dict]:
    """Query users by name."""
    ...

@db_tools.tool
def update_user(id: int, data: dict) -> bool:
    """Update user data."""
    ...

# Use in agent
agent = Agent('openai:gpt-4o', toolsets=[db_tools])

# Combine toolsets
all_tools = CombinedToolset([db_tools, api_tools])

Common Mistakes

Wrong: Context in tool_plain

@agent.tool_plain
async def bad_tool(ctx: RunContext[MyDeps]) -> str:  # ERROR!
    ...

Wrong: Missing context in tool

@agent.tool
def bad_tool(user_id: int) -> str:  # ERROR!
    ...

Wrong: Context not first parameter

@agent.tool
def bad_tool(user_id: int, ctx: RunContext[MyDeps]) -> str:  # ERROR!
    ...

Async vs Sync

Both work, but async is preferred for I/O:

# Async (preferred for I/O operations)
@agent.tool
async def fetch_data(ctx: RunContext[Deps]) -> str:
    return await ctx.deps.client.get('/data')

# Sync (fine for CPU-bound operations)
@agent.tool_plain
def compute(x: int, y: int) -> int:
    return x * y

Comments

Loading comments...