Skip to main content

You Own the Manifest

Grantex is a permission enforcement engine, not a connector catalog. The 53 pre-built manifests are a convenience — the real power is that you define permissions for any tool your agent calls.

Any Connector

Internal APIs, new SaaS tools, proprietary services — if your agent calls it, you can enforce it.

Zero Dependency

No waiting for a Grantex release. Define a manifest in your codebase, enforce immediately.

Identical at Runtime

Custom and pre-built manifests use the same enforce() engine, permission hierarchy, and JWT scope resolution.

Multiple Sources

Define inline, load from JSON files, load a directory, auto-generate from source code, or extend pre-built manifests.

Define Inline

The most common approach — define a manifest right in your code:
from grantex import Grantex, ToolManifest, Permission

grantex = Grantex(api_key="gx_...")

grantex.load_manifest(ToolManifest(
    connector="inventory-service",
    description="Internal warehouse inventory API",
    tools={
        "get_stock_level":   Permission.READ,
        "list_warehouses":   Permission.READ,
        "reserve_inventory": Permission.WRITE,
        "update_quantity":   Permission.WRITE,
        "remove_item":       Permission.DELETE,
        "force_stock_reset": Permission.ADMIN,
    },
))

# Works exactly like a pre-built manifest
result = grantex.enforce(
    grant_token=token,
    connector="inventory-service",
    tool="force_stock_reset",
)
# Token with tool:inventory-service:write:* → DENIED (write < admin)

Load from JSON Files

Store manifests as JSON for version control, code review, and team sharing:
inventory-service.json
{
  "connector": "inventory-service",
  "version": "1.0.0",
  "description": "Internal warehouse inventory API",
  "tools": {
    "get_stock_level": "read",
    "list_warehouses": "read",
    "reserve_inventory": "write",
    "update_quantity": "write",
    "remove_item": "delete",
    "force_stock_reset": "admin"
  }
}
grantex.load_manifest(ToolManifest.from_file("./manifests/inventory-service.json"))
ToolManifest.from_file() supports both JSON and YAML (.yml / .yaml). However, load_manifests_from_dir() only loads .json files — rename or convert YAML files before using directory loading.

Load a Directory

If you keep manifests as .json files in a folder, load them all at once:
manifests/
  inventory-service.json
  billing-api.json
  notification-service.json
  salesforce.json        ← you can mix custom and exported pre-built
grantex.load_manifests_from_dir("./manifests/")

Auto-Generate from Source Code

The CLI can scan your tool definitions and generate a manifest automatically:
# Generate from Python tool registry
grantex manifest generate agent_tools.py --out inventory-service.json

# Generate from TypeScript tool definitions
grantex manifest generate tools.ts --out inventory-service.json
The CLI infers permissions from tool name patterns (get_* → read, create_* → write, delete_* → delete). Always review the output — the inference is a starting point, not a guarantee.

Extend Pre-Built Manifests

Add tools to any existing manifest — pre-built or custom:
from grantex.manifests.salesforce import manifest as sf

# Add tools specific to your Salesforce org
sf.add_tool("custom_bulk_export", Permission.READ)
sf.add_tool("custom_data_purge", Permission.ADMIN)

grantex.load_manifest(sf)

Mix Custom and Pre-Built

Most production deployments use both. Load pre-built manifests for well-known connectors, custom manifests for everything else:
from grantex import Grantex, ToolManifest, Permission
from grantex.manifests.salesforce import manifest as sf
from grantex.manifests.stripe import manifest as stripe
from grantex.manifests.jira import manifest as jira

grantex = Grantex(api_key="gx_...")

# Pre-built for well-known connectors
grantex.load_manifests([sf, stripe, jira])

# Custom for your own services
grantex.load_manifest(ToolManifest(
    connector="billing-api",
    tools={
        "get_invoice":      Permission.READ,
        "create_charge":    Permission.WRITE,
        "issue_refund":     Permission.DELETE,
        "override_billing": Permission.ADMIN,
    },
))

grantex.load_manifests_from_dir("./manifests/")  # more custom manifests

Permission Hierarchy

All manifests — custom or pre-built — use the same four permission levels:
admin (level 3)
  └── delete (level 2)
       └── write (level 1)
            └── read (level 0)
Granted ScopeREAD ToolsWRITE ToolsDELETE ToolsADMIN Tools
tool:X:readAllowedDeniedDeniedDenied
tool:X:writeAllowedAllowedDeniedDenied
tool:X:deleteAllowedAllowedAllowedDenied
tool:X:adminAllowedAllowedAllowedAllowed
The scope format is tool:{connector}:{permission}:{resource}. Your custom connector name goes in place of {connector}:
tool:inventory-service:write:*       ← custom connector
tool:salesforce:read:*               ← pre-built connector
tool:billing-api:admin:*             ← custom connector

Validation

Validate your manifests before deploying:
# Load and inspect a custom manifest file
grantex manifest load ./manifests/inventory-service.json
The CLI commands grantex manifest validate and grantex enforce test currently only work with the 53 bundled manifests. For custom manifests, use grantex manifest load to inspect the file, and test enforcement programmatically using the SDK’s enforce() method directly.

FAQ

No. Define a ToolManifest in your codebase and load it at startup. The enforce engine makes no distinction between your manifests and the bundled ones.
Use the pre-built manifests for well-known connectors (Salesforce, Stripe, etc.). For third-party connectors not in the bundled set, define your own manifest based on the connector’s API documentation.
Yes. Load your own manifest with the same connector name — it fully replaces the previous one (all tools, not just overlapping ones). If you want to keep the original tools and add new ones, use add_tool() instead.
enforce() returns allowed: false with the reason “Unknown tool”. This fail-closed default means agents cannot call tools that were never declared.
Use the same format: tool:{your-connector}:{permission}:*. For example, tool:inventory-service:write:* grants write access to your inventory service.