Rightshold™ Sign up

Answers · agent safety

How do I keep an agent risk and approval record outside the agent's editable session?

Last updated

TL;DR: Store approvals and risk decisions where the agent cannot rewrite them: a server-owned database, an append-only ledger or a checkpointer the agent's tools can't open for write. Don't keep the only copy in chat history, the agent's scratch folder, or a serialized run state the client can edit. The OpenAI Agents SDK's human-in-the-loop guide says to keep the complete RunState snapshot in application-controlled server storage for browser or mobile approval UIs, send reviewers only display details and opaque ids, and never accept replacement tool calls or serialized state from the client. LangGraph's persistence docs say InMemorySaver is lost on restart and point production at PostgresSaver or SqliteSaver. Bind each yes to a hash of the exact action, expire it, and verify that hash again right before the risky step runs.

What should I check, step by step?

1. Decide which events are the risk record: approval requests, approve/deny decisions, policy changes, denials, expiries and revocations. Write each as its own append-only event with who, what, when and which agent.

  1. Put that store outside the agent's writable session: a server database the agent's tools can't UPDATE/DELETE, an external ledger, or a checkpointer/credentials vault the agent process doesn't mount read-write.
  2. Never treat chat memory, AGENTS.md, a local JSON file in the workspace, or the model's context as the system of record for approvals.
  3. For OpenAI Agents SDK pauses: keep result.state.toString() on the server; authenticate the reviewer from your session middleware (not the request body); atomically consume the pending request before resume so the same snapshot can't be replayed.
  4. For LangGraph: use a durable checkpointer (PostgresSaver or SqliteSaver), not InMemorySaver, and put interrupt()/resume on a thread_id your payment or tool runner owns.
  5. Show the reviewer the real arguments (tool name, amount, target), bind the decision to a hash of them, make the token single-use with a short expiry, and re-check the hash immediately before execution.
  6. Give the agent only a receipt id or opaque approval id, not the private decision token and not a mutable "approved=true" flag in its session.
  7. Log refusals and timeouts as well as approvals, and keep personal data to a stable user id where you can (OWASP logging guidance).

Why the agent's session is the wrong place

Anything in the prompt, tool results or a file the agent can edit can be changed by the next turn, a prompt injection or a hallucinated "user already approved". A risk record has to survive that.

What to record, and how to use it at runtime

For each risky action: grant or approval id, approver identity from your IdP, agent id, purpose, allowed actions and targets, limits, start/expiry, decision, and a hash of the exact arguments shown.

What can go wrong?

The only approval flag lives in the agent's session JSON, and a later turn overwrites it to true.

How do I ask Rightshold about this (free, no key)?

Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “Before my agent runs this risky tool call, ask me to approve the exact action (tool name and arguments), store the decision outside the agent's session, and wait for my yes or no.”

One-click setup

{
  "tool": "request_human_approval",
  "arguments": {
    "summary": "Allow research-agent to call transfer_funds for 25.00 USD to vendor-settlement.example.com",
    "action": {
      "type": "tool_call",
      "tool": "transfer_funds",
      "amount_minor": 2500,
      "currency": "USD",
      "merchant_domain": "vendor-settlement.example.com"
    },
    "expires_in_minutes": 30
  }
}

Rightshold records approval requests and signed decisions for agents that use it. It doesn't host your RunState blobs, run your identity provider, or stop an agent that never asks. Keep framework snapshots and checkpointers in storage the agent cannot edit. Not legal advice.

What are the sources?

Related

Not legal advice. JSON · Markdown · All answers

Get a free API key in one call

No card and no email needed. 100 free credits; the license and policy checks stay free without a key.

curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_...   # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
  -H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'