Skip to content

Agent Permissions

What are Agent Permissions?

In Nexus, agents are AI systems (CrewAI agents, LangGraph graphs, Claude SDK bots, OpenAI Agents, etc.) that operate on behalf of users. Agent permissions control:

  • πŸ” Authentication - How agents prove their identity
  • πŸ”‘ Authorization - What agents can access
  • πŸ‘₯ Inheritance - How agents inherit permissions from their owner users
  • 🎯 Direct Grants - Additional permissions granted specifically to agents

Nexus uses ReBAC (Relationship-Based Access Control) to manage agent permissions, with automatic inheritance from owner users.


Key Concepts

1. Agent Ownership (Agent β†’ User Hierarchy)

Every agent is owned by a user. This ownership is tracked in the Entity Registry:

graph TB
    T[Tenant: acme] --> U1[User: alice]
    T --> U2[User: bob]
    U1 --> A1[Agent: alice_research]
    U1 --> A2[Agent: alice_writer]
    U2 --> A3[Agent: bob_coder]

Key principle: Agents inherit ALL permissions from their owner user.


2. Two Authentication Models

Agent uses owner's API key and identifies itself via header:

# Alice's API key
export NEXUS_API_KEY="sk_alice_..."

# Agent identifies itself via X-Agent-ID header
curl -H "Authorization: Bearer $NEXUS_API_KEY" \
     -H "X-Agent-ID: alice_research" \
     http://localhost:2026/api/nfs/list

Why this is better: - βœ… No separate API key management - βœ… Agent inherits user's permissions automatically - βœ… Centralized auth (revoke user = revoke all agents) - βœ… Simpler security model

Model 2: Agent API Key (Legacy)

Agent has its own API key (independent authentication):

# Agent's own API key
export NEXUS_API_KEY="sk_agent_alice_research_..."

curl -H "Authorization: Bearer $NEXUS_API_KEY" \
     http://localhost:2026/api/nfs/list

When to use: - Long-running services (background jobs, daemons) - Agents that need independent lifecycle from user - Agent-specific rate limits or quotas


Agent Registration

Register Agent (No API Key)

Recommended for most agents:

# Register agent owned by alice
nexus agent register alice_research "Research Agent"

# Verify registration
nexus agent list

Python API:

from nexus.services.agents.agent_registry import AgentRegistry

agent_registry = AgentRegistry(session_factory=session_factory)
agent_registry.register(
    agent_id="alice_research",
    owner_id="alice",
    name="Research Agent",
    zone_id="default",
)

Create Agent with API Key (Optional)

For independent agent services:

# Create agent API key via admin
nexus admin create-agent-key alice alice_research --expires-days 90

# Output:
# βœ“ Created API key for agent alice_research
# API Key: sk_agent_alice_research_abc123...
# Expires: 2025-04-15T00:00:00Z

Python API:

from nexus.services.agents.agent_registry import AgentRegistry
from nexus.server.auth.database_key import DatabaseAPIKeyAuth
from datetime import timedelta, datetime, UTC

# Register agent via AgentRegistry
agent_registry = AgentRegistry(session_factory=session_factory)
agent_registry.register(
    agent_id="alice_research",
    owner_id="alice",
    name="Research Agent",
)

# Create API key separately
key_id, raw_key = DatabaseAPIKeyAuth.create_key(
    session,
    user_id="alice",
    name="Research Agent",
    subject_type="agent",
    subject_id="alice_research",
    expires_at=datetime.now(UTC) + timedelta(days=90),
)

print(f"API Key: {raw_key}")  # Save this - only shown once!

Permission Inheritance

How Inheritance Works

Agents automatically inherit ALL permissions from their owner user:

graph LR
    A[User alice] -->|direct_owner| B[File: /workspace/alice/]
    C[Agent: alice_research] -->|inherits| A
    C -.->|can access| B

    style C fill:#e1f5e1
    style A fill:#e3f2fd

Permission Check Flow:

  1. Direct check: Does agent have explicit grant? β†’ Yes = βœ… ALLOW
  2. Inheritance check: Look up agent's owner user
  3. User check: Does owner user have permission? β†’ Yes = βœ… ALLOW (agent inherits)
  4. Otherwise β†’ ❌ DENY

Example:

