Pydantic AI integration
Prismor adapter for Pydantic AI. Source lives at
adapters/pydantic-ai/, bundled into the main
prismor package (no separate PyPI package).
Registry entry: id: pydantic-ai in
prismor/runtime/integrations/registry.yaml.
Install
pip install "prismor[pydantic-ai]"
Connect to the console
To see this agent's tool calls in the Prismor console and control it from there:
- In the console, open Agents. Under SDK & deployed agents, enter a workload name and click Mint agent key. The key is shown once, so put it in your deployment's secret manager.
- Set it as
PRISMOR_AGENT_KEYin the agent's environment. - Run the agent. Its first guarded tool call pulls your org's signed policy and starts reporting, and the agent appears in the console under that workload name. Changes you make in the console (mode, blocked tools) reach it on its next tool call, at most about 30 seconds later.
Without a key the adapter still enforces your local policy but reports nothing. To check the connection, run prismor doctor with the same PRISMOR_AGENT_KEY set.
Why this hook point
Pydantic AI's real interception point is a WrapperToolset subclass:
call_tool(name, tool_args, ctx, tool) is the single choke point every tool
call passes through — plain Python functions, MCP-server tools, or any
composed toolset. Not calling super().call_tool(...) means the wrapped tool
never runs — a genuine pre-execution deny gate, not an observe-only callback.
Use
from pydantic_ai import Agent
from pydantic_ai.toolsets import FunctionToolset
from prismor.pydantic_ai import guard_toolsets
toolset = FunctionToolset([run_shell, read_file])
agent = Agent(
"openai:gpt-4o-mini",
toolsets=guard_toolsets([toolset], subject="user:alice", mode="enforce"),
)
A denied call raises pydantic_ai.exceptions.ToolFailed by default — the
model sees a definitive failure and adapts, without consuming the tool's
retry budget the way ModelRetry would (this is a policy denial, not a
transient/correctable error). Pass raise_on_block=True to raise
PrismorBlocked instead for a hard Python-level stop. mode="observe" is
log-only.
Per-user control
subject accepts a Subject, a "user:alice"-style string, or None
(resolved from PRISMOR_SUBJECT / the enrolled device at call time). It is
threaded into policy evaluation, IAM profile selection (user:<id> /
team:<id>), and telemetry — the same generic Subject/resolve_subject
plumbing every adapter uses, so per-user IAM profiles (.prismor/iam.yaml)
apply identically to LangChain, CrewAI, or any other adapter.
Verified
Live-tested against a real pydantic-ai Agent running openai:gpt-4o-mini
with a genuine OpenAI API key: a shell tool call matching a block_categories
rule (e.g. rm -rf /) was denied before execution — the tool's Python
implementation never ran — while a harmless command executed normally.
See also
- Framework adapters overview
- IAM — per-user permission profiles