# How do I record what triggered an AI agent, the permission decision and the exact tool call outside the agent's own memory, so the record can't be rewritten?

**Short answer:** An agent's memory (memory files, conversation summaries, a vector store, its scratchpad) is built to be rewritten, by the agent and by whatever content it reads, so it can't double as the record of what the agent did. Keep a separate action record that the agent can append to but never edit, written by the code that runs tools rather than by the model. For each consequential action write one entry before the tool runs: the trigger (the message, event, schedule or upstream agent that started this step, by id and hash), the permission decision (which policy or approval allowed it, its version, allow or deny), and the exact call (tool name, server, a hash of the canonical arguments, call id). Write a second entry after it runs with the result hash or error, and chain both to the previous entry by hash. Then if memory is poisoned or wiped, you can still show what the agent was asked, what it was allowed and what it actually called.

## Checklist
1. Decide which actions get a record: anything that writes, sends, pays, deletes, changes permissions or calls an outside service. Read-only lookups can go to normal logs.
2. Write the record from the tool-execution layer (your tool runner, a hook, a proxy or gateway), never from a tool the model calls to 'log' itself. The model chooses what to call; it shouldn't choose what gets written about it.
3. Before the call, write an intent entry: trigger type and id (user message id, webhook delivery id, cron job id, parent agent and task id), a hash of the trigger content, the policy or approval id and version that allowed it, the decision, tool name and server, call id and a hash of the canonical arguments.
4. After the call, write an outcome entry with the same call id: result hash or typed error, duration and whether the tool reported a side effect. A missing outcome after a crash is itself evidence.
5. Chain each entry to the previous one by hash, and sign or anchor the chain head now and then, so a deleted or edited entry shows up as a break.
6. Store it where the agent's credentials can append but not update or delete: a separate service, an append-only table with no update grant, or an outside ledger. The agent's memory directory and working folder are the wrong place.
7. Never let the agent read its own action record back into trusted memory as instructions. If it needs history, give it a summary marked as data.
8. Check memory against the record now and then: if memory says 'the user approved refunds over $500' and no approval entry exists, treat the memory as poisoned.

## Why can't an agent's memory be the record of what it did?
- Memory is meant to change. Anthropic's memory tool docs describe Claude creating, reading, updating and deleting files in a memory directory that persists between sessions, with your application running each operation. That is useful for continuity and wrong for evidence.
- OWASP's Top 10 for Agentic Applications 2026 lists Memory & Context Poisoning (ASI06): attackers corrupt or seed stored memory, summaries or retrieval stores so later reasoning and tool use go wrong, including across sessions. A record stored in the same memory is open to the same corruption.
- Even without an attack, summaries drop detail. A compacted note that says 'sent the invoice' doesn't tell you which recipient, amount or attachment went out.

## What should be recorded for each agent action?
- Trigger: what started this step and where it came from. Record the source (user, webhook, schedule, another agent), its id and a hash of the content, so you can tell a person's request from an instruction that arrived inside a fetched page.
- Permission decision: the policy id and version, or the approval id and approver, the decision, and a reason code. If no rule applied, record that too.
- Exact call: tool name, server or connector, call id, and a hash of the arguments in canonical form (fixed key order, RFC 8785 for JSON). Keep a redacted copy of the arguments if you need to read them later, and the full copy only where your data rules allow.
- Outcome: result hash or error, and the time from a clock the agent can't set.

## Why write the record before the tool runs?
- Writing the intent entry first means a crash, timeout or killed process mid-call still leaves a trace that the call was attempted and under which permission.
- It also gives you a place to stop: if the record can't be written, don't run the tool. An action with no record is one you can't account for later.
- Pair intent and outcome by call id. Intents with no outcome are the calls to check first after an incident.

