Guides

Delegation Guide

Let agents act on behalf of users with controlled, auditable delegations.

Delegation Guide

Delegations allow a human to grant an agent the right to act on their behalf at a specific service. Unlike regular grants (where the agent acts as itself), a delegated agent carries the human's identity — but only within the boundaries the human defined.

When to Use Delegations

ScenarioUse
Agent runs a command as itselfRegular grant
Agent acts as a specific humanDelegation

Examples:

  • A bot that files GitHub issues as alice@example.com instead of agent+bot@example.com
  • An agent that sends emails from a human's mailbox
  • A browser automation that logs into a web app as a specific user

Create a Delegation

# Login as the human who wants to delegate
grapes login --idp https://id.example.com

# Delegate to the agent
grapes delegate \
  --to agent+bot@example.com \
  --at escapes \
  --approval always \
  --reason "Allow bot to act on my behalf for deployments"

Options

FlagRequiredDescription
--toYesAgent email that receives the delegation
--atYesService/audience where the delegation applies
--scopesNoComma-separated scopes (e.g., read,write)
--approvalNoonce, timed, always (default: once)
--expiresNoISO 8601 expiration (e.g., 2026-12-31T23:59:59Z)

With Scopes

Scopes limit what the agent can do within the delegation:

# Only allow reading and commenting, not writing or deleting
grapes delegate \
  --to agent+reviewer@example.com \
  --at shapes \
  --scopes "read,comment" \
  --approval timed \
  --expires "2026-04-01T00:00:00Z"

With Expiry

# Delegate for one week
grapes delegate \
  --to agent+ops@example.com \
  --at escapes \
  --approval timed \
  --expires "2026-03-29T23:59:59Z" \
  --reason "On-call coverage while I'm on vacation"

List and Manage Delegations

# List active delegations
grapes delegations
grapes delegations --json

# Revoke a delegation (via API)
curl -X DELETE https://id.example.com/api/delegations/<id> \
  -H "Authorization: Bearer <token>"

Using Delegations in @openape/browser

The browser package supports delegation login — the agent can log into web applications as the delegated user:

import { createGrantedBrowser } from '@openape/browser'

const browser = await createGrantedBrowser({
  rulesFile: './rules.toml',
  idpUrl: 'https://id.example.com',
  agentEmail: 'agent+bot@example.com'
})

// Login as alice via delegation
await browser.loginAs({
  email: 'alice@example.com',
  delegationToken: '<delegation-jwt>'
})

// Browser now has alice's session
const page = await browser.newPage()
await page.goto('https://app.example.com/dashboard')
// → App sees alice@example.com, not agent+bot

How It Works

1. Alice delegates to agent+bot:
   grapes delegate --to agent+bot@example.com --at shapes

2. Agent requests a grant, including delegator:
   POST /api/grants { delegator: "alice@example.com", ... }

3. IdP checks:
   - Does alice have an active delegation to this agent?
   - Does the delegation cover this service/audience?
   - Are the scopes sufficient?

4. If valid, the AuthZ-JWT includes:
   { sub: "agent+bot@example.com", delegator: "alice@example.com", ... }

5. Target system sees both identities:
   - WHO is acting: agent+bot
   - ON BEHALF OF: alice
   - WHO approved: the approver

Delegation vs. Regular Grants

Regular GrantDelegation
Agent identityagent+bot@example.comagent+bot@example.com
Acting asItselfThe delegating human
AuthZ-JWT subAgent emailAgent email
AuthZ-JWT delegatorHuman email
Use caseAgent's own actionsActing on behalf of a user
ApprovalAgent's approverDelegating human + approver

Security Considerations

  • Delegations are traceable — the AuthZ-JWT always carries both the agent and the delegator identity
  • Delegations can be scoped — limit to specific actions/services
  • Delegations can expire — set an explicit end date
  • Delegations are revocable — the human can revoke at any time
  • The agent cannot create delegations for itself — only humans can delegate