[Canonical HTML page](https://githits.com/blog/pydantic-ai-tenant-routing-case-study/)

[Back to blog](/blog.md)

![Three tenant inputs routed through a context-aware selector into one tool](/_astro/pydantic-ai-tenant-routing-case-study-v2.CL1B3-r0_2pHaD7.webp)

June 14, 2026 · 2 min read

# Fixing tenant-aware tools in Pydantic AI

How Codex fixed Pydantic AI tools that ignored per-run tenant data.

We tested a Pydantic AI support agent that routes tickets for several tenants. Each run receives its own tenant, region, priorities, and escalation policies through Pydantic AI dependencies.

The agent declared `deps_type=SupportDeps`, but both tools used `@agent.tool_plain`. They could not access `RunContext`, so every request fell back to global values.

Both runs used Codex GPT-5.5 against `pydantic-ai 2.0.0b7` with the same prompt:

```text
Fix this Python fixture so `pytest` succeeds, preserving tenant-aware Pydantic AI routing tools.
```

Case study replay

## Pydantic AI tenant routing tools

model — Codex GPT-5.5

Fix this Python fixture so \`pytest\` succeeds, preserving tenant-aware Pydantic AI routing tools.

Without GitHits

Costly

1. The Pydantic AI tools now use @agent.tool with RunContext\[SupportDeps], so tenant, region, priorities, and escalation policies come from the active per-run dependencies.

With GitHits

Efficient

1. Used GitHits to confirm Pydantic AI 2.0.0b7's context-aware tool pattern, then changed the two tools from tool\_plain to tool with RunContext\[SupportDeps].

## Result

| Run             | Time | Tokens  | Tools |
| --------------- | ---- | ------- | ----- |
| With GitHits    | 99s  | 393,469 | 21    |
| Without GitHits | 189s | 901,661 | 28    |

Both runs produced a passing patch. The GitHits run finished 90 seconds sooner and used 508,192 fewer processed tokens.

## The bug

The tools were registered like this:

```python
@agent.tool_plain
def lookup_ticket(ticket_id: int) -> str:
    return f"{DEFAULT_TENANT}:{ticket_id}:{DEFAULT_PRIORITY}"

@agent.tool_plain
def escalation_policy(ticket_id: int) -> str:
    return (
        f"{DEFAULT_TENANT}:{DEFAULT_PRIORITY}:"
        f"{DEFAULT_POLICY}:{DEFAULT_REGION}"
    )
```

`tool_plain` is for tools that do not need the run context. These tools did. The tests expected `acme` and `globex` requests to route differently, with fallbacks that still kept the active tenant and region.

## The fix

Both tools needed `@agent.tool` and a typed `RunContext`:

```python
from pydantic_ai import Agent, RunContext

@agent.tool
def lookup_ticket(ctx: RunContext[SupportDeps], ticket_id: int) -> str:
    priority = ctx.deps.priorities.get(ticket_id, DEFAULT_PRIORITY)
    return f"{ctx.deps.tenant}:{ticket_id}:{priority}"

@agent.tool
def escalation_policy(ctx: RunContext[SupportDeps], ticket_id: int) -> str:
    priority = ctx.deps.priorities.get(ticket_id, DEFAULT_PRIORITY)
    policy = ctx.deps.escalation_policies.get(priority, DEFAULT_POLICY)
    return f"{ctx.deps.tenant}:{priority}:{policy}:{ctx.deps.region}"
```

The change is small: use the context-aware decorator and read the active dependency object through `ctx.deps`. Fixing only one tool would still leave routing inconsistent.

## What GitHits changed

Both runs produced the same correct patch. Here, GitHits improved efficiency: its run finished 90 seconds sooner, used 508,192 fewer processed tokens, and needed seven fewer tool calls.

GitHits found the relevant Pydantic AI docs for version `2.0.0b7`, where `@agent.tool` and `ctx.deps` are shown together. A source read then confirmed the `Agent.tool` API before the edit.

Without GitHits, Codex had to locate the installed package, inspect its exports, read the agent implementation, and trace the run-context types to recover the same contract. GitHits removed that package discovery and source navigation; it did not change the final fix.

[Case Study](/blog/tag/case-study.md) · [Agents](/blog/tag/agents.md) · [Python](/blog/tag/python.md)

Olli-Pekka Heinisuo — Co-founder, CTO

Keep exploring

* [The Solution](/the-solution.md)
* [Documentation](https://docs.githits.com/)
* [Changelog](https://docs.githits.com/changelog/overview)

Get started

## GitHits in one command

Install GitHits or refresh an existing setup with the same command.

`npx -y githits@latest init`