# Alice owns /workspace/alice/
nx.rebac.create("user", "alice", "direct_owner", "file", "/workspace/alice/")

# Register agent owned by alice
agent_registry.register(agent_id="alice_research", owner_id="alice", ...)

# Agent inherits alice's permissions
ctx = OperationContext(
    user="alice",
    agent_id="alice_research",
    subject_type="agent",
    subject_id="alice_research"
)

# Permission check
can_read = enforcer.check("/workspace/alice/data.txt", Permission.READ, ctx)
# βœ… True - agent inherits from alice

Inheritance Code Implementation

File: src/nexus/core/permissions_enhanced.py:737-784

# Check if agent inherits from user
if (
    not result  # Direct check failed
    and context.subject_type == "agent"
    and context.agent_id
    and self.entity_registry
):
    # Look up agent's owner
    parent = self.entity_registry.get_parent(
        entity_type="agent",
        entity_id=context.agent_id
    )

    if parent and parent.entity_type == "user":
        # Check if user has permission
        user_result = self.rebac_manager.rebac_check(
            subject=("user", parent.entity_id),
            permission=permission_name,
            object=(object_type, object_id),
            zone_id=zone_id,
        )
        if user_result:
            # βœ… Agent inherits user's permission
            return True

Direct ReBAC Grants to Agents

In addition to inherited permissions, agents can receive direct grants:

Grant Agent Permission

# Grant agent editor permission on specific file
nexus rebac create agent alice_research direct_editor file /shared/report.txt

# Grant agent viewer permission on directory
nexus rebac create agent alice_research direct_viewer directory /workspace/shared/

# Grant agent owner permission on specific resource
nexus rebac create agent alice_research direct_owner memory user_preferences

Permission Hierarchy: - direct_owner β†’ read, write, execute - direct_editor β†’ read, write - direct_viewer β†’ read only


Combined Permissions (Inherited + Direct)

Agents can have BOTH inherited and direct permissions:

graph TB
    A[Agent: alice_research]

    U[User alice<br/>owns /workspace/alice/]
    G1[Direct Grant:<br/>editor on /shared/]
    G2[Direct Grant:<br/>viewer on /logs/]

    F1[/workspace/alice/data.txt]
    F2[/shared/report.txt]
    F3[/logs/system.log]

    A -->|inherits from| U
    A -->|direct grant| G1
    A -->|direct grant| G2

    U -.->|can access| F1
    G1 -.->|can access| F2
    G2 -.->|can access| F3

    style A fill:#e1f5e1
    style U fill:#e3f2fd
    style G1 fill:#fff3e0
    style G2 fill:#fff3e0

Example:

# Alice owns /workspace/alice/
nexus rebac create user alice direct_owner file /workspace/alice/

# Grant agent ADDITIONAL access to /shared/
nexus rebac create agent alice_research direct_editor file /shared/

# Agent can now access:
# βœ… /workspace/alice/* (inherited from alice)
# βœ… /shared/* (direct grant)

Complete Workflow Example

1. Setup User and Agent

# Create user alice
nexus admin create-user alice --name "Alice Smith" --expires-days 90
# Output: API_KEY_ALICE="sk_user_alice_..."

# Save admin key
export ADMIN_KEY="sk_admin_..."

# Register agent owned by alice (no API key)
export NEXUS_API_KEY="$ADMIN_KEY"
nexus agent register alice_research "Research Agent"

# Verify registration
nexus agent list
# Output:
# alice_research (owner: alice) - Research Agent

2. Grant User Permissions

# Grant alice ownership of her workspace
nexus rebac create user alice direct_owner file /workspace/alice/

# Grant alice viewer on shared workspace
nexus rebac create user alice direct_viewer file /workspace/shared/

3. Test Agent Inheritance

# Use alice's API key + X-Agent-ID header
export NEXUS_API_KEY="$API_KEY_ALICE"

# Agent can list alice's workspace (inherited)
nexus ls /workspace/alice/ --agent-id alice_research
# βœ… Works! (inherited from alice)

# Agent can write to alice's workspace
echo "research data" | nexus write /workspace/alice/research.txt --input - --agent-id alice_research
# βœ… Works! (inherited owner permission)

