Documentation Index
Fetch the complete documentation index at: https://docs.grantex.dev/llms.txt
Use this file to discover all available pages before exploring further.
Why Scope Enforcement Matters
AI agents call real APIs — Salesforce, Jira, Stripe, S3 — using shared service account credentials. The credentials themselves do not restrict what an agent can do. Without enforcement, an agent authorized to read contacts can also delete contacts if the underlying credential allows it. Grantex scope enforcement closes this gap: every tool call is checked against an explicit permission manifest before execution, ensuring agents can only perform the actions their grant token authorizes.
Quick Start
Add scope enforcement to your agent in five lines:
from grantex import Grantex
from grantex.manifests.salesforce import manifest as sf
grantex = Grantex(api_key="gx_...")
grantex.load_manifest(sf)
result = grantex.enforce(grant_token=token, connector="salesforce", tool="delete_contact")
if not result.allowed:
raise PermissionError(result.reason)
That is all you need. The enforce() call decodes the JWT, resolves the tool’s required permission from the manifest, and checks whether the token’s scopes cover it.
Loading Manifests
Grantex enforces permissions on any connector you define. You bring the manifest, Grantex enforces it. Load manifests before calling enforce().
Custom Manifests — Define Your Own
Every tool your agent calls — whether it’s an internal API, a new SaaS connector, or a proprietary service — can be enforced with a custom manifest. No waiting for a Grantex release, no dependency on us.
Inline definition:
from grantex import ToolManifest, Permission
grantex.load_manifest(ToolManifest(
connector="inventory-service",
description="Internal warehouse inventory API",
tools={
"get_stock_level": Permission.READ,
"reserve_inventory": Permission.WRITE,
"force_stock_reset": Permission.ADMIN,
},
))
From a JSON file:
grantex.load_manifest(ToolManifest.from_file("./manifests/inventory-service.json"))
From a directory (load all at once):
grantex.load_manifests_from_dir("./manifests/")
Auto-generate from source code:
grantex manifest generate agent_tools.py --out my-connector.json
Extend a pre-built manifest:
from grantex.manifests.salesforce import manifest as sf_manifest
sf_manifest.add_tool("bulk_delete_all", Permission.ADMIN)
sf_manifest.add_tool("export_all_contacts", Permission.READ)
grantex.load_manifest(sf_manifest)
Custom and pre-built manifests are identical at runtime. The enforce() engine, permission hierarchy, and JWT scope resolution make no distinction between them.
Pre-Built Manifests — 53 Included
As a convenience, Grantex ships 53 pre-built manifests covering finance, HR, marketing, ops, and comms connectors. Use them as-is or as a starting point:
from grantex import Grantex
from grantex.manifests.salesforce import manifest as sf
from grantex.manifests.hubspot import manifest as hs
from grantex.manifests.jira import manifest as jira
grantex = Grantex(api_key="gx_...")
grantex.load_manifests([sf, hs, jira])
Browse all 53 with grantex manifest list. Mix pre-built and custom manifests freely — most production deployments use both.
LangChain Integration
Wrap any LangChain tool with wrap_tool() to enforce scope checks automatically on every invocation:
protected_tool = grantex.wrap_tool(
my_langchain_tool,
connector="salesforce",
tool="create_lead",
grant_token=lambda: current_state["grant_token"],
)
# Use protected_tool in your LangChain agent — enforcement happens
# automatically before every call. If the token lacks write scope,
# the tool raises PermissionError instead of executing.
Express / FastAPI Middleware
Add one-line enforcement to your tool execution endpoints:
import { Grantex } from '@grantex/sdk';
import { salesforceManifest } from '@grantex/sdk/manifests/salesforce';
const grantex = new Grantex({ apiKey: 'gx_...' });
grantex.loadManifest(salesforceManifest);
app.use('/api/tools/*', grantex.enforceMiddleware({
extractToken: (req) => req.headers.authorization?.replace('Bearer ', ''),
extractConnector: (req) => req.params.connector,
extractTool: (req) => req.params.tool,
}));
CLI Workflow
The CLI provides a complete manifest workflow: list available manifests, validate your agent’s tools against them, and dry-run enforcement.
# Browse all 53 pre-built manifests (or use your own)
grantex manifest list
# Filter by category
grantex manifest list --category finance
# Show tools in a specific manifest
grantex manifest show salesforce
# Validate that your agent's tools all have manifest entries
grantex manifest validate --agent-tools create_lead,query,delete_contact --connector salesforce
# Dry-run enforcement against a real token
grantex enforce test --token "eyJ..." --connector salesforce --tool delete_contact
See CLI manifest reference and CLI enforce reference for full details.
Permission Hierarchy
Grantex uses a four-level permission hierarchy. Higher levels subsume all lower levels:
| Level | Permission | Allows | Example Tools |
|---|
| 0 | read | Query, list, get, search, fetch, download | get_contact, list_invoices, search_emails |
| 1 | write | Read + create, update, send, upload | create_lead, send_email, update_issue |
| 2 | delete | Read + write + delete, remove, void, terminate | delete_contact, void_envelope, reject_application |
| 3 | admin | Everything | run_payroll, run_period_close, force_stock_reset |
Coverage rules:
| Granted Scope | READ Tools | WRITE Tools | DELETE Tools | ADMIN Tools |
|---|
tool:X:read | Allowed | Denied | Denied | Denied |
tool:X:write | Allowed | Allowed | Denied | Denied |
tool:X:delete | Allowed | Allowed | Allowed | Denied |
tool:X:admin | Allowed | Allowed | Allowed | Allowed |
Tool enforcement scopes use the format:
tool:{connector}:{permission}:{resource}[:capped:{N}]
Examples:
| Scope | Meaning |
|---|
tool:salesforce:write:* | Write access to all Salesforce tools |
tool:s3:read:* | Read-only access to S3 tools |
tool:stripe:write:*:capped:500 | Write access to Stripe tools, capped at $500 per operation |
tool:jira:admin:* | Full admin access to all Jira tools |
Complete Example
A full agent with scope enforcement from token exchange to tool execution:
import os
from grantex import Grantex, ExchangeTokenParams
from grantex.manifests.salesforce import manifest as sf
from grantex.manifests.gmail import manifest as gmail
# 1. Initialize client and load manifests
grantex = Grantex(api_key=os.environ["GRANTEX_API_KEY"])
grantex.load_manifests([sf, gmail])
# 2. Exchange authorization code for a grant token
token_response = grantex.tokens.exchange(ExchangeTokenParams(
code="auth_code_from_callback",
agent_id="agt_sales_rep",
))
grant_token = token_response.grant_token
# Token scopes: ["tool:salesforce:write:*", "tool:gmail:read:*"]
# 3. Before every tool call, enforce scope
def call_tool(connector: str, tool: str, **kwargs):
result = grantex.enforce(
grant_token=grant_token,
connector=connector,
tool=tool,
)
if not result.allowed:
raise PermissionError(f"Agent denied: {result.reason}")
# Proceed with the actual tool execution
return execute_connector_tool(connector, tool, **kwargs)
# 4. These calls succeed
call_tool("salesforce", "create_lead", name="Acme Corp") # write -> write: allowed
call_tool("salesforce", "query", soql="SELECT Id FROM Lead") # write -> read: allowed
call_tool("gmail", "search_emails", query="from:acme") # read -> read: allowed
# 5. These calls are denied
call_tool("salesforce", "delete_contact", id="003xx") # write -> delete: DENIED
call_tool("gmail", "send_email", to="ceo@acme.com") # read -> write: DENIED