{
  "question": "How do I require two independent human approvals (four-eyes / maker-checker) before an AI agent takes a high-impact action?",
  "slug": "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",
  "short_answer": "For high-impact agent actions — spend above a threshold, permission or role changes, production writes, issuing credentials — do not let a single yes release the call. Require two different humans to approve the same action hash (tool + canonical args + target + amount if any + policy version). The requester (or the person who asked the agent to act) cannot be one of the two; the second approver sees the first decision and the same preview; both receipts bind to that hash; and a pending request expires so a stale yes cannot be reused. Record both decisions outside the agent's editable session on an append-only ledger the agent cannot rewrite. That is maker-checker / four-eyes applied to agents: one compromised account, one coerced person, or one honest mistake is not enough to move money or open a gate. request_human_approval hashes the action object you send; call it twice with distinct approver slots (or gate on two receipts), then verify_human_approval against the same action before execution; ledger_verify and record_ai_run keep the trail checkable.",
  "checklist": [
    "List the action classes that need four-eyes: spend over a threshold, permission or scope changes, production writes, credential or key issuance, irreversible deletes. Everything else can stay single-approver or auto.",
    "Build one action object the agent cannot edit after the request: tool name, RFC 8785 (JCS) canonical args (then sha256), target or environment, amount and currency if any, policy_id and policy_version, and a requester_id that is not eligible to approve.",
    "Open two approval requests bound to that same action hash (or one request that requires n-of-m with n=2). Reject any decision where approver_id equals requester_id or equals the other approver.",
    "Show the second approver the first decision (who, when, note) and the same preview the first person saw. Independent eyes means a second look at the same facts, not a rubber stamp on a different summary.",
    "Expire the pending request (for example 15–60 minutes). After expiry, deny execution and require a fresh dual approval; never let an old first-yes pair with a new second-yes on a changed action.",
    "At execution, recompute the action hash and verify both receipts with verify_human_approval against that hash. Fail closed if either receipt is missing, expired, for a different hash, or from the same person.",
    "Write both decisions (approve or deny), plus expiries, to an append-only ledger outside the agent's credentials. Denials and abandoned requests matter as much as approvals.",
    "Drill it: attempt self-approval, attempt two approvals from one person with two accounts, change args between the two yeses, and confirm the gate blocks every case."
  ],
  "sections": [
    {
      "heading": "Why one human yes is not enough for high-impact agent actions",
      "points": [
        "A single approver is a single point of failure: stolen session, rushed click, social engineering, or the same person who asked the agent to act approving their own request. Banks and payment firms already treat that as unacceptable for money movement; agents that can spend, change access or write production deserve the same bar.",
        "NIST SP 800-53 Rev. 5 AC-5 (separation of duties) and AC-3(2) (dual authorization) are the control language for this: divide duties so one person cannot complete a sensitive operation alone, and require two authorizations for designated actions. Maker-checker / four-eyes is the operational pattern.",
        "How to require human approval before an AI agent spends money and how to require human confirmation before MCP write tools run cover the single-approver gate. This page is the dual-control layer on top for the actions where one person is not enough."
      ]
    },
    {
      "heading": "Binding both approvals to the same action hash",
      "points": [
        "Independence is worthless if the two people approved different things. Canonicalize the tool arguments (RFC 8785 JCS), hash them, and put tool, args_sha256, target, amount and policy_version into the action object both receipts must match.",
        "The second approver must see the first receipt (approver_id, decided_at, note) and the same evidence_ref / preview. If the first person approved a $500 refund and the agent quietly changes the amount, the second look and the hash check both catch it.",
        "request_human_approval on Rightshold hashes the action you send; decide_human_approval (owner account key) returns a signed, timestamped decision receipt; verify_human_approval is free and fails when the tool, args or other bound fields no longer match. For four-eyes, require two distinct receipts for the same action before the tool runs."
      ]
    },
    {
      "heading": "Recording dual control outside the agent",
      "points": [
        "Keep both receipts, the requester_id, the policy version and the final execution decision in a store the agent's API key cannot UPDATE or DELETE. An agent that can edit its own approval history can invent a second yes.",
        "Rightshold's ledger is hash-chained and signed; ledger_verify recomputes every payload, leaf and block hash without a key. record_ai_run can seal what the model produced for the same call so the dual-approval trail and the model output stay linked.",
        "How to record a named approver and policy version in a tamper-evident entry for every agent approval covers the per-approval entry shape; this page requires two of those entries, from different people, on one action hash."
      ]
    }
  ],
  "checks": [],
  "ask_rightshold": {
    "start": "https://www.rightshold.com/start?ref=seo",
    "mcp_endpoint": "https://www.rightshold.com/mcp",
    "ask": "Before my agent runs this high-impact tool call, require two independent human approvals bound to the same action hash (tool, args_sha256, target, amount, policy version). The requester must not be either approver; expire the pending request in 30 minutes.",
    "mcp_call": {
      "tool": "request_human_approval",
      "arguments": {
        "summary": "four-eyes: production deploy of release sha256:8f3a… under change-mgmt policy v7 (rule dual-control-prod)",
        "action": {
          "type": "tool_call",
          "tool": "deploy_release",
          "args_sha256": "sha256:8f3a…",
          "target": "env:production",
          "amount": null,
          "policy_id": "change-mgmt",
          "policy_version": "v7",
          "rule": "dual-control-prod",
          "requester_id": "idp:alex@example.com",
          "approval_mode": "two_independent",
          "required_approvals": 2
        },
        "expires_in_minutes": 30
      }
    },
    "also": [
      "Needs your API key. Open two approval requests (or one n-of-m gate) on the same action; each decide_human_approval (owner or designated approver key) signs a receipt onto the ledger.",
      "verify_human_approval is free: check both receipts against the same action object before execution; fail if either is missing, expired, self-approved, or for a different hash.",
      "ledger_verify is free and keyless and recomputes the chain so an edited or removed dual-approval entry shows up.",
      "record_ai_run seals what the agent's model produced for the call; verify_ai_run is free."
    ],
    "scope": "Rightshold records approval requests and owner decisions on a signed, hash-chained ledger and verifies that a receipt still matches the action. Enforcing two distinct humans, rejecting the requester as an approver, and sequencing the second look are policy and workflow you configure around those receipts. Rightshold does not run your identity provider or decide which action classes need four-eyes. Not legal advice."
  },
  "sources": [
    {
      "title": "NIST SP 800-53 Rev. 5: AC-5 (separation of duties) and AC-3(2) (dual authorization)",
      "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 guardrails on Rightshold",
      "url": "https://www.rightshold.com/agent-guardrails"
    }
  ],
  "related": [
    {
      "title": "How to require human approval before an AI agent spends money",
      "url": "https://www.rightshold.com/answers/how-to-require-human-approval-before-an-ai-agent-spends-money"
    },
    {
      "title": "How to require human confirmation before MCP write tools run",
      "url": "https://www.rightshold.com/answers/how-to-require-human-confirmation-before-mcp-write-tools-run"
    },
    {
      "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"
    },
    {
      "title": "How to bind approver identity to a content-addressed artifact hash and version before side effects",
      "url": "https://www.rightshold.com/answers/how-to-bind-approver-identity-to-content-addressed-artifact-hash-and-version-before-side-effects"
    }
  ],
  "computed_from": "Curated guidance; license verdicts computed from Rightshold's license profiles at render time. Not legal advice.",
  "updated": "2026-11-07"
}