# Agent can READ shared workspace (inherited viewer permission)
nexus cat /workspace/shared/doc.txt --agent-id alice_research
# βœ… Works! (inherited viewer permission)

# Agent CANNOT write to shared workspace (only has viewer)
echo "new data" | nexus write /workspace/shared/new.txt --input - --agent-id alice_research
# ❌ Fails! (no write permission on /shared/)

4. Grant Agent Direct Permission

# Admin grants agent editor permission on shared workspace
export NEXUS_API_KEY="$ADMIN_KEY"
nexus rebac create agent alice_research direct_editor file /workspace/shared/

# Now agent can write to shared workspace
export NEXUS_API_KEY="$API_KEY_ALICE"
echo "new data" | nexus write /workspace/shared/new.txt --input - --agent-id alice_research
# βœ… Works! (direct grant overrides inherited viewer)

5. Create Agent with Its Own API Key (Optional)

# Create agent API key
export NEXUS_API_KEY="$ADMIN_KEY"
AGENT_KEY=$(nexus admin create-agent-key alice alice_research --expires-days 1)

# Agent authenticates independently
export NEXUS_API_KEY="$AGENT_KEY"
nexus ls /workspace/alice/
# βœ… Works! (still inherits from alice)

Permission Check Examples

Example 1: Inherited Permission

Request: Agent alice_research wants to READ /workspace/alice/data.txt

1. Extract subject: ("agent", "alice_research")

2. Direct ReBAC check:
   β”œβ”€ alice_research has direct_owner on /workspace/alice/? β†’ No
   β”œβ”€ alice_research has direct_editor on /workspace/alice/? β†’ No
   └─ alice_research has direct_viewer on /workspace/alice/? β†’ No

3. Inheritance check:
   β”œβ”€ Find agent's owner: alice_research.parent β†’ ("user", "alice")
   β”œβ”€ Check if alice has permission on /workspace/alice/:
   β”‚  β”œβ”€ alice has direct_owner on /workspace/alice/? β†’ Yes! βœ“
   β”‚  └─ alice is owner β†’ has READ permission
   β”‚
   └─ Result: ALLOW (agent inherits from user)

4. Return: βœ… GRANTED

Example 2: Direct Permission

Request: Agent alice_research wants to WRITE /shared/report.txt

1. Extract subject: ("agent", "alice_research")

2. Direct ReBAC check:
   β”œβ”€ alice_research has direct_editor on /shared/report.txt? β†’ Yes! βœ“
   └─ direct_editor includes WRITE permission

3. Return: βœ… GRANTED (no need to check inheritance)

Example 3: Permission Denied

Request: Agent alice_research wants to WRITE /workspace/bob/data.txt

1. Extract subject: ("agent", "alice_research")

2. Direct ReBAC check:
   β”œβ”€ alice_research has direct_owner on /workspace/bob/? β†’ No
   β”œβ”€ alice_research has direct_editor on /workspace/bob/? β†’ No
   └─ alice_research has direct_viewer on /workspace/bob/? β†’ No

3. Inheritance check:
   β”œβ”€ Find agent's owner: alice_research.parent β†’ ("user", "alice")
   β”œβ”€ Check if alice has permission on /workspace/bob/:
   β”‚  β”œβ”€ alice has direct_owner on /workspace/bob/? β†’ No
   β”‚  β”œβ”€ alice has direct_editor on /workspace/bob/? β†’ No
   β”‚  └─ alice has direct_viewer on /workspace/bob/? β†’ No
   β”‚
   └─ Result: DENY (neither agent nor user has permission)

4. Return: ❌ DENIED

Multi-Tenant Isolation

All agent permissions are tenant-scoped:

# Create agent in tenant "acme"
nexus admin create-agent-key alice alice_research --tenant-id acme

# Permission only applies in tenant "acme"
nexus rebac create agent alice_research direct_editor file /data.txt \
    --tenant-id acme

# Same agent in different tenant is ISOLATED
nexus rebac create agent alice_research direct_editor file /data.txt \
    --tenant-id techcorp
# β†’ Different permissions for different tenants!

Key points: - Agents are registered per tenant - ReBAC tuples are tenant-scoped - Same agent_id in different tenants = different agents - No cross-tenant access (unless explicitly granted via global scope)


CLI Reference

Agent Management

