Authdog

Authorizing tool calls for LangGraph

Last updated Oct 21, 2026
View as Markdown

The route admits a caller. Each node still has to respect what that subject may do. The sample graph has one node, respond, and it only formats subject:<id>. It does not call another tool.

Read the subject from state

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

state["subject"] was copied from userinfo inside the route. A node that needs a privileged action should see that string and refuse when the subject is missing or not allowed. Do not re-read the Authorization header inside the node. The graph was compiled once and can be invoked from anywhere. The header is only present on the HTTP request, and only the route is supposed to see it.

If you add a tool node, treat it like any other API call:

Check Where
Bearer accepted require_auth on /invoke, before ainvoke
Allowed tools Trust-store row, if your process enforces it. This sample does not.
The action itself Authorization in the node, using state["subject"]

A reply of subject:<id> means the route accepted the bearer. It is not an allow list. Revoke in Agents stops new tokens when the subject is the OIDC client id. Tokens already issued last until expires_in unless the route's userinfo check, or a trust-store check you add, rejects them.

When the token is an RFC 8693 delegation, put the user id in subject and keep the acting agent beside it if the node needs both. Authorizing the agent as the user skips the delegation.

Read To learn how to
Custom channel auth for LangGraph Stop unauthenticated invokes
Enriching instructions for LangGraph Give a model the subject from state
Authorization Pick the check the node should call
Agents Revoke the caller and set allowed tools

Learn more