Tool authorization
The simplest model represents tool authorization for a Model Context Protocol server. When a task starts, you write tuples granting it permission to call the tools it needs. Atool represents a capability (e.g., slack_send_message), and a tool_resource represents a specific target within that tool (e.g., a Slack channel). Granting can_call on a tool automatically grants access to all of its resources. You can also grant access to individual resources, or use task:* to allow any task to call a tool.
For example, you can grant task:1 access to send any Slack message, while restricting task:2 to a specific channel:
task:2 can call tool_resource:slack_send_message/XGA14FG, send a contextual tuple linking the resource to its tool. This avoids storing a tuple for every channel — you provide the tool-to-resource relationship at query time.
Contextual tuple: Link the tool_resource to its parent tool
Domain-specific models
The model above is generic. If you are building agents for your own application, your authorization model should reflect your domain. Consider a project management system: This enriches an existing user-oriented model by addingtask as a principal. Granting a task the write relation on a project gives it permission to read and edit the project and all its tickets. You can also grant permissions at the ticket level for more granular control. This makes your application ready for agent authorization with minimal changes to your existing model.
If you follow this approach, your application needs to perform both user and task authorization. This means two separate checks: one to verify the user has access to a resource, and another to verify the task has permission to perform the action on behalf of the agent, as described in Binding agents to tasks.
Scoping permissions to sessions and agents
In interactive scenarios, users may create multiple sessions. You can scope permissions to a session so that access applies to all tasks within it. You can also scope permissions to an agent so they persist across sessions. Thecan_call relation accepts three types of assignments:
task— grant permission to a specific task.session#task— grant permission to all tasks in a session. When the user says “allow this for this session”, write a tuple likeuser: session:1#task, relation: can_call, object: tool:slack_send_message.agent#task— grant permission to all tasks for an agent, across sessions. When the user says “always allow this”, write a tuple withagent:1#taskinstead.
Expiration and call count
You can use OpenFGA conditions to make permissions expire after a duration, or limit how many times the tool can be called. Theexpiration condition grants access for a fixed duration from the grant time. The max_call_count condition limits how many times the tool can be called. When writing the tuple, you provide the condition parameters:
Binding agents to tasks
The examples above do not verify that the agent making the call is actually assigned to the task. You can enforce this using contextual tuples and an intersection (and) in the model, similar to the Authorization Through Organization Context pattern.
The can_call relation requires both that the task has been granted access and that the agent making the call is linked to the task. When the task is created, link it to its agent:
true:
Contextual tuple: The agent making the call
If a different agent tries to use task:1, the check returns false because the agent-to-task link does not match:
Contextual tuple: A different agent making the call
Delegating task permissions to sub-agents
Sub-agents also start with no permissions. When delegating work, you have two options:- Share the task: assign the same task to the sub-agent, giving it all the task’s permissions.
- Restrict further: create a new task with a narrower set of permissions for the sub-agent.
Tuple cleanup
When a task completes, delete all tuples associated with it to revoke its permissions.Further reading
Mapping user intent to the right set of permissions is an active area of research. These resources explore the topic:- From Scopes To Intent: Reimagining Authorization for Autonomous Agents, MCP Dev Summit NY 2026 code repository and demo
- Intent-Based Access Control: Securing Agentic AI Through Fine-Grained Authorization
- Delegated Authorization for Agents Constrained to Semantic Task-to-Scope Matching
- The Mission Shaping Problem
- Securing Agentic AI: authorization patterns for autonomous systems
Related Sections
Take a look at the following sections for more information.Conditions
Learn how to model relationships with conditions such as expiration and call count
Contextual Tuples
Learn how to use contextual tuples to send dynamic context at query time