Skip to main content

Delegate Access to an Agent

Overview

Grant an AI agent permission to act on your behalf with specific, time-bound, and revocable constraints. Delegation is how you give agents the authority to perform tasks while maintaining full control and accountability.

Human Passports: how delegation is signed

Your primary Passport auth key stays on the device (WebAuthn). The API cannot pretend it has that key. So when documentation shows delegate(...), there are two supported ways to obtain a signed delegation JWT for a human Passport:

  1. Interactive: Complete WebAuthn, then exchange your session at POST /v1/sessions/delegation-tokens for a delegation token.
  2. Programmatic (automation / CI): While logged in with a live session, call POST /v1/passports/:id/api-signing-keys with a label to create a Human API Signing Key (server-held, KEK-encrypted, revocable). Store the returned key_id as a secret. Later, call POST /v1/passports/:id/delegate with optional signing_key_id (omit to use the newest active key).

These keys only sign delegation JWTs — they are not your WebAuthn identity key and are not used for VC issuance. Revoke a key with DELETE /v1/passports/:id/api-signing-keys/:keyId when a pipeline or integration is retired.

What is Delegation?

Delegation in HUMΛN means:

  • Explicit authorization - The agent can only do what you explicitly permit
  • Time-bound - Delegations expire automatically
  • Revocable - You can revoke access at any time
  • Auditable - Every action the agent takes is logged and signed

Think of it like: Giving someone power of attorney, but cryptographically enforced and instantly revocable.

SDK Examples

typescript:TypeScript
```typescript
import { Passport } from '@human/sdk';

// Your Passport identity
const myPassport = await Passport.load('did:human:550e8400...');

// Delegate to an agent
const delegation = await myPassport.delegate({
  // Which agent gets access
  agentDid: 'did:human:agent:invoice-processor-v2',
  
  // What they can do
  scopes: [
    'invoices:read',
    'invoices:process',
    'payments:approve_under_1000'
  ],
  
  // Time constraints
  expiresAt: new Date('2026-12-31'),
  
  // Business rules
  constraints: {
    maxAmount: 1000,
    requiresHumanApproval: (action) => action.amount > 500
  }
});

console.log(`Delegation created: ${delegation.id}`);
console.log(`Agent can now process invoices under $1000`);
```

python:Python
```python
from human_sdk import Passport

# Your Passport identity
my_passport = await Passport.load('did:human:550e8400...')

# Delegate to an agent
delegation = await my_passport.delegate(
    agent_did='did:human:agent:invoice-processor-v2',
    scopes=[
        'invoices:read',
        'invoices:process',
        'payments:approve_under_1000'
    ],
    expires_at=datetime(2026, 12, 31),
    constraints={
        'max_amount': 1000,
        'requires_human_approval': lambda action: action.amount > 500
    }
)

print(f"Delegation created: {delegation.id}")
print(f"Agent can now process invoices under $1000")
```

go:Go
```go
package main

import (
    "time"
    "github.com/human/sdk-go/passport"
)

func main() {
    // Your Passport identity
    myPassport, _ := passport.Load("did:human:550e8400...")
    
    // Delegate to an agent
    delegation, _ := myPassport.Delegate(passport.DelegationOptions{
        AgentDID: "did:human:agent:invoice-processor-v2",
        Scopes: []string{
            "invoices:read",
            "invoices:process",
            "payments:approve_under_1000",
        },
        ExpiresAt: time.Date(2026, 12, 31, 0, 0, 0, 0, time.UTC),
        Constraints: passport.Constraints{
            MaxAmount: 1000,
            RequiresHumanApproval: func(action Action) bool {
                return action.Amount > 500
            },
        },
    })
    
    fmt.Printf("Delegation created: %s\n", delegation.ID)
}
```

How Agents Use Delegation

Once you've delegated access, the agent uses the delegation token to prove authority:

typescript:TypeScript
```typescript
import { Agent } from '@human/sdk';

class InvoiceAgent extends Agent {
  async processInvoice(invoice: Invoice) {
    // Agent uses delegated authority
    const result = await this.passport.act({
      action: 'invoices:process',
      target: invoice.id,
      delegation: this.delegationToken, // Proves human authorization
    });
    
    // All actions are logged with provenance chain
    console.log(`Processed invoice ${invoice.id} on behalf of ${this.delegation.grantor}`);
  }
}
```

python:Python
```python
from human_sdk import Agent

class InvoiceAgent(Agent):
    async def process_invoice(self, invoice: Invoice):
        # Agent uses delegated authority
        result = await self.passport.act(
            action='invoices:process',
            target=invoice.id,
            delegation=self.delegation_token  # Proves human authorization
        )
        
        # All actions are logged with provenance chain
        print(f"Processed invoice {invoice.id} on behalf of {self.delegation.grantor}")
```

Use Cases

1. Enterprise Automation

Scenario: Finance team needs an agent to process invoices, but with safety limits.

