Skip to main content

Overview

The enforce API verifies that an agent’s grant token includes sufficient scope to call a specific tool on a specific connector. It combines JWT verification with manifest-based permission resolution in a single call.

enforce()

Check whether a grant token permits a tool call.

Parameters

Response: EnforceResult

Example

Capped Scopes

When a token includes a capped scope, pass the amount to enforce against the cap:
From version 0.7.0 (breaking): a call without amount under a capped scope is denied with reason_code cap_exceeded and sub_reason amount_missing (details carries limit). Earlier releases allowed the missing amount without checking its cap. caps_mode="warn" (on the client or per call) keeps allowing it and reports the denial in result.would_deny_all (and in result.would_deny when it is the first warning of the call, so a call that also lacks a decision grant under decisions_mode="warn" shows the decision there and amount_missing only in would_deny_all); caps_mode="off" skips it. The cap covers every tool of the connector, read tools included, so pass an amount (0 when there is none) for those too. See Amount caps.

Grant token audience

Available in published grantex==0.7.0. This is a breaking change: a grant token that carries an aud claim is denied unless the client expects that audience. A token without aud is denied if the client expects an audience; only tokens and clients both lacking an audience keep their previous semantics. Online revocation is now the default.
A grant token requested with an audience carries it in the aud claim (RFC 7519 section 4.1.3): the token is only for that relying party. enforce() checks aud right after the signature, before revocation and scopes: aud may be a string or an array of strings; it matches when the expected audience is one of its values, compared as exact strings (no case folding, no trailing-slash or prefix matching). The denial’s details carry token_audience (a list) and, for audience_mismatch, expected_audience. Audience denials are not relaxed by enforce_mode="permissive": they stay allowed=False, with the same reason_code, sub_reason and details, in every enforce mode, because the token was issued for another relying party (or the client does not know its own audience). Set the audience on the client, and override it for one call:
To keep the earlier behaviour while you find each service’s audience, create the client with audience_check="off"; remove it once audience is set.

load_manifest()

Load a single tool manifest into the client. Must be called before enforce() for the corresponding connector.

Example


load_manifests()

Load multiple tool manifests at once.

Example


ToolManifest

A manifest declares the permission level required for each tool on a connector.

Constructor

get_permission()

Look up the required permission for a tool. Returns None if the tool is not in the manifest.

add_tool()

Add a tool to an existing manifest. Useful for extending pre-built manifests with custom tools.

from_file()

Create a manifest from a JSON file on disk:
The JSON file format:

from_dict()

Create a manifest from a Python dictionary:

Permission

A class representing the four permission levels in the hierarchy.
Higher levels subsume all lower levels: admin > delete > write > read.

covers()

Check whether this permission level covers a required permission level:

is_valid()

Check whether a string is a valid permission level:

wrap_tool()

Wrap a LangChain StructuredTool so that enforcement runs automatically before every invocation.
extract_amount (from version 0.7.0) receives the tool call’s keyword arguments and returns the call’s amount, which is passed to enforce() as amount. Under a capped scope, a wrapper without it (or an extractor returning None) denies every call with amount_missing. An extractor that raises refuses the call with PermissionError before enforce() runs; a value that is not a finite number is denied with invalid_amount.

Example


FastAPI Integration

Use GrantexAuth from grantex_fastapi as a FastAPI dependency for automatic enforcement on tool execution routes:

Ownership

Grantex is owned by Orchestrum Technologies LLP. Inventor and owner: Sanjeev Kumar. Ownership contact: sanjeev@orchestrum.in or mishra.sanjeev@gmail.com.
Last modified on September 28, 2026