Type-Safe Agent Identity for Pydantic AI: Permissions and Audit Trails the Pydantic Way
Your Agents Have Type Safety. Do They Have Identity?
Pydantic AI is one of the fastest-growing AI agent frameworks in 2026, and for good reason. It brings Python's type system to agent development: structured outputs, dependency injection, model-agnostic design, and the kind of validation that catches bugs before they hit production.
But type safety solves one problem. Agent identity solves a different one.
When your Pydantic AI agent calls a tool, who is it? What is it allowed to do? Is there a record of what it did? If something goes wrong at 3am, can you trace which agent, with which permissions, took which action?
Today we're releasing vorim.pydantic_ai, a type-safe integration that adds cryptographic identity, scoped permissions, and tamper-proof audit trails to Pydantic AI agents through dependency injection.
The Pattern: VorimDeps
Pydantic AI's dependency injection lets you pass typed context to your agents and tools via RunContext. Vorim plugs directly into this pattern.
from vorim.pydantic_ai import VorimDeps
from pydantic_ai import Agent, RunContext
agent = Agent('openai:gpt-4o', deps_type=VorimDeps)
@agent.tool
async def fetch_data(ctx: RunContext[VorimDeps], query: str) -> str:
# Check permission before acting
check = ctx.deps.check('data:read')
if not check.get('allowed'):
return 'Permission denied: data:read not granted'
result = await do_something(query)
# Log the action
ctx.deps.emit('data.fetch', outcome='success')
return result
# Run with Vorim identity
deps = VorimDeps(api_key='agid_sk_...', agent_id='agid_abc123')
result = await agent.run('Fetch the latest data', deps=deps)check(scope)— verify the agent has a permission before acting (sub-5ms via Redis)emit(action, outcome)— log an audit event with SHA-256 hash linkinggrant(scope)— grant a permission to the agentverify()— check the agent's trust score (0-100)
The Vorim client is lazy-initialized, so creating VorimDeps is instant. The API connection only happens when you call a method.
The vorim_tool Decorator
Manually calling check() and emit() in every tool works, but it's boilerplate. The vorim_tool decorator handles it automatically:
from vorim.pydantic_ai import VorimDeps, vorim_tool
agent = Agent('openai:gpt-4o', deps_type=VorimDeps)
@agent.tool
@vorim_tool(scope='data:read', action='data.fetch')
async def fetch_data(ctx: RunContext[VorimDeps], query: str) -> str:
# Permission is checked before this runs
# Audit event is emitted after this returns
return await do_something(query)What happens under the hood: 1. Before your tool runs: checks if the agent has the required scope. If denied, returns a configurable deny message and logs a denial event. 2. After your tool runs: emits an audit event with the action name and outcome (success or error). 3. If the tool throws: catches the exception, logs an error event, then re-raises.
Every tool call becomes an identifiable, auditable, permission-checked action. Zero additional code in the tool itself.
Why This Matters for Production
In development, agents run in a sandbox with your credentials. Nobody cares about permissions. In production, agents run autonomously across systems with access to real data, real APIs, and real money.
- "Which agent modified that customer record?" — Without per-agent identity, you can't tell. With VorimDeps, every action is tied to a specific agent ID with a cryptographic keypair.
- "Was the agent allowed to do that?" — Without scoped permissions, agents inherit whatever access the host application has. With
vorim_tool(scope='data:write'), the agent is blocked if it doesn't have the right scope. - "Prove to the auditor that the agent acted within its bounds." — Without tamper-proof logs, you have "we think this happened." With Vorim's SHA-256 hash chain, you have cryptographic proof that the log hasn't been altered.
One-Call Agent Creation
If you want to skip the manual setup, create_vorim_agent registers a new agent with Vorim and returns a pre-configured Pydantic AI Agent with VorimDeps:
from vorim.pydantic_ai import create_vorim_agent
agent, deps = create_vorim_agent(
model='openai:gpt-4o',
api_key='agid_sk_...',
agent_name='research-agent',
scopes=['data:read', 'agent:execute'],
system_prompt='You are a research agent.',
)
# Agent is registered with Vorim, permissions granted, ready to go
result = await agent.run('Find the latest papers on agent security', deps=deps)Behind the scenes: registers the agent (Ed25519 keypair generated), grants the requested scopes, and wires up the dependency type. The deps object already has the agent ID set.
Sync and Async
The vorim_tool decorator works with both synchronous and asynchronous tools. Pydantic AI supports both, and so does the Vorim integration:
# Async tool
@agent.tool
@vorim_tool(scope='data:read', action='data.fetch')
async def fetch_data(ctx: RunContext[VorimDeps], query: str) -> str:
return await async_fetch(query)
# Sync tool — works the same way
@agent.tool
@vorim_tool(scope='data:read', action='data.lookup')
def lookup_data(ctx: RunContext[VorimDeps], key: str) -> str:
return sync_lookup(key)Testing with VorimDeps
Pydantic AI's agent.override(deps=...) pattern works naturally with VorimDeps. In tests, you can override with a mock or a test instance:
# Test with a real Vorim test environment
test_deps = VorimDeps(
api_key='agid_sk_test_...',
agent_id='agid_test_agent',
base_url='https://vorim.ai/v1', # or your test instance
)
with agent.override(deps=test_deps):
result = await agent.run('Test query')
assert 'expected' in result.dataThe Broader Picture
- LangChain, OpenAI, Claude, CrewAI, LlamaIndex — framework integrations for TypeScript and Python
- Google A2A Protocol — identity and trust for agent-to-agent communication
- MCP Server — 17 tools for Claude and MCP-compatible clients
- CLI Tool —
npx @vorim/cli initfor terminal-first developers - IETF Internet-Draft — standardizing agent identity across the industry
Pydantic AI is the seventh framework integration and the most type-safe one yet. If you care about code quality enough to use Pydantic AI, you probably care about security enough to want identity and audit trails.
Get Started
pip install vorim pydantic-aiFull documentation: vorim.ai/docs (Pydantic AI section) PyPI: pypi.org/project/vorim/ GitHub: github.com/Vorim-AI-Labs/vorim-ai
If you're building with Pydantic AI and thinking about agent security, reach out at team@vorim.ai or book a call at vorim.ai/contact.
Ready to build with agent identity?
Free plan: 3 agents, 10K auth events/month, full SDK access. No credit card.