The sample graph has no model and no system prompt. reply is subject: plus the id the route already verified. If you add a model node, feed it that state. Leave the bearer in the HTTP header.
What the graph can see
class State(TypedDict):
subject: str
reply: strThe route sets subject from userinfo, then calls ainvoke. A model node should read state["subject"] and should be told not to invent a different one. If the node calls a tool, the tool's permission check uses that same subject. The prompt does not grant the tool.
Keep the access token and AUTHDOG_CLIENT_SECRET out of state. The secret never belonged on this process. The token was consumed by require_auth. Copying it into state puts it in checkpoints, traces, and logs.
When the caller is acting for a person, subject is the user from the delegation token. If the model needs to know an agent was involved, pass act as its own field. Do not overwrite subject with the agent id and then tell the model it is the user.
A prompt that matches the gate
Tell the model the subject is already decided, and that a node which returns an authorization error should be repeated to the caller as a refusal. A prompt that says "ask the user who they are" ignores the route. The route already returned 401 when userinfo did not accept the bearer.
Related
| Read | To learn how to |
|---|---|
| Authorizing tool calls for LangGraph | Refuse work inside a node |
| Custom channel auth for LangGraph | Copy the subject into state |
| LangGraph | See the reply the sample returns |
| API keys and M2M for LangGraph | Keep the secret on the caller |