# Consent Memory

> Pattern 07 · Standing authority · part of Agent Consent Patterns.
> Human page: https://agentconsent.dev/patterns/consent-memory/

“Always allow” is the fastest way out of a prompt, which is exactly why users reach for it without noticing they just signed a standing grant. Make the durability of a decision a legible choice, with each option’s future spelled out.

## Problem

The moment an agent asks permission is the worst moment to decide how long that permission should last. The user is mid-task, focused on the thing they were doing, and the prompt is in the way. Faced with "Allow once / Always allow," the rational move under task focus is the one that makes the interruption stop recurring: *Always*. The button that ends the friction forever is the button that grants the most power.

So the standing grant, the one that should be the most deliberate decision in the whole flow, gets made the most carelessly, as a side effect of wanting to get on with something else. Weeks later the agent does something the user doesn't remember authorizing, because they didn't experience it as authorizing anything. They experienced it as dismissing a dialog.

## Solution

Treat *duration* as a first-class part of the decision, not a modifier bolted onto a yes. Offer a graded set of durabilities, and make each one state, right next to the choice, the future it signs the user up for.

- **Just this once** is the safe resting default, pre-selected. The agent asks again next time; nothing standing is created.
- **For this session** trades a little friction for a bounded window that ends on its own.
- **Scoped standing** ("always, for Dana") is a durable grant deliberately narrowed to a condition, so "always" doesn't have to mean "everything."
- **Unconditional standing** ("always, for anyone") is available, but drawn with visible weight, never as the quiet, obvious way out.

Every option carries a plain-language consequence line, and the confirm button names what it will do, so the durability stays legible right up to the click.

> **Live demo** — an interactive Consent Memory demo runs on the page: https://agentconsent.dev/patterns/consent-memory/

The demo is the `ConsentMemory` component from `@agentconsent/react`. Notice that the standing options read heavier than the default, and the confirm button relabels itself. The interface never lets "always" masquerade as "once."

## Anatomy

> **Anatomy** — a labeled breakdown of the Consent Memory component's parts is shown on the interactive page: https://agentconsent.dev/patterns/consent-memory/

## When to use it

- **Any prompt you expect to repeat.** If the same request will recur, users will want to stop being asked, so give them a legible way to instead of letting them reach for a hidden "always."
- **Where a standing grant is genuinely useful.** Consent Memory is for cases where remembering the answer is a real convenience; the point is to make it deliberate, not to forbid it.
- **Alongside a revocation surface.** A standing grant is only safe if it can be seen and undone later. Pair it with a [Connection Card](/patterns/connection-card/) so "always" is never a one-way door.

## When not to use it

- **Genuinely one-off, high-stakes actions.** If an action should always be confirmed afresh (moving money, irreversible deletion), don't offer to remember the answer at all. That's an [Irreversibility Gate](/patterns/irreversibility-gate/), not a memory prompt.
- **When the grant belongs in settings.** If the user is deliberately configuring what an agent may do, use the full [Authority Boundary](/patterns/authority-boundary/) surface rather than capturing it as a by-product of an in-task prompt.
- **To pre-check "always" for engagement.** Defaulting to the standing option because it reduces future prompts is the anti-pattern this exists to prevent.

## Real-world examples

- **iOS location prompts.** "Allow Once / While Using the App / Always" made duration a first-class part of the OS permission dialog. iOS also periodically re-surfaces standing "Always" grants ("app has used your location N times in the background") so the durable choice gets reconsidered, not just remembered.
- **Chrome site permissions.** One-time versus persistent grants per site, with every remembered decision listed and revocable in site settings. The memory is paired with a place to forget.
- **Claude Code tool approvals.** The approval prompt distinguishes "Yes" from "Yes, don't ask again," and remembered rules are scoped (per project, per tool, per command pattern) and reviewable with `/permissions`, a shipped example of standing grants that stay legible and undoable.

*Annotated screenshots of these flows are being collected. Products are credited, annotations follow the site-wide callout conventions, and any screenshot is removed on request, see [About](/about/).*

## Accessibility

- The prompt is a labelled `form`; the durability choices are a genuine radio group in a `fieldset`/`legend`, so assistive tech announces "how long should this apply" as one grouping with N options.
- **Each option owns its consequence.** The consequence line is associated with its radio via `aria-describedby`, so a screen-reader user hears the standing implication as they land on the choice, not only if they happen to read on.
- **The safe default is the selected default.** "Just this once" is pre-checked, so the resting state of the control is the least-standing grant; reaching a standing grant always takes a deliberate move.
- **The confirm names the durability.** The primary button relabels itself from "Allow once" to "Allow always," so the commitment is spoken, not just colored. The persistence is never carried by styling alone.
- Standing weight is conveyed with a text hint ("Standing · always") and layout, in addition to the accent color, so the distinction survives without color.

## Anti-patterns

- **"Always" as the default or the easy path.** Pre-selecting the standing grant, or making it the biggest, brightest button, is exactly how careless standing grants happen. The safe choice is the default; the broad one earns its weight.
- **Duration as a buried checkbox.** A "□ Don't ask again" tucked under an OK button hides the most consequential part of the decision. Make durability a primary choice, not fine print.
- **Standing grants with no exit.** Remembering "always" without a surface that shows and revokes it turns a moment's convenience into a permanent, invisible capability. Always pair memory with a way to forget.
- **Vague durability.** "Remember my choice." For how long, for what? Name the window and the scope; an unspecified "remember" is a blank check.
- **Consequence-free options.** Listing "Once / Session / Always" without saying what each *does* asks the user to price a decision with no price tag.

## Code

```tsx
import { ConsentMemory } from "@agentconsent/react";
import "@agentconsent/react/theme.css";

<ConsentMemory.Root
  defaultValue="once"                 // the safe default is pre-selected
  onAllow={(value) => remember(value)} // "once" | "session" | "scoped" | "always"
  onDeny={() => dismiss()}
>
  <ConsentMemory.Header>
    <ConsentMemory.Icon>✦</ConsentMemory.Icon>
    <ConsentMemory.Title>
      Allow Inbox Assistant to send email?
    </ConsentMemory.Title>
  </ConsentMemory.Header>

  <ConsentMemory.Description>
    The agent drafted a reply to Dana and wants to send it now.
  </ConsentMemory.Description>

  <ConsentMemory.Options>
    <ConsentMemory.Option
      value="once"
      durability="once"
      label="Just this once"
      consequence="The agent asks again next time it wants to send email."
    />
    <ConsentMemory.Option
      value="scoped"
      durability="scoped"
      label="Always, for Dana"
      consequence="The agent can email Dana any time without asking."
    />
    <ConsentMemory.Option
      value="always"
      durability="always"
      label="Always, for anyone"
      consequence="The agent can email any recipient, any time, without asking."
    />
  </ConsentMemory.Options>

  <ConsentMemory.Actions>
    <ConsentMemory.Deny>Not now</ConsentMemory.Deny>
    <ConsentMemory.Allow>
      {({ durability }) =>
        durability === "once" ? "Allow once" : "Allow always"}
    </ConsentMemory.Allow>
  </ConsentMemory.Actions>
</ConsentMemory.Root>
```

Each `Option` declares its own `durability`, which drives its weight and the
confirm button's label, so the standing implication has one source of truth.
Point `defaultValue` at the `once` option to keep the safe choice resting. All
parts are unstyled primitives with `data-acp` attributes; skip `theme.css` and
style them yourself, or override the `--acp-*` tokens to retheme.
