Version: 1.0 | Status: Final | Last updated: February 2026 (rev 3)The specification is frozen. Changes require a new version.
Abstract
Grantex defines an open protocol for delegated authorization of AI agents acting on behalf of human users. It specifies: cryptographic agent identity, a human-consent-based grant flow, a signed token format, a revocation model, an append-only audit trail schema, a policy engine for automated authorization decisions, enterprise identity federation, and anomaly detection for runtime behavioral monitoring.
1. Motivation
AI agents increasingly take autonomous actions — submitting forms, initiating payments, sending communications — on behalf of humans across third-party services. No interoperable standard exists for:
- Verifying that an agent is who it claims to be
- Confirming that a specific human authorized a specific agent to perform a specific action
- Revoking that authorization in real time
- Producing a tamper-proof record of what the agent did
Grantex fills this gap as an open, model-neutral, framework-agnostic protocol.
2. Definitions
| Term | Definition |
|---|
| Agent | An AI-powered software process that takes autonomous actions on behalf of a Principal |
| Principal | The human user who authorizes an Agent to act on their behalf |
| Developer | The organization or individual who built and operates the Agent |
| Service | Any API or platform that receives requests from an Agent |
| Grant | A record of permission given by a Principal to an Agent for specific Scopes |
| Grant Token | A signed JWT representing a valid, non-revoked Grant |
| Scope | A named permission following the format resource:action[:constraint] |
| DID | Decentralized Identifier — the Agent’s cryptographic identity |
| Policy | A rule that auto-approves or auto-denies an authorization before the consent UI is shown |
| Anomaly | A detected behavioral deviation from an agent’s established activity baseline |
3. Agent Identity
Every Agent registered with a Grantex-compatible Identity Service receives a DID:
Where <agent_id> is a ULID (Universally Unique Lexicographically Sortable Identifier).
3.2 Identity Document
The DID resolves to an identity document containing:
{
"@context": "https://grantex.dev/v1/identity",
"id": "did:grantex:ag_01HXYZ123abcDEF456ghi",
"developer": "org_yourcompany",
"name": "travel-booker",
"description": "Books flights and hotels on behalf of users",
"declaredScopes": ["calendar:read", "payments:initiate:max_500"],
"status": "active",
"createdAt": "2026-02-01T00:00:00Z",
"verificationMethod": [{
"id": "did:grantex:ag_01HXYZ123abcDEF456ghi#key-1",
"type": "JsonWebKey2020",
"publicKeyJwk": { "..." : "..." }
}]
}
3.3 Key Management
- Identity Services MUST use RS256 (RSA + SHA-256) for signing
- Private keys MUST never leave the Identity Service
- Public keys MUST be published at
/.well-known/jwks.json
- Key rotation MUST be supported without changing the DID
4. Scopes
resource:action[:constraint]
4.2 Standard Scope Registry
| Scope | Description |
|---|
calendar:read | Read calendar events |
calendar:write | Create, modify, and delete calendar events |
email:read | Read email messages |
email:send | Send emails on the Principal’s behalf |
email:delete | Delete email messages |
files:read | Read files and documents |
files:write | Create and modify files |
payments:read | View payment history and balances |
payments:initiate | Initiate payments of any amount |
payments:initiate:max_N | Initiate payments up to N in the account’s base currency |
profile:read | Read profile and identity information |
contacts:read | Read address book and contacts |
4.3 Custom Scopes
Services MAY define custom scopes using reverse-domain notation:
com.stripe.charges:create:max_5000
io.github.issues:create
4.4 Scope Governance
Grantex maintains the canonical scope registry in §4.2 as normative. Implementations MUST support all standard scopes. Custom scopes MUST use reverse-domain notation.
4.5 Scope Display
Identity Services MUST maintain a human-readable description for each scope. Consent UIs MUST display human-readable descriptions, never raw scope strings.
5. Grant Flow
5.1 Overview
Developer App Grantex Principal
│ │ │
│ POST /authorize │ │
│ {agentId, scopes, │ │
│ redirectUri} │ │
│────────────────────►│ │
│ │ │
│◄────────────────────│ │
│ {consentUrl} │ │
│ │ │
│ redirect user ─────────────────────────────► │
│ │ consent UI displayed │
│ │◄──────────────────────────│
│ │ Principal approves │
│ │ │
│◄────────────────────────────────────────────────│
│ redirectUri?code=AUTH_CODE │
│ │ │
│ POST /token │ │
│ {code} │ │
│────────────────────►│ │
│◄────────────────────│ │
│ {grantToken, │ │
│ refreshToken} │ │
5.2 Authorization Request
POST /v1/authorize
Authorization: Bearer <api_key>
Content-Type: application/json
{
"agentId": "ag_01HXYZ123abc",
"principalId": "user_abc123",
"scopes": ["calendar:read", "payments:initiate:max_500"],
"expiresIn": "24h",
"redirectUri": "https://yourapp.com/auth/callback",
"state": "<csrf_token>",
"audience": "https://api.targetservice.com"
}
5.3 Token Exchange
POST /v1/token
Authorization: Bearer <api_key>
Content-Type: application/json
{
"code": "AUTH_CODE",
"agentId": "ag_01HXYZ123abc"
}
{
"alg": "RS256",
"typ": "JWT",
"kid": "grantex-2026-02"
}
6.2 Payload
{
"iss": "https://grantex.dev",
"sub": "user_abc123",
"aud": "https://api.targetservice.com",
"agt": "did:grantex:ag_01HXYZ123abc",
"dev": "org_yourcompany",
"grnt": "grnt_01HXYZ...",
"scp": ["calendar:read", "payments:initiate:max_500"],
"iat": 1709000000,
"exp": 1709086400,
"jti": "tok_01HXYZ987xyz"
}
6.3 Custom Claims
| Claim | Type | Description |
|---|
agt | string | Agent DID |
dev | string | Developer org ID |
grnt | string | Grant ID (for revocation lookup) |
scp | string[] | Granted scopes |
6.4 Validation Rules
Services receiving a Grant Token MUST verify:
- Signature using the JWKS at
iss/.well-known/jwks.json
exp has not passed
aud matches the service’s identifier (if set)
scp contains the required scopes for the requested operation
- (Online verification only) Token has not been revoked
7. Revocation
7.1 Revoke a Grant
DELETE /v1/grants/{grantId}
Effect: all active tokens under this Grant are immediately invalidated.
7.2 Revoke a Specific Token
POST /v1/tokens/revoke
Content-Type: application/json
{ "jti": "tok_01HXYZ987xyz" }
7.3 Online Revocation Check
POST /v1/tokens/verify
Content-Type: application/json
{ "token": "eyJhbGciOiJSUzI1NiJ9..." }
7.4 Token Lifetime Guidance
| Use Case | Recommended TTL |
|---|
| High-stakes actions (payments, send) | 1 hour |
| Standard agent tasks | 8 hours |
| Long-running background agents | 24 hours (max) |
Implementations caching revocation state MUST NOT cache for longer than 5 minutes.
8. Audit Trail
8.1 Log Entry Schema
{
"entryId": "alog_01HXYZ...",
"agentId": "did:grantex:ag_01HXYZ123abc",
"grantId": "grnt_01HXYZ...",
"principalId": "user_abc123",
"developerId": "org_yourcompany",
"action": "payment.initiated",
"status": "success",
"metadata": { "amount": 420, "currency": "USD" },
"timestamp": "2026-02-01T12:34:56.789Z",
"hash": "sha256:abc123...",
"prevHash": "sha256:xyz789..."
}
8.2 Hash Chain
Each entry’s hash is SHA-256(canonical_json(entry) + prevHash). This makes any retrospective tampering detectable.
9. Multi-Agent Authorization
Sub-agent tokens carry delegation claims:
{
"sub": "user_abc123",
"agt": "did:grantex:ag_B_456",
"parentAgt": "did:grantex:ag_A_123",
"parentGrnt": "grnt_parentXYZ",
"scp": ["email:read"],
"delegationDepth": 1
}
Rules:
- Sub-agent scopes MUST be a subset of the parent’s scopes
delegationDepth is incremented at each hop
- Hard cap of 10 delegation hops
- Revoking a root grant cascades to all descendants atomically
10. Self-Hosting Endpoints
Core Endpoints (Required)
| Endpoint | Description |
|---|
POST /v1/agents | Register agent |
POST /v1/authorize | Initiate authorization |
POST /v1/token | Exchange code for token |
POST /v1/tokens/verify | Verify token online |
POST /v1/tokens/revoke | Revoke token |
GET /v1/grants | List grants |
DELETE /v1/grants/:id | Revoke grant (cascades) |
POST /v1/grants/delegate | Delegate to sub-agent |
POST /v1/audit/log | Write audit entry |
GET /v1/audit/entries | Query audit log |
GET /.well-known/jwks.json | Public keys |
GET /health | Health check |
Optional Extensions
Policy Engine, Webhooks, SCIM 2.0, SSO (OIDC), Anomaly Detection, Compliance, and Billing endpoints are optional extensions. See the full specification for details.
11. Policy Engine
Evaluates rules against each authorization request before consent UI. Deny rules are evaluated first — the first matching auto_deny wins. Then allow rules. If no rule matches, consent UI is shown.
12. Enterprise Identity (SCIM & SSO)
SCIM 2.0 user provisioning from enterprise IdPs (Okta, Azure AD). SSO via OIDC with state and nonce validation.
13. Anomaly Detection
Advisory-only runtime monitoring. Anomaly types: unusual_scope_access, high_frequency, off_hours_activity, new_principal, cascade_delegation.
14. Security Considerations
- Tokens MUST be signed with RS256. HS256 and
alg: none MUST be rejected.
- Token replay MUST be detectable via
jti tracking.
- Consent UIs MUST validate
state to prevent CSRF.
- Redirect URIs MUST be pre-registered and exactly matched.
- Audit logs MUST be append-only (no update or delete endpoints).
- SCIM endpoints MUST use dedicated bearer tokens, separate from API keys.
- SSO callbacks MUST validate
state and nonce.
- Policy engine MUST evaluate deny before allow.
- Anomaly detection MUST NOT block token issuance.
The full specification is maintained at github.com/mishrasanjeev/grantex/blob/main/SPEC.md and is licensed under Apache 2.0.