## How is this different from a tool-call log?
- A tool-call audit log answers 'what did the agent call'. This record also ties each call to why it ran (the trigger) and what allowed it (the decision), and it's written before the call, so the chain holds up when the agent's own state doesn't.
- Gateway recording captures calls at the network edge. This record can sit there too, but its point is the separation from memory: nothing the agent remembers, summarises or forgets changes it.

## What are the common failure modes?
- The 'audit log' is a file in the agent's working folder, which a later step tidies up or overwrites.
- The model writes its own log entries through a logging tool, so a prompt injection can make it log something other than what happened.
- Only the tool name is stored, not the arguments hash, so you can't tell which recipient or amount was used.
- The trigger isn't recorded, so after the fact nobody can tell whether a person asked for the action or a fetched web page did.
- The record is fed back into memory as trusted context, and a poisoned entry gets repeated as if it were history.

## Ask Rightshold (free, no key)
Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code (one-click setup: https://www.rightshold.com/start?ref=seo), then ask: "Before this agent runs the tool call, record a signed entry with what triggered it, the permission decision, and the exact call (tool, server, call id, argument hash), then record the result hash after it runs."

```json
{
  "tool": "record_ai_run",
  "arguments": {
    "model": "<agent or model id>",
    "provider": "<runtime or framework>",
    "prompt_sha256": "<sha256 of the trigger content + canonical tool-call arguments>",
    "output_sha256": "<sha256 of the tool result, or of the intent entry before the call>",
    "params": {
      "phase": "intent",
      "trigger_type": "webhook",
      "trigger_id": "<delivery id>",
      "decision": "allow",
      "policy_id": "pol_…",
      "policy_version": 7,
      "tool": "send_invoice",
      "server": "<mcp server or connector>",
      "call_id": "call_…",
      "args_sha256": "<sha256>",
      "prev_entry_sha256": "<sha256 of previous entry>"
    },
    "ran_at": "2026-11-07T08:00:00Z"
  }
}
```
- Needs an API key. Only hashes and the fields you send are recorded; the receipt is Ed25519-signed and written to Rightshold's append-only ledger, outside the agent's memory.
- request_human_approval puts a person's yes or no on the record for actions that need one, bound to a hash of the exact action, so the approval id you put in the entry points at a real, checkable decision.
- verify_ai_run (free, no key) checks an entry's signature and, given the original content, that it matches the recorded hashes.

_Rightshold records the hashes and fields your tool runner sends and signs them. It doesn't run your agent, see its memory, intercept tool calls or stop a call your code didn't record. The record only covers actions your execution layer writes to it. Not legal advice._

## Sources
- [OWASP GenAI Security Project: Top 10 for Agentic Applications for 2026 (ASI06 Memory & Context Poisoning)](https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/)
- [Claude Docs: Memory tool](https://docs.claude.com/en/docs/agents-and-tools/tool-use/memory-tool)
- [MCP specification: Tools (security considerations)](https://modelcontextprotocol.io/specification/2025-06-18/server/tools)
- [RFC 8785: JSON Canonicalization Scheme](https://www.rfc-editor.org/rfc/rfc8785)

## Related
- [How to log every AI agent tool call for audit](https://www.rightshold.com/answers/how-to-log-every-ai-agent-tool-call-for-audit)
- [How to record MCP tool calls at the gateway with scope grant binding](https://www.rightshold.com/answers/how-to-record-mcp-tool-calls-at-the-gateway-with-scope-grant-binding)
- [How to keep an agent risk and approval record outside the agent's editable session](https://www.rightshold.com/answers/how-to-keep-an-agent-risk-approval-record-outside-the-agents-editable-session)
- [How to build an agent audit trail tied to grant, spend cap and revocation](https://www.rightshold.com/answers/how-to-build-an-agent-audit-trail-tied-to-grant-spend-cap-and-revocation)

_Not legal advice. Updated 2026-11-07. JSON: https://www.rightshold.com/answers/how-to-record-an-ai-agents-trigger-permission-decision-and-tool-call-outside-its-own-memory.json_