# Register agent (no API key)
nexus agent register <agent_id> <name>

# List all agents
nexus agent list

# Show agent details
nexus agent info <agent_id>

# Delete agent
nexus agent delete <agent_id> --yes

Admin Commands

# Create agent API key
nexus admin create-agent-key <user_id> <agent_id> [--expires-days N]

# List all users and agents
nexus admin list-users

# Get detailed info
nexus admin get-user --user-id <user_id>

# Revoke API key
nexus admin revoke-key <key_id>

# Update API key
nexus admin update-key <key_id> --expires-days 180

ReBAC Commands

# Grant agent permission
nexus rebac create agent <agent_id> <relation> <object_type> <object_id>

# Examples
nexus rebac create agent alice_research direct_owner file /workspace/data/
nexus rebac create agent alice_research direct_editor file /shared/doc.txt
nexus rebac create agent alice_research direct_viewer directory /logs/

# Check agent permission
nexus rebac check agent <agent_id> <permission> <object_type> <object_id>

# Example
nexus rebac check agent alice_research write file /shared/doc.txt
# Output: βœ… Granted

# List agent's permissions
nexus rebac list-tuples --subject-type agent --subject-id alice_research

# Revoke permission
nexus rebac delete <tuple_id>

Python SDK Examples

Example 1: CrewAI Agent with Permissions

from crewai import Agent, Task, Crew
from nexus import connect
from nexus.services.agents.agent_registry import AgentRegistry

# Setup Nexus
nx = connect()

# Register agent
# Use the AgentRegistry for registration
nx.agent_registry.register(
    agent_id="crewai_researcher",
    owner_id="alice",
    name="CrewAI Research Agent",
    zone_id="default",
)

# Grant agent permissions
nx.rebac.create(
    subject=("agent", "crewai_researcher"),
    relation="direct_editor",
    object=("file", "/workspace/research/"),
    zone_id="default"
)

# Create CrewAI agent with Nexus tools
def write_research(content: str) -> str:
    """Write research findings"""
    ctx = OperationContext(
        user="alice",
        agent_id="crewai_researcher",
        subject_type="agent",
        subject_id="crewai_researcher"
    )
    nx.write("/workspace/research/findings.txt", content.encode(), context=ctx)
    return "βœ“ Research saved"

researcher = Agent(
    role="Research Agent",
    goal="Gather and store research findings",
    tools=[write_research]
)

Example 2: LangGraph Agent with Inheritance

from langgraph.prebuilt import create_react_agent
from nexus import connect
from nexus.contracts.types import OperationContext

nx = connect()

# Agent inherits from user "alice"
def read_user_files() -> str:
    """Read files from user's workspace"""
    ctx = OperationContext(
        user="alice",
        agent_id="langgraph_agent",
        subject_type="agent",
        subject_id="langgraph_agent"
    )

    # Agent inherits alice's permissions
    files = nx.readdir("/workspace/alice/", context=ctx)
    return "\n".join([f.name for f in files])

agent = create_react_agent(model, tools=[read_user_files])

Example 3: OpenAI Agents with API Key

from agents import Agent, function_tool
from nexus.remote import RemoteNexusFS
import os

# Agent authenticates with its own API key
nx = RemoteNexusFS(
    server_url=os.environ['NEXUS_URL'],
    api_key=os.environ['AGENT_API_KEY']  # Agent's own key
)

@function_tool
async def store_data(data: str) -> str:
    """Store data in Nexus"""
    # Agent has direct_editor permission on /data/
    nx.write("/data/output.txt", data.encode())
    return "βœ“ Data stored"

agent = Agent(
    name="StorageAgent",
    instructions="Store data in Nexus filesystem",
    tools=[store_data],
    model="gpt-4o"
)

Best Practices

1. Use User Auth + X-Agent-ID for Most Agents

# βœ… Recommended
export NEXUS_API_KEY="$USER_API_KEY"
curl -H "X-Agent-ID: alice_research" ...

# ❌ Avoid (unless agent needs independent lifecycle)
export NEXUS_API_KEY="$AGENT_API_KEY"
curl ...

Why: Simpler security, centralized auth, automatic inheritance.


2. Grant Minimum Permissions

# βœ… Good: Grant specific permissions
nexus rebac create agent alice_research direct_viewer file /logs/system.log

