{
  "question": "How do I keep an audit trail of which human authorized an AI agent's actions?",
  "slug": "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",
  "short_answer": "Record each authorization as its own event, separate from the tool calls, and link every action to the grant it used. For any action an agent takes on someone's behalf, the trail should answer: which person granted the authority, exactly what they granted (actions, targets, limits, expiry), when and how they approved, which agent and session acted, and which calls used that grant. Standards supply the vocabulary. OAuth 2.0 Token Exchange (RFC 8693) keeps the user a token is about separate from the actor using it through the act claim, and nested act claims form a history of prior actors. Rich Authorization Requests (RFC 9396) let a grant spell out actions and locations as structured authorization_details instead of a bare scope string. Log where each approval came from, too: Claude Code's tool_decision telemetry tells a one-time Yes from a person (user_temporary) apart from a saved rule or policy (config). Because config doesn't say which rule matched, keep your own record of who wrote and approved each rule. Then make the records tamper-evident so the trail holds up when someone disputes it.",
  "checklist": [
    "Give each agent its own identity (service account, OAuth client or API key), and don't let it act under a person's own credentials, or the log will show that person did everything.",
    "Write a grant record whenever a person authorizes work: grant id, the approver's identity from your identity provider (not a typed name), the agent, the purpose, allowed actions and targets, limits such as amount or data categories, start and expiry, and how they approved (UI click, signed request, ticket).",
    "Carry the grant id with the work, in the token, a header or a tool argument, and write it into every tool-call log entry so each action points at exactly one grant. With RFC 8693 delegation tokens, sub names the user and act names the agent.",
    "For risky actions, record the approval per action: who was asked, what they were shown (the exact arguments, or a hash of them), their answer and the time. Keep one-off approvals distinct from standing rules, and log every rule change with its author.",
    "When an agent hands work to a sub-agent, record the hand-off as a new, narrower grant that names its parent, so you can rebuild the chain from the person to the last actor.",
    "Log refusals, expiries and revocations as well as approvals. A denied request or a revoked grant is evidence too.",
    "Keep personal data to what you need: a stable user id rather than an email where possible, and no tokens, passwords or session ids in the log (OWASP).",
    "Make the trail tamper-evident: append-only storage written by an account that can't edit or delete, plus regular hash commitments kept somewhere the agent's operator can't rewrite."
  ],
  "sections": [
    {
      "heading": "What the standards give you",
      "points": [
        "RFC 8693 distinguishes impersonation from delegation. When A impersonates B, A is indistinguishable from B in that context. With delegation, A keeps its own identity, and a composite token names both parties. An audit trail needs delegation, so the agent stays visible as the actor.",
        "The act claim names the current actor. Nesting act claims expresses a chain of delegation, with the least recent actor most deeply nested, and the RFC calls this a history trail. For access control only the top-level claims and the current actor count; prior actors are informational. The may_act claim states who is authorized to become the actor. To limit abuse of delegated rights, the RFC suggests the scope claim and limited token lifetimes.",
        "RFC 9396 adds authorization_details, an array of JSON objects, each with a required type and optional fields such as actions and locations. A grant can then say 'initiate a payment of 123.50 EUR to Merchant A' instead of a coarse scope. Store that object with the grant record and you have exactly what was approved.",
        "OWASP's Logging Cheat Sheet lists who (human or machine user) and user identity among the event attributes to record. It also asks for tamper detection, protection against modification and deletion, and a process that notices when logging stops."
      ]
    },
    {
      "heading": "What an agent tool's telemetry does and doesn't tell you",
      "points": [
        "Claude Code's OpenTelemetry tool_decision event records accept or reject plus a source. user_temporary means a one-time Yes at a prompt, and user_permanent means 'don't ask again', which saves an allow rule. user_reject and user_abort are refusals. hook means a PreToolUse or PermissionRequest hook decided. config covers decisions made without a prompt: by settings, managed policy, command-line flags, the permission mode or the auto mode classifier.",
        "The docs note that config doesn't say which of those sources matched. In the interactive CLI, later calls covered by a saved rule or a session-wide grant also report config. The telemetry shows that a decision was automatic, not which person wrote the rule, so keep settings and policy files in version control, where each rule has an author and a reviewer.",
        "Events carry user.email when it's available, plus a tool_use_id you can join to your hook logs. In Claude Tag channel sessions, Claude works as the organization's shared identity, and the docs say not to rely on the user.* attributes to identify who tagged Claude. Record the requester yourself in that case."
      ]
    }
  ],
  "checks": [],
  "ask_rightshold": {
    "start": "https://www.rightshold.com/start?ref=seo",
    "mcp_endpoint": "https://www.rightshold.com/mcp",
    "ask": "Here is the proof bundle for the intent my agent acted under. Check that the agent signed it, that the operator's mandate is attached, and when it was on the ledger.",
    "mcp_call": {
      "tool": "verify_intent_proof",
      "arguments": {
        "proof": "<the JSON bundle that intent_proof returned>"
      }
    },
    "also": [
      "Free, no key. It checks the statement hash, the agent's signature, the commitment, the Merkle proof and block signature, and the operator's mandate if there is one.",
      "With an API key: declare_intent records what the agent may do (purpose, operations, targets, budget, expiry), mandate_intent adds the operator's Ed25519 signature authorizing it, and intent_proof returns a bundle you can hand to an auditor.",
      "A sub-agent's intent must fit inside its parent's, and revoking a parent intent ends every intent delegated under it."
    ],
    "scope": "Rightshold records intents and operator mandates for agents that use it and verifies proof bundles. It doesn't run your identity provider, see your agents' actions in other systems, or decide who in your organization may approve what. Not legal advice."
  },
  "sources": [
    {
      "title": "RFC 8693: OAuth 2.0 Token Exchange (delegation vs impersonation, act and may_act claims)",
      "url": "https://www.rfc-editor.org/rfc/rfc8693"
    },
    {
      "title": "RFC 9396: OAuth 2.0 Rich Authorization Requests (authorization_details)",
      "url": "https://www.rfc-editor.org/rfc/rfc9396"
    },
    {
      "title": "OWASP Logging Cheat Sheet",
      "url": "https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html"
    },
    {
      "title": "Claude Code docs: Monitoring (tool_decision event and decision sources)",
      "url": "https://code.claude.com/docs/en/monitoring-usage"
    }
  ],
  "related": [
    {
      "title": "How to log every AI agent tool call for audit",
      "url": "https://www.rightshold.com/answers/how-to-log-every-ai-agent-tool-call-for-audit"
    },
    {
      "title": "How to scope OAuth tokens per task for AI agents",
      "url": "https://www.rightshold.com/answers/how-to-scope-oauth-tokens-per-task-for-ai-agents"
    },
    {
      "title": "How can an AI agent prove a verified human is behind it?",
      "url": "https://www.rightshold.com/answers/how-can-an-ai-agent-prove-a-verified-human-is-behind-it"
    },
    {
      "title": "How to require AI agent commits to go through pull requests",
      "url": "https://www.rightshold.com/answers/how-to-require-ai-agent-commits-to-go-through-pull-requests"
    }
  ],
  "computed_from": "Curated guidance; license verdicts computed from Rightshold's license profiles at render time. Not legal advice.",
  "updated": "2026-10-30"
}