---
title: "Poppy's Standing Permissions Work on Trust"
date: "2026-10-13T14:00:00-07:00"
lastmod: "2026-10-13T14:00:00-07:00"
description: "Poppy's launch promised that a business would know what the customer approved. When an agent confirms an action on a standing permission, the business still sees only a label. A proposed Mission extension lets the User approve the limits on the Company's own page and lets the Company check them before it accepts a confirmation."
summary: "A User wants a back-ordered jacket exchanged for at most $75 more and will be gone when the quote arrives. Under PAP the agent can confirm on its standing permission, but the store sees only a label and cannot check the limit. A proposed Mission extension lets the User approve the limit on the store\u0026rsquo;s page and the store enforce it: a $73 quote is confirmed without the User, a $90 quote is refused, and the task can be revoked without ending unrelated access."
slug: "poppys-standing-permissions-work-on-trust"
tags:
  - "Agentic Identity"
  - "Authorization"
  - "OAuth"
  - "Mission-Bound Authorization"
  - "Personal Agent Protocol"
  - "Standards"
---


Meta and Sierra
[announced](https://sierra.ai/blog/poppy) the
[Personal Agent Protocol](https://personalagentprotocol.org/docs/spec)
(PAP, also called Poppy) on October 6 as the way a person's AI agent
works with a business. The launch coverage described its promise as
control: customers set limits, and a business that had
[no standard way to know](https://www.pymnts.com/news/artificial-intelligence/2026/meta-sierra-poppy-lets-customers-set-limits-ai-agents/)
what the customer approved now would. That holds while the User is
present. When the agent acts on its own under a standing permission,
the business still learns only what the agent tells it.

A User asks their personal agent to exchange a Stormline jacket for the
insulated version, which is back-ordered in medium and expected this
week, if the exchange costs no more than $75 more. The quote will arrive
when the jacket is back in stock, after the User has gone. The store, a
Company in PAP's terms, supports its
[Operations extension](https://personalagentprotocol.org/docs/extensions/operations),
so when stock arrives it proposes the exchange as an operation: revision
1, $70.00 more, charged to the card on the order. The agent confirms on
the User's standing permission:

```json
{ "revision": 1, "approved_by": "standing_permission" }
```

PAP already allows this. A standing permission covers a revision whose
terms fit it, so the agent can confirm $70, or a $73 reprice, without
asking the User again (Operations section 5.1). The store cannot check
the $75 limit, though. It sees only the label, and an agent whose model
had been misled by injected content would send the same request for a
$90 quote. Section 8 of the extension says `approved_by` "works on
trust", so a store that will not take the agent's word sets
`user_approval_required` and makes the User approve every revision,
which defeats the purpose of letting the agent act while the User is
away. The jacket is PAP's own example. The
same label would confirm the other actions the extension names, such as
changing a booking or cancelling a subscription, at partners like
United Airlines.

Section 8 also names a remedy and leaves it undefined: a Company "can
ask the User to approve on its own website, signed in, the way Direct
Sign-In works." **This proposal defines a version of that step for
standing permissions.** Before leaving, the User approves the jacket, the
replacement, the $75 limit, and the expiry on the store's own page, and
the store keeps that approval as a record called a Mission: what the
User approved, within what limits, until when, and whether it still
stands. When the
agent confirms, the store checks the operation against the Mission: it
admits $70 or $73 without the User and refuses $90, whatever the agent's
model has come to believe. The store's check does not rely on the
agent's judgment; the Limits section covers what it leaves open.

PAP is a draft that Meta and Sierra are developing with partners
including Shopify, Stripe, and Walmart, and its
[design partners](https://personalagentprotocol.org/docs/path-to-1)
also include OpenAI, Target, Bank of America, and United Airlines. I
write the
[Mission-Bound Authorization drafts](https://mcguinness.github.io/mission-bound-authorization/),
and the [design note](https://github.com/mcguinness/mission-bound-authorization/blob/main/notes/pap-mission-sketch.md)
behind this proposal is mine. Neither PAP nor the Mission drafts have
adopted it. This reading uses PAP Draft 0.1, updated October 13, 2026.

{{< tldr >}}

- **PAP supplies the operation.** Terms are fixed per revision, every
  channel confirms one operation record, and retries cannot run it twice.
- **PAP leaves the permission with the agent.** The agent may confirm a
  revision its standing permission covers, but the store cannot check
  that permission, so a cautious store asks the User about every
  revision.
- **A Mission gives the store the permission.** The User approves the
  task and its limits once on the store's page, and the store checks
  them each time it admits a confirmation: $73 goes through while the
  User is away, and $90 does not.
- **What the store builds.** An approval step on its own sign-in page, a
  stored record of each approved task, tokens tied to that record, a
  check before it accepts a confirmation, and a revoke control in account
  settings. The agent's confirm request stays the same.
- **What it does not cover.** An agent that also holds other write access
  can go around the check, so whether agents get write access outside
  Missions is the store's call. Limits on how often a permission is used,
  and proof that the User saw each revision, need further work.

{{< /tldr >}}

## What the Store Decides

Under the jacket Mission, the store decides each attempt itself:

| Attempt | Store decision under this Mission |
| --- | --- |
| Confirm the $70 revision for the approved item and replacement | Admit while the Mission is active |
| The store reprices to $73 in revision 2, and the agent confirms it without the User | Admit: the latest revision still fits the Mission |
| Confirm a revision 2 that charges $90 | Refuse: outside the approved authority |
| Confirm an old revision after the quote changes | Refuse under PAP's revision check |
| Substitute another item or replacement | Refuse: the constrained terms do not match |
| Keep the price at $70 but add a $10 fee | Refuse: the net amount, $80, exceeds the cap |
| Confirm a second exchange of the same item | Refuse: the store's one-exchange-per-item rule, checked at admission, fails it |
| With the Mission's token, change `approved_by` to `user` to accept the $90 quote | Refuse: the label does not enlarge the Mission |
| Retry an admitted confirmation | Return the existing result: the exchange runs once |

The agent's own software can and should check the limit too, but the
store cannot see whether it did, and the store is the one facing the
dispute or the chargeback when a quote the User never allowed goes
through. That is why the store needs its own record.

## The Permission PAP Leaves with the Agent

PAP already gives an authorization check something precise to evaluate.
A proposal names the terms, a confirmation selects one revision, and the
store keeps the operation's identity through retries and uncertain
outcomes.

The permission itself is kept by the agent. PAP's
[Guides](https://personalagentprotocol.org/docs/guides) tell the agent
to store each standing permission with the Company, account, kind of
action, limits, and expiry, and to compare them with the proposed terms
before confirming. PAP's scopes, including those a Company defines,
limit which APIs an agent may call. They do not record this jacket task,
its $75 limit, or whether the User still allows it.

For the User, a Mission is one approval per task at each company and one
place to revoke it. Suppose the store also lets agents act through its
own MCP server, outside PAP. The jacket task is still one Mission:
approved once on the store's page, shown once in the User's settings,
and revocable in one place, whichever path the agent takes. Each path
gets its own token from the same Mission, and each path's enforcement
point checks the action against it. A path that can perform the
exchange without that check, such as an MCP server acting on its own
backend credentials, is not covered. A permission defined separately
for each protocol would give the User a record, and a
place to revoke it, for each one.

A store could build its own record from standard parts. A PAP-specific
RFC 9396 `authorization_details` type, a consent record, a check at
confirm, and RFC 7009 revocation of the grant would implement this
example, and
[Grant Management](https://openid.net/specs/oauth-v2-grant-management-ID1.html)
would make the grant durable, queryable, and revocable. A Mission
standardizes what otherwise stays specific to each application: the
identity of the approved task, a fixed copy of exactly what the User
approved, and a lifecycle shared by every credential and authorization
decision that serves the task: when it ends, nothing new is admitted
under it. The Mission drafts
define those rules once, from the same standard parts, which is what
lets one Mission cover both the PAP path and the MCP path.

## Approving the Jacket Task

The design note proposes a PAP extension named
`karlmcguinness.com/mission`, under the domain prefix PAP requires until
it adopts an extension, built on the Mission drafts'
[OAuth specification](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission.html)
and
[Resource Access Profile](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-oauth-mission-resource-access.html).
A store that supports it lists in its `poppy.json` each action it
governs and the terms it can enforce for that action.

Most of the work comes before the User approves anything. The agent
finds what the store can enforce, resolves the order, the item, and the
replacement, and turns the User's request into those constraints; "find
me a warmer jacket" would need more discovery first. If the store cannot
enforce a limit the User set, the agent does not drop it silently. It
asks the User, who can accept the wider authority the store can hold,
have the agent ask before each confirmation, or stop.

The agent pushes the task and its proposed authority to the store's
authorization server through a pushed authorization request (PAR), which
keeps them out of the browser, then opens the store's Direct Sign-In
page. The User signs in and reviews what the store will grant, which can
be less than the agent asked for:

> View your account. See or cancel the exchange of this jacket for the
> Stormline Insulated Jacket (M). Confirm it if you pay at most $75.00
> more, after the credit for this jacket and including fees and tax,
> before October 31.

The User's approval, the Mission's tokens, and every later check use
that granted authority, here three RFC 9396 `authorization_details`
entries:

```json
[
  { "type": "mission_resource_access",
    "resource": "https://api.example.com",
    "actions": ["poppy:read"] },
  { "type": "mission_resource_access",
    "resource": "https://api.example.com/poppy/operations",
    "actions": ["exchange.read", "exchange.cancel"],
    "constraints": {
      "order_id": "ord_7Hk2",
      "item_id": "itm_4Qa",
      "replacement_sku": "stormline-insulated-m"
    } },
  { "type": "mission_resource_access",
    "resource": "https://api.example.com/poppy/operations",
    "actions": ["exchange.confirm"],
    "constraints": {
      "order_id": "ord_7Hk2",
      "item_id": "itm_4Qa",
      "replacement_sku": "stormline-insulated-m",
      "max_amount": { "amount": "75.00", "currency": "USD" }
    } }
]
```

Because read and cancel are separate from confirm, the agent can inspect
or decline a $90 quote without being able to accept it. The first entry
becomes PAP's ordinary `poppy:read` scope, which satisfies PAP's rule
that every sign-in requests a scope and still allows reads across the
account; the Mission narrows only the exchange. No entry grants a
general write scope.

The store then issues the Mission's tokens. They sit beside any ordinary
tokens the agent holds rather than replacing them, and none outlives the
Mission.

```mermaid
sequenceDiagram
    participant U as User
    participant PA as Personal Agent
    participant AS as Store sign-in
    participant API as Store API
    participant OPS as Operations endpoint
    PA->>AS: Pushed request with the task and proposed authority
    PA->>U: Open the store's sign-in page
    U->>AS: Sign in, review the bounded task, approve
    AS-->>PA: Code, returned through the User's browser
    PA->>AS: Exchange the code for this Session
    AS-->>PA: Mission-bound Account Token and Session Token
    Note over U,PA: The User leaves. The jacket comes back in stock.
    PA->>API: Request the jacket exchange
    API-->>PA: Operation exc_5Rt2, revision 1, USD 70 more
    PA->>OPS: Confirm revision 1 with standing_permission
    OPS->>OPS: Check the authority and the Mission's state, admit atomically
    OPS-->>PA: Result, with the Mission named in the confirmation
```

The [design note](https://github.com/mcguinness/mission-bound-authorization/blob/main/notes/pap-mission-sketch.md)
has the discovery fields, the pushed request, the token response, and
the full decision procedure.

## Checking the Permission at Confirm

Under the Mission's tokens, the store's APIs, its MCP tools, and its
Company Agent (the store's own conversational agent) only propose
governed operations; none performs one. An endpoint that only writes
directly, with no proposal step, refuses the token. A User who signs in to the store's website in their
own browser is not on a PAP Session and acts on their own authority,
outside the Mission. A browser on the agent's Mission Session is bound by
the Mission, so any website path that confirms operations runs the same
check or refuses Mission Sessions.

The confirm request is the one shown at the top, unchanged, sent with
the Mission's token.

PAP's ownership, revision, expiry, and operation-state checks still
apply. For a Mission token, the granted entries replace PAP's check for
a write scope: the store identifies the action from its own operation
record, finds a granted `exchange.confirm` entry, and evaluates its
constraints against the stored revision. The store documents what each
governed action does, such as what an exchange charges and ships, and
keeps the version of that documentation the User approved with the
Mission. If the store later changes what an exchange does, a
confirmation under the old Mission is refused rather than allowed to
pick up the new behavior.

The store defines the cap against the net amount the User pays, after
the credit for the returned jacket and including fees and tax. It
computes that amount from the revision, whose `terms` must describe
every charge (Operations section 3). The order, item, and replacement
must match, and the store's own eligibility rules still apply. Those
checks produce the decisions in the table above.

An admitted confirmation names the Mission it was checked against, in
the one field the extension adds to PAP's confirmation record:

```json
"confirmation": {
  "revision": 2,
  "approved_by": "standing_permission",
  "confirmed_at": "2026-10-15T12:04:31-07:00",
  "mission": { "id": "msn_8RfX2Lqv9TqM", "issuer": "https://auth.example.com" }
}
```

A refusal reuses PAP's `insufficient_scope` error with a `mission_denial`
attribute. Only an agent that supports the extension holds Mission
tokens, and on a Mission denial it does not sign in for more scopes or
retry with another credential; the request goes back to the User, for a
new Mission or the User's own decision. The design note has the exact
response.

## Revoking One Task

The store's account settings list the agent's Missions, each with a
revoke control, so the User can withdraw the jacket permission while a
separate delivery-tracking task keeps working. Each Mission runs in its
own Sessions, because PAP signs out every Session a revoked Account
Token signed in. The agent revokes the Mission itself when it finishes,
by revoking the Mission's Account Token at PAP's existing RFC 7009
endpoint. Disconnecting the agent still revokes everything.

Once revocation commits, the store admits no further confirmation under
the Mission, and the Mission's tokens stop working because the store
checks Mission state on every request. The store has to order the two:
it must never admit a confirmation on a Mission state read before a
revocation that has since committed. That is simple in one transactional
store and real engineering when the sign-in server and the order service
keep separate databases. An operation admitted before revocation still
finishes under PAP's rules; revocation stops new commitments and does
not reverse a charge or shipment already admitted. The Mission's tokens
also lose read and cancel access, so the store's account page should
list operations still in progress and let the User cancel them where
PAP allows.

## Limits

**Other credentials.** PAP lets any signed-in Session of the same agent
and account confirm an operation (Operations section 3.2), so an agent
that also holds an ordinary Account Token with write access can confirm
outside the Mission with `approved_by: "user"`, on its own word. The
agent's trusted runtime can keep that credential out of the task, but
only the store can enforce the boundary: for a governed action, it
accepts an agent's confirmation only under a Mission, or outside one
only with an approval it verifies itself.

**Use counts.** The $75 cap applies to each operation, not to total
spending: two different operations can each fit it. The
jacket example stays at one exchange only because the store allows one
exchange per order item. A store without such a rule needs a one-use
bound, which belongs to the separate
[Mission Metering](https://mcguinness.github.io/mission-bound-authorization/#go.draft-mcguinness-mission-metering.html)
work; until then, the agent keeps the use counts PAP's Guides describe.

**Approvals.** `approved_by: "user"` remains the agent's statement, so
this first version does not support the Mission drafts'
`requires_action_approval` constraint, which needs a verified approval
of each action. PAP forbids an agent to complete the store's sign-in
page itself, but a store cannot always detect one that does (spec
section 4.4). The store can make that impractical by requiring a sign-in
that needs the User present, such as a passkey, which is what makes the
approval on its page stronger than a label. A passkey gives stronger
assurance that the account holder took part in the approval. The store
binds that sign-in to the exact authority it showed and granted, which
is evidence of approval for a bounded class of exchanges, not proof that
the User reviewed each later revision.

**Scope.** The first version needs Direct Sign-In, because Device
Sign-In has no way yet to carry the request and Mediated Sign-In has no
page the store renders. Each Company keeps its own Missions, so no
shared Mission reference correlates a User across Companies.

## When a Mission Is Worth Its Cost

For a small task the User would confirm anyway, an approval on the
store's page adds little value. A Mission is worth the work when the
User wants the agent to act while they are away, within limits the
store enforces, and the store wants its own record of what the User
allowed.

PAP's authors ask for feedback on "weaknesses in sign-in, sessions,
tokens, permissions" before 1.0. Three changes would close this gap,
with or without the extension:

1. Define the approval step Operations section 8 leaves open: the User
   approving a standing permission on the Company's own page. The
   extension proposed here, a short page in PAP's own format proposed
   for adoption as `mission`, is one way to do it, and the
   [design note](https://github.com/mcguinness/mission-bound-authorization/blob/main/notes/pap-mission-sketch.md)
   has the tests an implementer would run.
2. Add an action identifier and a typed representation of consequential
   effects, including charges, to operations, so a standing permission
   can be checked by machine instead of by reading `terms` each Company
   defines.
3. Let a Company require that a standing permission it accepts is one it
   holds, and refuse `standing_permission` otherwise.

Once the User approves the task, the store has its own answer to the
next confirmation: $73 is within the permission, $90 is outside it, and
a revoked permission authorizes neither.