typescript:TypeScript
```typescript
// CFO delegates invoice processing with constraints
const delegation = await cfoPassport.delegate({
  agentDid: 'did:human:agent:finance-processor',
  scopes: ['invoices:process', 'payments:initiate'],
  constraints: {
    maxAmount: 5000, // Can't approve over $5K
    requiresHumanApproval: (action) => {
      return action.vendor === 'new' || action.amount > 2000;
    },
    allowedVendors: ['approved-vendor-list'],
  }
});
```

python:Python
```python
# CFO delegates invoice processing with constraints
delegation = await cfo_passport.delegate(
    agent_did='did:human:agent:finance-processor',
    scopes=['invoices:process', 'payments:initiate'],
    constraints={
        'max_amount': 5000,  # Can't approve over $5K
        'requires_human_approval': lambda action: (
            action.vendor == 'new' or action.amount > 2000
        ),
        'allowed_vendors': ['approved-vendor-list']
    }
)
```

2. Personal Assistant

Scenario: Delegate calendar and email management to a personal AI assistant.

typescript:TypeScript
```typescript
const delegation = await myPassport.delegate({
  agentDid: 'did:human:agent:personal-assistant',
  scopes: [
    'calendar:read',
    'calendar:write',
    'email:read',
    'email:send_as_draft' // Can draft, but not send
  ],
  expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
  constraints: {
    requiresHumanApproval: (action) => action.type === 'calendar:delete'
  }
});
```

python:Python
```python
delegation = await my_passport.delegate(
    agent_did='did:human:agent:personal-assistant',
    scopes=[
        'calendar:read',
        'calendar:write',
        'email:read',
        'email:send_as_draft'  # Can draft, but not send
    ],
    expires_at=datetime.now() + timedelta(days=7),  # 7 days
    constraints={
        'requires_human_approval': lambda action: action.type == 'calendar:delete'
    }
)
```

3. Temporary Access

Scenario: Grant time-limited access to a contractor agent for a specific project.

typescript:TypeScript
```typescript
const delegation = await projectManager.delegate({
  agentDid: 'did:human:agent:contractor-bot',
  scopes: ['project:read', 'tasks:update'],
  expiresAt: new Date('2026-03-31'), // End of Q1
  constraints: {
    projectIds: ['project-xyz'], // Only this project
    cannotDelete: true
  }
});

// Automatically revoked on March 31, 2026
```

python:Python
```python
delegation = await project_manager.delegate(
    agent_did='did:human:agent:contractor-bot',
    scopes=['project:read', 'tasks:update'],
    expires_at=datetime(2026, 3, 31),  # End of Q1
    constraints={
        'project_ids': ['project-xyz'],  # Only this project
        'cannot_delete': True
    }
)

# Automatically revoked on March 31, 2026
```

Delegation Chains

Agents can further delegate to other agents (with restrictions):

typescript:TypeScript
```typescript
// Manager delegates to senior agent
const seniorDelegation = await manager.delegate({
  agentDid: 'did:human:agent:senior-processor',
  scopes: ['invoices:process'],
  constraints: { maxAmount: 5000 }
});

// Senior agent sub-delegates to junior agent (with tighter limits)
const juniorDelegation = await seniorAgent.delegate({
  agentDid: 'did:human:agent:junior-processor',
  scopes: ['invoices:process'],
  constraints: { maxAmount: 1000 }, // Reduced limit
  delegationChain: seniorDelegation.id
});
```

python:Python
```python
# Manager delegates to senior agent
senior_delegation = await manager.delegate(
    agent_did='did:human:agent:senior-processor',
    scopes=['invoices:process'],
    constraints={'max_amount': 5000}
)

# Senior agent sub-delegates to junior agent (with tighter limits)
junior_delegation = await senior_agent.delegate(
    agent_did='did:human:agent:junior-processor',
    scopes=['invoices:process'],
    constraints={'max_amount': 1000},  # Reduced limit
    delegation_chain=senior_delegation.id
)
```

Provenance Chain:

Alice [Human] (did:human:alice) → Acme Corp [Organization] (did:human:org:acme-corp) → Senior Agent (did:human:agent:senior-processor) → Junior Agent (did:human:agent:junior-processor) → Action: Processes invoice ($800)

Every action is traced back through the full delegation chain: humans, organizations, and agents.

Security Considerations

DO:

  • Use minimum required scopes (principle of least privilege)
  • Add business rule constraints (maxAmount, allowedActions)
  • Set reasonable expiration times
  • Require human approval for sensitive actions

DON'T:

  • Grant *:* (wildcard) scopes in production
  • Create delegations without expiration
  • Skip constraint validation
  • Reuse delegation tokens across agents

Revoking Delegation

Revoke access instantly:

typescript:TypeScript
```typescript
await myPassport.revokeDelegation(delegation.id);

// Agent receives a `403 Forbidden` error on next API call
// Audit log records the revocation with timestamp
```

python:Python
```python
await my_passport.revoke_delegation(delegation.id)

# Agent receives a 403 Forbidden error on next API call
# Audit log records the revocation with timestamp
```

Next Steps


See Also

← All patterns