# ❌ Bad: Grant broad permissions
nexus rebac create agent alice_research direct_owner file /

3. Use Expiring API Keys

# βœ… Good: Short-lived keys
nexus admin create-agent-key alice alice_research --expires-days 1

# ❌ Bad: Permanent keys
nexus admin create-agent-key alice alice_research  # No expiration

4. Register Agents in Entity Registry

# βœ… Good: Register agent with owner
agent_registry.register(agent_id="alice_research", owner_id="alice", ...)

# ❌ Bad: Skip registration (no inheritance)
# Agent won't inherit user permissions!

5. Use Tenant Isolation for Multi-Org

# βœ… Good: Separate tenants
nexus rebac create agent alice_research direct_owner file /data.txt --tenant-id acme
nexus rebac create agent bob_coder direct_owner file /code.txt --tenant-id techcorp

# ❌ Bad: Mix tenants
nexus rebac create agent alice_research direct_owner file /data.txt  # Default tenant
# All agents can see each other!

Demo Scripts

Run Agent Permissions Demo

./examples/cli/agent_permissions_demo.sh

Tests: - βœ… Agent registration - βœ… Agent API key creation - βœ… Permission inheritance from user - βœ… File operations (list, read, write) - βœ… Permission isolation - βœ… Direct ReBAC grants


Run Inheritance Demo

./examples/cli/agent_permissions_inheritance_demo.sh

Tests: - βœ… User directory visibility - βœ… Agent registration under user - βœ… Agent inherits user permissions - βœ… Multi-level permission checking


Troubleshooting

Agent Can't Access Files

Problem: Agent gets "Permission denied" errors.

Check: 1. Is agent registered in Entity Registry?

nexus agent list | grep alice_research

  1. Does agent's owner user have permission?

    nexus rebac check user alice read file /workspace/data.txt
    

  2. Does agent have direct grant (if needed)?

    nexus rebac list-tuples --subject-type agent --subject-id alice_research
    


Agent Inherits Too Many Permissions

Problem: Agent has more access than intended.

Solution: Use agent-specific API key with direct grants (don't inherit from user):

# Create agent API key
nexus admin create-agent-key alice alice_research --expires-days 1

# Grant ONLY specific permissions (no inheritance)
nexus rebac create agent alice_research direct_viewer file /logs/


Can't Create Agent API Key

Problem: nexus admin create-agent-key fails.

Check: 1. Is user registered?

nexus admin list-users | grep alice

  1. Are you using admin API key?

    echo $NEXUS_API_KEY  # Should be admin key
    

  2. Is agent registered?

    nexus agent register alice_research "Research Agent"
    


FAQ

Q: When should agents have their own API keys?

A: Only when they need independent lifecycle: - Long-running background services - Scheduled jobs (cron, celery) - Agent-specific rate limits

Otherwise, use user auth + X-Agent-ID header.


Q: Can agents grant permissions to other agents?

A: Only if agent has admin privilege or is owner of the resource:

# Grant agent admin privilege
nexus admin create-agent-key alice alice_admin --admin

# Now agent can grant permissions
export NEXUS_API_KEY="$AGENT_ADMIN_KEY"
nexus rebac create agent bob_research direct_viewer file /shared/


Q: What happens when user is deleted?

A: All owned agents lose access (inheritance breaks). Best practice:

# Before deleting user, reassign agents or revoke permissions
nexus agent delete alice_research --yes
nexus admin delete-user alice


Q: Can agents in different tenants share files?

A: No, unless explicitly granted via global scope. Tenants are isolated by design.


Next Steps


  • Core: src/nexus/core/agent_registry.py:1
  • Permissions: src/nexus/core/permissions_enhanced.py:737
  • Entity Registry: src/nexus/core/entity_registry.py:1
  • CLI Agent: src/nexus/cli/commands/agent.py:1
  • CLI Admin: src/nexus/cli/commands/admin.py:1
  • CLI ReBAC: src/nexus/cli/commands/rebac.py:1
  • Demo 1: examples/cli/agent_permissions_demo.sh:1
  • Demo 2: examples/cli/agent_permissions_inheritance_demo.sh:1
  • Tests: tests/unit/core/test_agent_registry.py:1