Agent Server Authentication & Authorization
LangGraph Platform's built-in auth system: when to use it, how @auth.authenticate and @auth.on.resource.action work, the metadata-filter contract that prevents data leaks, and the exact failure modes that hit production.
Quick Reference
- →@auth.authenticate runs on every request — inject authorization, headers, or path by name; return a MinimalUserDict
- →@auth.on.resource.action attribute syntax, not string — @auth.on.threads.create, @auth.on.threads.search, etc.
- →Supported filter operators: $eq (exact match) and $contains (list membership) — $in does not exist
- →Metadata set on create must match the filter returned on read — mismatch = silent data leak
- →Auth.exceptions.HTTPException, not Auth.HTTPException — wrong path raises AttributeError at runtime
- →ctx.user is attribute access, not dict — ctx.user.identity not ctx.user['identity']
- →Always register @auth.on.store separately — global @auth.on does not cover the store namespace
When to Use LangGraph Auth (and When Not To)
LangGraph Platform ships a built-in auth system that intercepts every request before it reaches a thread, assistant, cron, or store namespace. It gives you resource-level access control without custom middleware. Whether you should use it depends on your deployment model.
| Scenario | Use LangGraph auth | Use instead |
|---|---|---|
| LangGraph Cloud or self-hosted LangGraph Platform, Python | Yes — designed for this | — |
| JavaScript/TypeScript LangGraph deployment | No — Python only as of 2026 | API gateway or FastAPI middleware |
| Custom FastAPI app that wraps LangGraph | Optional — depends on whether you call Platform APIs directly | FastAPI middleware if you control every route |
| Auth patterns that span resources outside LangGraph (databases, S3, other services) | Partial — handles LangGraph resources only | Combine: LangGraph auth for Platform resources + your own middleware for the rest |
A self-hosted LangGraph Platform deployment with no auth configuration accepts all requests unauthenticated. There is no built-in API key by default. You must add @auth.authenticate explicitly — or any caller with network access can read and write any thread.