Google ADK 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 `adk/python` in [authdog/agents-samples](https://github.com/authdog/agents-samples). That folder is not published yet, so this page does not pin `google-adk`. Python 3.10+.

Channel auth, machine credentials, tool checks, and instructions for this framework are the other pages under Google ADK in [AI](/docs/ai/adk/channel-auth).

## The hook

```python
def before_agent_callback(callback_context):
    token = callback_context.state.get("authdog_token")
    subject = subject_if_accepted(token)
    callback_context.state["authdog_token"] = None
    if subject is None:
        return types.Content(
            role="model",
            parts=[types.Part(text="unauthorized")],
        )
    callback_context.state["subject"] = subject
    return None
```

The parameter name is `callback_context`. ADK passes callback arguments by keyword. Returning `types.Content` skips the agent body. Returning `None` lets it run. The token lives in callback state, which the host set. It is not the user message. Clear it before the model runs. `AuthCredential` on a tool is outbound tool auth. It is not this check, and it is not a place for the agent client secret.

This is agent identity: `client_credentials`, then this hook. It is not [Agent Sign-In](/docs/agent-sign-in). A browser sign-in does not replace the hook.

## What you should see

A callback with no token, or a token userinfo rejects, returns content whose text is `unauthorized`. The agent body does not run.

A callback with a bearer userinfo accepts stores the subject and returns `None`.

`pytest` in `adk/python` is how the sample will prove both. It does not call a model.

## Configure

| Name | Purpose |
| --- | --- |
| Callback state `authdog_token` | Access token, set by the host before the run. Cleared before the model sees state. |

The shared exchange is in [Agent frameworks](/docs/agent-frameworks#mint-the-bearer). There is no refresh token. Repeat it before `expires_in`.

> **Caution**
>
> Do not commit the client secret, and do not put the access token in the prompt. The public key selects the identity host. It does not mint tokens.

## Related

| Read | To learn how to |
| --- | --- |
| [Agent frameworks](/docs/agent-frameworks) | Mint the bearer this hook checks |
| [CrewAI](/docs/agent-frameworks/crewai) | The previous hook |
| [Pydantic AI](/docs/agent-frameworks/pydantic-ai) | The next hook |
| [Custom channel auth for Google ADK](/docs/ai/adk/channel-auth) | The same check, as the auth boundary |
