{
  "question": "How do I enforce segregation of duties so an AI agent cannot both create and approve a payment?",
  "slug": "how-to-enforce-segregation-of-duties-so-an-ai-agent-cannot-both-create-and-approve-a-payment",
  "url": "https://www.rightshold.com/answers/how-to-enforce-segregation-of-duties-so-an-ai-agent-cannot-both-create-and-approve-a-payment",
  "short_answer": "Split create and approve across different principals with different credentials: the agent (or human) that drafts or submits a payment request must not hold the credential that can approve or settle it. Bind the request to a create_principal_id and a separate approve_principal_id; record both identities on an append-only ledger the agent cannot rewrite; and at settlement re-check that the approver is not the creator and that authorize_spend still matches the approved action. That is segregation of duties for money moves — distinct from four-eyes (two independent yeses on one action), quote-bound approval (binding a yes to a quoted amount), and named-approver pages (recording who said yes). Here the control is the role split itself: create vs approve cannot be the same principal. request_human_approval opens the approval for a non-creator; verify_human_approval and authorize_spend gate settlement; ledger_verify keeps both identities checkable.",
  "checklist": [
    "Name the two roles for every money move: creator (drafts or submits the payment request) and approver/settler (may authorize release). Write that the same principal_id and the same credential must never hold both.",
    "Issue separate credentials: an agent key that can call request_human_approval (or create a pending payment) but cannot call decide_human_approval or hold the owner/approver key; an owner or second-agent key that alone can decide and that authorize_spend will accept for settlement.",
    "Put create_principal_id (and optional create_credential_id) inside the action object the approval hashes. Reject any decide_human_approval where the approver equals the creator, and reject any settlement where the settler equals the creator.",
    "Show the approver the same payee, amount, currency, rail and memo the creator submitted — not a rewritten chat summary. Hash those fields (RFC 8785 JCS then sha256) so a quiet change fails verify_human_approval.",
    "At release, recompute the action hash, verify_human_approval against it, confirm approver_id ≠ create_principal_id, then call authorize_spend under the approver/settler credential only.",
    "Write create and approve events as separate ledger entries (who, when, action hash, decision). The agent's API key must not UPDATE or DELETE either row.",
    "Drill it: attempt self-approval with the agent key, attempt approve-with-creator-id, change amount between create and approve, and confirm every path denies.",
    "Keep vendor or bank-detail changes on a third path or under the approver role — a creator that can also re-point payout accounts defeats the split."
  ],
  "sections": [
    {
      "heading": "Why create and approve must be different principals",
      "points": [
        "If one agent credential can both queue a payment and mark it approved, a prompt injection, a fake invoice, or a compromised key completes the whole path alone. Segregation of duties (SoD) exists so no single actor finishes a sensitive money move by itself.",
        "NIST SP 800-53 Rev. 5 AC-5 (separation of duties) is the control language: divide duties so the person or process that initiates a transaction is not the one that authorizes it. For agents, that means separate principal ids and separate credentials, not two prompts in one session.",
        "How to keep segregation of duties when an AI agent pays bills covers accounting-system roles (clerk vs approver vs payer in QuickBooks). This page is the create-vs-approve credential and ledger split for any agent payment path, including wallets and APIs outside the books."
      ]
    },
    {
      "heading": "How this differs from four-eyes, quote-bound and named-approver controls",
      "points": [
        "Four-eyes requires two independent humans on one action hash — still useful for high-impact moves, but it does not by itself stop the creator from being one of the approvers unless you also enforce the role split.",
        "Quote-bound approval binds a yes to a quoted amount and payee so settlement cannot drift. Named-approver pages record which human said yes and which policy version. Keep those; add SoD so the creator credential is never eligible to approve or settle.",
        "request_human_approval hashes the action you send (include create_principal_id); decide_human_approval needs the owner or designated approver key and refuses delegated agent keys that would let the creator approve itself; verify_human_approval is free and fails when the bound fields no longer match."
      ]
    },
    {
      "heading": "Recording both identities and gating settlement",
      "points": [
        "Ledger both events: payment_request_created (create_principal_id, credential_id, action hash, amount, payee) and payment_approved or payment_denied (approve_principal_id, decision, same action hash). Denials matter as much as approvals.",
        "authorize_spend should run only under the settler/approver credential after a matching verified approval. set_spend_policy on that credential still caps per-tx and daily totals so a wrong yes cannot empty the wallet.",
        "ledger_verify is free and keyless: it recomputes every payload, leaf and block hash so an edited create or approve entry shows up. Pair with record_ai_run when you need the model output that produced the draft tied to the same trail."
      ]
    }
  ],
  "checks": [],
  "ask_rightshold": {
    "start": "https://www.rightshold.com/start?ref=seo",
    "mcp_endpoint": "https://www.rightshold.com/mcp",
    "ask": "My purchasing agent drafted a payment. Open a human approval for the exact payee, amount and rail, bound to create_principal_id of the agent, and refuse any approval or settlement from that same principal.",
    "mcp_call": {
      "tool": "request_human_approval",
      "arguments": {
        "summary": "SoD create≠approve: pay vendor V-8842 420.00 USD (ACH …3210) drafted by agent crd_buyer",
        "action": {
          "type": "pay",
          "vendor_ref": "V-8842",
          "amount_minor": 42000,
          "currency": "USD",
          "rail": "ach",
          "account_last4": "3210",
          "create_principal_id": "agent:buyer-bot",
          "create_credential_id": "crd_buyer",
          "rule": "create-vs-approve",
          "policy_id": "ap-sod",
          "policy_version": "v2"
        },
        "expires_in_minutes": 60
      }
    },
    "also": [
      "Needs your API key. decide_human_approval (owner or designated approver account key) signs the yes; delegated agent keys that match the creator are refused so the drafter cannot approve itself.",
      "verify_human_approval is free: re-check the receipt against the same action (including create_principal_id) right before settlement; fail if the approver equals the creator or the hash drifted.",
      "authorize_spend under the approver/settler credential returns a signed allow or deny against that credential's spend policy — never under the creator key.",
      "ledger_verify is free and keyless for the create and approve entries."
    ],
    "scope": "Rightshold records approval requests, owner decisions and signed spend allow/deny decisions on a hash-chained ledger. It never holds or moves money and does not run your identity provider. Enforcing that the creator credential cannot call decide_human_approval, and that settlement refuses creator==approver, is policy you configure around those receipts. Not financial or legal advice."
  },
  "sources": [
    {
      "title": "NIST SP 800-53 Rev. 5: AC-5 (separation of duties) and AC-3 (access enforcement)",
      "url": "https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final"
    },
    {
      "title": "RFC 8785: JSON Canonicalization Scheme (JCS)",
      "url": "https://www.rfc-editor.org/rfc/rfc8785"
    },
    {
      "title": "RFC 6962: Certificate Transparency (append-only Merkle hash logs)",
      "url": "https://www.rfc-editor.org/rfc/rfc6962"
    },
    {
      "title": "EU AI Act, Regulation (EU) 2024/1689: Article 14 (human oversight)",
      "url": "https://eur-lex.europa.eu/eli/reg/2024/1689/oj"
    },
    {
      "title": "Human approvals on Rightshold",
      "url": "https://www.rightshold.com/human-approvals"
    },
    {
      "title": "Agent spending policies on Rightshold",
      "url": "https://www.rightshold.com/agent-spending-policies"
    }
  ],
  "related": [
    {
      "title": "How to keep segregation of duties when an AI agent pays bills",
      "url": "https://www.rightshold.com/answers/how-to-keep-segregation-of-duties-when-an-ai-agent-pays-bills"
    },
    {
      "title": "How to require two independent approvals before an AI agent acts",
      "url": "https://www.rightshold.com/answers/how-to-require-two-independent-approvals-before-an-ai-agent-acts"
    },
    {
      "title": "How to require quote-bound approval before an agent payment settles",
      "url": "https://www.rightshold.com/answers/how-to-require-quote-bound-approval-before-an-agent-payment-settles"
    },
    {
      "title": "How to record a named approver and policy version in a tamper-evident entry for every agent approval",
      "url": "https://www.rightshold.com/answers/how-to-record-a-named-approver-and-policy-version-in-a-tamper-evident-ledger-entry-for-every-agent-approval"
    }
  ],
  "computed_from": "Curated guidance; license verdicts computed from Rightshold's license profiles at render time. Not legal advice.",
  "updated": "2026-11-07"
}