Understanding Task-Based Access Control
Task-Based Access Control (TBAC) is an authorization model for AI agents that enforces permissions based on what work is being done rather than who is doing it.
Why Traditional Access Control Fails for AI Agents
AI agents run dynamic workflows that span multiple systems. Traditional models create mismatches:
| Model | Issue | Example | 
|---|---|---|
| RBAC (Role-Based) | Static roles don't match dynamic workflows | Agent needs "Finance Manager" role to check budgets, but inherits payroll and forecast access | 
| ABAC (Attribute-Based) | Attribute combinations explode in complexity | Managing hundreds of time/location/resource attributes becomes unmaintainable | 
| Impersonation | Accountability breaks down | Logs show user identity, not autonomous agent action | 
The core problem: These models assume relatively stable human user permissions. AI agents need different access for different workflows—sometimes changing minute by minute.
The Three Dimensions of TBAC
TBAC enforces authorization through three progressive layers:
1. Tasks
Business-level objectives the agent is authorized to perform.
"authorized_tasks": ["expense_approval", "financial_reporting"]
Purpose: Validate the agent is authorized for this type of work before checking system access.
Example: An expense agent can perform "expense_approval" tasks but cannot perform "payroll_management" tasks.
2. Tools
MCP server and tool access that controls which specific MCP servers and their exposed tools the agent can invoke.
In MCP, tools are functions that servers expose (like get_weather, query_database, send_email). These are the actual capabilities invoked via tools/call.
Purpose: Limit lateral movement—even if authorized for a task, the agent can only invoke specific MCP tools from specific servers.
Choosing Your JWT Structure
You have two options for structuring tool permissions in your JWT. Your choice depends on whether you need server-specific constraints, not on how many MCP servers you have.
Option 1: Hierarchical structure—Use when you need per-server constraints
"tools": {
  "github_mcp": {
    "actions": ["create_issue", "add_comment"],
    "allowed_repos": ["org/frontend", "org/backend"]
  },
  "slack_mcp": {
    "actions": ["post_message"],
    "allowed_channels": ["#incidents", "#engineering"]
  }
}
When to use: When different MCP servers need different constraints (like allowed repositories, channels, folders, or rate limits).
Policy example:
- match: "Contains(`jwt.tools.github_mcp.actions`, `${mcp.params.name}`)"
  action: allow
Option 2: Flat array structure—Use for basic tool lists
"allowed_tools": ["create_issue", "post_message", "query_logs"]
When to use: When you only need to allow/deny specific tools without server-specific constraints.
Policy example:
- match: "Contains(`jwt.allowed_tools`, `${mcp.params.name}`)"
  action: allow
Can Both Structures Be Used Together?
Yes! You can use both in the same JWT:
{
  "allowed_tools": ["create_issue", "post_message"],
  "tools": {
    "github_mcp": {
      "allowed_repos": ["org/frontend"]
    }
  },
  "max_requests_per_hour": 100
}
This lets you use allowed_tools for quick checks and nest other constraints under tools where needed.
Example scenario: Your incident response agent might need the github_mcp server for create_issue (but only in specific repos), and the slack_mcp server for post_message (but only to specific channels).
It cannot access delete_repository or post to #executive-announcements.
3. Transactions
Parameter-level constraints on what the agent can do with each tool.
"approval_limit": 2500,
"department": "sales",
"categories": ["travel", "meals"]
Purpose: Enforce business rules and compliance constraints at the operation level.
Example: The agent approves expenses up to $2,500, only for the sales department, only for travel and meals categories.
How the Layers Work Together
┌─────────────────────────────────────┐
│ 1. Task Check                       │
│ Is "expense_approval" in            │
│ authorized_tasks?                   │  ✅ Pass → Continue
└─────────────────────────────────────┘  ❌ Fail → Deny
┌─────────────────────────────────────┐
│ 2. Tool Check                       │
│ Is "submit_expense" in the          │
│ expense_mcp server's actions?       │  ✅ Pass → Continue
└─────────────────────────────────────┘  ❌ Fail → Deny
┌─────────────────────────────────────┐
│ 3. Transaction Check                │
│ - Amount ≤ approval_limit?          │
│ - Department matches?               │