create_lead, delete_contact, run_payroll, and search_emails, the agent can call any of them. There is no built-in mechanism to say “this user only approved read access” or “this agent should never be able to delete anything.” The LLM picks the tool based on its reasoning, and whatever it picks, runs.
This post shows how to add real permissions to LangChain agent tools — scoped, per-user, revocable, and enforced before execution.
The Problem: LangChain Tools Have No Access Control
Here is a typical LangChain agent setup:delete_contact repeatedly. There is no permission check, no scope enforcement, and no audit trail.
Three specific gaps:
- No per-user permissions. Every user gets the same tools with the same access level. You cannot give User A read-only access and User B write access without building custom middleware.
- No runtime enforcement. Once a tool is in the tools array, it is callable. There is no check at invocation time to verify the caller has permission.
- No audit logging. LangChain does not record which tools were called, by which agent, on behalf of which user, or whether the call was authorized.
The Solution: Scope-Enforced LangChain Tools
Grantex adds per-tool scope enforcement to LangChain agents. The core idea: every tool call is checked against the user’s approved scopes before execution. If the token does not include the required scope, the tool rejects the call immediately — the underlying function never runs. There are two approaches, depending on how much control you want.Approach 1: createGrantexTool — Per-Tool Scope Wrapping
The @grantex/langchain package provides createGrantexTool, which creates a LangChain DynamicTool with a scope check baked in:
scp claim from the JWT directly, no network call needed. If a user’s grant token only includes contacts:read, calling delete_contact throws a PermissionError before your function executes.
Approach 2: wrapTool with Manifests — Manifest-Based Enforcement
For larger agents with many tools, defining scopes inline gets repetitive. Grantex manifests let you define all tool-to-permission mappings in one place and wrap existing LangChain tools:
grantex manifest list from the CLI.
Adding Audit Logging to LangChain Agents
Scope enforcement blocks unauthorized calls. Audit logging records authorized ones. TheGrantexAuditHandler is a LangChain callback that automatically logs every tool invocation to the Grantex audit trail:
gx.audit.list() or stream events in real time via gx.events.stream().
Custom Manifests for Custom Tools
Most production agents use a mix of SaaS connectors and internal APIs. You can define custom manifests for any tool:The Permission Hierarchy
Grantex uses a four-level permission hierarchy. Higher levels subsume lower ones:| Level | Permission | Allows | Example Scopes |
|---|---|---|---|
| 0 | read | Query, list, search, fetch | tool:crm:read |
| 1 | write | Read + create, update, send | tool:crm:write |
| 2 | delete | Read + write + delete, remove | tool:crm:delete |
| 3 | admin | Everything | tool:crm:admin |
tool:crm:write can use both search_contacts (read) and create_contact (write), but not delete_contact (delete) or export_all (admin). This is enforced automatically — you do not need to implement the hierarchy logic yourself.
Putting It All Together
Here is a complete example: a LangChain agent with scoped tools, manifest enforcement, and audit logging:userGrantToken only contains tool:salesforce:read, the create_lead call is blocked before execution. The audit trail records both the successful search and the denied creation attempt.
Next Steps
- LangChain integration docs — full API reference
- Scope enforcement guide — manifests, permission hierarchy, middleware
- Custom manifests guide — build manifests for your own tools
- Quickstart — get a Grantex API key and grant token in 5 minutes
- GitHub — open source, Apache 2.0