{
  "question": "How do I re-check agent authority at execution time, not only at plan time?",
  "slug": "how-to-re-check-agent-authority-at-execution-time",
  "url": "https://www.rightshold.com/answers/how-to-re-check-agent-authority-at-execution-time",
  "short_answer": "A plan-time \"yes\" is not a standing warrant. Issue a short-lived execution grant that names the exact action, binds a hash of the arguments, and records the policy version (or settings hash) that was in force when the human or classifier approved. Immediately before the side effect — shell, MCP tools/call, payment, or deploy — load that grant again, confirm it is unexpired and unused, re-hash the arguments, and compare the live policy version. If the policy changed, the grant is missing, or the arguments drifted, fail closed and ask again. Claude Code re-evaluates permission rules on each tool call (deny → ask → allow) and applies /permissions edits from the next call in the same turn; Cursor Auto-review evaluates each shell, MCP, and Fetch call before it runs. Your own runners should do the same with an external grant store the agent cannot edit.",
  "checklist": [
    "Split plan from execute: planning/read-only work can use a broad explore mode; anything that writes, pays, sends, or reaches the network needs an execution-time check.",
    "When you approve (human or policy engine), mint a grant: grant id, agent id, action type, argument hash, policy_version (or hash of permissions.json / spend policy / CLAUDE settings), issued_at, expires_at (minutes, not days), and single-use.",
    "Store the grant outside the agent's editable session (server DB, ledger, or checkpointer the agent's tools cannot UPDATE). Give the agent only the grant id.",
    "In the tool runner, on every risky call: load grant by id → reject if missing/expired/consumed → recompute argument hash → reject on mismatch → load current policy_version → reject if ≠ grant.policy_version → then run and mark the grant consumed.",
    "Wire client-native per-call checks too: Claude Code permission modes and /permissions rules are enforced per tool call; Cursor Run Modes (Auto-review / Allowlist) gate shell, MCP, and Fetch before execution — do not disable them because you already \"approved the plan.\"",
    "On policy edits (spend caps, deny rules, allowlists, mode changes), bump policy_version so in-flight grants fail closed instead of silently following the old yes.",
    "Log allows, denies, expiries and policy-mismatch failures with the grant id and policy_version so you can audit which authority was live at the moment of execution.",
    "Never treat chat memory, a checkbox in the prompt, or approved=true in session JSON as the authority check at execution time."
  ],
  "sections": [
    {
      "heading": "Why plan-time approval is not enough",
      "points": [
        "Between \"looks good\" and the write/pay call, the user can tighten deny rules, lower a spend cap, revoke a credential, or the agent can change arguments (amount, path, recipient) after the yes.",
        "Claude Code's docs: when you add or remove a /permissions rule while Claude is working, the change applies starting with the next tool call in the same turn — which only helps if every call is checked again, not once per plan.",
        "Cursor's Run Modes page: Auto-review applies to each shell, MCP, and Fetch call in order (allowlist → sandbox when possible → classifier). Cloud Agents are a separate trust boundary; local Run Modes still expect per-call evaluation.",
        "OpenAI Agents SDK human-in-the-loop guidance keeps approval state server-side and verifies before resume; a client-uploaded RunState is not authorization."
      ]
    },
    {
      "heading": "Short-lived grants tied to a policy version",
      "points": [
        "Policy version is a monotonic integer or content hash of the rules that mattered: spend caps, tool allow/deny lists, permission mode, and network allowlists. Stamp it on the grant at approve time.",
        "At execution: if live policy_version !== grant.policy_version, refuse — even if the grant has not expired. That is how a mid-run lockdown wins.",
        "Keep TTLs short (often under 30 minutes for high-risk actions). Single-use for payments, deletes, and production deploys; bounded reuse only for identical argument hashes you deliberately allow.",
        "Combine with product controls: request_human_approval binds a hash of the action; set_spend_policy + authorize_spend re-check caps at spend time; verify_* tools fail when the receipt no longer matches."
      ]
    },
    {
      "heading": "What can go wrong",
      "points": [
        "The plan was approved in Plan/ask mode, then the session switched to bypassPermissions or Run Everything and no second check ran.",
        "Argument hash is skipped, so an approved \"transfer $25\" becomes \"$2500\" with the same grant id.",
        "Policy is edited (new deny rule, lower daily cap) but existing grants keep working until wall-clock expiry.",
        "The only copy of approved=true lives in the agent's session file, which the next turn overwrites."
      ]
    }
  ],
  "checks": [],
  "ask_rightshold": {
    "start": "https://www.rightshold.com/start?ref=seo",
    "mcp_endpoint": "https://www.rightshold.com/mcp",
    "ask": "Before my agent executes this risky tool call, ask me to approve the exact action, bind the yes to a hash of the arguments and to the current policy version, expire it quickly, and wait for my decision.",
    "mcp_call": {
      "tool": "request_human_approval",
      "arguments": {
        "summary": "Allow deploy-agent to run kubectl apply for manifests/payments-v3.yaml in prod (policy_version 14)",
        "action": {
          "type": "tool_call",
          "tool": "kubectl_apply",
          "path": "manifests/payments-v3.yaml",
          "cluster": "prod",
          "policy_version": 14
        },
        "expires_in_minutes": 15
      }
    },
    "also": [
      "Needs your API key. The action is hashed; you decide once with decide_human_approval. verify_human_approval fails if arguments changed after the yes.",
      "set_spend_policy and authorize_spend re-check per-purchase and daily caps at execution time for money moves.",
      "record_ai_run stores a signed receipt of the plan→execute decision (policy_version, argument hashes) outside the agent's session.",
      "How to keep an agent risk/approval record outside the agent's editable session covers where to store the grant."
    ],
    "scope": "Rightshold records approval requests, spend authorizations and signed receipts for agents that call it. It does not replace Claude Code permissions, Cursor Run Modes, or your orchestrator's tool runner. Fail closed in those runners when the grant or policy_version check fails. Not legal advice."
  },
  "sources": [
    {
      "title": "Claude Code: Configure permissions (per-tool evaluation; /permissions applies from next tool call)",
      "url": "https://code.claude.com/docs/en/permissions"
    },
    {
      "title": "Cursor Docs: Run Modes (Auto-review per shell/MCP/Fetch call)",
      "url": "https://cursor.com/docs/agent/security/run-modes"
    },
    {
      "title": "OpenAI Agents SDK (JS): Human-in-the-loop",
      "url": "https://openai.github.io/openai-agents-js/guides/human-in-the-loop/"
    },
    {
      "title": "Model Context Protocol specification 2026-07-28: Tools (human in the loop)",
      "url": "https://modelcontextprotocol.io/specification/2026-07-28/server/tools"
    },
    {
      "title": "Human approvals on Rightshold",
      "url": "https://www.rightshold.com/human-approvals"
    }
  ],
  "related": [
    {
      "title": "How to keep an agent risk/approval record outside the agent's editable session",
      "url": "https://www.rightshold.com/answers/how-to-keep-an-agent-risk-approval-record-outside-the-agents-editable-session"
    },
    {
      "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 audit which human authorized an AI agent action",
      "url": "https://www.rightshold.com/answers/how-to-audit-which-human-authorized-an-ai-agent-action"
    },
    {
      "title": "How to show a human the actual change before approving an AI agent action",
      "url": "https://www.rightshold.com/answers/how-to-show-a-human-the-actual-change-before-approving-an-ai-agent-action"
    }
  ],
  "computed_from": "Curated guidance; license verdicts computed from Rightshold's license profiles at render time. Not legal advice.",
  "updated": "2026-11-06"
}