Sub-Delegation

Sub-delegations allow an agent to pass a subset of its authority to another agent. The child policy must not escalate beyond the parent — this is the Principle of Least Authority (POLA).

Attenuation rules

Parent policy fieldChild constraint
allowed_tools: [A, B, C]Child allowed_tools must be ⊆ {A, B, C}
max_cost_usd: 50Child max_cost_usd must be ≤ 50
pii_access: falseChild must have pii_access: false
write_access: falseChild must have write_access: false
max_calls: 100Child max_calls must be ≤ 100
exp: TChild exp must be ≤ T
nbf: TChild nbf must be ≥ T

Violation at issuance throws DrsError: POLICY_ESCALATION. Violation in a received bundle fails Block D of verify_chain.

Example: narrowing authority

import { issueSubDelegation } from '@drs/sdk';

const parentPolicy = {
  allowed_tools: ['web_search', 'write_file', 'read_file'],
  max_cost_usd: 50.00,
  pii_access: false,
  write_access: true,
};

// Agent narrows authority before delegating
const subDR = await issueSubDelegation({
  signingKey:   agentPrivateKey,
  issuerDid:    'did:key:z6MkAgent1...',
  subjectDid:   'did:key:z6MkHuman...',   // always the original human
  audienceDid:  'did:key:z6MkAgent2...',
  cmd: '/mcp/tools/call',
  policy: {
    allowed_tools: ['web_search'],         // ⊆ parent's [web_search, write_file, read_file]
    max_cost_usd:  5.00,                   // ≤ parent's 50
    pii_access:    false,                  // same (can't relax)
    write_access:  false,                  // tightened: parent allowed true
  },
  nbf:          parentNbf,                 // ≥ parent's nbf
  exp:          parentNbf + 3600,          // ≤ parent's exp
  parentJwt:    parentDR,
  parentPolicy: parentPolicy,
  parentNbf:    parentNbf,
  parentExp:    parentExp,
});

What happens if you escalate?

// This throws POLICY_ESCALATION:
await issueSubDelegation({
  policy: {
    allowed_tools: ['web_search', 'write_file', 'execute_code'],  // added execute_code
    max_cost_usd: 100,                                             // exceeded parent's 50
  },
  // ...
});
// DrsError: POLICY_ESCALATION — allowed_tools contains execute_code not in parent policy

The error fires before any signing. Invalid chains cannot be created.

The sub field never changes

The sub (subject) field represents the original resource owner — always the human at the root of the chain. It must remain identical through every sub-delegation:

rootDR.sub  = "did:key:z6MkHuman..."
subDR.sub   = "did:key:z6MkHuman..."   ← same
inv.sub     = "did:key:z6MkHuman..."   ← same

Changing sub in a sub-delegation is a structural error caught by Block B.