Authdog

Pydantic AI

Last updated Oct 22, 2026
View as Markdown

Pydantic AI keeps its own auth hook. Authdog stays the identity provider. The planned sample attaches an agent access token there and refuses the run when that token is missing or userinfo rejects it.

Sample planned at pydantic-ai/python in authdog/agents-samples. That folder is not published yet, so this page does not pin pydantic-ai. Python 3.10+.

Channel auth, machine credentials, tool checks, and instructions for this framework are the other pages under Pydantic AI in AI.

The hook

@dataclass(frozen=True)
class Caller:
    token: str

agent = Agent("test", deps_type=Caller)

@agent.tool
async def whoami(ctx: RunContext[Caller]) -> str:
    """Return the Authdog subject for this caller. Do not invent one."""
    return await fetch_subject(ctx.deps.token)

Caller.token is the access token. The client secret is not a field on Caller. fetch_subject sends Authorization: Bearer to an API whose route depends on require_auth. A missing or rejected token does not return a subject. Tests call that helper and the route. They do not call the model.

This is agent identity: client_credentials, then this hook. It is not Agent Sign-In. A browser sign-in does not replace the hook.

What you should see

GET /whoami with no token is 401. The helper, given an empty token, does not return a subject.

The same call with a bearer userinfo accepts returns {"subject":"<id>"}. The tool result is that string.

pytest in pydantic-ai/python is how the sample will prove both. It does not call a model.

Configure

Name Purpose
PK_AUTHDOG Public key on the API process.
Caller.token Access token on the run. Not the client secret.

The shared exchange is in Agent frameworks. There is no refresh token. Repeat it before expires_in.

Read To learn how to
Agent frameworks Mint the bearer this hook checks
Google ADK The previous hook
Claude Agent SDK The next hook
Custom channel auth for Pydantic AI The same check, as the auth boundary

Learn more