> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pydantic/monty/llms.txt
> Use this file to discover all available pages before exploring further.

# PydanticAI Integration

> Use Monty to power code-mode in PydanticAI agents for faster, more reliable tool execution

## Overview

Monty powers code-mode in [PydanticAI](https://github.com/pydantic/pydantic-ai). Instead of making sequential tool calls, the LLM writes Python code that calls your tools as functions, and Monty executes it safely.

<Info>
  Code-mode allows agents to work faster, cheaper, and more reliably by writing Python code instead of relying on traditional tool calling.
</Info>

## How It Works

The `CodeModeToolset` wraps your existing `FunctionToolset` and converts it into executable Python code that Monty can run safely in a sandbox.

## Complete Example

Here's a weather agent that uses Monty's code-mode to compare weather across multiple cities:

<Steps>
  <Step title="Define your tools">
    Create a `FunctionToolset` with your agent's tools:

    ```python theme={null}
    from pydantic_ai import RunContext
    from pydantic_ai.toolsets.function import FunctionToolset
    from httpx import AsyncClient
    from typing_extensions import TypedDict
    import json

    class LatLng(TypedDict):
        lat: float
        lng: float

    weather_toolset: FunctionToolset[AsyncClient] = FunctionToolset()

    @weather_toolset.tool
    async def get_lat_lng(
        ctx: RunContext[AsyncClient], location_description: str
    ) -> LatLng:
        """Get the latitude and longitude of a location."""
        r = await ctx.deps.get(
            'https://demo-endpoints.pydantic.workers.dev/latlng',
            params={'location': location_description},
        )
        r.raise_for_status()
        return json.loads(r.content)

    @weather_toolset.tool
    async def get_temp(ctx: RunContext[AsyncClient], lat: float, lng: float) -> float:
        """Get the temp at a location."""
        r = await ctx.deps.get(
            'https://demo-endpoints.pydantic.workers.dev/number',
            params={'min': 10, 'max': 30},
        )
        r.raise_for_status()
        return float(r.text)

    @weather_toolset.tool
    async def get_weather_description(
        ctx: RunContext[AsyncClient], lat: float, lng: float
    ) -> str:
        """Get the weather description at a location."""
        r = await ctx.deps.get(
            'https://demo-endpoints.pydantic.workers.dev/weather',
            params={'lat': lat, 'lng': lng},
        )
        r.raise_for_status()
        return r.text
    ```
  </Step>

  <Step title="Wrap with CodeModeToolset">
    Replace the `FunctionToolset` with a `CodeModeToolset` wrapper:

    ```python theme={null}
    from pydantic_ai import Agent
    from pydantic_ai.toolsets.code_mode import CodeModeToolset

    agent = Agent(
        'gateway/anthropic:claude-sonnet-4-5',
        toolsets=[CodeModeToolset(weather_toolset)],
        deps_type=AsyncClient,
    )
    ```

    <Note>
      The `CodeModeToolset` converts your function tools into a Python environment that the LLM can write code against.
    </Note>
  </Step>

  <Step title="Run your agent">
    Execute the agent normally - it will generate Python code internally:

    ```python theme={null}
    import asyncio
    import logfire

    logfire.configure()
    logfire.instrument_pydantic_ai()

    async def main():
        async with AsyncClient() as client:
            await agent.run(
                'Compare the weather of London, Paris, and Tokyo.',
                deps=client
            )

    if __name__ == '__main__':
        asyncio.run(main())
    ```
  </Step>
</Steps>

## What CodeModeToolset Does

The `CodeModeToolset` wrapper:

1. **Generates type stubs** - Creates Python type definitions for all your tools
2. **Provides execution context** - Gives the LLM access to your tools as callable functions
3. **Handles external calls** - Routes function calls back to your host implementation
4. **Enforces safety** - Runs all code in Monty's secure sandbox

## Benefits Over Traditional Tool Calling

<CodeGroup>
  ```python Traditional Tool Calling theme={null}
  # Agent makes sequential tool calls
  result1 = await get_lat_lng('London')
  result2 = await get_temp(result1['lat'], result1['lng'])
  result3 = await get_lat_lng('Paris')
  result4 = await get_temp(result3['lat'], result3['lng'])
  # Many round-trips to the LLM
  ```

  ```python Code-Mode with Monty theme={null}
  # Agent writes code that calls all tools
  locations = ['London', 'Paris', 'Tokyo']
  weather_data = []
  for city in locations:
      coords = await get_lat_lng(city)
      temp = await get_temp(coords['lat'], coords['lng'])
      weather_data.append({'city': city, 'temp': temp})
  # Single LLM call, efficient execution
  ```
</CodeGroup>

Code-mode is:

* **Faster** - Fewer round-trips to the LLM
* **Cheaper** - Less token usage
* **More reliable** - Complex logic is easier to express in code

## Security

All code runs in Monty's sandbox with:

* No filesystem access
* No network access
* No environment variable access
* Only functions you explicitly provide

<Info>
  Monty ensures that even malicious code generated by the LLM cannot escape the sandbox or access your host system.
</Info>
