LangGraph compiles a graph. It does not authenticate the HTTP caller. Put `require_auth` on the route that invokes the graph, and pass the Authdog subject in as state. The graph reads that state. It does not read the `Authorization` header.

Sample: [langgraph/python](https://github.com/authdog/agents-samples/tree/main/langgraph/python). Python 3.10+. Package `langgraph==1.2.16`.

## The route is the hook

```python
class State(TypedDict):
    subject: str
    reply: str

def build_graph():
    def respond(state: State) -> dict[str, str]:
        return {"reply": f"subject:{state['subject']}"}

    graph = StateGraph(State)
    graph.add_node("respond", respond)
    graph.add_edge(START, "respond")
    graph.add_edge("respond", END)
    return graph.compile()

authdog = Authdog(public_key=public_key)
compiled = build_graph()

@app.post("/invoke")
async def invoke(user=Depends(authdog.require_auth)):
    result = await compiled.ainvoke(
        {"subject": subject_of(user), "reply": ""}
    )
    return {"reply": result["reply"]}
```

`Authdog` comes from `authdog.fastapi`. `require_auth` is a FastAPI dependency, so a missing or rejected token never enters `invoke`. `subject_of` reads `id`, then `sub`, from the userinfo user.

Call `graph.invoke` or `ainvoke` only from a route that already depends on `require_auth`. A second route that invokes the compiled graph directly skips Authdog. This sample has one route.

The caller mints the bearer elsewhere. Use the exchange in [Agent frameworks](/docs/agent-frameworks), or the client in the [A2A sample](/docs/agent-frameworks/a2a). This process does not take `AUTHDOG_CLIENT_SECRET`.

## What you should see

`POST /invoke` with no token returns `401`. The body does not contain `subject:`.

The same call with `Authorization: Bearer <token>` that userinfo accepts returns:

```json
{"reply": "subject:<id>"}
```

`pytest` checks both: `401` with no token, and `subject:agent_1` when userinfo returns that id.

## Configure

| Variable | Purpose |
| --- | --- |
| `PK_AUTHDOG` | Public key for `Authdog(public_key=...)`. |

```bash
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements-dev.txt
export PK_AUTHDOG=pk_...
uvicorn server:create_app --factory --port 8000
```

> **Caution**
>
> Install `authdog-fastapi` from the pinned [web-sdk](https://github.com/authdog/web-sdk) commit in the sample `requirements.txt`, with the `fastapi` extra.

## Related

| Read | To learn how to |
| --- | --- |
| [OpenAI Agents SDK](/docs/agent-frameworks/openai-agents) | The caller that presents this token from a tool |
| [MCP](/docs/agent-frameworks/mcp) | The same userinfo check behind `token_verifier` |
| [Backend requests](/docs/backend) | `require_auth` on an API that is not a graph |
