> ## 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.

# Tool Manifests

> How tool manifests map every tool to a permission level, enabling precise scope enforcement for AI agent tool calls.

## What Is a Tool Manifest?

A tool manifest is a declarative mapping from tool names to permission levels for a specific connector. It tells Grantex exactly which permission is required to call each tool, so enforcement does not have to guess from tool name keywords.

```json theme={null}
{
  "connector": "salesforce",
  "version": "1.0.0",
  "description": "Salesforce CRM connector",
  "tools": {
    "create_lead": "write",
    "update_opportunity": "write",
    "query": "read",
    "create_task": "write",
    "get_account": "read",
    "list_opportunities": "read"
  }
}
```

When an agent calls `create_lead`, Grantex looks up the manifest, sees that `create_lead` requires `write` permission, and checks whether the agent's grant token includes a scope that covers `write` on the `salesforce` connector.

***

## The Permission Hierarchy

Grantex defines four permission levels in a strict hierarchy. Higher levels subsume all lower levels:

```
admin (level 3)
  └── delete (level 2)
       └── write (level 1)
            └── read (level 0)
```

| Level | Permission | Typical Operations                               |
| ----- | ---------- | ------------------------------------------------ |
| 0     | `read`     | Query, list, get, search, fetch, check, download |
| 1     | `write`    | Create, update, send, post, upload, apply        |
| 2     | `delete`   | Delete, remove, void, terminate, revoke, cancel  |
| 3     | `admin`    | Run payroll, period close, force reset, purge    |

### Coverage Rules

A scope grants access to all tools at or below its permission level:

|  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   |

**Example:** An agent with `tool:salesforce:write:*` can call `query` (read) and `create_lead` (write) but cannot call `delete_contact` (delete) or `run_period_close` (admin).

***

## Scope Format

Tool enforcement scopes follow the format:

```
tool:{connector}:{permission}:{resource}[:capped:{N}]
```

| Part         | Required | Description                                                               |
| ------------ | -------- | ------------------------------------------------------------------------- |
| `tool`       | Yes      | Fixed prefix identifying this as a tool scope                             |
| `connector`  | Yes      | The connector name (e.g., `salesforce`, `s3`, `stripe`)                   |
| `permission` | Yes      | The maximum permission level granted (`read`, `write`, `delete`, `admin`) |
| `resource`   | Yes      | The resource pattern (`*` for all tools on this connector)                |
| `capped:N`   | No       | Optional spending cap per operation (e.g., `capped:500`)                  |

### Examples

| Scope                            | Meaning                                                        |
| -------------------------------- | -------------------------------------------------------------- |
| `tool:salesforce:write:*`        | Write access to all Salesforce tools (covers read + write)     |
| `tool:s3:read:*`                 | Read-only access to all 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                            |
| `tool:okta:delete:*`             | Delete access to all Okta tools (covers read + write + delete) |

***

## How enforce() Uses Manifests

When you call `enforce()`, Grantex performs these steps:

1. **Decode the JWT** — extract `scp` (scopes), `grnt`/`jti` (grant ID), `agt` (agent DID)
2. **Look up the manifest** — find the loaded manifest for the given connector
3. **Resolve the permission** — look up the tool name in the manifest to get its required permission level
4. **Check coverage** — determine if any scope in the token covers the required permission on this connector
5. **Check caps** — if the scope is capped and an amount was provided, verify the amount is within the cap
6. **Return the result** — `allowed: true` or `allowed: false` with a reason

```python theme={null}
result = grantex.enforce(
    grant_token=token,           # JWT with scp: ["tool:salesforce:write:*"]
    connector="salesforce",      # Look up salesforce manifest
    tool="delete_contact",       # Manifest says: delete permission required
)
# Token grants write, tool requires delete -> DENIED
# result.allowed = False
# result.reason = "write scope does not permit delete operations on salesforce"
```

***

## Defining Manifests

Grantex enforces permissions on **any connector you define** — not just the ones we ship. You own the manifest, you own the permission mapping.

### Custom Manifests

Define a manifest for any tool, API, or internal service. No dependency on Grantex to add support:

* **Inline** — define in code with `ToolManifest(...)`:

```python theme={null}
from grantex import ToolManifest, Permission

grantex.load_manifest(ToolManifest(
    connector="my-internal-crm",
    description="Internal CRM API",
    tools={
        "search_contacts": Permission.READ,
        "create_deal":     Permission.WRITE,
        "delete_account":  Permission.DELETE,
        "manage_roles":    Permission.ADMIN,
    },
))
```

* **JSON file** — load from disk with `ToolManifest.from_file("./manifests/my-service.json")`
* **Directory** — load all manifests from a folder with `grantex.load_manifests_from_dir("./manifests/")`
* **Extend** — add tools to any manifest with `manifest.add_tool("new_tool", Permission.WRITE)`
* **CLI generate** — auto-generate manifests from source code with `grantex manifest generate agent_tools.py`

<Tip>
  The `enforce()` engine, permission hierarchy, and JWT scope resolution work identically for custom and pre-built manifests. There is no difference at runtime.
</Tip>

### Pre-Built Manifests

As a convenience, Grantex ships 53 pre-built manifests covering 339 tools across five categories:

| Category  | Connectors | Tools | Examples                                   |
| --------- | ---------- | ----- | ------------------------------------------ |
| Finance   | 11         | 78    | Stripe, SAP, QuickBooks, NetSuite          |
| HR        | 8          | 56    | Darwinbox, Okta, DocuSign, Greenhouse      |
| Marketing | 16         | 94    | Salesforce, HubSpot, Mailchimp, Google Ads |
| Ops       | 7          | 46    | Jira, Confluence, ServiceNow, Zendesk      |
| Comms     | 11         | 65    | Gmail, Slack, GitHub, S3, Twilio           |

Import and load them directly:

```python theme={null}
from grantex.manifests.salesforce import manifest as sf
from grantex.manifests.stripe import manifest as stripe

grantex.load_manifests([sf, stripe])
```

These are a starting point, not a boundary. Mix pre-built and custom manifests freely — most production deployments use both.

***

## Fail-Closed Default

If `enforce()` is called with a connector or tool that has no manifest loaded, the call is **denied by default**:

```python theme={null}
result = grantex.enforce(
    grant_token=token,
    connector="unknown-service",
    tool="do_something",
)
# result.allowed = False
# result.reason = "No manifest loaded for connector 'unknown-service'. Load a manifest first."
```

This fail-closed behavior ensures that agents cannot bypass enforcement by calling tools that were never declared. Every tool must have an explicit permission entry in a loaded manifest.

For development and testing, you can switch to permissive mode:

```python theme={null}
grantex = Grantex(
    api_key=key,
    enforce_mode="strict",       # default -- deny unknown tools
    # enforce_mode="permissive", # dev only -- allow unknown tools with warning
)
```

<Warning>
  Never use `enforce_mode="permissive"` in production. It defeats the purpose of scope enforcement.
</Warning>

***

## JSON Manifest File Format

When storing manifests as files (for git, CI, or team sharing), use this JSON format:

```json theme={null}
{
  "connector": "inventory-service",
  "version": "1.0.0",
  "description": "Internal warehouse inventory API",
  "tools": {
    "get_stock_level": "read",
    "reserve_inventory": "write",
    "release_reservation": "write",
    "adjust_stock": "write",
    "force_stock_reset": "admin"
  }
}
```

| Field         | Type     | Required | Description                                                                       |
| ------------- | -------- | -------- | --------------------------------------------------------------------------------- |
| `connector`   | `string` | Yes      | Unique connector identifier                                                       |
| `version`     | `string` | No       | Semantic version of the manifest (default `"1.0.0"`)                              |
| `description` | `string` | No       | Human-readable description                                                        |
| `tools`       | `object` | Yes      | Map of tool name to permission level (`"read"`, `"write"`, `"delete"`, `"admin"`) |

***

## Related

* [Custom Manifests guide](/guides/custom-manifests) — define manifests for any connector
* [Scope Enforcement guide](/guides/scope-enforcement) — end-to-end walkthrough
* [Scopes concept](/concepts/scopes) — the `resource:action[:constraint]` scope format
* [TypeScript SDK enforce()](/sdks/typescript/enforce) — API reference
* [Python SDK enforce()](/sdks/python/enforce) — API reference
* [CLI manifest commands](/cli/manifest) — browse and validate manifests
* [AgenticOrg case study](/case-studies/agenticorg) — 53 pre-built + custom manifests enforced in production
